博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FFMPEG函数try_decode_frame()
阅读量:6079 次
发布时间:2019-06-20

本文共 27978 字,大约阅读时间需要 93 分钟。

hot3.png

FFMPEG版本3.2release,文件位于libavformat/utils.c

函数 try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, AVDictionary **options)主要功能分为三部分

/* returns 1 or 0 if or if not decoded data was returned, or a negative error */static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,                            AVDictionary **options){    AVCodecContext *avctx = st->internal->avctx;    const AVCodec *codec;    int got_picture = 1, ret = 0;    AVFrame *frame = av_frame_alloc();    AVSubtitle subtitle;    AVPacket pkt = *avpkt;    int do_skip_frame = 0;    enum AVDiscard skip_frame;    if (!frame)        return AVERROR(ENOMEM);    if (!avcodec_is_open(avctx) &&        st->info->found_decoder <= 0 &&        (st->codecpar->codec_id != -st->info->found_decoder || !st->codecpar->codec_id)) {        AVDictionary *thread_opt = NULL;        codec = find_probe_decoder(s, st, st->codecpar->codec_id);        if (!codec) {            st->info->found_decoder = -st->codecpar->codec_id;            ret                     = -1;            goto fail;        }        /* Force thread count to 1 since the H.264 decoder will not extract         * SPS and PPS to extradata during multi-threaded decoding. */        av_dict_set(options ? options : &thread_opt, "threads", "1", 0);        if (s->codec_whitelist)            av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0);        ret = avcodec_open2(avctx, codec, options ? options : &thread_opt);        if (!options)            av_dict_free(&thread_opt);        if (ret < 0) {            st->info->found_decoder = -avctx->codec_id;            goto fail;        }        st->info->found_decoder = 1;    } else if (!st->info->found_decoder)        st->info->found_decoder = 1;    if (st->info->found_decoder < 0) {        ret = -1;        goto fail;    }    if (avpriv_codec_get_cap_skip_frame_fill_param(avctx->codec)) {        do_skip_frame = 1;        skip_frame = avctx->skip_frame;        avctx->skip_frame = AVDISCARD_ALL;    }    while ((pkt.size > 0 || (!pkt.data && got_picture)) &&           ret >= 0 &&           (!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||            (!st->codec_info_nb_frames &&             (avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {        got_picture = 0;        if (avctx->codec_type == AVMEDIA_TYPE_VIDEO ||            avctx->codec_type == AVMEDIA_TYPE_AUDIO) {            ret = avcodec_send_packet(avctx, &pkt);            if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)                break;            if (ret >= 0)                pkt.size = 0;            ret = avcodec_receive_frame(avctx, frame);            if (ret >= 0)                got_picture = 1;            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)                ret = 0;        } else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {            ret = avcodec_decode_subtitle2(avctx, &subtitle,                                           &got_picture, &pkt);            if (ret >= 0)                pkt.size = 0;        }        if (ret >= 0) {            if (got_picture)                st->nb_decoded_frames++;            ret       = got_picture;        }    }    if (!pkt.data && !got_picture)        ret = -1;fail:    if (do_skip_frame) {        avctx->skip_frame = skip_frame;    }    av_frame_free(&frame);    return ret;}

 

函数find_probe_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id)

通过codec id得到解码器AVCodec,例如,如果视频为h264,则得到ff_h264_decoder

static const AVCodec *find_probe_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id){    const AVCodec *codec;#if CONFIG_H264_DECODER    /* Other parts of the code assume this decoder to be used for h264,     * so force it if possible. */    if (codec_id == AV_CODEC_ID_H264)        return avcodec_find_decoder_by_name("h264");#endif    codec = find_decoder(s, st, codec_id);    if (!codec)        return NULL;    if (codec->capabilities & AV_CODEC_CAP_AVOID_PROBING) {        const AVCodec *probe_codec = NULL;        while (probe_codec = av_codec_next(probe_codec)) {            if (probe_codec->id == codec_id &&                    av_codec_is_decoder(probe_codec) &&                    !(probe_codec->capabilities & (AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_EXPERIMENTAL))) {                return probe_codec;            }        }    }    return codec;}

 

函数avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)

