17911|0

888

帖子

3

TA的资源

五彩晶圆(初级)

楼主
 

flvdemux对flv文件格式解析 [复制链接]

1、flv格式标准
     参考手册:video_file_format_spec_v10_1.pdf (附件可以下载)


2、flv头信息解析
     通过手册的68页,在flv文件的前面9个字节的数据中识别出为flv文件,是否包含音频,视频包含视频信息;
     


3、flv的body信息解析
    接下来的就是解析flv的tag信息,在tag的前面有4个字节的数据,这个数据是表示前面一个tag的长度为多少,像第一个数据,前面是没有tag的,所以always 0;
   
     在每一个tag里面也会有这个tag的长度信息,我们就可以把这个tag给提取出来,分析是里面是音频帧数据还是视频帧数据,长度是多少,解析完后,可以通过后面的previous tag size 来进行校验;


4、flv的tag数据的解析
      通过上面的分析,大家可以提取出tag的数据出来,下面我们对tag的数据进行解析,tag 数据里面会有一个tagtype,通过这个位段的数据,我们可以分析出这个tag是音频数据、视频数据、medadata信息;
      再解析对应的数据;
   


5、关于音频tag数据的解析
    我们解析只分析aac数据的解析,这里的前面2个字节的tag头信息,里面会包含音频的类型、采样率、位宽、声道信息;后面的数据是adts的raw数据,也就是这个数据是没有adts的固定头和可变头信息的;
    如果我们需要把数据还原为aac的数据,必须补充前面的7个字节的信息,通过上面解析出来的音频信息组包7字节作为adts的raw数据的头,这样解析出来的音频才能正常的播放出来;
   
      aac协议的解析可以参考:
    https://bbs.eeworld.com.cn/thread-478714-1-1.html
  1. <font size="3">            if((aac_config_data.SoundFormat == FLV_CODECID_AAC) && (aac_config_data.AACPacketType == 0x01))  // 0x00 Synchronous data, 0x01 raw data
  2.             {
  3.                 // dynamic parameters
  4.                 switch (aac_config_data.SoundRate)
  5.                 {
  6.                     case FLV_SAMPLERATE_44100HZ:
  7.                         adts_header_data.sampling_frequency_index = 4;
  8.                         break;
  9.                     case FLV_SAMPLERATE_22050HZ:
  10.                         adts_header_data.sampling_frequency_index = 7;
  11.                         break;
  12.                     case FLV_SAMPLERATE_11025HZ:
  13.                         adts_header_data.sampling_frequency_index = 10;
  14.                         break;
  15.                     case FLV_SAMPLERATE_SPECIAL:
  16.                         adts_header_data.sampling_frequency_index = 11; // 8kHz
  17.                         break;
  18.                     default:
  19.                         adts_header_data.sampling_frequency_index = 4;
  20.                         break;
  21.                 }

  22.                 switch (aac_config_data.SoundType)
  23.                 {
  24.                     case FLV_MONO:
  25.                         adts_header_data.channel_configuration = 1;
  26.                         break;
  27.                     case FLV_STEREO:
  28.                         adts_header_data.channel_configuration = 2;
  29.                         break;
  30.                     default:
  31.                         adts_header_data.channel_configuration = 2;
  32.                         break;
  33.                 }

  34.                 adts_header_data.aac_frame_length = flvdemux.flv_tag.date_size + 5;
  35.                 adts_write_frame_header_buf(adts_header_buf,&adts_header_data);
  36.                 fwrite(adts_header_buf,7,1,fp_audio_destfile);
  37.                 fwrite(flvdemux.flv_tag.data+2,flvdemux.flv_tag.date_size-2,1,fp_audio_destfile);
  38.             }</font>
复制代码




6、关于视频tag数据的解析
        下面我只针对视频H264数据来进行分析,下面是video tag 的结构信息,通过avc packet type来分析出这个数据是同步数据包还是编码数据包;
   
如果这个数据包是avc sequence header的数据,可以按下面的协议的来进行解析;
    ISO 14496-15, 5.2.4.1 for the description of AVCDecoderConfigurationRecord. This contains the same
    information that would be stored in an avcC box in an MP4/FLV file.


