[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