主要功能为AVCodecContext *avctx->internal结构体指针分配空间,此外执行avctx->codec->init(),其中init函数回调相应解码器的函数,以h264为例,回调函数ff_h264_decode_init(AVCodecContext *avctx)。

通过函数ff_h264_decode_init(AVCodecContext *avctx)得到sps和pps的数据。

int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options){    int ret = 0;    AVDictionary *tmp = NULL;    const AVPixFmtDescriptor *pixdesc;    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->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)        return AVERROR(EINVAL);    if (options)        av_dict_copy(&tmp, *options, 0);    ret = ff_lock_avcodec(avctx, codec);    if (ret < 0)        return ret;    avctx->internal = av_mallocz(sizeof(AVCodecInternal));    if (!avctx->internal) {        ret = AVERROR(ENOMEM);        goto end;    }    avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool));    if (!avctx->internal->pool) {        ret = AVERROR(ENOMEM);        goto free_and_end;    }    avctx->internal->to_free = av_frame_alloc();    if (!avctx->internal->to_free) {        ret = AVERROR(ENOMEM);        goto free_and_end;    }    avctx->internal->buffer_frame = av_frame_alloc();    if (!avctx->internal->buffer_frame) {        ret = AVERROR(ENOMEM);        goto free_and_end;    }    avctx->internal->buffer_pkt = av_packet_alloc();    if (!avctx->internal->buffer_pkt) {        ret = AVERROR(ENOMEM);        goto free_and_end;    }    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 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, &tmp)) < 0)            goto free_and_end;    } else {        avctx->priv_data = NULL;    }    if ((ret = av_opt_set_dict(avctx, &tmp)) < 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_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0           || av_image_check_size(avctx->width,       avctx->height,       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 the decoder init function was already called previously,     * free the already allocated subtitle_header before overwriting it */    if (av_codec_is_decoder(codec))        av_freep(&avctx->subtitle_header);    if (avctx->channels > FF_SANE_NB_CHANNELS) {        ret = AVERROR(EINVAL);        goto free_and_end;    }    avctx->codec = 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");        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";        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 (!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)) {        ff_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, options ? *options : NULL);        ff_lock_avcodec(avctx, codec);        if (ret < 0)            goto free_and_end;    }    if (HAVE_THREADS        && !(avctx->internal->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->capabilities & AV_CODEC_CAP_AUTO_THREADS))        avctx->thread_count = 1;    if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {        av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",               avctx->codec->max_lowres);        avctx->lowres = avctx->codec->max_lowres;    }#if FF_API_VISMV    if (avctx->debug_mv)        av_log(avctx, AV_LOG_WARNING, "The 'vismv' option is deprecated, "               "see the codecview filter instead.\n");#endif    if (av_codec_is_encoder(avctx->codec)) {        int i;#if FF_API_CODED_FRAMEFF_DISABLE_DEPRECATION_WARNINGS        avctx->coded_frame = av_frame_alloc();        if (!avctx->coded_frame) {            ret = AVERROR(ENOMEM);            goto free_and_end;        }FF_ENABLE_DEPRECATION_WARNINGS#endif        if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) {            av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n");            ret = AVERROR(EINVAL);            goto free_and_end;        }        if (avctx->codec->sample_fmts) {            for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {                if (avctx->sample_fmt == avctx->codec->sample_fmts[i])                    break;                if (avctx->channels == 1 &&                    av_get_planar_sample_fmt(avctx->sample_fmt) ==                    av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) {                    avctx->sample_fmt = avctx->codec->sample_fmts[i];                    break;                }            }            if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) {                char buf[128];                snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt);                av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n",                       (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf));                ret = AVERROR(EINVAL);                goto free_and_end;            }        }        if (avctx->codec->pix_fmts) {            for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++)                if (avctx->pix_fmt == avctx->codec->pix_fmts[i])                    break;            if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE                && !((avctx->codec_id == AV_CODEC_ID_MJPEG || avctx->codec_id == AV_CODEC_ID_LJPEG)                     && avctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) {                char buf[128];                snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt);                av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is invalid or not supported\n",                       (char *)av_x_if_null(av_get_pix_fmt_name(avctx->pix_fmt), buf));                ret = AVERROR(EINVAL);                goto free_and_end;            }            if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P ||                avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ411P ||                avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P ||                avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P ||                avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P)                avctx->color_range = AVCOL_RANGE_JPEG;        }        if (avctx->codec->supported_samplerates) {            for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++)                if (avctx->sample_rate == avctx->codec->supported_samplerates[i])                    break;            if (avctx->codec->supported_samplerates[i] == 0) {                av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n",                       avctx->sample_rate);                ret = AVERROR(EINVAL);                goto free_and_end;            }        }        if (avctx->sample_rate < 0) {            av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n",                    avctx->sample_rate);            ret = AVERROR(EINVAL);            goto free_and_end;        }        if (avctx->codec->channel_layouts) {            if (!avctx->channel_layout) {                av_log(avctx, AV_LOG_WARNING, "Channel layout not specified\n");            } else {                for (i = 0; avctx->codec->channel_layouts[i] != 0; i++)                    if (avctx->channel_layout == avctx->codec->channel_layouts[i])                        break;                if (avctx->codec->channel_layouts[i] == 0) {                    char buf[512];                    av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout);                    av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf);                    ret = AVERROR(EINVAL);                    goto free_and_end;                }            }        }        if (avctx->channel_layout && avctx->channels) {            int channels = av_get_channel_layout_nb_channels(avctx->channel_layout);            if (channels != avctx->channels) {                char buf[512];                av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout);                av_log(avctx, AV_LOG_ERROR,                       "Channel layout '%s' with %d channels does not match number of specified channels %d\n",                       buf, channels, avctx->channels);                ret = AVERROR(EINVAL);                goto free_and_end;            }        } else if (avctx->channel_layout) {            avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout);        }        if (avctx->channels < 0) {            av_log(avctx, AV_LOG_ERROR, "Specified number of channels %d is not supported\n",                    avctx->channels);            ret = AVERROR(EINVAL);            goto free_and_end;        }        if(avctx->codec_type == AVMEDIA_TYPE_VIDEO) {            pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt);            if (    avctx->bits_per_raw_sample < 0                || (avctx->bits_per_raw_sample > 8 && pixdesc->comp[0].depth <= 8)) {                av_log(avctx, AV_LOG_WARNING, "Specified bit depth %d not possible with the specified pixel formats depth %d\n",                    avctx->bits_per_raw_sample, pixdesc->comp[0].depth);                avctx->bits_per_raw_sample = pixdesc->comp[0].depth;            }            if (avctx->width <= 0 || avctx->height <= 0) {                av_log(avctx, AV_LOG_ERROR, "dimensions not set\n");                ret = AVERROR(EINVAL);                goto free_and_end;            }        }        if (   (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO)            && avctx->bit_rate>0 && avctx->bit_rate<1000) {            av_log(avctx, AV_LOG_WARNING, "Bitrate %"PRId64" is extremely low, maybe you mean %"PRId64"k\n", (int64_t)avctx->bit_rate, (int64_t)avctx->bit_rate);        }        if (!avctx->rc_initial_buffer_occupancy)            avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3 / 4;        if (avctx->ticks_per_frame && avctx->time_base.num &&            avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) {            av_log(avctx, AV_LOG_ERROR,                   "ticks_per_frame %d too large for the timebase %d/%d.",                   avctx->ticks_per_frame,                   avctx->time_base.num,                   avctx->time_base.den);            goto free_and_end;        }        if (avctx->hw_frames_ctx) {            AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;            if (frames_ctx->format != avctx->pix_fmt) {                av_log(avctx, AV_LOG_ERROR,                       "Mismatching AVCodecContext.pix_fmt and AVHWFramesContext.format\n");                ret = AVERROR(EINVAL);                goto free_and_end;            }        }    }    avctx->pts_correction_num_faulty_pts =    avctx->pts_correction_num_faulty_dts = 0;    avctx->pts_correction_last_pts =    avctx->pts_correction_last_dts = INT64_MIN;    if (   !CONFIG_GRAY && avctx->flags & AV_CODEC_FLAG_GRAY        && avctx->codec_descriptor->type == AVMEDIA_TYPE_VIDEO)        av_log(avctx, AV_LOG_WARNING,               "gray decoding requested but not enabled at configuration time\n");    if (   avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME)        || avctx->internal->frame_thread_encoder)) {        ret = avctx->codec->init(avctx);        if (ret < 0) {            goto free_and_end;        }    }    ret=0;#if FF_API_AUDIOENC_DELAY    if (av_codec_is_encoder(avctx->codec))        avctx->delay = avctx->initial_padding;#endif    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->sub_charenc) {            if (avctx->codec_type != AVMEDIA_TYPE_SUBTITLE) {                av_log(avctx, AV_LOG_ERROR, "Character encoding is only "                       "supported with subtitles codecs\n");                ret = AVERROR(EINVAL);                goto free_and_end;            } else if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) {                av_log(avctx, AV_LOG_WARNING, "Codec '%s' is bitmap-based, "                       "subtitles character encoding will be ignored\n",                       avctx->codec_descriptor->name);                avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_DO_NOTHING;            } else {                /* input character encoding is set for a text based subtitle                 * codec at this point */                if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_AUTOMATIC)                    avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_PRE_DECODER;                if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_PRE_DECODER) {#if CONFIG_ICONV                    iconv_t cd = iconv_open("UTF-8", avctx->sub_charenc);                    if (cd == (iconv_t)-1) {                        ret = AVERROR(errno);                        av_log(avctx, AV_LOG_ERROR, "Unable to open iconv context "                               "with input character encoding \"%s\"\n", avctx->sub_charenc);                        goto free_and_end;                    }                    iconv_close(cd);#else                    av_log(avctx, AV_LOG_ERROR, "Character encoding subtitles "                           "conversion needs a libavcodec built with iconv support "                           "for this codec\n");                    ret = AVERROR(ENOSYS);                    goto free_and_end;#endif                }            }        }#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:    ff_unlock_avcodec(codec);    if (options) {        av_dict_free(options);        *options = tmp;    }    return ret;free_and_end:    if (avctx->codec &&        (avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP))        avctx->codec->close(avctx);    if (codec->priv_class && codec->priv_data_size)        av_opt_free(avctx->priv_data);    av_opt_free(avctx);#if FF_API_CODED_FRAMEFF_DISABLE_DEPRECATION_WARNINGS    av_frame_free(&avctx->coded_frame);FF_ENABLE_DEPRECATION_WARNINGS#endif    av_dict_free(&tmp);    av_freep(&avctx->priv_data);    if (avctx->internal) {        av_packet_free(&avctx->internal->buffer_pkt);        av_frame_free(&avctx->internal->buffer_frame);        av_frame_free(&avctx->internal->to_free);        av_freep(&avctx->internal->pool);    }    av_freep(&avctx->internal);    avctx->codec = NULL;    goto end;}

 

