ffmpeg 解码视频流程

引用雷神原图:


image.png

可以看出 av_register_all() 是必备的第一步 (?)
个人可用解码流程

av_register_all();
avcodec_register_all();
avformat_network_init();
//初始化三个
//打开视频文件
av_format_open_input();
赋值:AVFormatContext,链接地址(可本地可网络),AVInputFormat,AVDictionary。

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
后二值可NULL,返回0则打开失败
//检查数据流
avformat_find_stream_info();
av_find_stream_info();(弃用?)
赋值:AVFormatContext,AVDictionary

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
后值可NULL,返回小于0检查失败
//根据视频流找到第一帧
av_find_best_stream();
赋值:AVFormatContext,AVMediaType,wanted_stream_nb,related_stream,AVCodec,flags。
int av_find_best_stream(AVFormatContext *ic,
                        enum AVMediaType type,
                        int wanted_stream_nb,
                        int related_stream,
                        AVCodec **decoder_ret,
                        int flags);
//举例
if((videoStream = av_find_best_stream(spFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &pCodec, 0))< 0){
        NSLog(@"没有找到第一个视频流");    
}

此时已经可以获取第一帧数据流对应的CodecContext

    stream = spFormatCtx ->streams[videoStream];
    spCodecCtx = stream ->codec;

打印视频流的详细信息

av_dump_format(spFormatCtx, videoStream, filePath, 0);
void av_dump_format(AVFormatContext *ic,
                    int index,
                    const char *url,
                    int is_output);
//打印关于输入或输出格式的详细信息,例如
持续时间,比特率,流,容器,程序,元数据,侧数据,
编解码器和时基。

这里就可以算出帧率:fps

if(stream ->avg_frame_rate.den && stream ->avg_frame_rate.num){
  fps = av_q2d(stream->avg_frame_rate);
}else{
  fps=30.0;
//讲道理这里应该不给默认值30的,谁也不知道是多少,给个30让人心里觉得很安慰
}

查找解码器

avcodec_find_decoder();
AVCodec *avcodec_find_decoder(enum AVCodecID id);
//根据上文找到第一帧数据流中的解码器id
AVFormatContext -> steams[找到的第一帧下标] (AVSteam) -> AVCodecContext ->codec_id

打开解码器

avcodec_open2();
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
//最后值可NULL 返回值小于0 为打开解码器失败

这里就可以知道源视频的宽高
AVCodecContext -> width;
AVCodecContext -> height;

无限读针(用在判断,返回下一个帧是否存在,不存在结束循环,有帧,是否为视频包,不是视频包接着返回读取下一帧,是视频帧调用解包,如下个方法)

//返回下一个针
av_read_frame();
int av_read_frame(AVFormatContext *s, AVPacket *pkt);

解码

avcodec_decode_video2();
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                         int *got_picture_ptr,
                         const AVPacket *avpkt);
//其中AVFrame 已经得到下一帧,就拿改AVFrame 中 data 字段进行转图片操作。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 教程一:视频截图(Tutorial 01: Making Screencaps) 首先我们需要了解视频文件的一些基...
    90后的思维阅读 4,849评论 0 3
  • 原文地址:http://blog.csdn.net/yipie/article/details/7912291 摘...
    冬的天阅读 7,252评论 1 6
  • 摘要 该配置文件定义了支持高质量音频分发所需的Bluetooth®设备的要求。这些要求以终端用户服务的方式表达,并...
    公子小水阅读 10,151评论 0 4
  • 现状:现在视频直播非常的火,所以在视频直播开发中,使用的对视频进行遍解码的框架显得尤为重要了,其实,这种框架蛮多的...
    ZHANG_GO阅读 3,222评论 0 2
  • 那天从丽江回来陈宇皓就接到要调回成都的通知,他原本还想带李宾和她女朋友一起去七星湖看看的,可惜就是崔茜铃假期不够,...
    春城一粟阅读 884评论 0 1