FFmpeg源代码简单分析-通用-av_find_decoder()和av_find_encoder()

参考链接

avcodec_find_encoder 

  • avcodec_find_encoder()用于查找FFmpeg的编码器
  • avcodec_find_encoder()的声明位于libavcodec\codec.h  版本差异
  • avcodec_find_encoder()的源代码位于allcodecs.c   版本差异
  • 函数的参数是一个编码器的ID,返回查找到的编码器(没有找到就返回NULL)
const AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
    return find_codec(id, av_codec_is_encoder);
}

 avcodec_find_decoder

  • avcodec_find_decoder()用于查找FFmpeg的解码器
  • avcodec_find_decoder()的声明位于libavcodec\codec.h  版本差异
  • avcodec_find_decoder()的源代码位于allcodecs.c   版本差异
  • 函数的参数是一个解码器的ID,返回查找到的解码器(没有找到就返回NULL)

const AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
    return find_codec(id, av_codec_is_decoder);
}

函数调用关系图

  • avcodec_find_encoder()和avcodec_find_decoder()的函数调用关系图如下所示。

find_encdec() 

  • find_encdec()中有一个循环,该循环会遍历AVCodec结构的链表,逐一比较输入的ID和每一个编码器的ID,直到找到ID取值相等的编码器。
  • 在这里有几点需要注意: 
    • remap_deprecated_codec_id()用于将一些过时的编码器ID映射到新的编码器ID。 
    • 版本差异很大
static const AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *))
{
    const AVCodec *p, *experimental = NULL;
    void *i = 0;

    id = remap_deprecated_codec_id(id);

    while ((p = av_codec_iterate(&i))) {
        if (!x(p))
            continue;
        if (p->id == id) {
            if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) {
                experimental = p;
            } else
                return p;
        }
    }

    return experimental;
}

av_codec_is_encoder() ​​​​​​​ 

  • av_codec_is_encoder()是一个判断AVCodec是否为编码器的函数。如果是编码器,返回非0值,否则返回0。
  • 从源代码可以看出,av_codec_is_encoder()判断了一下AVCodec是否包含了encode()或者encode_sub()接口函数。

int av_codec_is_encoder(const AVCodec *avcodec)
{
    const FFCodec *const codec = ffcodec(avcodec);
    return codec && (codec->cb_type == FF_CODEC_CB_TYPE_ENCODE     ||
                     codec->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB ||
                     codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET);
}
enum FFCodecType {
    /* The codec is a decoder using the decode callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_DECODE,
    /* The codec is a decoder using the decode_sub callback;
     * subtitle codecs only. */
    FF_CODEC_CB_TYPE_DECODE_SUB,
    /* The codec is a decoder using the receive_frame callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_RECEIVE_FRAME,
    /* The codec is an encoder using the encode callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_ENCODE,
    /* The codec is an encoder using the encode_sub callback;
     * subtitle codecs only. */
    FF_CODEC_CB_TYPE_ENCODE_SUB,
    /* The codec is an encoder using the receive_packet callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_RECEIVE_PACKET,
};
枚举 FFCodecType {
     /* 编解码器是使用解码回调的解码器;
      * 仅限音频和视频编解码器。 */
     FF_CODEC_CB_TYPE_DECODE,
     /* 编解码器是使用 decode_sub 回调的解码器;
      * 仅字幕编解码器。 */
     FF_CODEC_CB_TYPE_DECODE_SUB,
     /* 编解码器是使用接收帧回调的解码器;
      * 仅限音频和视频编解码器。 */
     FF_CODEC_CB_TYPE_RECEIVE_FRAME,
     /* 编解码器是使用编码回调的编码器;
      * 仅限音频和视频编解码器。 */
     FF_CODEC_CB_TYPE_ENCODE,
     /* 编解码器是使用 encode_sub 回调的编码器;
      * 仅字幕编解码器。 */
     FF_CODEC_CB_TYPE_ENCODE_SUB,
     /* 编解码器是一个使用 receive_packet 回调的编码器;
      * 仅限音频和视频编解码器。 */
     FF_CODEC_CB_TYPE_RECEIVE_PACKET,
};

av_codec_is_decoder() ​​​​​​​ 

  • av_codec_is_decoder()是一个判断AVCodec是否为解码器的函数。如果是解码器,返回非0值,否则返回0。
  • 从源代码可以看出,av_codec_is_decoder()判断了一下AVCodec是否包含了decode()或者decode_sub()接口函数。

int av_codec_is_decoder(const AVCodec *avcodec)
{
    const FFCodec *const codec = ffcodec(avcodec);
    return codec && (codec->cb_type == FF_CODEC_CB_TYPE_DECODE     ||
                     codec->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB ||
                     codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME);
}
enum FFCodecType {
    /* The codec is a decoder using the decode callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_DECODE,
    /* The codec is a decoder using the decode_sub callback;
     * subtitle codecs only. */
    FF_CODEC_CB_TYPE_DECODE_SUB,
    /* The codec is a decoder using the receive_frame callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_RECEIVE_FRAME,
    /* The codec is an encoder using the encode callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_ENCODE,
    /* The codec is an encoder using the encode_sub callback;
     * subtitle codecs only. */
    FF_CODEC_CB_TYPE_ENCODE_SUB,
    /* The codec is an encoder using the receive_packet callback;
     * audio and video codecs only. */
    FF_CODEC_CB_TYPE_RECEIVE_PACKET,
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值