ffmpeg 解复用视频文件

解复用视频文件:就是提取出音频文件和视频文件的ES流数据。而对于aac和h264来说,提取出来的数据直接保存并不能成功的播放,原因就在ffmpeg解出的ES数据比较纯净,没有ADTS头,而很多解码器都是需要ADTS头信息来进行解码的,所以就要对aac数据进行头部adts结构的添加。
     对于h264文件来说,h264有两种封装,
一种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中
一种是mp4模式,一般mp4 mkv会有,没有startcode,SPS和PPS以及其它信息被封装在container中,每一个frame前面是这个frame的长度
很多解码器只支持annexb这种模式,因此需要将mp4做转换:
在ffmpeg中用h264_mp4toannexb_filter可以做转换
实现:
注册filter
avcbsfc = av_bitstream_filter_init("h264_mp4toannexb");
转换bitstream
av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
AVCodecContext *avctx, const char *args,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe)

核心代码:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <libavformat/avformat.h>  
  2. #include <libavcodec/avcodec.h>  
  3. #include <stdio.h>  
  4. static int audioindex = -1;  
  5. static int videoindex = -1;  
  6. static int isaaccodec = -1;  
  7. int main(int argc ,char **argv)  
  8. {  
  9.     av_register_all();  
  10.     FILE *f = NULL;  
  11.     FILE *g = NULL;  
  12.     f = fopen("audio","wb");  
  13.     g = fopen("video","wb");  
  14.     if(!f || !g)  
  15.     {  
  16.         printf("open write file errorn");  
  17.         return 0;  
  18.     }  
  19.     AVFormatContext *fmtctx = NULL;  
  20.   
  21.     AVPacket audiopack;  
  22.     if(avformat_open_input(&fmtctx,argv[1],NULL,NULL) < 0)  
  23.     {  
  24.         printf("open fmtctx errorn");  
  25.         return 0;  
  26.     }  
  27.   
  28.     if(avformat_find_stream_info(fmtctx,NULL) < 0)  
  29.     {  
  30.         printf("find stream info n");  
  31.         return 0;  
  32.     }  
  33.     int streamnum = fmtctx->nb_streams;  
  34.     printf("stream num is %dn",streamnum);  
  35.     int i=0;  
  36.     for(;i<streamnum;i++)  
  37.     {  
  38.         if(fmtctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audioindex == -1)  
  39.         {  
  40.             audioindex = i;   
  41.         }  
  42.         else if(fmtctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videoindex == -1)  
  43.         {  
  44.             videoindex = i;  
  45.         }  
  46.     }  
  47.     printf("audioindex is %dn",audioindex);  
  48.   
  49.     printf("videoindex is %dn",videoindex);  
  50.   
  51.     AVCodecContext *codecctx = fmtctx->streams[videoindex]->codec;  
  52.     AVCodec *decode = avcodec_find_decoder(codecctx->codec_id);  
  53.   
  54.     AVCodecContext *audioCodecCtx = fmtctx->streams[audioindex]->codec;  
  55.     AVCodec *audiodecode = avcodec_find_decoder(audioCodecCtx->codec_id);  
  56.     if(audiodecode->id == AV_CODEC_ID_AAC)  
  57.     {  
  58.         isaaccodec = 1;  
  59.     }  
  60.   
  61.     if(avcodec_open2(codecctx,decode,NULL) < 0)  
  62.     {  
  63.         return -1;  
  64.     }  
  65.     if(avcodec_open2(audioCodecCtx,audiodecode,NULL) < 0)  
  66.     {  
  67.         return -1;  
  68.     }  
  69.     printf("extradata size is %dn",audioCodecCtx->extradata_size);  
  70.   
  71.     AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("h264_mp4toannexb");  
  72.     AVBitStreamFilterContext* aacbsfc = av_bitstream_filter_init("aac_adtstoasc");  
  73.     if(!bsfc || !aacbsfc)  
  74.     {  
  75.         return 0;  
  76.     }  
  77.     AVFrame picture;  
  78.     while(!(av_read_frame(fmtctx,&audiopack)))  
  79.     {  
  80.         if(audiopack.stream_index == 1)  
  81.         {  
  82.             if(isaaccodec == 1)  
  83.             {  
  84.                 char bits[7] = {0};  
  85.                 int sample_index = 0 , channel = 0;  
  86.                 char temp = 0;  
  87.                 int length = 7 + audiopack.size;  
  88.                 sample_index = (audioCodecCtx->extradata[0] & 0x07) << 1;  
  89.                 temp = (audioCodecCtx->extradata[1]&0x80);  
  90.                 switch(audioCodecCtx->sample_rate)  
  91.                 {  
  92.                     case 44100:  
  93.                         {  
  94.                             sample_index = 0x7;  
  95.                         }break;  
  96.                     default:  
  97.                         {  
  98.                             sample_index = sample_index + (temp>>7);  
  99.                         }break;  
  100.                 }  
  101.                 channel = ((audioCodecCtx->extradata[1] - temp) & 0xff) >> 3;  
  102.                 bits[0] = 0xff;  
  103.                 bits[1] = 0xf1;  
  104.                 bits[2] = 0x40 | (sample_index<<2) | (channel>>2);  
  105.                 bits[3] = ((channel&0x3)<<6) | (length >>11);  
  106.                 bits[4] = (length>>3) & 0xff;  
  107.                 bits[5] = ((length<<5) & 0xff) | 0x1f;  
  108.                 bits[6] = 0xfc;  
  109.   
  110.                 fwrite(bits,1,7,f);  
  111.             }  
  112.             fwrite(audiopack.data,1,audiopack.size,f);  
  113.             printf("audio pts is %fn",audiopack.pts*av_q2d(fmtctx->streams[audioindex]->time_base));  
  114.         }  
  115.         else if(audiopack.stream_index == videoindex){  
  116.             AVPacket pkt = audiopack;  
  117.               
  118.             int a = av_bitstream_filter_filter(bsfc, codecctx, NULL, &pkt.data, &pkt.size, audiopack.data, audiopack.size, audiopack.flags & AV_PKT_FLAG_KEY);  
  119.             if(a > 0)  
  120.             {  
  121.                 audiopack = pkt;  
  122.             }  
  123.             fwrite(audiopack.data,1,audiopack.size,g);  
  124.             int gotfinished = 0;  
  125.             if(avcodec_decode_video2(codecctx,&picture,&gotfinished,&audiopack) < 0)  
  126.             {  
  127.                 printf("decode video errorn");  
  128.             }  
  129.             if(picture.key_frame)  
  130.             {  
  131.                 //printf("key framen");  
  132.             }  
  133.             else{  
  134.                 //printf("frame num is %dn",picture.pict_type);  
  135.             }  
  136.   
  137.             //printf("video pts is %f, %dn",picture.pkt_dts * av_q2d(fmtctx->streams[videoindex]->codec->time_base),picture.pts );  
  138.         }  
  139.         av_free_packet(&audiopack);  
  140.     }  
  141.     fclose(f);  
  142. }  


最后就可以用vlc 或ffplay来查看解析出来的音频aac文件和264文件,本套代码是通用解析器,任何视频文件都可以解析,只是对于264和aac单独做了处理。
贴上最后的效果图:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值