函数avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)

主要作用为调用do_decode(AVCodecContext *avctx, AVPacket *pkt),解码一帧数据。

int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt){    int ret;    if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))        return AVERROR(EINVAL);    if (avctx->internal->draining)        return AVERROR_EOF;    if (avpkt && !avpkt->size && avpkt->data)        return AVERROR(EINVAL);    if (!avpkt || !avpkt->size) {        avctx->internal->draining = 1;        avpkt = NULL;        if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))            return 0;    }    if (avctx->codec->send_packet) {        if (avpkt) {            AVPacket tmp = *avpkt;            int did_split = av_packet_split_side_data(&tmp);            ret = apply_param_change(avctx, &tmp);            if (ret >= 0)                ret = avctx->codec->send_packet(avctx, &tmp);            if (did_split)                av_packet_free_side_data(&tmp);            return ret;        } else {            return avctx->codec->send_packet(avctx, NULL);        }    }    // Emulation via old API. Assume avpkt is likely not refcounted, while    // decoder output is always refcounted, and avoid copying.    if (avctx->internal->buffer_pkt->size || avctx->internal->buffer_frame->buf[0])        return AVERROR(EAGAIN);    // The goal is decoding the first frame of the packet without using memcpy,    // because the common case is having only 1 frame per packet (especially    // with video, but audio too). In other cases, it can't be avoided, unless    // the user is feeding refcounted packets.    return do_decode(avctx, (AVPacket *)avpkt);}

 

