溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

FFmpeg av_find_input_format函數剖析

發布時間:2020-07-30 13:36:08 來源:網絡 閱讀:4864 作者:fengyuzaitu 欄目:編程語言

AVInputFormat結構體
AVInputFormat 每種碼流輸入格式(例如h364,FLV, MKV, MP4, AVI)對應一個結構體,用來保存視音頻的解碼參數,目前以h364碼流格式為例,描述結構體成員:
name:封裝格式名稱簡寫(short_name)[h364]
long_name:碼流輸入格式的長名稱[raw H.264 video]
extensions:碼流輸入格式的擴展名[h36l,h364,264,avc]
raw_codec_id:碼流輸入格式ID[28]
read_packet:avformat-57.dll!0x000007fee101ca90 (加載符號以獲取其他信息)
read_header:avformat-57.dll!0x000007fee101cb70 (加載符號以獲取其他信息)

關鍵函數:int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
read_packet函數讀取一個AVPacket,然后放在pkt,這個函數在進行分幀
av_read_frame函數的里面會被調用到,調用相應的×××獲取一幀的完整數據


問題:各種碼流輸入格式是什么時候被加載的?
回答:當第一次調用av_register_all的時候就會注冊復用器,其中就包含了各種碼流的輸入格式的處理函數

查看調用關系
av_register_all
?? ?register_all
?? ??? ?REGISTER_MUXDEMUX(H264,???????????? h364);
?? ??? ??? ?#define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)

#define REGISTER_MUXER(X, x)??????????????????????????????????????????? \
??? {?????????????????????????????????????????????????????????????????? \
??????? extern AVOutputFormat ff_##x##_muxer;?????????????????????????? \
??????? if (CONFIG_##X##_MUXER)???????????????????????????????????????? \
??????????? av_register_output_format(&ff_##x##_muxer);???????????????? \
??? }

#define REGISTER_DEMUXER(X, x)????????????????????????????????????????? \
??? {?????????????????????????????????????????????????????????????????? \
??????? extern AVInputFormat ff_##x##_demuxer;????????????????????????? \
??????? if (CONFIG_##X##_DEMUXER)?????????????????????????????????????? \
??????????? av_register_input_format(&ff_##x##_demuxer);??????????????? \
??? }

看看注冊碼流輸入格式的函數
void av_register_input_format(AVInputFormat *format)
{
??? AVInputFormat **p = last_iformat;

??? // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
??? while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
??????? p = &(*p)->next;

??? if (!format->next)
??????? last_iformat = &format->next;
}
其中關鍵的全局變量是
static AVInputFormat *first_iformat = NULL;
static AVInputFormat **last_iformat = &first_iformat;
保存了所有碼流格式

AVInputFormat *av_iformat_next(const AVInputFormat *f)
{
??? if (f)
??????? return f->next;
??? else
??????? return first_iformat;
}

AVInputFormat *av_find_input_format(const char *short_name)
{
??? AVInputFormat *fmt = NULL;
??? while ((fmt = av_iformat_next(fmt)))//獲取×××的鏈表指針,
??????? if (av_match_name(short_name, fmt->name))//根據輸入的碼流格式簡寫,輪詢鏈表查找×××
??????????? return fmt;
??? return NULL;
}

在avformat_open_input函數優化篇就直接指定碼流的輸入格式,從而減少了探測碼流格式的時間

參考
http://blog.csdn.net/leixiaohua1020/article/details/12677129
http://blog.csdn.net/neustar1/article/details/38231937


AVFMT_NOFILE宏定義剖析
使用說明
??? 當前為了避免在調用init_input函數的時候,讀取緩存區的數據,從而設置了該標志位,但是最終在avformat_open_input的其他地方還是讀取了緩沖區的數據
??????? pAVInputFormat = av_find_input_format("h364");
??????? pAVInputFormat->flags |= AVFMT_NOFILE;

宏定義
/// Demuxer will use avio_open, no opened file should be provided by the caller.
//解復用器將調用avio_open函數,調用者提供一個沒有打開的文件,估計是打開的文件會被占用
#define AVFMT_NOFILE??????? 0x0001
#define AVFMT_NEEDNUMBER??? 0x0002 /**< Needs '%d' in filename. */
#define AVFMT_SHOW_IDS????? 0x0008 /**< Show format stream IDs numbers. */


AVFMT_NOFILE formats will not have a AVIOContext
當設置了AVFMT_NOFILE標志,將不會攜帶AVIOContext


/* Open input file and probe the format if necessary. */
static int init_input(AVFormatContext *s, const char *filename,
????????????????????? AVDictionary **options)
{
??? int ret;
??? AVProbeData pd = { filename, NULL, 0 };
??? int score = AVPROBE_SCORE_RETRY;

??? //這里探測碼流的方式,企圖通過AVIOContext結構體中的read_packet函數
??? //如果碼流格式已經指定并且指定了標志位,直接返回
??? if (s->pb) {
??????? s->flags |= AVFMT_FLAG_CUSTOM_IO;
??? //如果沒有指定輸入格式,開始探測碼流格式
??????? if (!s->iformat)
??????????? return av_probe_input_buffer2(s->pb, &s->iformat, filename,
???????????????????????????????????????? s, 0, s->format_probesize);
??????? else if (s->iformat->flags & AVFMT_NOFILE)
??????????? av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
????????????????????????????????????? "will be ignored with AVFMT_NOFILE format.\n");
??????? return 0;
??? }
?? //這里探測碼流的方式,企圖通過通過進來的文件名稱
?? //如果碼流格式已經指定并且指定了標志位,直接返回
?? //這里非常明顯網絡RTSP流,肯定是不會走到這里
??? if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
??????? (!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
??????? return score;

??? //如果指定了iformat結構體,并且沒有設置標志位,肯定執行下面的語句,該語句會調用read_packet函數
??? //進行分析碼流
??? if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)
??????? return ret;

??? if (s->iformat)
??????? return 0;
??? return av_probe_input_buffer2(s->pb, &s->iformat, filename,
???????????????????????????????? s, 0, s->format_probesize);
}


從下面的說明可以得知,當添加了AVFMT_NOFILE標志位,AVIOContext *pb會設置為空
??? /**
???? * I/O context.
???? *
???? * - demuxing: either set by the user before avformat_open_input() (then
???? *???????????? the user must close it manually) or set by avformat_open_input().
???? * - muxing: set by the user before avformat_write_header(). The caller must
???? *?????????? take care of closing / freeing the IO context.
???? *
???? * Do NOT set this field if AVFMT_NOFILE flag is set in
???? * iformat/oformat.flags. In such a case, the (de)muxer will handle
???? * I/O in some other way and this field will be NULL.
???? */
??? AVIOContext *pb;

??? /**
???? * Custom interrupt callbacks for the I/O layer.
???? *
???? * demuxing: set by the user before avformat_open_input().
???? * muxing: set by the user before avformat_write_header()
???? * (mainly useful for AVFMT_NOFILE formats). The callback
???? * should also be passed to avio_open2() if it's used to
???? * open the file.
???? */
??? AVIOInterruptCB interrupt_callback;

/**
?* Guess the file format.
?*
?* @param pd??????? data to be probed
?* @param is_opened Whether the file is already opened; determines whether
?*????????????????? demuxers with or without AVFMT_NOFILE are probed.
?*/
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max);
AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score_ret);

?

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女