zoukankan      html  css  js  c++  java
  • ffmpeg之avcodec_open2

    官方源码

    /**
     * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
     * function the context has to be allocated with avcodec_alloc_context3().
     * 利用第二个参数codec初始化codec_ctx,此函数调用前必须使用avcodec_alloc_context3为codec_ctx分配空间
     *
     * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
     * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
     * retrieving a codec.
     * avcodec_find_encoder avcodec_find_encoder_by_name avcodec_find_decoder avcodec_find_decoder_by_name可以很方便的查找指定编解码器
     * 
     * @warning This function is not thread safe!
     * 此函数不是线程安全的!!!
     * @note Always call this function before using decoding routines (such as
     * @ref avcodec_receive_frame()).
     *
     * @code
     * av_dict_set(&opts, "b", "2.5M", 0);
     * codec = avcodec_find_decoder(AV_CODEC_ID_H264);
     * if (!codec)
     *     exit(1);
     *
     * context = avcodec_alloc_context3(codec);
     *
     * if (avcodec_open2(context, codec, opts) < 0)
     *     exit(1);
     * @endcode
     *
     * @param avctx The context to initialize.
     * actx: 要初始化的上下文
     * @param codec The codec to open this context for. If a non-NULL codec has been
     *              previously passed to avcodec_alloc_context3() or
     *              for this context, then this parameter MUST be either NULL or
     *              equal to the previously passed codec.
     * @param options A dictionary filled with AVCodecContext and codec-private options.
     *                On return this object will be filled with options that were not found.
     *
     * @return zero on success, a negative value on error
     * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),
     *      av_dict_set(), av_opt_find().
     */
     int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
    {
        int ret = 0;
        AVCodecInternal *avci;
    
         // 已经初始化过,则直接退出
        if (avcodec_is_open(avctx))
            return 0;
    
        if (!codec && !avctx->codec) {
            av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2()\n");
            return AVERROR(EINVAL);
        }
        if (codec && avctx->codec && codec != avctx->codec) {
            av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, "
                                        "but %s passed to avcodec_open2()\n", avctx->codec->name, codec->name);
            return AVERROR(EINVAL);
        }
        if (!codec)
            codec = avctx->codec;
    
        if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) &&
            avctx->codec_id == AV_CODEC_ID_NONE) {
            avctx->codec_type = codec->type;
            avctx->codec_id   = codec->id;
        }
        if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type &&
                                             avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) {
            av_log(avctx, AV_LOG_ERROR, "Codec type or id mismatches\n");
            return AVERROR(EINVAL);
        }
        avctx->codec = codec;
    
        if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)
            return AVERROR(EINVAL);
    
        lock_avcodec(codec);
    
        avci = av_mallocz(sizeof(*avci));
        if (!avci) {
            ret = AVERROR(ENOMEM);
            goto end;
        }
         
        // 标记已经完成初始化
        avctx->internal = avci;
        
        // 分配缓存空间
        avci->buffer_frame = av_frame_alloc();
        avci->buffer_pkt = av_packet_alloc();
        avci->es.in_frame = av_frame_alloc();
        avci->ds.in_pkt = av_packet_alloc();
        avci->last_pkt_props = av_packet_alloc();
        avci->pkt_props = av_fifo_alloc(sizeof(*avci->last_pkt_props));
        if (!avci->buffer_frame || !avci->buffer_pkt          ||
            !avci->es.in_frame  || !avci->ds.in_pkt           ||
            !avci->last_pkt_props || !avci->pkt_props) {
            ret = AVERROR(ENOMEM);
            goto free_and_end;
        }
    
        avci->skip_samples_multiplier = 1;
    
        if (codec->priv_data_size > 0) {
            if (!avctx->priv_data) {
                avctx->priv_data = av_mallocz(codec->priv_data_size);
                if (!avctx->priv_data) {
                    ret = AVERROR(ENOMEM);
                    goto free_and_end;
                }
                if (codec->priv_class) {
                    *(const AVClass **)avctx->priv_data = codec->priv_class;
                    av_opt_set_defaults(avctx->priv_data);
                }
            }
            if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, options)) < 0)
                goto free_and_end;
        } else {
            avctx->priv_data = NULL;
        }
        if ((ret = av_opt_set_dict(avctx, options)) < 0)
            goto free_and_end;
    
        if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) {
            av_log(avctx, AV_LOG_ERROR, "Codec (%s) not on whitelist \'%s\'\n", codec->name, avctx->codec_whitelist);
            ret = AVERROR(EINVAL);
            goto free_and_end;
        }
    
        // only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensions
        if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height &&
              (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F || avctx->codec_id == AV_CODEC_ID_DXV))) {
            if (avctx->coded_width && avctx->coded_height)
                ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
            else if (avctx->width && avctx->height)
                ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
            if (ret < 0)
                goto free_and_end;
        }
    
        if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height)
            && (  av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0
               || av_image_check_size2(avctx->width,       avctx->height,       avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0)) {
            av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n");
            ff_set_dimensions(avctx, 0, 0);
        }
    
        if (avctx->width > 0 && avctx->height > 0) {
            if (av_image_check_sar(avctx->width, avctx->height,
                                   avctx->sample_aspect_ratio) < 0) {
                av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n",
                       avctx->sample_aspect_ratio.num,
                       avctx->sample_aspect_ratio.den);
                avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
            }
        }
    
        if (avctx->channels > FF_SANE_NB_CHANNELS || avctx->channels < 0) {
            av_log(avctx, AV_LOG_ERROR, "Too many or invalid channels: %d\n", avctx->channels);
            ret = AVERROR(EINVAL);
            goto free_and_end;
        }
    
        if (avctx->sample_rate < 0) {
            av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate);
            ret = AVERROR(EINVAL);
            goto free_and_end;
        }
        if (avctx->block_align < 0) {
            av_log(avctx, AV_LOG_ERROR, "Invalid block align: %d\n", avctx->block_align);
            ret = AVERROR(EINVAL);
            goto free_and_end;
        }
    
        avctx->frame_number = 0;
        avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id);
    
        if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
            avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
            const char *codec_string = av_codec_is_encoder(codec) ? "encoder" : "decoder";
            const AVCodec *codec2;
            av_log(avctx, AV_LOG_ERROR,
                   "The %s '%s' is experimental but experimental codecs are not enabled, "
                   "add '-strict %d' if you want to use it.\n",
                   codec_string, codec->name, FF_COMPLIANCE_EXPERIMENTAL);
            codec2 = av_codec_is_encoder(codec) ? avcodec_find_encoder(codec->id) : avcodec_find_decoder(codec->id);
            if (!(codec2->capabilities & AV_CODEC_CAP_EXPERIMENTAL))
                av_log(avctx, AV_LOG_ERROR, "Alternatively use the non experimental %s '%s'.\n",
                    codec_string, codec2->name);
            ret = AVERROR_EXPERIMENTAL;
            goto free_and_end;
        }
    
        if (avctx->codec_type == AVMEDIA_TYPE_AUDIO &&
            (!avctx->time_base.num || !avctx->time_base.den)) {
            avctx->time_base.num = 1;
            avctx->time_base.den = avctx->sample_rate;
        }
    
        if (av_codec_is_encoder(avctx->codec))
            ret = ff_encode_preinit(avctx);  
        else
            ret = ff_decode_preinit(avctx);
        if (ret < 0)
            goto free_and_end;
    
        if (!HAVE_THREADS)
            av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n");
    
        if (CONFIG_FRAME_THREAD_ENCODER && av_codec_is_encoder(avctx->codec)) {
            unlock_avcodec(codec); //we will instantiate a few encoders thus kick the counter to prevent false detection of a problem
            ret = ff_frame_thread_encoder_init(avctx);
            lock_avcodec(codec);
            if (ret < 0)
                goto free_and_end;
        }
    
        if (HAVE_THREADS
            && !(avci->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME))) {
            ret = ff_thread_init(avctx);
            if (ret < 0) {
                goto free_and_end;
            }
        }
        if (!HAVE_THREADS && !(codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS))
            avctx->thread_count = 1;
    
        if (!(avctx->active_thread_type & FF_THREAD_FRAME) ||
            avci->frame_thread_encoder) {
            if (avctx->codec->init) {
                ret = avctx->codec->init(avctx);
                if (ret < 0) {
                    avci->needs_close = avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP;
                    goto free_and_end;
                }
            }
            avci->needs_close = 1;
        }
    
        ret=0;
    
        if (av_codec_is_decoder(avctx->codec)) {
            if (!avctx->bit_rate)
                avctx->bit_rate = get_bit_rate(avctx);
            /* validate channel layout from the decoder */
            if (avctx->channel_layout) {
                int channels = av_get_channel_layout_nb_channels(avctx->channel_layout);
                if (!avctx->channels)
                    avctx->channels = channels;
                else if (channels != avctx->channels) {
                    char buf[512];
                    av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout);
                    av_log(avctx, AV_LOG_WARNING,
                           "Channel layout '%s' with %d channels does not match specified number of channels %d: "
                           "ignoring specified channel layout\n",
                           buf, channels, avctx->channels);
                    avctx->channel_layout = 0;
                }
            }
            if (avctx->channels && avctx->channels < 0 ||
                avctx->channels > FF_SANE_NB_CHANNELS) {
                ret = AVERROR(EINVAL);
                goto free_and_end;
            }
            if (avctx->bits_per_coded_sample < 0) {
                ret = AVERROR(EINVAL);
                goto free_and_end;
            }
    
    #if FF_API_AVCTX_TIMEBASE
            if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
                avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1}));
    #endif
        }
        if (codec->priv_data_size > 0 && avctx->priv_data && codec->priv_class) {
            av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class);
        }
    
    end:
        unlock_avcodec(codec);
    
        return ret;
    free_and_end:
        avcodec_close(avctx);
        goto end;
    }
    

    本文来自博客园,作者:faithlocus,转载请注明原文链接:https://www.cnblogs.com/faithlocus/p/15701979.html

  • 相关阅读:
    hiho#1445 重复旋律5 求子串数量 后缀自动机
    SPOJ LCS2 后缀自动机
    SPOJ-LCS 后缀自动机
    bzoj 3261 最大异或和 可持久化字典树(01树)
    【洛谷1297】单选错位
    【HAOI2008】木棍分割
    【SDOI2016】排列计数
    【HAOI2008】下落的圆盘
    【HAOI2008】硬币购物
    【洛谷5520】青原樱
  • 原文地址:https://www.cnblogs.com/faithlocus/p/15701979.html
Copyright © 2011-2022 走看看