百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

超强详解FLV解复?实战之FlvParser源码分析

cac55 2024-11-02 10:56 35 浏览 0 评论

1.环境准备

下载flvparser的源码:https://github.com/riverlight/FlvParser

qt工具设置如下:

在以下这个函数打下端点:

这个函数很长,只截出了一部分。


打印的媒体数据如下,与MediaInfo输出的一致:


如下图,是FLVParser的源码结构图:

1.main函数调用Process输出。

2.在process方法,把解析的数据存到内存里。


3.看看这个Parser方法。使用CheckBuffer、CreateFlvHeader检测9字节header。


4.进入CreateFlvHeader方法,观察flvHeader及其debug的数据结构。

pHeader->pFlvHeader = new uint8_t[pHeader->nHeadSize];
 memcpy(pHeader->pFlvHeader, pBuf, pHeader->nHeadSize);

//把这9个字节拷贝起来,然后再缓存起来,最终写到文件里。

flvHeader描述的就是一些flv header的信息,与MediaInfo分析出的信息一样。


还有TagHeader。

关于TAG的父类结构体。

子类CVideoTag、CAudioTag、CMetaDataTag都是继承上面父类的TAG。如下:

其中int ParseH264Configuration(CFlvParser *pParser, uint8_t *pTagData);这里一般就是一个AVC头部信息的解析,这里就是int ParseNalu(CFlvParser *pParser, uint8_t *pTagData)的数据NALU的解析;。int ParseAudioSpecificConfig(CFlvParser *pParser, uint8_t *pTagData);这里一般就是一个AAC音频头的解析,int ParseRawAAC(CFlvParser *pParser, uint8_t *pTagData);对于AAC数据的解析。


这里就会分析出相关信息。


关于媒体脚本数据就是解析视频宽高,采样率等。源码如下。



这里就是一些字段信息。



5.需要有完整的15个字节才能检查出TAG Header。15个字节的来源就是nPrevSize(4字节) + Tag header(11字节)。没有15个字节,就不一定能够检查出来,就需要使用return返回。


识别不同的TAG,然后进行解析。返回,不管是什么类型的TAG,然后插入到队列中。这里可以看出,音视频的裸流是没有时间戳。

6.分别详细看看VideoTag,AudioTag,ScriptTag。


初始化是把头部和body信息一起拷贝了。这里的_pTagData就是body信息。这里表示只处理AVC类型。


再来看看ParseH264Tag的数据包做了什么。

nAVCPacketType = pd[1]表示数据包类型,视频数据被压缩之后被打包成数据包在网上传输。根据包类型,分别去解析视频配置信息,还是真正的视频数据包。

注意:有两种类型的数据包:视频信息包(sps、pps等)和视频数据包(视频的压缩数据)。

那我们接下来,继续看看H264的配置信息,也就是具体解析AVC sequence header。要解析H264的配置信息,那么需要跨过 Tag Data的5个字节,比如VIDEODATA(1字节) AVCVIDEOPACKET(AVCPacketType(1字节) 和CompositionTime(3字节) 4字节),这样才能找到相关的配置信息结构体AVCDecoderConfigurationRecord。

注意:这里还有添加TAG Header的start code。

AVCDecoderConfigurationRecord结构体:


这里要说明下,为什么NALU的长度信息,需要4字节长度对齐。

_nNalUnitLength 这个变量告诉我们用几个字节来存储NALU的长度,如果NALULengthSizeMinusOne是0,那么每个NALU使用一个字节的前缀来指定长度,那么每个NALU包的最大长度是255字节,这个明显太小了,使用2个字节的前缀来指定长度,那么每个NALU包的最大长度是64K字节,也不一定够,一般分辨率达到1280*720 的图像编码出的I帧,可能大于64K;3字节是比较完美的,但是因为一些原因(例如对齐)没有被广泛支持;因此4字节长度的前缀是目前使用最多的方式。

注意下:这几个数据结构的说明。一般的flv和MP4文件都是不带startcode,所以解析的时候就需要添加startcode,这样dump下来的裸流才能够正确播放。

