zoukankan      html  css  js  c++  java
  • flv文件解析(纯c解析代码)

    参考链接: 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] = '';
    239     
    240     data += MAX_SIGNATURE_LEN;
    241     
    242     flvHeader.version = data[0];
    243     
    244     data += 1;
    245     
    246     flvHeader.flags_audio = data[0] >> 2 & 0x1;
    247     flvHeader.flags_video = data[0] & 0x1;
    248     
    249     data += 1;
    250     
    251     flvHeader.headersize = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
    252     
    253     if (0x1 != flvHeader.version)
    254     {
    255         printf("version is not 1, todo...
    ");
    256     }
    257     
    258 #ifdef PRINTF_DEBUG
    259     printf("+FLV Header
    ");
    260     printf("%ssignature: %s, version: %d, flags_audio: %d, flags_video: %d, headersize: %d
    ",
    261             TAB44, flvHeader.signature, flvHeader.version, flvHeader.flags_audio, flvHeader.flags_video, flvHeader.headersize);
    262 #endif
    263 }
    264 
    265 static void DealTagHeader(unsigned char* const headerData, T_FLV_TAG_HEADER *tagHeader)
    266 {
    267     static int videoTagNum = 0;
    268     static int audioTagNum = 0;
    269     
    270     unsigned char *data = NULL;
    271     
    272     T_FLV_TAG_HEADER header = {0};
    273     
    274     data = headerData;
    275     
    276     memset(&header, 0x0, sizeof(T_FLV_TAG_HEADER));
    277     
    278     header.type = data[0];
    279     
    280     data += 1;
    281     
    282     header.data_size = (data[0] << 16) | (data[1] << 8) | data[2];
    283     
    284     data += 3;
    285     
    286     header.timestamp = (data[0] << 16) | (data[1] << 8) | data[2];
    287     
    288     data += 3;
    289     
    290     header.timestamp_extended = data[0];
    291     
    292     data += 1;
    293     
    294     header.streamid = (data[0] << 16) | (data[1] << 8) | data[2];
    295     
    296     memcpy(tagHeader, &header, sizeof(T_FLV_TAG_HEADER));
    297     
    298 #ifdef PRINTF_DEBUG
    299     switch (tagHeader->type)
    300     {
    301         case 0x12:
    302             printf("%s+Script Tag
    ", TAB44);
    303             
    304             break;
    305             
    306         case 0x9:
    307             videoTagNum++;
    308             
    309             printf("%s+Video Tag[%d]
    ", TAB44, videoTagNum);
    310 
    311             break;
    312 
    313         case 0x8:
    314             audioTagNum++;
    315             
    316             printf("%s+Audio Tag[%d]
    ", TAB44, audioTagNum);
    317 
    318             break;
    319 
    320         default:
    321             break;
    322     }
    323     
    324     printf("%s%s+Tag Header
    ", TAB44, TAB44);
    325     printf("%s%s%stype: %d, data_size: %d, timestamp: %d, timestamp_extended: %d, streamid: %d
    ",
    326             TAB44, TAB44, TAB44, tagHeader->type, tagHeader->data_size, tagHeader->timestamp, tagHeader->timestamp_extended, tagHeader->streamid);
    327 #endif
    328 }
    329 
    330 /*
    331     第一个AMF包:
    332            第1个字节表示AMF包类型, 一般总是0x02, 表示字符串, 其他值表示意义请查阅文档.
    333            第2-3个字节为UI16类型值, 表示字符串的长度, 一般总是0x000A("onMetaData"长度).
    334            后面字节为字符串数据, 一般总为"onMetaData".
    335      
    336     第二个AMF包:
    337            第1个字节表示AMF包类型, 一般总是0x08, 表示数组.
    338            第2-5个字节为UI32类型值, 表示数组元素的个数.
    339            后面即为各数组元素的封装, 数组元素为元素名称和值组成的对. 表示方法如下:
    340            第1-2个字节表示元素名称的长度, 假设为L. 后面跟着为长度为L的字符串. 第L+3个字节表示元素值的类型.
    341            后面跟着为对应值, 占用字节数取决于值的类型.
    342 
    343     0 = Number type (double, 8)
    344     1 = Boolean type
    345     2 = String type
    346     3 = Object type
    347     4 = MovieClip type
    348     5 = Null type
    349     6 = Undefined type
    350     7 = Reference type
    351     8 = ECMA array type
    352     10 = Strict array type
    353     11 = Date type
    354     12 = Long string type
    355     
    356     1. 不要频繁的malloc小内存(内存碎片, 代价);
    357     2. 如该函数中arrayKey, arrayValue, amfStrData设置成指针, 然后malloc就有问题(字符串后残留上述三个最大长度中的字符);
    358     3. 可能的解释: 当用free释放的你用malloc分配的存储空间, 释放的存储空间并没有从进程的地址空间中删除, 而是保留在可用存储区池中,
    359        当再次用malloc时只要可用存储区池中有足够的地址空间, 都不会再向内可申请内存了, 而是在可用存储区池中分配了.
    360        
    361 实际分析时: 8的数组后还有一串 00 00 09, 暂时不清楚, 先跳过if (tagDataSize <= 3)
    362 */
    363 static void DealScriptTagData(unsigned char* const tagData, unsigned int tagDataSize)
    364 {
    365     int i = 0;
    366     int amfType = 0;
    367     int amfIndex = 0;
    368     int valueType = 0;
    369     int valueSize = 0;
    370     int keySize = 0;
    371     int arrayCount = 0;
    372     int amfStringSize = 0;
    373     
    374     double amfNum = 0;
    375     
    376     unsigned char amfStr[MAX_AMF_STR_SIZE+1] = {0};
    377     
    378     unsigned char *data = NULL;
    379     
    380     data = tagData;
    381     
    382     for (;;)
    383     {
    384         if (tagDataSize <= 3)
    385         {
    386             break;
    387         }
    388         
    389         amfType = data[0];
    390         
    391         amfIndex += 1;
    392         
    393         data += 1;
    394         tagDataSize -= 1;
    395 
    396 #ifdef PRINTF_DEBUG
    397         printf("%s%s%sAMF%d type: %d
    ", TAB44, TAB44, TAB44, amfIndex, amfType);
    398 #endif
    399         
    400         switch (amfType)
    401         {
    402             case 2:
    403                 amfStringSize = (data[0] << 8) | data[1];
    404 
    405 #ifdef PRINTF_DEBUG
    406         printf("%s%s%sAMF%d String size: %d
    ", TAB44, TAB44, TAB44, amfIndex, amfStringSize);
    407 #endif
    408                 
    409                 data += 2;
    410                 tagDataSize -= 2;
    411                 
    412                 memset(amfStr, 0x0, sizeof(amfStr));
    413                 
    414                 memcpy(amfStr, data, amfStringSize);
    415                 
    416                 amfStr[amfStringSize] = '';
    417                     
    418 #ifdef PRINTF_DEBUG
    419         printf("%s%s%sAMF%d String: %s
    ", TAB44, TAB44, TAB44, amfIndex, amfStr);
    420 #endif
    421                 
    422                 data += amfStringSize;
    423                 tagDataSize -= amfStringSize;
    424 
    425                 break;
    426 
    427             case 8:
    428                 arrayCount = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
    429 
    430 #ifdef PRINTF_DEBUG
    431         printf("%s%s%sAMF%d Metadata count: %d
    ", TAB44, TAB44, TAB44, amfIndex, arrayCount);
    432         printf("%s%s%s+Metadata
    ", TAB44, TAB44, TAB44);
    433 #endif
    434                 
    435                 data += 4;
    436                 tagDataSize -= 4;
    437                 
    438                 for (i=0; i<arrayCount; i++)
    439                 {
    440                     keySize = (data[0] << 8) | data[1];
    441                     
    442                     data += 2;
    443                     tagDataSize -= 2;
    444                     
    445                     memset(amfStr, 0x0, sizeof(amfStr));
    446 
    447                     memcpy(amfStr, data, keySize);
    448 
    449                     amfStr[keySize] = '';
    450                 
    451 #ifdef PRINTF_DEBUG
    452                     printf("%s%s%s%s%s: ", TAB44, TAB44, TAB44, TAB44, amfStr);
    453 #endif
    454                     
    455                     data += keySize;
    456                     tagDataSize -= keySize;
    457                     
    458                     valueType = data[0];
    459                     
    460                     data += 1;
    461                     tagDataSize -= 1;
    462                     
    463                     if (0 == valueType)
    464                     {
    465                         amfNum = dealAmfNumber(data);
    466 #ifdef PRINTF_DEBUG
    467                         printf("%lf
    ", amfNum);
    468 #endif
    469 
    470                         data += 8;
    471                         tagDataSize -= 8;
    472                     }
    473                     else if (1 == valueType)
    474                     {
    475 #ifdef PRINTF_DEBUG
    476                         printf("%d
    ", data[0]);
    477 #endif
    478                         data += 1;
    479                         tagDataSize -= 1;
    480                     }
    481                     else if (2 == valueType)
    482                     {
    483                         valueSize = (data[0] << 8) | data[1];
    484                         
    485                         data += 2;
    486                         tagDataSize -= 2;
    487                         
    488                         memset(amfStr, 0x0, sizeof(amfStr));
    489 
    490                         memcpy(amfStr, data, valueSize);
    491 
    492                         amfStr[valueSize] = '';
    493 
    494 #ifdef PRINTF_DEBUG
    495                         printf("%s
    ", amfStr);
    496 #endif
    497                         
    498                         data += valueSize;
    499                         tagDataSize -= valueSize;
    500                     }
    501                     else 
    502                     {
    503                         //printf("now can not parse value type: %d
    ", valueType);
    504                         
    505                         return;
    506                     }
    507                 }
    508 
    509                 break;
    510                 
    511             default:
    512                 break;
    513         }
    514     }
    515 }
    516 
    517 /*
    518    Video Header = | FrameType(4) | CodecID(4) |
    519    VideoData = | FrameType(4) | CodecID(4) | VideoData(n) |
    520 */
    521 static void DealVideoTagData(unsigned char* const tagData)
    522 {
    523     unsigned char *data = NULL;
    524 
    525     data = tagData;
    526     
    527     T_FLV_TAG_VIDEO_HEADER vTagHeader = {0};
    528     T_FLV_TAG_AVC_VIDEO_PACKET avcVideoPacket = {0};
    529     
    530     memset(&vTagHeader, 0x0, sizeof(vTagHeader));
    531     
    532     vTagHeader.freameType = data[0] >> 4 & 0xf;
    533     vTagHeader.codecId = data[0] & 0xf;
    534     
    535     data++;
    536     
    537 #ifdef PRINTF_DEBUG
    538     printf("%s%s%sFrameType: %d
    ", TAB44, TAB44, TAB44, vTagHeader.freameType);
    539     printf("%s%s%sCodecId: %d
    ", TAB44, TAB44, TAB44, vTagHeader.codecId);
    540 #endif
    541     
    542     /* now just avc(h264) */
    543     switch (vTagHeader.codecId)
    544     {
    545         case 0x07:
    546             memset(&avcVideoPacket, 0x0, sizeof(avcVideoPacket));
    547             
    548             avcVideoPacket.avcPacketType = data[0];
    549             avcVideoPacket.compositionTime = (data[1] << 16) | (data[2] << 8) | data[3];
    550             
    551             data += 4;
    552             
    553             if (0 == avcVideoPacket.avcPacketType)
    554             {
    555 #ifdef PRINTF_DEBUG
    556                 printf("%s%s%s+AVCVideoPacket
    ", TAB44, TAB44, TAB44);
    557                 printf("%s%s%s%sAVCPacketType: %d
    ", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.avcPacketType);
    558                 printf("%s%s%s%sCompositionTime Offset: %d
    ", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.compositionTime);
    559 #endif
    560                 printf("%s%s%s%s+AVCDecoderConfigurationRecord
    ", TAB44, TAB44, TAB44, TAB44);
    561                 
    562                 avcVideoPacket.vp.avcDecCfg.configurationVersion = data[0];
    563                 avcVideoPacket.vp.avcDecCfg.AVCProfileIndication = data[1];
    564                 avcVideoPacket.vp.avcDecCfg.profile_compatibility = data[2];
    565                 avcVideoPacket.vp.avcDecCfg.AVCLevelIndication = data[3];
    566                 avcVideoPacket.vp.avcDecCfg.lengthSizeMinusOne = data[4] & 0x3;
    567                 avcVideoPacket.vp.avcDecCfg.numOfSequenceParameterSets = data[5] & 0x1f;
    568                 avcVideoPacket.vp.avcDecCfg.spsLen = (data[6] << 8) | data[7];
    569                 
    570                 // todo, parse sps
    571                 
    572                 data += (8+avcVideoPacket.vp.avcDecCfg.spsLen);
    573                 
    574                 avcVideoPacket.vp.avcDecCfg.numOfPictureParameterSets = data[0];
    575                 avcVideoPacket.vp.avcDecCfg.ppsLen = (data[1] << 8) | data[2];
    576                 
    577                 // todo, parse pps
    578 
    579 #ifdef PRINTF_DEBUG
    580             printf("%s%s%s%s%sconfigurationVersion: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.configurationVersion);
    581             printf("%s%s%s%s%sAVCProfileIndication: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.AVCProfileIndication);
    582             printf("%s%s%s%s%sprofile_compatibility: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.profile_compatibility);
    583             printf("%s%s%s%s%sAVCLevelIndication: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.AVCLevelIndication);
    584             printf("%s%s%s%s%slengthSizeMinusOne: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.lengthSizeMinusOne);
    585             printf("%s%s%s%s%snumOfSequenceParameterSets: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.numOfSequenceParameterSets);
    586             printf("%s%s%s%s%ssequenceParameterSetLength: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.spsLen);
    587             printf("%s%s%s%s%snumOfPictureParameterSets: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.numOfPictureParameterSets);
    588             printf("%s%s%s%s%spictureParameterSetLength: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, avcVideoPacket.vp.avcDecCfg.ppsLen);
    589 #endif
    590             }
    591             else
    592             {
    593 #ifdef PRINTF_DEBUG
    594                 printf("%s%s%s+Video Data
    ", TAB44, TAB44, TAB44);
    595                 printf("%s%s%s%sAVCPacketType: %d
    ", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.avcPacketType);
    596                 printf("%s%s%s%sCompositionTime Offset: %d
    ", TAB44, TAB44, TAB44, TAB44, avcVideoPacket.compositionTime);
    597                 printf("%s%s%s%sData
    ", TAB44, TAB44, TAB44, TAB44);
    598 #endif
    599             }
    600             
    601             break;
    602             
    603         default:
    604             break;
    605     }
    606 }
    607 
    608 static void DealAudioTagData(unsigned char* const tagData)
    609 {
    610     unsigned char *data = NULL;
    611 
    612     data = tagData;
    613     
    614     T_FLV_TAG_AUDIO_HEADER audioHeader = {0};
    615     T_FLV_TAG_AAC_AUDIO_PACKET aPacket = {0};
    616     
    617     memset(&audioHeader, 0x0, sizeof(T_FLV_TAG_AUDIO_HEADER));
    618     
    619     audioHeader.soundFormat = (data[0] >> 4) & 0xf;
    620     audioHeader.soundRate = (data[0] >> 2) & 0x3;
    621     audioHeader.soundSize = (data[0] >> 1) & 0x1;
    622     audioHeader.soundType = data[0] & 0x1;
    623     
    624 #ifdef PRINTF_DEBUG
    625     printf("%s%s%sSoundFormat: %d
    ", TAB44, TAB44, TAB44, audioHeader.soundFormat);
    626     
    627     switch (audioHeader.soundRate)
    628     {
    629         case 0:
    630             printf("%s%s%sSoundRate: 5.5-KHz
    ", TAB44, TAB44, TAB44);
    631             break;
    632             
    633         case 1:
    634             printf("%s%s%sSoundRate: 11-KHz
    ", TAB44, TAB44, TAB44);
    635         break;
    636         
    637         case 2:
    638             printf("%s%s%sSoundRate: 22-KHz
    ", TAB44, TAB44, TAB44);
    639         break;
    640         
    641         case 3:
    642             printf("%s%s%sSoundRate: 44-KHz
    ", TAB44, TAB44, TAB44);
    643         break;
    644         
    645         default:
    646             printf("%s%s%sSoundRate: %d
    ", TAB44, TAB44, TAB44, audioHeader.soundRate);
    647     }
    648     
    649     switch (audioHeader.soundSize)
    650     {
    651         case 0:
    652             printf("%s%s%sSoundSize: snd8bit
    ", TAB44, TAB44, TAB44);
    653             break;
    654         
    655         case 1:
    656             printf("%s%s%sSoundSize: snd16bit
    ", TAB44, TAB44, TAB44);
    657         break;
    658         
    659         default:
    660             printf("%s%s%sSoundSize: %d
    ", TAB44, TAB44, TAB44, audioHeader.soundSize);
    661     }
    662     
    663     switch (audioHeader.soundType)
    664     {
    665         case 0:
    666             printf("%s%s%sSoundType: sndMono
    ", TAB44, TAB44, TAB44);
    667             break;
    668         
    669         case 1:
    670             printf("%s%s%sSoundType: sndStereo
    ", TAB44, TAB44, TAB44);
    671         break;
    672         
    673         default:
    674             printf("%s%s%sSoundSize: %d
    ", TAB44, TAB44, TAB44, audioHeader.soundSize);
    675     }
    676 #endif
    677     
    678     data++;
    679     
    680     /* now just for aac */
    681     switch (audioHeader.soundFormat)
    682     {
    683         case 0xa:
    684             memset(&aPacket, 0x0, sizeof(T_FLV_TAG_AAC_AUDIO_PACKET));
    685             
    686             aPacket.aacPacketType = data[0];
    687             
    688             if (0 == aPacket.aacPacketType)
    689             {
    690 #ifdef PRINTF_DEBUG
    691                 printf("%s%s%s+AACAudioData
    ", TAB44, TAB44, TAB44);
    692                 printf("%s%s%s%sAACPacketType: %d
    ", TAB44, TAB44, TAB44, TAB44, aPacket.aacPacketType);
    693 #endif
    694                 aPacket.ap.aacSpecCfg.audioObjectType = (data[1] >> 3) & 0x1f;
    695                 aPacket.ap.aacSpecCfg.samplingFreqIndex = ((data[1] & 0x7) << 1) | ((data[2] >> 7) & 0x1);
    696                 aPacket.ap.aacSpecCfg.channelCfg = (data[2] >> 3) & 0xf;
    697                 
    698 #ifdef PRINTF_DEBUG
    699                 printf("%s%s%s%s+AudioSpecificConfig
    ", TAB44, TAB44, TAB44, TAB44);
    700                 
    701                 printf("%s%s%s%s%sAudioObjectType: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, aPacket.ap.aacSpecCfg.audioObjectType);
    702                 printf("%s%s%s%s%sSamplingFrequencyIndex: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, aPacket.ap.aacSpecCfg.samplingFreqIndex);
    703                 printf("%s%s%s%s%sChannelConfiguration: %d
    ", TAB44, TAB44, TAB44, TAB44, TAB44, aPacket.ap.aacSpecCfg.channelCfg);
    704 #endif
    705             }
    706             else
    707             {
    708 #ifdef PRINTF_DEBUG
    709                 printf("%s%s%s+AACAudioData
    ", TAB44, TAB44, TAB44);
    710                 printf("%s%s%s%sAACPacketType: %d
    ", TAB44, TAB44, TAB44, TAB44, aPacket.aacPacketType);
    711                 printf("%s%s%s%sData(Raw AAC frame data)
    ", TAB44, TAB44, TAB44, TAB44);
    712 #endif
    713             }
    714             
    715             break;
    716             
    717         default:
    718             break;
    719     }
    720 }
    721 
    722 static void DealTagData(unsigned char* const tagData, const int tagType, const unsigned int tagSize)
    723 {
    724 #ifdef PRINTF_DEBUG
    725     printf("%s%s%s
    ", TAB44, TAB44, "+Tag Data");
    726 #endif
    727 
    728     switch (tagType)
    729     {
    730         case 0x12:
    731             DealScriptTagData(tagData, tagSize);
    732 
    733             break;
    734 
    735         case 0x9:
    736             DealVideoTagData(tagData);
    737 
    738             break;
    739 
    740         case 0x8:
    741             DealAudioTagData(tagData);
    742 
    743             break;
    744 
    745         default:
    746             break;
    747     }
    748 }
    749 
    750 int main(int argc, char *argv[])
    751 {
    752     int dataLen = 0;
    753     int previousTagSize = 0;
    754     
    755     FILE *fp = NULL;
    756     
    757     unsigned char *tagData = NULL;
    758     
    759     unsigned char flvHeaderData[MIN_FLV_HEADER_LEN+1] = {0};
    760     unsigned char preTagSizeData[MAX_PRE_TAG_SIZE_LEN+1] = {0};
    761     unsigned char tagHeaderData[MAX_TAG_HEADER_LEN+1] = {0};
    762     
    763     T_FLV_TAG_HEADER tagHeader = {0};
    764     
    765     if (2 != argc)
    766     {
    767         printf("Usage: flvparse **.flv
    ");
    768 
    769         return -1;
    770     }
    771 
    772     fp = fopen(argv[1], "rb");
    773     if (!fp)
    774     {
    775         printf("open file[%s] error!
    ", argv[1]);
    776 
    777         return -1;
    778     }
    779     
    780     memset(flvHeaderData, 0x0, sizeof(flvHeaderData));
    781     
    782     dataLen = fread(flvHeaderData, 1, MIN_FLV_HEADER_LEN, fp);
    783     if (dataLen != MIN_FLV_HEADER_LEN)
    784     {
    785         printf("read flv header error!
    ");
    786         
    787         fclose(fp);
    788         
    789         return -1;
    790     }
    791     
    792     flvHeaderData[MIN_FLV_HEADER_LEN] = '';
    793     
    794     DealFlvHeader(flvHeaderData);
    795     
    796 #ifdef PRINTF_DEBUG
    797     printf("+FLV Body
    ");
    798 #endif
    799 
    800     while (1)
    801     {
    802         memset(preTagSizeData, 0x0, sizeof(preTagSizeData));
    803         
    804         dataLen = fread(preTagSizeData, 1, MAX_PRE_TAG_SIZE_LEN, fp);
    805         if (dataLen != MAX_PRE_TAG_SIZE_LEN)
    806         {
    807             break;
    808         }
    809         
    810         preTagSizeData[MAX_PRE_TAG_SIZE_LEN] = '';
    811 
    812 #ifdef PRINTF_DEBUG
    813         printf("%spreviousTagSize: %d
    ", TAB44, (preTagSizeData[0]<<24) | (preTagSizeData[1]<<16) | (preTagSizeData[2]<<8) | preTagSizeData[3]);
    814 #endif
    815 
    816         memset(tagHeaderData, 0x0, sizeof(tagHeaderData));
    817         
    818         dataLen = fread(tagHeaderData, 1, MAX_TAG_HEADER_LEN, fp);
    819         if (dataLen != MAX_TAG_HEADER_LEN)
    820         {
    821             continue;
    822         }
    823         
    824         memset(&tagHeader, 0x0, sizeof(T_FLV_TAG_HEADER));
    825         
    826         DealTagHeader(tagHeaderData, &tagHeader);
    827 
    828         tagData = (unsigned char*)malloc(tagHeader.data_size);
    829         if (!tagData)
    830         {
    831             continue;
    832         }
    833         
    834         memset(tagData, 0x0, tagHeader.data_size);
    835         
    836         dataLen = fread(tagData, 1, tagHeader.data_size, fp);
    837         if (dataLen != tagHeader.data_size)
    838         {
    839             continue;
    840         }
    841         
    842         DealTagData(tagData, tagHeader.type, tagHeader.data_size);
    843         
    844         free(tagData);
    845         tagData = NULL;
    846     }
    847     
    848     fclose(fp);
    849     
    850     return 0;
    851 }
    View Code

       最后如果您觉得本篇对您有帮助,可以打赏下,谢谢!!!

     

  • 相关阅读:
    openresty + gor+minio 集成
    openresty docker 镜像集成gor
    goreplay v1.1.0 支持pro特性docker 镜像
    编译goreplay v1.1.0 minio 集成支持
    编译goreplay v1.1.0 支持二进制协议捕捉
    goreplay v1.1.0 发布
    super-expressive 可以基于js 直接编写正则
    monio 的一些安全实践
    minio+ nginx rewrite 实现saas租户的个性化管理
    LDAP概念和原理介绍
  • 原文地址:https://www.cnblogs.com/leaffei/p/10463111.html
Copyright © 2011-2022 走看看