X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffplay.c;h=c0b326c8ccc95ec041157512fa8724fbc1b0d234;hb=516c213f089d797cbe98648c5bf957ae30ced162;hp=cf138dc51513eaba4f8392ba3e2288e4ddb64c14;hpb=8c71d1b06028b1de2558647f7db7421d1c6e9bee;p=ffmpeg diff --git a/ffplay.c b/ffplay.c index cf138dc5151..c0b326c8ccc 100644 --- a/ffplay.c +++ b/ffplay.c @@ -187,7 +187,6 @@ enum { typedef struct Decoder { AVPacket pkt; - AVPacket pkt_temp; PacketQueue *queue; AVCodecContext *avctx; int pkt_serial; @@ -551,88 +550,96 @@ static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, 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) { @@ -1974,11 +1981,11 @@ static int audio_thread(void *arg) 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; @@ -1990,10 +1997,10 @@ static int audio_thread(void *arg) 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; @@ -2012,7 +2019,7 @@ static int audio_thread(void *arg) 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}); @@ -2139,7 +2146,7 @@ static int video_thread(void *arg) #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 } @@ -2283,13 +2290,13 @@ static int audio_decode_frame(VideoState *is) 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 || @@ -2304,13 +2311,13 @@ static int audio_decode_frame(VideoState *is) 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; } @@ -3505,7 +3512,7 @@ static int opt_codec(void *optctx, const char *opt, const char *arg) static int dummy; static const OptionDef options[] = { -#include "cmdutils_common_opts.h" + CMDUTILS_COMMON_OPTIONS { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" }, { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" }, { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },