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\n");  
  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\n");  
  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=============\n");  
  131.         printf("type : %s\n", header->type);  
  132.         printf("versions : %u\n", header->versions);  
  133.         printf("stream_info : %u\n", header->stream_info);  
  134.         printf("length : %d\n", header->length);  
  135.         printf("====================================\n");  
  136. #endif  
  137.   
  138.     return 1;  
  139. __err_exit:      
  140.     free(header);  
  141.     fprintf(stderr, "read file header error\n");  
  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\n");  
  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\n");  
  160.     }  
  161.   
  162.     //UB[0] = 1 Video  
  163.     if (header->stream_info & 0x01) {  
  164.         printf("have video tag\n");  
  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\n");  
  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\n", *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\n");  
  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 =======\n");          
  232.     printf("tag_type:%x\n", header->type);  
  233.     printf("data_size:%x\n", header->data_size);  
  234.     printf("timestemp:%x\n", header->timestemp);  
  235.     printf("time_stamp_extended:%x\n", header->time_stamp_extended);  
  236.     printf("stream_id:%x\n", header->stream_id);  
  237. #endif  
  238.   
  239.     return 1;  
  240. __err_exit:      
  241.     free(header);  
  242.     fprintf(stderr, "read tag header error\n");  
  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\n");  
  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\n");  
  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====\n");  
  314.     printf("format:%x\n", audio_format);  
  315.     printf("samplerate:%x\n", audio_samplerate);  
  316.     printf("samplelenght:%x\n", audio_samplelenght);  
  317.     printf("type:%x\n", 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====\n");  
  348.     printf("frame_type:%x\n", video_frame_type);  
  349.     printf("code_id:%x\n", 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\n");  
  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\n");  
  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\n");  
  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. }  

猜你喜欢

转载自www.cnblogs.com/lidabo/p/9020407.html
FLV