typedef struct Decoder {
AVPacket pkt;
- AVPacket pkt_temp;
PacketQueue *queue;
AVCodecContext *avctx;
int pkt_serial;
d->queue = queue;
d->empty_queue_cond = empty_queue_cond;
d->start_pts = AV_NOPTS_VALUE;
+ d->pkt_serial = -1;
}
static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
- int got_frame = 0;
-
- do {
- int ret = -1;
+ int ret = AVERROR(EAGAIN);
- if (d->queue->abort_request)
- return -1;
+ for (;;) {
+ AVPacket pkt;
- if (!d->packet_pending || d->queue->serial != d->pkt_serial) {
- AVPacket pkt;
+ if (d->queue->serial == d->pkt_serial) {
do {
- if (d->queue->nb_packets == 0)
- SDL_CondSignal(d->empty_queue_cond);
- if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
+ if (d->queue->abort_request)
return -1;
- if (pkt.data == flush_pkt.data) {
- avcodec_flush_buffers(d->avctx);
- d->finished = 0;
- d->next_pts = d->start_pts;
- d->next_pts_tb = d->start_pts_tb;
- }
- } while (pkt.data == flush_pkt.data || d->queue->serial != d->pkt_serial);
- av_packet_unref(&d->pkt);
- d->pkt_temp = d->pkt = pkt;
- d->packet_pending = 1;
- }
- switch (d->avctx->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- ret = avcodec_decode_video2(d->avctx, frame, &got_frame, &d->pkt_temp);
- if (got_frame) {
- if (decoder_reorder_pts == -1) {
- frame->pts = av_frame_get_best_effort_timestamp(frame);
- } else if (!decoder_reorder_pts) {
- frame->pts = frame->pkt_dts;
- }
+ switch (d->avctx->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ ret = avcodec_receive_frame(d->avctx, frame);
+ if (ret >= 0) {
+ if (decoder_reorder_pts == -1) {
+ frame->pts = frame->best_effort_timestamp;
+ } else if (!decoder_reorder_pts) {
+ frame->pts = frame->pkt_dts;
+ }
+ }
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ ret = avcodec_receive_frame(d->avctx, frame);
+ if (ret >= 0) {
+ AVRational tb = (AVRational){1, frame->sample_rate};
+ if (frame->pts != AV_NOPTS_VALUE)
+ frame->pts = av_rescale_q(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb);
+ else if (d->next_pts != AV_NOPTS_VALUE)
+ frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
+ if (frame->pts != AV_NOPTS_VALUE) {
+ d->next_pts = frame->pts + frame->nb_samples;
+ d->next_pts_tb = tb;
+ }
+ }
+ break;
}
- break;
- case AVMEDIA_TYPE_AUDIO:
- ret = avcodec_decode_audio4(d->avctx, frame, &got_frame, &d->pkt_temp);
- if (got_frame) {
- AVRational tb = (AVRational){1, frame->sample_rate};
- if (frame->pts != AV_NOPTS_VALUE)
- frame->pts = av_rescale_q(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb);
- else if (d->next_pts != AV_NOPTS_VALUE)
- frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
- if (frame->pts != AV_NOPTS_VALUE) {
- d->next_pts = frame->pts + frame->nb_samples;
- d->next_pts_tb = tb;
- }
+ if (ret == AVERROR_EOF) {
+ d->finished = d->pkt_serial;
+ avcodec_flush_buffers(d->avctx);
+ return 0;
}
- break;
- case AVMEDIA_TYPE_SUBTITLE:
- ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &d->pkt_temp);
- break;
+ if (ret >= 0)
+ return 1;
+ } while (ret != AVERROR(EAGAIN));
}
- if (ret < 0) {
- d->packet_pending = 0;
+ do {
+ if (d->queue->nb_packets == 0)
+ SDL_CondSignal(d->empty_queue_cond);
+ if (d->packet_pending) {
+ av_packet_move_ref(&pkt, &d->pkt);
+ d->packet_pending = 0;
+ } else {
+ if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0)
+ return -1;
+ }
+ } while (d->queue->serial != d->pkt_serial);
+
+ if (pkt.data == flush_pkt.data) {
+ avcodec_flush_buffers(d->avctx);
+ d->finished = 0;
+ d->next_pts = d->start_pts;
+ d->next_pts_tb = d->start_pts_tb;
} else {
- d->pkt_temp.dts =
- d->pkt_temp.pts = AV_NOPTS_VALUE;
- if (d->pkt_temp.data) {
- if (d->avctx->codec_type != AVMEDIA_TYPE_AUDIO)
- ret = d->pkt_temp.size;
- d->pkt_temp.data += ret;
- d->pkt_temp.size -= ret;
- if (d->pkt_temp.size <= 0)
- d->packet_pending = 0;
+ if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ int got_frame = 0;
+ ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &pkt);
+ if (ret < 0) {
+ ret = AVERROR(EAGAIN);
+ } else {
+ if (got_frame && !pkt.data) {
+ d->packet_pending = 1;
+ av_packet_move_ref(&d->pkt, &pkt);
+ }
+ ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVERROR_EOF);
+ }
} else {
- if (!got_frame) {
- d->packet_pending = 0;
- d->finished = d->pkt_serial;
+ if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) {
+ av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
+ d->packet_pending = 1;
+ av_packet_move_ref(&d->pkt, &pkt);
}
}
+ av_packet_unref(&pkt);
}
- } while (!got_frame && !d->finished);
-
- return got_frame;
+ }
}
static void decoder_destroy(Decoder *d) {
tb = (AVRational){1, frame->sample_rate};
#if CONFIG_AVFILTER
- dec_channel_layout = get_valid_channel_layout(frame->channel_layout, av_frame_get_channels(frame));
+ dec_channel_layout = get_valid_channel_layout(frame->channel_layout, frame->channels);
reconfigure =
cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
- frame->format, av_frame_get_channels(frame)) ||
+ frame->format, frame->channels) ||
is->audio_filter_src.channel_layout != dec_channel_layout ||
is->audio_filter_src.freq != frame->sample_rate ||
is->auddec.pkt_serial != last_serial;
av_log(NULL, AV_LOG_DEBUG,
"Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
- frame->sample_rate, av_frame_get_channels(frame), av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
+ frame->sample_rate, frame->channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
is->audio_filter_src.fmt = frame->format;
- is->audio_filter_src.channels = av_frame_get_channels(frame);
+ is->audio_filter_src.channels = frame->channels;
is->audio_filter_src.channel_layout = dec_channel_layout;
is->audio_filter_src.freq = frame->sample_rate;
last_serial = is->auddec.pkt_serial;
goto the_end;
af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
- af->pos = av_frame_get_pkt_pos(frame);
+ af->pos = frame->pkt_pos;
af->serial = is->auddec.pkt_serial;
af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
#endif
duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
- ret = queue_picture(is, frame, pts, duration, av_frame_get_pkt_pos(frame), is->viddec.pkt_serial);
+ ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
av_frame_unref(frame);
#if CONFIG_AVFILTER
}
frame_queue_next(&is->sampq);
} while (af->serial != is->audioq.serial);
- data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(af->frame),
+ data_size = av_samples_get_buffer_size(NULL, af->frame->channels,
af->frame->nb_samples,
af->frame->format, 1);
dec_channel_layout =
- (af->frame->channel_layout && av_frame_get_channels(af->frame) == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
- af->frame->channel_layout : av_get_default_channel_layout(av_frame_get_channels(af->frame));
+ (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
+ af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels);
wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
if (af->frame->format != is->audio_src.fmt ||
if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
av_log(NULL, AV_LOG_ERROR,
"Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
- af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), av_frame_get_channels(af->frame),
+ af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->channels,
is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
swr_free(&is->swr_ctx);
return -1;
}
is->audio_src.channel_layout = dec_channel_layout;
- is->audio_src.channels = av_frame_get_channels(af->frame);
+ is->audio_src.channels = af->frame->channels;
is->audio_src.freq = af->frame->sample_rate;
is->audio_src.fmt = af->frame->format;
}