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()函数主要作用为选择解码器,并解码一帧数据。