接下来再看看,真正解析H264的视频数据,ParseNalu。这里也需要跨过Tag Data的5个字节,分别是VIDEODATA(1字节) AVCVIDEOPACKET(AVCPacketType和CompositionTime 4字节。132 - 5 = 127 = _nNalUnitLength(4字节) + NALU(123字节)=startcode(4字节) + NALU(123字节) = 127。所以一般NALU数据的也包含了NALU的长度。 计算NALU(视频数据被包装成NALU在网上传输)的长度,一个tag可能包含多个nalu(所以可能就有多帧), 所以每个nalu前面有NalUnitLength字节表示每个nalu的长度,来去表示不同的数据长度。这里的switch就描述了,NALU的长度用多少个字节去描述。

大概就是类似这样的图:


这里有个文件是,用户可以根据自己的需要,对该函数进行修改或者扩展,功能大致就是往视频中写入SEI信息等。如果起始码后面的两个字节是0x05或者0x06,那么表示IDR图像或者SEI信息。


继续看看音频的AudioTag, CAudioTag 音频Tag Data区域开始的第一个字节包含了音频数据的参数信息,这里的第一个字节的信息,就仅供参考了,正真的还是要看AACsecuquence里面的参数配置。从第二个字节开始为音频流数据,但第二个字节对于AAC也要判断是AAC sequence header还是AAC raw。可以对照代码看。


第一个字节:SoundFormat 4bit 音频格式 0 = Linear PCM, platform endian
                        1 =ADPCM; 2 = MP3; 3 = Linear PCM, little endian
                        4 = Nellymoser 16-kHz mono ; 5 = Nellymoser 8-kHz mono
                        6 = Nellymoser;  7 = G.711 A-law logarithmic PCM
                        8 = G.711 mu-law logarithmic PCM; 9 = reserved
                        10 = AAC ; 11  Speex 14 = MP3 8-Khz
                        15 = Device-specific sound
              SoundRate 2bit 采样率 0 = 5.5-kHz; 1 = 11-kHz; 2 = 22-kHz; 3 = 44-kHz
                        对于AAC总是3。但实际上AAC是可以支持到48khz以上的频率。
              SoundSize 1bit 采样精度  0 = snd8Bit; 1 = snd16Bit
                        此参数仅适用于未压缩的格式,压缩后的格式都是将其设为1
              SoundType 1bit  0 = sndMono 单声道; 1 = sndStereo 立体声,双声道
                        对于AAC总是1

这里还要根据数据包类型去解析配置信息还是解析音频数据。

在ParseAudioSpecificConfig才会正真拿到解析配置信息,虽然关于媒体脚本包里面也有音频的相关值,比如采样率,通道数,但是最终还是以这里获取处理的值为准。

接下来在ParseRawAAC就是为了解析AAC的真实的数据,这里正如前面文章分析的,如果输入文件是flv或MP4的时候,一样要每帧裸数据前添加adts头,也就是代码注释中制作元数据的地方。最终把裸流和ADTS头一起拼装起来。

注意: memcpy(_pMedia + 7, pTagData + 2, dataSize),这里 pTagData + 2,表示跳过了2个字节,表示分别跳过了AAC header和AAC RAW里的packet type,他们加在一起是2个字节,这里就是跳过了2个字节。

  // 是bits的最高8bit,实际为0  
  p64[0] = (uint8_t)(bits >> 56); 
   // 才是ADTS起始头 0xfff的高8bit
    p64[1] = (uint8_t)(bits >> 48); 
    p64[2] = (uint8_t)(bits >> 40);
    p64[3] = (uint8_t)(bits >> 32);
    p64[4] = (uint8_t)(bits >> 24);
    p64[5] = (uint8_t)(bits >> 16);
    p64[6] = (uint8_t)(bits >> 8);
    p64[7] = (uint8_t)(bits);


再来看看CMetaDataTag,画红色框的部分,这里的m_amf1_type一定是2,否则就视为错误。如果是2,就去解析MetaDataTag。

这里的不同颜色部分,就表示不同的amf包,就表示一个完整的字段。

看看parseMeta具体解析做了什么工作。为什么这里 uint32_t offset = 13,是偏移了13个字节呢?

根据MediaInfo信息,这里Type是1个字节,Value_Size是2个字节,Value是占用了10个字节,一共就是13个字节,所以就需要偏移13个字节,这个值一般也是固定值。



前面已经把相应字段的名字和value值都读取出来了,就是可以去赋值给相应的字段了。

这里pd[offset++] == 0x08就需要判断类型,读4个字节,就偏移4个字节。


通过分析上面的,每个字段都有一个数据长度,然后才是具体字段的值。结合上面代码的注释看,就是结合不同类型,去读取不同的值,然后获取相应的长度,得到相应的偏移值。

为了解析方便,加上这个打印函数,就可以打印出如下值:


截取dump flv数据的一部分。

DumpH264:

这种dump数据,也是非常实用。


本篇解析源码,也花了很长时间整理,如果对你有用,欢迎关注,点赞,转发,收藏。

如果需要源码注释版本,可以关注,私信。

相关推荐

三星电视通过VGA端口接连笔记本教程

科技的发达不仅仅表现于智能电视的功能有多全面,手机、笔记本、电视盒子有多智能,而是这些电子产品是否能够相互连接、多屏互动进而进行多媒体播放与数据传输等。目前,三星电视早已可以实现多项设备间的连接与使用...

KVM210UA 2口USB电脑切换器VGA KVM切换器 键鼠控制2台电脑 免电源

登昌恒KVM210UA2口USB电脑切换器VGAKVM切换器键鼠控制2台电脑免外接电源即时切换显示画面不延迟热插拔免驱动适合MAC苹果电脑笔记本和台式电脑...

大神自己将老旧笔记本改装成多方面强悍的“超极本”

文/自己建房子亲戚有个03年的清华紫光笔记本,配置是奔腾1.8G,XP勉强运行,亲戚今年帮了非常大的忙,无以回报,把他这个垃圾本改一下略为回报新配置:CPU是i53470t的,内存是4G两条组成双...

正点原子开拓者FPGA开发板资料连载第二十二章RGBTFT-LCD彩条显示

1)实验平台:正点原子开拓者FPGA开发板2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子3)全套实验源码+手册+视频下载地址:http://www.openedv.c...

