FFmpeg源代碼簡(jiǎn)單分析:av_find_decoder()和av_find_encoder()
來(lái)源:程序員人生 發(fā)布時(shí)間:2015-03-10 08:08:49 閱讀次數(shù):6525次
本文記錄FFmpeg的兩個(gè)API函數(shù):avcodec_find_encoder()和avcodec_find_decoder()。avcodec_find_encoder()用于查找FFmpeg的編碼器,avcodec_find_decoder()用于查找FFmpeg的解碼器。
avcodec_find_encoder()的聲明位于libavcodecavcodec.h,以下所示。
/**
* Find a registered encoder with a matching codec ID.
*
* @param id AVCodecID of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_encoder(enum AVCodecID id);
函數(shù)的參數(shù)是1個(gè)編碼器的ID,返回查找到的編碼器(沒(méi)有找到就返回NULL)。
avcodec_find_decoder()的聲明也位于libavcodecavcodec.h,以下所示。
/**
* Find a registered decoder with a matching codec ID.
*
* @param id AVCodecID of the requested decoder
* @return A decoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_decoder(enum AVCodecID id);
函數(shù)的參數(shù)是1個(gè)解碼器的ID,返回查找到的解碼器(沒(méi)有找到就返回NULL)。
avcodec_find_encoder()函數(shù)最典型的例子可以參考:
最簡(jiǎn)單的基于FFMPEG的視頻編碼器(YUV編碼為H.264)
avcodec_find_decoder()函數(shù)最典型的例子可以參考:
最簡(jiǎn)單的基于FFMPEG+SDL的視頻播放器 ver2 (采取SDL2.0)
其實(shí)這兩個(gè)函數(shù)的實(shí)質(zhì)就是遍歷AVCodec鏈表并且取得符合條件的元素。有關(guān)AVCodec鏈表的建立可以參考文章:
ffmpeg 源代碼簡(jiǎn)單分析 : av_register_all()
函數(shù)調(diào)用關(guān)系圖
avcodec_find_encoder()和avcodec_find_decoder()的函數(shù)調(diào)用關(guān)系圖以下所示。
avcodec_find_encoder()
avcodec_find_encoder()的源代碼位于libavcodecutils.c,以下所示。
AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
return find_encdec(id, 1);
}
從源代碼可以看出avcodec_find_encoder()調(diào)用了1個(gè)find_encdec(),注意它的第2個(gè)參數(shù)是0。
下面我們看1下find_encdec()的定義。
find_encdec()
find_encdec()的源代碼位于libavcodecutils.c,以下所示。
static AVCodec *first_avcodec;
static AVCodec *find_encdec(enum AVCodecID id, int encoder)
{
AVCodec *p, *experimental = NULL;
p = first_avcodec;
id= remap_deprecated_codec_id(id);
while (p) {
if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) &&
p->id == id) {
if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
experimental = p;
} else
return p;
}
p = p->next;
}
return experimental;
}
find_encdec()中有1個(gè)循環(huán),該循環(huán)會(huì)遍歷AVCodec結(jié)構(gòu)的鏈表,逐1比較輸入的ID和每個(gè)編碼器的ID,直到找到ID取值相等的編碼器。
在這里有幾點(diǎn)需要注意:
(1)first_avcodec是1個(gè)全局變量,存儲(chǔ)AVCodec鏈表的第1個(gè)元素。
(2)remap_deprecated_codec_id()用于將1些過(guò)時(shí)的編碼器ID映照到新的編碼器ID。
(3)函數(shù)的第2個(gè)參數(shù)encoder用于肯定查找編碼器還是解碼器。當(dāng)該值為1的時(shí)候,用于查找編碼器,此時(shí)會(huì)調(diào)用av_codec_is_encoder()判斷AVCodec是不是為編碼器;當(dāng)該值為0的時(shí)候,用于查找解碼器,此時(shí)會(huì)調(diào)用av_codec_is_decoder()判斷AVCodec是不是為解碼器。
av_codec_is_encoder()
av_codec_is_encoder()是1個(gè)判斷AVCodec是不是為編碼器的函數(shù)。如果是編碼器,返回非0值,否則返回0。
/**
* @return a non-zero number if codec is an encoder, zero otherwise
*/
int av_codec_is_encoder(const AVCodec *codec);
av_codec_is_encoder()源代碼很簡(jiǎn)單,以下所示。
int av_codec_is_encoder(const AVCodec *codec)
{
return codec && (codec->encode_sub || codec->encode2);
}
從源代碼可以看出,av_codec_is_encoder()判斷了1下AVCodec是不是包括了encode2()或encode_sub()接口函數(shù)。
av_codec_is_decoder()
av_codec_is_decoder()是1個(gè)判斷AVCodec是不是為解碼器的函數(shù)。如果是解碼器,返回非0值,否則返回0。
/**
* @return a non-zero number if codec is a decoder, zero otherwise
*/
int av_codec_is_decoder(const AVCodec *codec);
av_codec_is_decoder()源代碼也很簡(jiǎn)單,以下所示。
int av_codec_is_decoder(const AVCodec *codec)
{
return codec && codec->decode;
}
從源代碼可以看出,av_codec_is_decoder()判斷了1下AVCodec是不是包括了decode()接口函數(shù)。
avcodec_find_decoder()
avcodec_find_decoder()的源代碼位于libavcodecutils.c,以下所示。
AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
return find_encdec(id, 0);
}
可以看出avcodec_find_decoder()一樣調(diào)用了find_encdec(),只是第2個(gè)參數(shù)設(shè)置為0。因此不再詳細(xì)分析。
雷霄驊
leixiaohua1020@126.com
http://blog.csdn.net/leixiaohua1020
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)