`
chriszeng87
  • 浏览: 718108 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ffmpeg解复用视频文件

阅读更多

转自:http://blog.chinaunix.net/uid-24922718-id-3692670.html

 

 解复用视频文件:就是提取出音频文件和视频文件的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)

核心代码:

点击(此处)折叠或打开

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


最后就可以用vlc 或ffplay来查看解析出来的音频aac文件和264文件,本套代码是通用解析器,任何视频文件都可以解析,只是对于264和aac单独做了处理。
贴上最后的效果图:

分享到:
评论

相关推荐

    解复用FLV文件(基于FFMPEG解析FLV(h264+aac))

    基于FFMPEG解析FLV文件,FLV由H264视频和AAC音频组成。

    ffmpeg实现解复用MP4并解码音视频流

    该代码主要实现解复用MP4的媒体流,并且将视频流 音频流进行解码;保存到文件中; 目录: 1. 打开输入流 2.获取视频解码器 3.获取音频解码器 4.解复用 5.存文件; 存文件需要根据yuv的类型进行不同的存储方式: yuv...

    FFmpeg视频、音频复用(VC2010)

    VC2010下,基于FFmpeg实现H264视频、AAC音频复用合成为MP4影音文件,因我的两个资源原本就是一个TS流中解出来的,所以复用后是影音同步的,注释详尽,表示感谢雷霄骅,因我做FFmpeg的项目过程中,用了不少他的代码,...

    FLV解复用代码实现!!!!

    使用ffmpeg协议解复用FLV文件,获得h264视频数据和aac音频数据。 源码已经编译通过 并能够运行 能够进行循环读取文件, 通过数据类型获取音频,视频, 源码采用文件IO模式读取数据,另外还有内存IO模式获取数据,具体...

    FFMPEG 常用命令.pdf

    2. 解复用 3. 视频转码 4. 视频封装 5. 视频剪切 6. 视频录制 7.叠加水印 8.将MP3转换为PCM数据 9. 推送RTP流、接收RTP流并存为ts文件 10. ffmpeg 编码 11. ffmpeg 解码 12. 截取 YUV 13. 压缩分辨率 14...

    FFmpeg入门指南

    1. ffmpeg 视频文件转换命令行工具, 也支持经过实时电视卡抓取和编码成视频文 件. 2. ffserver 基于HTTP 、RTSP 用于实时广播的多媒体服务器. 也支持时间平移 3. ffplay 用SDL和FFmpeg 库开发的一个简单的媒体...

    harmonyos2-ffmpeg-guide:ffmpeg指南

    是领先的多媒体框架,能够解码、编码、转码、复用、解复用、流、过滤和播放人类和机器创建的几乎任何东西。 它支持最前沿的最晦涩的古代格式。 它包含了大量的功能。 对于初学者来说,这可能令人生畏。 对于专家来说...

    Android-Video-Trimmer-master.zip

    MediaCodec是Android提供的编解码类,MediaMuxer则是复用类(生成视频文件)。从易用性的角度上来说肯定不如MediaRecorder,但是允许我们进行更加灵活的操作,比如需要给录制的视频添加水印等各种效果。 优点: 与...

    单个文件C库,用于解码MPEG1视频和MP2音频-C/C++开发

    PL_MPEG-MPEG1视频解码器,MP2音频解码器,MPEG-PS解复用器C / C ++的MIT单文件许可库。有关文档,请参阅pl_mpeg.h。 为什么? 这是将视频播放到您的应用或游戏中的一种简单方法。 诸如ffmpeg之类的其他解决方案则...

    Fasthumb:GPU加速的视频缩略图生成器

    当处理TB级的视频文件时,您最终意识到刚刚启动的缩略图作业将需要数小时甚至数天的时间。 如果您花费10秒钟来处理1 GB,则20 TB的视频内容将花费近57个小时来完成。 通过使用自定义的解复用器并利用GPU解码的功能...

    hevcesbrowser:HEVCESBrowser是用于分析hevc(h265)比特流的工具

    如果需要分析任何类型容器中的视频(例如.ts或.mp4文件中的视频),则需要进行初步的解复用。 例如,您可以为此使用ffmpeg:ffmpeg -i your_file -vcodec复制-an video.h265。 该产品中有gui和cli应用程序。 当前...

    流媒体基本知识及流媒体服务器搭建知识大全

    5.5.1 解复用(Demux) 77 5.5.2 解码 (Decode) 78 5.5.3 Ffmpeg中解码流程对应的API函数 78 第6章GStreamer学习摘录 80 6.1 GStreamer简介 80 6.2 GStreamer编写MP3播放器实例 80 6.2.1 初始化GStreamer 80 6.2.2 ...

    jswebm:Webm Demuxer(matroska)的javascript实现

    audioPackets :解复用的音频数据包的数组 docType :文档类型 audioCodec :音轨的音频编解码器 eof :布尔值(如果已到达文件末尾) 职能 queueData(buffer) :对传入的数据块进行排队,必须是顺序的 demux() :...

Global site tag (gtag.js) - Google Analytics