flv视频解析:音视频学习(四、FLV格式解析) 2024-05-07 01:06:55 0 0 由于上一节使用到了rtmp推流,然后一直推一直出错,用rtmp推流的数据格式是FLV,所以这一节分析一下FLV的格式,补充补充知识。 4.1 FLV格式解析 4.1.1 FLV总体认识 FLV 是FLASH VIDEO的简称,FLV流媒体格式是随着Flash MX的推出发展而来的视频格式。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等问题。 FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。(大端字节序) 4.1.2 header解析 heard部分由一下几个部分组成: Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte) 详细信息见下图: 这个是昨天拉流,保存出来的flv视频,通过这个查看这个视屏的二进制格式,我们就能到,上面的描述的对的。 4.1.3 body解析 FLV body由⼀对对的(Previous Tag Size字段 + tag)组成。 Previous Tag Size字段 排列在Tag之前,占⽤4个字节。 Previous Tag Size记录了前⾯⼀个Tag的⼤⼩,⽤于逆向读取处理。 FLV header后的第⼀个Pervious Tag Size的值为0。 Tag⼀般可以分为3种类型:脚本(帧)数据类型、⾳频数据类型、视频数据。 tag组成:tag type+tag data size+Timestamp+TimestampExtended+stream id+ tag data 详细见下图: 实例分析一下: 我们来看一下tag1,首先我框起来的是Pervious Tag Size0,因为是第一个,所以填为0; 接下来就到TAG: type:0x12 是script 数据 data size: 0x00 01 a0 = 0x1a0长度的数据 Timestamp:0x000000 TimestampExtended:0x00 stream id:0x00 00 00 0x00000018地址开始就是tag1 data数据的开始,然后data size=0x01a0,所以计算出下一个tag1结束的地址:0x000001B8,这个地址就很好找,刚好是最后框的地方,这里4个字节正好是Pervious Tag Size1=0x01ab,我们之前得到的data size=0x01a0,tag head刚好=0x0b,所以tag1加起来的大小刚好=0x01ab,所以我们找的位置是正确。flv⽂件中Timestamp和TimestampExtended拼出来的是dts。也就是解码时间。Timestamp和TimestampExtended拼出来dts单位为ms。(如果不存在B帧,当然dts等于pts)CompositionTime 表示PTS相对于DTS的偏移值, 在每个视频tag的第14~16字节。显示时间(pts) = 解码时间(tag的第5~8字节) + CompositionTime。CompositionTime的单位也是ms。 4.1.4 script data script data脚本数据就是描述视频或者音频的信息数据,如宽度、高度、时间等等,一个文件中通常只有一个script数据。该类型的tag又被称为MeteData Tag。 第⼀个AMF包: 第1个字节表示AMF包类型,⼀般总是0x02,表示字符串。第2-3个字节为UI16类型值,标识字符串的⻓度,⼀般总是0x000A(“onMetaData”⻓度)。后⾯字节为具体的字符串,⼀般总为“onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。 第⼆个AMF包: 第1个字节表示AMF包类型,⼀般总是0x08,表示数组。第2-5个字节为UI32类型值,表示数组元素的个数。后⾯即为各数组元素的封装,数组元素为元素名称和值组成的对。 具体对二进制我这里就不解析了,看着上面的文字都能解析,我使用了一个工具,可以解析flv的,直接看这个工具的显示就可以了。 是不是很清楚,就是不知道为什么有一个0x03的type,难道是昨天的拉流可能还有问题,先不管。 4.1.5 audio data audio数据又是一个新的tag了,所以简单看一下head: 对号入座吧,我就不用了,直接来结果公布: audio data:第⼀个字节包含了⾳频数据的参数信息 下面是第一个字节具体分析: 前4位为音频格式值类型0Linear PCM, platform endian1ADPCM2MP33Linear PCM, little endian4Nellymoser 16-kHz mono5Nellymoser 8-kHz mono6Nellymoser7G.711 A-law logarithmic PCM8G.711 mu-law logarithmic PCM9reserved10AAC11Speex14MP3 8-Khz15Device-specific sound 接着2位为采样率值类型05.5-kHz111-kHz222-kHz344-kHz AAC 总是3 接着1位为采样的长度值类型0snd8Bit1snd16Bit 压缩过的音频都是16bit 接着1位为音频类型值类型0sndMono1sndStereo AAC 总是1 第⼆个字节开始为⾳频流数据 需要判断该数据是真正的⾳频数据,还是⾳频config信息 如果音频格式=10(AAC类型)第二个数据就是音频config数据。 4.1.6 video data 还是先取得video head数据,现在就不用细说了,都比较熟悉了。 解析结果: video data数据,跟音频一样第⼀个字节包含视频数据的参数信息 前4位为帧类型Frame Type值类型1keyframe (for AVC, a seekable frame) 关键帧2inter frame (for AVC, a non-seekable frame)3disposable inter frame (H.263 only)4generated keyframe (reserved for server use only)5video info/command frame 后4位为编码ID (CodecID)值类型1JPEG (currently unused)2Sorenson H.2633Screen video4On2 VP65On2 VP6 with alpha channel6Screen video version 27AVC第⼆个字节开始为视频流数据 但是如果上面的编码ID为AVC的话(h264),VideoTagHeader会多出4个字节的信息,AVCPacketType 和CompositionTime AVCPacketType 占1个字节值类型0AVCDecoderConfigurationRecord(AVC sequence header)1AVC NALU2AVC end of sequence (lower level NALU sequence ender is not required or supported) AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag.(这个详情以后看h264部分) CompositionTime 占3个字节条件值AVCPacketType ==1Composition time offsetAVCPacketType !=10 注意:CompositionTime 单位毫秒。CompositionTime 单位为ms : 显示时间 = 解码时间(tag的第58字节,位置索引[4][7]) + CompositionTime。 这次就不用对二进制数据了吧,感兴趣自己去分析一下二进制数据。 2020-06-26补加 之前没有考虑到需要用到sps/pps的数据,所以就不写,等到后面用到了,现在在来补充一下知识: sps pps 前面我们提到第一个video 一般存放的是sps和pps。这里我们具体解析下sps和pps内容。先看下存储的格式 0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+pps 主要参考博客:flv格式详解+实例剖析 收藏(0)