引用雷神原圖:
image.png
可以看出 av_register_all() 是必備的第一步 (?)
個(gè)人可用解碼流程
av_register_all();
avcodec_register_all();
avformat_network_init();
//初始化三個(gè)
//打開視頻文件
av_format_open_input();
賦值:AVFormatContext,鏈接地址(可本地可網(wǎng)絡(luò)),AVInputFormat,AVDictionary。
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
后二值可NULL,返回0則打開失敗
//檢查數(shù)據(jù)流
avformat_find_stream_info();
av_find_stream_info();(棄用?)
賦值:AVFormatContext,AVDictionary
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
后值可NULL,返回小于0檢查失敗
//根據(jù)視頻流找到第一幀
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(@"沒有找到第一個(gè)視頻流");
}
此時(shí)已經(jīng)可以獲取第一幀數(shù)據(jù)流對(duì)應(yīng)的CodecContext
stream = spFormatCtx ->streams[videoStream];
spCodecCtx = stream ->codec;
打印視頻流的詳細(xì)信息
av_dump_format(spFormatCtx, videoStream, filePath, 0);
void av_dump_format(AVFormatContext *ic,
int index,
const char *url,
int is_output);
//打印關(guān)于輸入或輸出格式的詳細(xì)信息,例如
持續(xù)時(shí)間,比特率,流,容器,程序,元數(shù)據(jù),側(cè)數(shù)據(jù),
編解碼器和時(shí)基。
這里就可以算出幀率:fps
if(stream ->avg_frame_rate.den && stream ->avg_frame_rate.num){
fps = av_q2d(stream->avg_frame_rate);
}else{
fps=30.0;
//講道理這里應(yīng)該不給默認(rèn)值30的,誰也不知道是多少,給個(gè)30讓人心里覺得很安慰
}
查找解碼器
avcodec_find_decoder();
AVCodec *avcodec_find_decoder(enum AVCodecID id);
//根據(jù)上文找到第一幀數(shù)據(jù)流中的解碼器id
AVFormatContext -> steams[找到的第一幀下標(biāo)] (AVSteam) -> AVCodecContext ->codec_id
打開解碼器
avcodec_open2();
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
//最后值可NULL 返回值小于0 為打開解碼器失敗
這里就可以知道源視頻的寬高
AVCodecContext -> width;
AVCodecContext -> height;
無限讀針(用在判斷,返回下一個(gè)幀是否存在,不存在結(jié)束循環(huán),有幀,是否為視頻包,不是視頻包接著返回讀取下一幀,是視頻幀調(diào)用解包,如下個(gè)方法)
//返回下一個(gè)針
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 已經(jīng)得到下一幀,就拿改AVFrame 中 data 字段進(jìn)行轉(zhuǎn)圖片操作。