• flv 解封装


    [cpp] view plain copy
     
    1. #include <stdio.h>  
    2. #include <stdlib.h>  
    3. #include <string.h>  
    4.   
    5. #define DEBUG_INFO  
    6.   
    7. typedef struct FileHeader {  
    8.     unsigned char type[4]; // UI8 * 3  "FLV"  
    9.     unsigned char versions; // UI8   版本号  
    10.     unsigned char stream_info;//UI8  流信息  
    11.     unsigned int length; // UI32  文件长度  
    12. }_FileHeader;  
    13.   
    14. typedef struct TagHeader {  
    15.     unsigned char type;  // UI8   tag类型  
    16.     unsigned int data_size; // UI24 数据区长度  
    17.     unsigned int timestemp; // UI24 时间戳  
    18.     unsigned char time_stamp_extended; //UI8 扩展时间戳  
    19.     unsigned int stream_id; //UI24 流id  
    20. }_TagHeader;  
    21.   
    22. typedef struct Tag {  
    23.     _TagHeader *header;  
    24.     unsigned char *data;  
    25. }_Tag;  
    26.   
    27. _Tag *malloc_tag()  
    28. {  
    29.     _Tag *tag = malloc(sizeof(_Tag));  
    30.     if (tag == NULL) {  
    31.         fprintf(stderr, "malloc tag error ");  
    32.         perror("malloc error:");  
    33.         return NULL;  
    34.     }  
    35.   
    36.     tag->header = NULL;  
    37.     tag->data = NULL;  
    38.       
    39.     return tag;  
    40. }  
    41.   
    42. void free_tag(_Tag **tag)  
    43. {  
    44.     if(tag != NULL){  
    45.         if(*tag == NULL){  
    46.             return;  
    47.         }  
    48.           
    49.         if ((*tag)->header != NULL) {  
    50.             free((*tag)->header);  
    51.             (*tag)->header = NULL;  
    52.         }  
    53.           
    54.         if ((*tag)->data != NULL) {  
    55.             free((*tag)->data);  
    56.             (*tag)->data = NULL;  
    57.         }  
    58.           
    59.         *tag = NULL;  
    60.     }  
    61. }  
    62.   
    63. int reverse_32(unsigned int a)  
    64. {  
    65.     union {  
    66.         int i;  
    67.         char c[4];  
    68.     } u, r;  
    69.   
    70.     u.i = a;  
    71.     r.c[0] = u.c[3];  
    72.     r.c[1] = u.c[2];  
    73.     r.c[2] = u.c[1];  
    74.     r.c[3] = u.c[0];  
    75.   
    76.     return r.i;  
    77. }  
    78.   
    79. int reverse_24(unsigned int a)  
    80. {  
    81.     union {  
    82.         int i;  
    83.         char c[4];  
    84.     } u, r;  
    85.   
    86.     u.i = a;  
    87.     r.c[0] = u.c[2];  
    88.     r.c[1] = u.c[1];  
    89.     r.c[2] = u.c[0];  
    90.     r.c[3] = 0;  
    91.           
    92.     return r.i;  
    93. }  
    94.   
    95. int read_file_header(FILE *pf, _FileHeader **p_header)  
    96. {  
    97.     int ret = 0;  
    98.   
    99.     _FileHeader *header = malloc(sizeof(_FileHeader));  
    100.     if (header == NULL) {  
    101.         fprintf(stderr, "malloc file header error ");  
    102.         perror("malloc error:");  
    103.         return -1;  
    104.     }  
    105.     memset(header, 0, sizeof(_FileHeader));  
    106.   
    107.     //read file type  
    108.     if ((ret = fread(header->type, 3, 1, pf)) <= 0) {  
    109.         goto __err_exit;  
    110.     }  
    111.   
    112.     // read version, Usually 1  
    113.     if ((ret = fread(&(header->versions), 1, 1, pf)) <= 0) {  
    114.         goto __err_exit;  
    115.     }  
    116.   
    117.     // read stream info  
    118.     if ((ret = fread(&(header->stream_info), 1, 1, pf)) <= 0) {  
    119.         goto __err_exit;  
    120.     }  
    121.   
    122.     // read file length  
    123.     if((ret = fread(&(header->length), 4, 1, pf)) <= 0){  
    124.         goto __err_exit;  
    125.     }  
    126.     header->length = reverse_32(header->length);  
    127.     *p_header = header;  
    128.       
    129. #ifdef DEBUG_INFO  
    130.         printf("=========== file header============= ");  
    131.         printf("type : %s ", header->type);  
    132.         printf("versions : %u ", header->versions);  
    133.         printf("stream_info : %u ", header->stream_info);  
    134.         printf("length : %d ", header->length);  
    135.         printf("==================================== ");  
    136. #endif  
    137.   
    138.     return 1;  
    139. __err_exit:      
    140.     free(header);  
    141.     fprintf(stderr, "read file header error ");  
    142.     perror("fread error:");  
    143.   
    144.     return ret;  
    145. }  
    146.   
    147. int check_file_header(_FileHeader *header)  
    148. {  
    149.     // is flv file?  
    150.     if ((header->type[0] != 0x46/*'F'*/) || (header->type[1] != 0x4C/*'L'*/) || (header->type[2] != 0x56/*'V'*/)) {  
    151.         fprintf(stderr, "check file header type error ");  
    152.         return -1;  
    153.     }  
    154.   
    155.     //UB[7]~UB[3]总为0,  
    156.     //UB[1]总为0  
    157.     //UB[2]=1 Audio  
    158.     if (header->stream_info & 0x04) {  
    159.         printf("have audio tag ");  
    160.     }  
    161.   
    162.     //UB[0] = 1 Video  
    163.     if (header->stream_info & 0x01) {  
    164.         printf("have video tag ");  
    165.     }  
    166.   
    167.     return 1;  
    168. }  
    169.   
    170. int read_last_tag_size(FILE *pf, unsigned int *p_last_tag_size)  
    171. {  
    172.     int ret = 0;  
    173.     unsigned int last_tag_size = 0;  
    174.   
    175.     if ((ret = fread(&last_tag_size, 4, 1, pf)) <= 0) {  
    176.         fprintf(stderr, "read last tag size error ");  
    177.         perror("fread error:");  
    178.         return ret;  
    179.     }  
    180.     *p_last_tag_size = reverse_32(last_tag_size);  
    181.   
    182. #ifdef DEBUG_INFO  
    183.     printf("---last tag size %x ", *p_last_tag_size);  
    184. #endif  
    185.   
    186.     return 1;  
    187. }  
    188.   
    189. int read_tag_header(FILE *pf, _TagHeader **p_header)  
    190. {  
    191.     int ret = 0;  
    192.     _TagHeader *header = NULL;  
    193.   
    194.     header = malloc(sizeof(_TagHeader));  
    195.     if (header == NULL) {  
    196.         fprintf(stderr, "malloc tag header error ");  
    197.         perror("malloc error:");  
    198.         return -1;  
    199.     }  
    200.   
    201.     // read tag type , 0x08 is audio, 0x09 is video, 0x12 is script  
    202.     if ((ret = fread(&(header->type), 1, 1, pf)) <= 0) {  
    203.         goto __err_exit;  
    204.     }  
    205.   
    206.     // read tag data size  
    207.     if ((ret = fread(&(header->data_size), 3, 1, pf)) <= 0) {  
    208.         goto __err_exit;  
    209.     }  
    210.     header->data_size = reverse_24(header->data_size);  
    211.   
    212.     // read tag timestemp  
    213.     if ((ret = fread(&(header->timestemp), 3, 1, pf)) <= 0) {  
    214.         goto __err_exit;  
    215.     }  
    216.     header->timestemp = reverse_24(header->timestemp);  
    217.   
    218.     //read tag extended time stemp  
    219.     if ((ret = fread(&(header->time_stamp_extended), 1, 1, pf)) <= 0) {  
    220.         goto __err_exit;  
    221.     }  
    222.   
    223.     //read stream id  
    224.     if ((ret = fread(&(header->stream_id), 3, 1, pf)) <= 0) {  
    225.         goto __err_exit;  
    226.     }  
    227.     header->stream_id = reverse_24(header->stream_id);  
    228.     *p_header = header;  
    229.   
    230. #ifdef DEBUG_INFO  
    231.     printf("======= tag header ======= ");          
    232.     printf("tag_type:%x ", header->type);  
    233.     printf("data_size:%x ", header->data_size);  
    234.     printf("timestemp:%x ", header->timestemp);  
    235.     printf("time_stamp_extended:%x ", header->time_stamp_extended);  
    236.     printf("stream_id:%x ", header->stream_id);  
    237. #endif  
    238.   
    239.     return 1;  
    240. __err_exit:      
    241.     free(header);  
    242.     fprintf(stderr, "read tag header error ");  
    243.     perror("fread error:");  
    244.   
    245.     return ret;  
    246. }  
    247.   
    248. int read_tag_data(FILE *pf, unsigned char **p_data, unsigned int size)  
    249. {  
    250.     int ret = 0;  
    251.     unsigned char *data = NULL;  
    252.   
    253.     data = malloc(size + 1);  
    254.     if (data == NULL) {  
    255.         fprintf(stderr, "malloc tag data error ");  
    256.         perror("malloc error:");  
    257.         return -1;  
    258.     }  
    259.     data[size] = 0;  
    260.       
    261.     if ((ret = fread(data, size, 1, pf)) <= 0) {  
    262.         free(data);          
    263.         fprintf(stderr, "read tag data error ");  
    264.         perror("fread error:");  
    265.         return ret;  
    266.     }  
    267.       
    268.     *p_data = data;  
    269.   
    270.     return 1;  
    271. }  
    272.   
    273. void audio_tag_data(unsigned char *data)  
    274. {  
    275.     unsigned char audio_info = 0;  
    276.     unsigned char audio_format = 0;  
    277.     unsigned char audio_samplerate = 0;  
    278.     unsigned char audio_samplelenght = 0;  
    279.     unsigned char audio_type = 0;  
    280.   
    281.     // the first byte is the adio info  
    282.     audio_info = data[0];  
    283.   
    284.     //UB[7]~UB[4] is the audo format  
    285.     // 0 -- 未压缩   
    286.     // 1 -- ADPCM   
    287.     // 2 -- MP3  
    288.     // 5 -- Nellymoser 8kHz momo  
    289.     // 6 -- Nellymose  
    290.     audio_format = audio_info & 0xf0;  
    291.     audio_format >>= 4;  
    292.   
    293.     //UB[3]~UB[2] is the sample rate  
    294.     // 0 -- 5.5kHz  
    295.     // 1 -- 11kHz  
    296.     // 2 -- 22kHz  
    297.     // 3 -- 44kHz   
    298.     audio_samplerate = audio_info & 0x0c;  
    299.     audio_samplerate >>= 2;  
    300.   
    301.     //UB[1] is the sample length  
    302.     // 0 -- snd8Bit  
    303.     // 1 -- snd16Bit  
    304.     audio_samplelenght = audio_info & 0x02;  
    305.     audio_samplelenght >>= 1;  
    306.   
    307.     //UB[0] is the type  
    308.     // 0 -- sndMomo  
    309.     // 1 -- sndStereo  
    310.     audio_type = audio_info & 0x01;  
    311.   
    312. #ifdef DEBUG_INFO  
    313.     printf("=======audio_info==== ");  
    314.     printf("format:%x ", audio_format);  
    315.     printf("samplerate:%x ", audio_samplerate);  
    316.     printf("samplelenght:%x ", audio_samplelenght);  
    317.     printf("type:%x ", audio_type);  
    318. #endif  
    319. }  
    320.   
    321. void video_tag_data(unsigned char *data)  
    322. {  
    323.     int size = 0;  
    324.     unsigned char video_info = 0;  
    325.     unsigned char video_frame_type = 0;  
    326.     unsigned char video_code_id = 0;  
    327.   
    328.     // the first byte is the adio info  
    329.     video_info = data[0];  
    330.   
    331.     //UB[7]~UB[4] is the video format  
    332.     // 1 -- keyframe  
    333.     // 2 -- inner frame  
    334.     // 3 -- disposable inner frame (H.263 only)   
    335.     video_frame_type = video_info & 0xf0;  
    336.     video_frame_type >>= 4;  
    337.   
    338.     // UB[3]~UB[0] is the encoder id      
    339.     // 2 -- Seronson H.263  
    340.     // 3 -- Screen video  
    341.     // 4 -- On2 VP6  
    342.     // 5 -- On2 VP6 without channel  
    343.     // 6 -- Screen video version 2  
    344.     video_code_id = video_info & 0x0f;  
    345.   
    346. #ifdef DEBUG_INFO  
    347.     printf("=======video_info==== ");  
    348.     printf("frame_type:%x ", video_frame_type);  
    349.     printf("code_id:%x ", video_code_id);  
    350. #endif  
    351. }  
    352.   
    353. void script_tag_data(unsigned char *data)  
    354. {  
    355.     //Metadata Tag  
    356.     /* 
    357.     * 该类型Tag又通常被称为Metadata Tag, 
    358.     * 会放一些关于FLV视频和音频的参数信息, 
    359.     * 如duration、width、height等。 
    360.     * 通常该类型Tag会跟在File Header后面作为第一个Tag出现, 
    361.     * 而且只有一个。      
    362.     * 一般来说,该Tag Data结构包含两个AMF包。 
    363.     * 第一个AMF包封装字符串类型数据, 
    364.     * 用来装入一个“onMetaData”标志, 
    365.     * 这个标志与Adobe的一些API调用有,在此不细述。 
    366.     * 第二个AMF包封装一个数组类型, 
    367.     * 这个数组中包含了音视频信息项的名称和值。 
    368.     */  
    369.   
    370.     // amf 封闭在这里不解了,会在以后文章中见到。  
    371. }  
    372.   
    373. int read_tag(FILE *pf, unsigned int *p_last_tag_size, _Tag *tag)  
    374. {  
    375.     int ret = 0;  
    376.   
    377.     // last tag size  
    378.     if ((ret = read_last_tag_size(pf, p_last_tag_size)) <= 0) {  
    379.         return ret;  
    380.     }  
    381.   
    382.     // read tag header  
    383.     if ((ret = read_tag_header(pf, &(tag->header))) <= 0) {  
    384.         return ret;  
    385.     }  
    386.   
    387.     //read tag data  
    388.     if ((ret = read_tag_data(pf, &(tag->data), tag->header->data_size)) <= 0) {  
    389.         return ret;  
    390.     }  
    391.   
    392.     // 通常第一个音频和视频包都是sequence header  
    393.     switch(tag->header->type){  
    394.         case 0x8:  //audio           
    395.             audio_tag_data(tag->data);  
    396.             break;  
    397.         case 0x9: //video  
    398.             video_tag_data(tag->data);  
    399.             break;  
    400.         case 0x12: //script  
    401.             script_tag_data(tag->data);  
    402.             break;  
    403.     }  
    404.   
    405.     return 1;  
    406. }  
    407.   
    408. int main()  
    409. {  
    410.     FILE *pf = NULL;  
    411.     _FileHeader *file_header = NULL;  
    412.     unsigned int last_tag_size = 0;  
    413.     _Tag *tag = NULL;  
    414.       
    415.     // open file  
    416.     if ((pf = fopen("./sample.flv", "rb")) == NULL) {  
    417.         perror("fopen error:");  
    418.         return -1;  
    419.     }  
    420.   
    421.     //read file header add check some info  
    422.     if (read_file_header(pf, &file_header) <= 0) {  
    423.         fclose(pf);  
    424.         fprintf(stderr, "read_file_header error ");  
    425.         return -1;  
    426.     }  
    427.   
    428.     // check header info  
    429.     if(check_file_header(file_header) <= 0){  
    430.         fclose(pf);  
    431.         free(file_header);  
    432.         fprintf(stderr, "check_file_header error ");  
    433.         return -1;  
    434.     }  
    435.   
    436.     for ( ; ; ) {           
    437.         free_tag(&tag);  
    438.         tag = malloc_tag();  
    439.         if(tag == NULL){  
    440.             fprintf(stderr, "malloc tag error ");  
    441.             perror("malloc error:");  
    442.             break;  
    443.         }  
    444.         if (read_tag(pf, &last_tag_size, tag) <= 0){  
    445.             break;  
    446.         }  
    447.           
    448.     }  
    449.       
    450.     free_tag(&tag);  
    451.     free(file_header);  
    452.     fclose(pf);  
    453.   
    454.     return 0;  
    455. }  
  • 相关阅读:
    python 元组操作
    python安装(python2.7)
    0、
    1、Centos 7 系统的初化始配置
    C# 6.0新特性
    ios学习之路
    Can 't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock '(2) ;
    px,em,rem,vw单位在网页和移动端的应用
    html5shiv.js和respond.min.js
    display:inline-block间隙问题
  • 原文地址:https://www.cnblogs.com/lidabo/p/9020407.html
Copyright © 2020-2023  润新知