函数do_decode(AVCodecContext *avctx, AVPacket *pkt)

static int do_decode(AVCodecContext *avctx, AVPacket *pkt){    int got_frame;    int ret;    av_assert0(!avctx->internal->buffer_frame->buf[0]);    if (!pkt)        pkt = avctx->internal->buffer_pkt;    // This is the lesser evil. The field is for compatibility with legacy users    // of the legacy API, and users using the new API should not be forced to    // even know about this field.    avctx->refcounted_frames = 1;    // Some codecs (at least wma lossless) will crash when feeding drain packets    // after EOF was signaled.    if (avctx->internal->draining_done)        return AVERROR_EOF;    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {        ret = avcodec_decode_video2(avctx, avctx->internal->buffer_frame,                                    &got_frame, pkt);        if (ret >= 0)            ret = pkt->size;    } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {        ret = avcodec_decode_audio4(avctx, avctx->internal->buffer_frame,                                    &got_frame, pkt);    } else {        ret = AVERROR(EINVAL);    }    if (ret == AVERROR(EAGAIN))        ret = pkt->size;    if (ret < 0)        return ret;    if (avctx->internal->draining && !got_frame)        avctx->internal->draining_done = 1;    if (ret >= pkt->size) {        av_packet_unref(avctx->internal->buffer_pkt);    } else {        int consumed = ret;        if (pkt != avctx->internal->buffer_pkt) {            av_packet_unref(avctx->internal->buffer_pkt);            if ((ret = av_packet_ref(avctx->internal->buffer_pkt, pkt)) < 0)                return ret;        }        avctx->internal->buffer_pkt->data += consumed;        avctx->internal->buffer_pkt->size -= consumed;        avctx->internal->buffer_pkt->pts   = AV_NOPTS_VALUE;        avctx->internal->buffer_pkt->dts   = AV_NOPTS_VALUE;    }    if (got_frame)        av_assert0(avctx->internal->buffer_frame->buf[0]);    return 0;}

 

总结:

try_decode_frame()函数主要作用为选择解码器,并解码一帧数据。

转载于:https://my.oschina.net/u/2326611/blog/809200

你可能感兴趣的文章
css知多少(8)——float上篇
查看>>
NLB网路负载均衡管理器详解
查看>>
水平添加滚动条
查看>>
PHP中”单例模式“实例讲解
查看>>
VS2008查看dll导出函数
查看>>
VM EBS R12迁移,启动APTier . AutoConfig错误
查看>>
atitit.细节决定成败的适合情形与缺点
查看>>
iOS - Library 库
查看>>
MATLAB 读取DICOM格式文件
查看>>
spring事务管理(Transaction)
查看>>
django.contrib.auth登陆注销学习
查看>>
js执行本地exe文件的3种方法
查看>>
理解B树索引
查看>>
vi编辑器的命令集合
查看>>
Mysql利用binlog恢复数据
查看>>
解决 Windows启动时要求验证
查看>>
我的友情链接
查看>>
用yum安装mariadb
查看>>
一点IT"边缘化"的人的思考
查看>>
Gallery循环滑动
查看>>