如果是avc nalu 数据,可以之间提取出来就可以了;
这里我们需要注意的一个地方是,拿到avc数据后,提取处理的时候需要加上nalu的头 00 00 00 01信息,否则数据解析出来后,播放器会无法播放出来;
  1. <font size="3">            if(flvdemux.flv_tag.video_data.codec_id != FLV_CODECID_H264 )
  2.             {
  3.                 printf("FLV format video coding is not avc, unable to properly parse !!! \n");
  4.                 return 0;
  5.             }

  6.             if(flvdemux.flv_tag.video_data.frame_type == 1 &&
  7.                 flvdemux.flv_tag.video_data.codec_id == 7 &&
  8.                 flvdemux.flv_tag.video_data.AVCPacketType == 0 &&
  9.                 flvdemux.flv_tag.video_data.CompositionTime == 0)
  10.             {
  11.                 //AVC sequence header , sps and pps
  12.                 avc_config_data.configurationVersion = flvdemux.flv_tag.data[i++];
  13.                 avc_config_data.AVCProfileIndication = flvdemux.flv_tag.data[i++];
  14.                 avc_config_data.profile_compatibility = flvdemux.flv_tag.data[i++];
  15.                 avc_config_data.AVCLevelIndication = flvdemux.flv_tag.data[i++];
  16.                 avc_config_data.lengthSizeMinusOne = flvdemux.flv_tag.data[i++] & 0x3;

  17.                 avc_config_data.numOfSequenceParameterSets = flvdemux.flv_tag.data[i++] & 0x1f;
  18.                 for(num = 0;num < avc_config_data.numOfSequenceParameterSets;num++)
  19.                 {
  20.                     length_a = flvdemux.flv_tag.data[i++];
  21.                     length_b = flvdemux.flv_tag.data[i++];
  22.                     avc_config_data.sequenceParameterSetLength = (length_a << 8 ) | length_b;
  23.                     sequence_buf[0] = 0x00;
  24.                     sequence_buf[1] = 0x00;
  25.                     sequence_buf[2] = 0x00;
  26.                     sequence_buf[3] = 0x01;
  27.                     memcpy(sequence_buf+4,flvdemux.flv_tag.data+i,avc_config_data.sequenceParameterSetLength);
  28.                     fwrite(sequence_buf,avc_config_data.sequenceParameterSetLength+4,1,fp_video_destfile);
  29.                     i+=avc_config_data.sequenceParameterSetLength;
  30.                 }

  31.                 avc_config_data.numOfPictureParameterSets = flvdemux.flv_tag.data[i++] & 0xff;
  32.                 for(num = 0;num < avc_config_data.numOfPictureParameterSets;num++)
  33.                 {
  34.                     length_a = flvdemux.flv_tag.data[i++];
  35.                     length_b = flvdemux.flv_tag.data[i++];
  36.                     avc_config_data.pictureParameterSetLength = (length_a << 8 ) | length_b;
  37.                     sequence_buf[0] = 0x00;
  38.                     sequence_buf[1] = 0x00;
  39.                     sequence_buf[2] = 0x00;
  40.                     sequence_buf[3] = 0x01;
  41.                     memcpy(sequence_buf+4,flvdemux.flv_tag.data+i,avc_config_data.pictureParameterSetLength);
  42.                     fwrite(sequence_buf,avc_config_data.pictureParameterSetLength+4,1,fp_video_destfile);
  43.                     i+=avc_config_data.sequenceParameterSetLength;
  44.                 }</font>
复制代码




复制代码



7、关于metadata的tag数据的解析;
    方法大致和上面的差不多;
    有一个比较不错的文章,大家可以来参考;
    http://blog.chinaunix.net/uid-11344913-id-3996948.html
    或者看下面的代码对应解析也可以的;


8、flv解析源代码,和相关的文档

游客,如果您要查看本帖隐藏内容请回复






点赞 关注
个人签名邮箱:ternence.hsu@foxmail.com
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表