[FFmpeg-devel] [PATCH 2/3] ffplay: convert to new decode API
wallak at free.fr
wallak at free.fr
Fri Mar 17 17:25:20 EET 2017
I tried the patch. Once av_assert0 test is removed, the crystalhd decoder is running till send_packet triggers AVERROR(EAGAIN), now the crystalhd buffer is likely overflowed, the video freezes. A few seconds later the decoder displays a few frames and the cycle goes on.
Im not sure how to properly implement the function to stop or resend send_packet frames, this is likely the only mechanism missing.
Best Regards,
Wallak.
----- Mail original -----
De: "Marton Balint" <cus at passwd.hu>
À: "FFmpeg development discussions and patches" <ffmpeg-devel at ffmpeg.org>
Cc: wallak at free.fr
Envoyé: Jeudi 16 Mars 2017 23:25:18
Objet: Re: [FFmpeg-devel] [PATCH 2/3] ffplay: convert to new decode API
On Wed, 15 Mar 2017, Marton Balint wrote:
> Since subtitles are not yet supported with the new API, CODEC_CAP_DELAY
> subtitle codecs (only libzvbi so far) may loose the last few buffered frames in
> the end of the stream.
>
> The impact of this is so limited, it seemded better to accept it than losing
> the simplification benefits of the new API.
Hi Wallak,
Have you had a chance to test this ffplay patch, and see if it fixes
CrystalHD decoding in ffplay or not?
Thanks,
Marton
>
> Signed-off-by: Marton Balint <cus at passwd.hu>
> ---
> ffplay.c | 92 +++++++++++++++++++++++++++++-----------------------------------
> 1 file changed, 41 insertions(+), 51 deletions(-)
>
> diff --git a/ffplay.c b/ffplay.c
> index cf138dc..06d1d22 100644
> --- a/ffplay.c
> +++ b/ffplay.c
> @@ -186,13 +186,10 @@ enum {
> };
>
> typedef struct Decoder {
> - AVPacket pkt;
> - AVPacket pkt_temp;
> PacketQueue *queue;
> AVCodecContext *avctx;
> int pkt_serial;
> int finished;
> - int packet_pending;
> SDL_cond *empty_queue_cond;
> int64_t start_pts;
> AVRational start_pts_tb;
> @@ -551,40 +548,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 +574,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,37 +587,46 @@ 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 (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
> + ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVERROR_EOF);
> } else {
> - if (!got_frame) {
> - d->packet_pending = 0;
> - d->finished = d->pkt_serial;
> - }
> + av_assert0(avcodec_send_packet(d->avctx, &pkt) != AVERROR(EAGAIN));
> }
> + av_packet_unref(&pkt);
> }
> - } while (!got_frame && !d->finished);
> -
> - return got_frame;
> + }
> }
>
> static void decoder_destroy(Decoder *d) {
> - av_packet_unref(&d->pkt);
> avcodec_free_context(&d->avctx);
> }
>
> --
> 2.10.2
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
More information about the ffmpeg-devel
mailing list