参考链接: 1. FLV科普12 FLV脚本数据解析-Metadata Tag解析 https://blog.csdn.net/cabbage2008/article/details/50500021
2. FLV科普9 FLV音频信息 https://blog.csdn.net/cabbage2008/article/details/50445023
3. FLV科普6 FLV Tag以及Tag头信息解析 https://blog.csdn.net/cabbage2008/article/details/50374083
4. FLV科普11 FLV视频信息 https://blog.csdn.net/cabbage2008/article/details/50449857
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <arpa/inet.h> 5 6 #define TAB44 " " 7 #define PRINTF_DEBUG 8 9 #define MAX_SIGNATURE_LEN 3 10 #define MAX_PRE_TAG_SIZE_LEN 4 11 #define MIN_FLV_HEADER_LEN 9 12 #define MAX_TAG_HEADER_LEN 11 13 #define MAX_PARSE_TAG_NUM 15 14 #define MAX_AMF_STR_SIZE 255 15 16 /************************************************************************************************************ 17 ** flv header: 记录了flv的类型, 版本等信息, 是flv的开头, 一般都差不多, 占9bytes 18 ** 19 ------------------------------------------------------------------------------------------------------------- 20 ** 字段名称 | 长度(bytes) | 有关描述 21 ------------------------------------------------------------------------------------------------------------- 22 ** signature | 3 | 文件标识, 总是为"FLV", 0x46 0x4c 0x56 23 ** version | 1 | 版本(目前为0x01) 24 ** flag | 3 | 文件的标志位说明. 前5位保留, 必须为0; 25 第6位为音频Tag: 1表示有音频; 第七位保留, 为0; 第8位为视频Tag: 1表示有视频 26 ** headersize | 4 | 整个header的长度, 一般为9(版本为0x01时); 大于9表示下面还有扩展信息 27 ************************************************************************************************************/ 28 /* 29 1. unsigned char reserved5: 5, flags_audio: 1, reserved1: 1, flags_video: 1; 30 2. unsigned char : 5, flags_audio: 1, : 1, flags_video: 1; (无名说明无法使用, 仅占位) 31 3. 下面结构体位域的另外两种写法. 32 */ 33 typedef struct t_flv_header 34 { 35 unsigned char signature[MAX_SIGNATURE_LEN+1]; 36 unsigned char version; 37 unsigned char : 5; 38 unsigned char flags_audio: 1; 39 unsigned char : 1; 40 unsigned char flags_video: 1; 41 42 int headersize; 43 } T_FLV_HEADER; 44 45 /************************************************************************************************************ 46 ** tag header 47 ** 48 ------------------------------------------------------------------------------------------------------------- 49 ** 字段名称 | 长度(bytes) | 有关描述 50 ------------------------------------------------------------------------------------------------------------- 51 ** type | 1 | 数据类型, (0x12)为脚本类型; (0x08)为音频类型; (0x09)为视频类型 52 ** data_size | 3 | 数据区长度 53 ** timestamp | 3 | 时间戳, 类型为(0x12)的tag时间戳一直为0, (0xFFFFFF)可以表示长度为4小时, 单位为毫秒. 54 ** timestamp_extended | 1 | 将时间戳扩展为4bytes, 代表高8位, 一般都为0, 长度为4小时的flv一般很少见了 55 ** streamid | 3 | 总为0 56 ************************************************************************************************************/ 57 typedef struct t_flv_tag_header 58 { 59 int type; 60 int data_size; 61 int timestamp; 62 int timestamp_extended; 63 int streamid; 64 } T_FLV_TAG_HEADER; 65 66 /************************************************************************************************************ 67 ** video tag header 68 ** 69 ------------------------------------------------------------------------------------------------------------- 70 ** 字段名称 | 长度(bytes) | 有关描述 71 ------------------------------------------------------------------------------------------------------------- 72 ** FreameType | 4(bits) | FrameType为数据类型, 1为关键帧, 2为非关键帧, 3为h263的非关键帧, 73 4为服务器生成关键帧, 5为视频信息或命令帧. 74 ** CodecId | 4(bits) | CodecID为包装类型, 1为JPEG, 2为H263, 3为Screen video, 75 4为On2 VP6, 5为On2 VP6, 6为Screen videoversion 2, 7为AVC 76 77 CodecID=2, 为H263VideoPacket; 78 CodecID=3, 为ScreenVideopacket; 79 CodecID=4, 为VP6FLVVideoPacket; 80 CodecID=5, 为VP6FLVAlphaVideoPacket; 81 CodecID=6, 为ScreenV2VideoPacket; 82 CodecID=7, 为AVCVideoPacket. 83 84 ** AVCVideoPacket Format: | AVCPacketType(8)| CompostionTime(24) | Data | 85 如果AVCPacketType=0x00, 为AVCSequence Header;--描述了SPS以及PPS的信息; 86 如果AVCPacketType=0x01, 为AVC NALU; 87 如果AVCPacketType=0x02, 为AVC end ofsequence; 88 CompositionTime为相对时间戳: 如果AVCPacketType=0x01, 为相对时间戳; 其它, 均为0; 89 90 Data为负载数据: 91 如果AVCPacketType=0x00, 为AVCDecorderConfigurationRecord; 92 如果AVCPacketType=0x01, 为NALUs; 93 如果AVCPacketType=0x02, 为空. 94 95 AVCDecorderConfigurationRecord格式, 包括文件的信息: 96 | cfgVersion(8) | avcProfile(8) | profileCompatibility(8) |avcLevel(8) | reserved(6) | lengthSizeMinusOne(2) | reserved(3) | numOfSPS(5) |spsLength(16) | sps(n) | numOfPPS(8) | ppsLength(16) | pps(n) | 97 ************************************************************************************************************/ 98 typedef struct t_flv_tag_video_header 99 { 100 unsigned char freameType:4, codecId:4; 101 } T_FLV_TAG_VIDEO_HEADER; 102 103 /************************************************************************************************************ 104 ** AVCDecoderConfigurationRecord 105 ** 106 ------------------------------------------------------------------------------------------------------------- 107 ** 字段名称 | 长度(bytes) | 有关描述 108 ------------------------------------------------------------------------------------------------------------- 109 ** configurationVersion | 1 | 配置版本占用8位, 一定为1 110 ** AVCProfileIndication | 1 | profile_idc占用8位, 从H.264标准SPS第一个字段profile_idc拷贝而来, 指明所用profile 111 ** profile_compatibility | 1 | 占用8位, 从H.264标准SPS拷贝的冗余字 112 ** AVCLevelIndication | 1 | level_idc占用8位, 从H.264标准SPS第一个字段level_idc拷贝而来, 指明所用 level 113 ** reserved | 6b | 保留位占6位, 值一定为'111111' 114 ** lengthSizeMinusOne | 2b | 占用2位, 表示NAL单元头的长度, 0表示1字节, 1表示2字节, 2表示3字节, 3表示4字节 115 ** reserved | 3b | 保留位占3位, 值一定为'111' 116 ** numOfSPS | 5b | numOfSequenceParameterSets占用5位, 表示当前SPS的个数 117 ** SPSLength | 2 | sequenceParameterSetLength占用16位, SPS占用的长度 118 ** SPSData | * | 119 ** numOfPPS | 5b | numOfPictureParameterSets占用8位, 表示当前PPS的个数 120 ** PPSLength | 2 | pictureParameterSetLength占用16位, PPS占用的长度 121 ** PPSData | * | numOfPictureParameterSets占用8位, 表示当前PPS的个数 122 123 AVCProfileIndication, profile_compatibility, AVCLevelIndication就是拷贝SPS的前3个字节 124 ************************************************************************************************************/ 125 typedef struct t_flv_tag_avc_dec_cfg 126 { 127 unsigned char configurationVersion; 128 unsigned char AVCProfileIndication; 129 unsigned char profile_compatibility; 130 unsigned char AVCLevelIndication; 131 unsigned char :6, lengthSizeMinusOne:2; 132 133 unsigned char :3, numOfSequenceParameterSets:5; 134 unsigned short spsLen; 135 unsigned char *spsData; 136 137 unsigned char numOfPictureParameterSets; 138 unsigned short ppsLen; 139 unsigned char *ppsData; 140 } T_FLV_TAG_AVC_DEC_CFG; 141 142 /************************************************************************************************************ 143 ** avc video packet header 144 ** 145 ------------------------------------------------------------------------------------------------------------- 146 ** 字段名称 | 长度(bytes) | 有关描述 147 ------------------------------------------------------------------------------------------------------------- 148 ** AVCPacketType占用1字节 | 1 | 149 ** CompositionTime | 3 | 150 151 AVCVideoPacket同样包括Packet Header和Packet Body两部分: 152 Packet Header: 153 AVCPacketType占用1字节, 仅在AVC时有此字段 154 0, AVC sequence header (SPS、PPS信息等) 155 1, AVC NALU 156 2, AVC end of sequence (lower level NALU sequence ender is not required or supported) 157 158 CompositionTime占用24位, 相对时间戳, 如果AVCPacketType=0x01为相对时间戳; 其它, 均为0; 159 该值表示当前帧的显示时间, tag的时间为解码时间, 显示时间等于 解码时间+CompositionTime. 160 ************************************************************************************************************/ 161 typedef struct t_flv_tag_avc_video_packet 162 { 163 unsigned char avcPacketType; 164 165 int compositionTime; 166 167 union videoPacket 168 { 169 T_FLV_TAG_AVC_DEC_CFG avcDecCfg; 170 } vp; 171 } T_FLV_TAG_AVC_VIDEO_PACKET; 172 173 typedef struct t_flv_tag_audio_header 174 { 175 unsigned char soundFormat:4, soundRate:2, soundSize:1, soundType:1; 176 } T_FLV_TAG_AUDIO_HEADER; 177 178 typedef struct t_flv_tag_aac_spec_cfg 179 { 180 unsigned char audioObjectType:5; 181 unsigned char samplingFreqIndex:4, channelCfg:2; 182 } T_FLV_TAG_AAC_SPEC_CFG; 183 184 typedef struct t_flv_tag_aac_audio_packet 185 { 186 unsigned char aacPacketType; 187 188 union audioPacket 189 { 190 T_FLV_TAG_AAC_SPEC_CFG aacSpecCfg; 191 } ap; 192 } T_FLV_TAG_AAC_AUDIO_PACKET; 193 194 typedef struct t_flv_tag 195 { 196 } T_FLV_TAG; 197 198 /* 小端转double */ 199 static double dealAmfNumber(unsigned char *amfNum) 200 { 201 double d = 0; 202 203 unsigned char *dp = (unsigned char *)&d; 204 205 dp[0] = amfNum[7]; 206 dp[1] = amfNum[6]; 207 dp[2] = amfNum[5]; 208 dp[3] = amfNum[4]; 209 dp[4] = amfNum[3]; 210 dp[5] = amfNum[2]; 211 dp[6] = amfNum[1]; 212 dp[7] = amfNum[0]; 213 214 return d; 215 } 216 217 /* 218 1. DealHeader(const unsigned char* headerData); 219 这样定义会报warning: assignment discards 'const' qualifier from pointer target type, 220 大意是指针丢掉"const"限定符. 221 2. 原因是: data = headerData; 这一句存在丢掉的风险(可通过给*data赋予不同的值, 使得headerData的数据也被修改, 失去const的作用) 222 3. const int *p; //这种情况表示*p是const无法进行修改, 而p是可以进行修改的; 223 int* const p; //这种情况表示p是const无法进行修改, 而*p是可以进行修改的; 224 const int* const p; //这种情况表示*p与p都无法进行修改. 225 */ 226 static void DealFlvHeader(unsigned char* const headerData) 227 { 228 unsigned char *data = NULL; 229 230 T_FLV_HEADER flvHeader = {0}; 231 232 data = headerData; 233 234 memset(&flvHeader, 0x0, sizeof(T_FLV_HEADER)); 235 236 memcpy(flvHeader.signature, data, MAX_SIGNATURE_LEN); 237 238 flvHeader.signature[MAX_SIGNATURE_LEN] = '