diff options
-rw-r--r-- | ffplay.c | 101 |
1 files changed, 54 insertions, 47 deletions
@@ -187,7 +187,6 @@ enum { typedef struct Decoder { AVPacket pkt; - AVPacket pkt_temp; PacketQueue *queue; AVCodecContext *avctx; int pkt_serial; @@ -551,40 +550,24 @@ 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; + int ret = AVERROR(EAGAIN); - do { - int ret = -1; + for (;;) { + AVPacket pkt; + if (d->queue->serial == d->pkt_serial) { + do { if (d->queue->abort_request) return -1; - if (!d->packet_pending || d->queue->serial != d->pkt_serial) { - AVPacket pkt; - 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) - 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) { + ret = avcodec_receive_frame(d->avctx, frame); + if (ret >= 0) { if (decoder_reorder_pts == -1) { frame->pts = av_frame_get_best_effort_timestamp(frame); } else if (!decoder_reorder_pts) { @@ -593,8 +576,8 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { } break; case AVMEDIA_TYPE_AUDIO: - ret = avcodec_decode_audio4(d->avctx, frame, &got_frame, &d->pkt_temp); - if (got_frame) { + 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); @@ -606,33 +589,57 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { } } break; - case AVMEDIA_TYPE_SUBTITLE: - ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &d->pkt_temp); - break; + } + if (ret == AVERROR_EOF) { + d->finished = d->pkt_serial; + avcodec_flush_buffers(d->avctx); + return 0; + } + 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) { |