引用雷神原图:
可以看出 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 字段进行转图片操作。