FFmpeg源代碼簡單分析:av_find_decoder()和av_find_encoder()
來源:程序員人生 發布時間:2015-03-10 08:08:49 閱讀次數:6514次
本文記錄FFmpeg的兩個API函數: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);
函數的參數是1個編碼器的ID,返回查找到的編碼器(沒有找到就返回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);
函數的參數是1個解碼器的ID,返回查找到的解碼器(沒有找到就返回NULL)。
avcodec_find_encoder()函數最典型的例子可以參考:
最簡單的基于FFMPEG的視頻編碼器(YUV編碼為H.264)
avcodec_find_decoder()函數最典型的例子可以參考:
最簡單的基于FFMPEG+SDL的視頻播放器 ver2 (采取SDL2.0)
其實這兩個函數的實質就是遍歷AVCodec鏈表并且取得符合條件的元素。有關AVCodec鏈表的建立可以參考文章:
ffmpeg 源代碼簡單分析 : av_register_all()
函數調用關系圖
avcodec_find_encoder()和avcodec_find_decoder()的函數調用關系圖以下所示。
avcodec_find_encoder()
avcodec_find_encoder()的源代碼位于libavcodecutils.c,以下所示。
AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
return find_encdec(id, 1);
}
從源代碼可以看出avcodec_find_encoder()調用了1個find_encdec(),注意它的第2個參數是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個循環,該循環會遍歷AVCodec結構的鏈表,逐1比較輸入的ID和每個編碼器的ID,直到找到ID取值相等的編碼器。
在這里有幾點需要注意:
(1)first_avcodec是1個全局變量,存儲AVCodec鏈表的第1個元素。
(2)remap_deprecated_codec_id()用于將1些過時的編碼器ID映照到新的編碼器ID。
(3)函數的第2個參數encoder用于肯定查找編碼器還是解碼器。當該值為1的時候,用于查找編碼器,此時會調用av_codec_is_encoder()判斷AVCodec是不是為編碼器;當該值為0的時候,用于查找解碼器,此時會調用av_codec_is_decoder()判斷AVCodec是不是為解碼器。
av_codec_is_encoder()
av_codec_is_encoder()是1個判斷AVCodec是不是為編碼器的函數。如果是編碼器,返回非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()源代碼很簡單,以下所示。
int av_codec_is_encoder(const AVCodec *codec)
{
return codec && (codec->encode_sub || codec->encode2);
}
從源代碼可以看出,av_codec_is_encoder()判斷了1下AVCodec是不是包括了encode2()或encode_sub()接口函數。
av_codec_is_decoder()
av_codec_is_decoder()是1個判斷AVCodec是不是為解碼器的函數。如果是解碼器,返回非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()源代碼也很簡單,以下所示。
int av_codec_is_decoder(const AVCodec *codec)
{
return codec && codec->decode;
}
從源代碼可以看出,av_codec_is_decoder()判斷了1下AVCodec是不是包括了decode()接口函數。
avcodec_find_decoder()
avcodec_find_decoder()的源代碼位于libavcodecutils.c,以下所示。
AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
return find_encdec(id, 0);
}
可以看出avcodec_find_decoder()一樣調用了find_encdec(),只是第2個參數設置為0。因此不再詳細分析。
雷霄驊
leixiaohua1020@126.com
http://blog.csdn.net/leixiaohua1020
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