显卡引出故障现象及排除(造成显卡故障的原因有哪些)

故障现象一:显示器黑屏故障排除:1、先确定是否是显卡有问题。判断的方法是听PC喇叭的叫声,一长两短声肯定是显卡发生了致命错误,只能更换。2、如果无法断定显卡的好坏,可以换一块试试,还不行的话则有几种情...

用FPGA/树莓派RP2040驱动HDMI的资源

如果能够用FPGA能够驱动显示器,就可以做不少与视频相关的实验,很多FPGA开发板使用了比较简单的VGA接口,连接非常简单,如下图:然后我们就可以用FPGA的逻辑来做各种游戏了:然而,现在的显示器基本...

STM32+A3P125 图形控制器方案,多参数监护仪数据采集模块深度解析

一、生理信号采集与转换架构多参数监护仪数据采集模块是将人体生理信号转化为数字信号的核心单元,其架构遵循“传感器感知→信号调理→模数转换→数字处理”的标准化流程:1.传感器类型与生理信号转换传感器...

电脑重启都提示AMD显卡错误“No AMD graphics driver is..”解决方法

电脑重装完系统后,每次重启都提示AMD显卡错误“NoAMDgraphicsdriveris......”怎么办?网上相关问题解决很多人方法是打驱动,可是有些是驱动打好了还是反复出现NoAM...

ipad1改造显示器之拆解篇(ipadair改显示器)

闲来无事,翻出来家里12年前的初代ipad,除了能正常充电开机盖泡面之外,好像啥也干不了……上网一搜有许多改成显示器的案例,按耐不住的激动的小手也想跃跃欲试一番,说干就干,先从拆解开始。注意,以hom...

老电脑显卡驱动装不上?降级旧版驱动一招解决!

老电脑显卡驱动装不上?降级旧版驱动一招解决!今天给家里的老台式机重装系统遇到了麻烦:i34130处理器配上HD7770显卡,装完Win7后,显卡驱动死活装不对!问题表现:最初状态:设备管理器“显...

想淘汰VGA 先得知道这些门道(vga是不是淘汰了)

不要说新显卡,就是在主板上,VGA接口也越来越少,眼看就被彻底淘汰了。当然小伙伴们的显示器应该早就不是只有VGA接口的旧型号了,彻底淘汰VGA就换个接口或者弄个转接呗,可是……真的这么简单吗?小编今天...

IMX258摄像头驱动(摄像头最新驱动)

IMX25813MPOISUSBCamera(A)说明IMX25813MPOISUSBCamera(A)功能简介特性USB通用摄像头1300万像素接口USB...

朗强科技:VGA视频信号分配原理分析

VGA分配器的主要功能是把一个视频信号重新分配成多个信号。高分辨率的视频分配放大器的作用是在接收一个来自计算机视频端口的信号后将其进行放大处理,并且在保持原有信号质量的情况下,将其信号分配到多个高分辨...

视频矩阵的应用及分类(视频矩阵的应用及分类)

视频矩阵-基本功能和要求视频矩阵-基本功能和要求  一个矩阵系统通常还应该包括以下基本功能:字符信号叠加;解码器接口以控制云台和摄像机;报警器接口;控制主机,以及音频控制箱、报警接口箱、控制键盘等附件...

告别蓝屏烦恼,Windows系统崩溃急救指南!

Windows系统蓝屏(BlueScreenofDeath,简称BSoD)是Windows操作系统在无法从系统错误中恢复时显示的屏幕图像,通常会伴随一个或多个错误代码,这些代码是诊断问题的关键线...

取消回复欢迎 发表评论: