diff mbox

[FFmpeg-devel] doc/examples/filtering_video: switch to new decoding API

Message ID CAOmVQXGQUm7kKnD5fcE=6U8NsuBcuiGD-3zCSh+YAxK9tR1k4A@mail.gmail.com
State Accepted
Headers show

Commit Message

Matthieu Bouron March 30, 2017, 11:35 a.m. UTC
On Wed, Mar 29, 2017 at 3:37 PM, wm4 <nfxjfg@googlemail.com> wrote:

> On Wed, 29 Mar 2017 15:03:55 +0200
> Matthieu Bouron <matthieu.bouron@gmail.com> wrote:
>
> > ---
> >  doc/examples/filtering_video.c | 32 ++++++++++++++++++++++++++------
> >  1 file changed, 26 insertions(+), 6 deletions(-)
> >
> > diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_
> video.c
> > index 15116d3881..b664c69f9d 100644
> > --- a/doc/examples/filtering_video.c
> > +++ b/doc/examples/filtering_video.c
> > @@ -211,6 +211,7 @@ int main(int argc, char **argv)
> >  {
> >      int ret;
> >      AVPacket packet;
> > +    int keep_packet = 0;
> >      AVFrame *frame = av_frame_alloc();
> >      AVFrame *filt_frame = av_frame_alloc();
> >      int got_frame;
> > @@ -234,14 +235,30 @@ int main(int argc, char **argv)
> >
> >      /* read all packets */
> >      while (1) {
> > -        if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)
> > -            break;
> > +        if (!keep_packet) {
> > +            if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)
> > +                break;
> > +            keep_packet = 1;
> > +        }
> >
> >          if (packet.stream_index == video_stream_index) {
> >              got_frame = 0;
> > -            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame,
> &packet);
> > -            if (ret < 0) {
> > -                av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");
> > +
> > +            ret = avcodec_send_packet(dec_ctx, &packet);
> > +            if (ret >= 0) {
> > +                keep_packet = 0;
> > +            } else if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
>
> If you have packets after the decoder entered the EOF state, you
> probably want to discard them. Either that, or reset the decoder after
> it's flushed and start over. Anyway, normally this shouldn't happen.
>
> You could also avoid the keep_packet business by running receive_frame
> in a loop after send_packet (then send_packet can never fail with
> EAGAIN).
>
> > +                av_log(NULL, AV_LOG_ERROR, "Error while sending a
> packet to the decoder\n");
> > +                break;
> > +            }
> > +
> > +            ret = avcodec_receive_frame(dec_ctx, frame);
> > +            if (ret >= 0) {
> > +                got_frame = 1;
> > +            } else if (ret == AVERROR_EOF) {
> > +                break;
> > +            } else if (ret != AVERROR(EAGAIN)) {
> > +                av_log(NULL, AV_LOG_ERROR, "Error while receiving a
> frame from the decoder\n");
> >                  break;
> >              }
> >
> > @@ -266,8 +283,11 @@ int main(int argc, char **argv)
> >                  }
> >                  av_frame_unref(frame);
> >              }
> > +        } else {
> > +            keep_packet = 0;
> >          }
> > -        av_packet_unref(&packet);
> > +        if (!keep_packet)
> > +           av_packet_unref(&packet);
> >      }
> >  end:
> >      avfilter_graph_free(&filter_graph);
>
> Otherwise should work.
>

New patch attached (removing the keep_packet logic).

Comments

wm4 March 30, 2017, 12:23 p.m. UTC | #1
On Thu, 30 Mar 2017 13:35:47 +0200
Matthieu Bouron <matthieu.bouron@gmail.com> wrote:

> From e9e5b3e679a12fdd9495c53177ade51c3dee7ba2 Mon Sep 17 00:00:00 2001
> From: Matthieu Bouron <matthieu.bouron@gmail.com>
> Date: Wed, 29 Mar 2017 14:58:01 +0200
> Subject: [PATCH] doc/examples/filtering_video: switch to new decoding API
> 
> ---
>  doc/examples/filtering_video.c | 46 +++++++++++++++++++++++++-----------------
>  1 file changed, 27 insertions(+), 19 deletions(-)
> 
> diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c
> index 15116d3881..4d973024f1 100644
> --- a/doc/examples/filtering_video.c
> +++ b/doc/examples/filtering_video.c
> @@ -213,7 +213,6 @@ int main(int argc, char **argv)
>      AVPacket packet;
>      AVFrame *frame = av_frame_alloc();
>      AVFrame *filt_frame = av_frame_alloc();
> -    int got_frame;
>  
>      if (!frame || !filt_frame) {
>          perror("Could not allocate frame");
> @@ -238,33 +237,42 @@ int main(int argc, char **argv)
>              break;
>  
>          if (packet.stream_index == video_stream_index) {
> -            got_frame = 0;
> -            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet);
> +            ret = avcodec_send_packet(dec_ctx, &packet);

I assume the "flush" packet makes it to this code as well...

>              if (ret < 0) {
> -                av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");
> +                av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");
>                  break;
>              }
>  
> -            if (got_frame) {
> -                frame->pts = av_frame_get_best_effort_timestamp(frame);
> -
> -                /* push the decoded frame into the filtergraph */
> -                if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
> -                    av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
> +            while (ret >= 0) {
> +                ret = avcodec_receive_frame(dec_ctx, frame);
> +                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
>                      break;

On EOF this assumes the demuxer takes care of it, and if the demuxer is
unexpectedly not EOF, the send call will error. So LGTM.

> +                } else if (ret < 0) {
> +                    av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");
> +                    goto end;
>                  }
>  
> -                /* pull filtered frames from the filtergraph */
> -                while (1) {
> -                    ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
> -                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
> +                if (ret >= 0) {
> +                    frame->pts = av_frame_get_best_effort_timestamp(frame);
> +
> +                    /* push the decoded frame into the filtergraph */
> +                    if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
> +                        av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
>                          break;
> -                    if (ret < 0)
> -                        goto end;
> -                    display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
> -                    av_frame_unref(filt_frame);
> +                    }
> +
> +                    /* pull filtered frames from the filtergraph */
> +                    while (1) {
> +                        ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
> +                        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
> +                            break;
> +                        if (ret < 0)
> +                            goto end;
> +                        display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
> +                        av_frame_unref(filt_frame);
> +                    }
> +                    av_frame_unref(frame);
>                  }
> -                av_frame_unref(frame);
>              }
>          }
>          av_packet_unref(&packet);

LGTM.
Matthieu Bouron March 30, 2017, 1:23 p.m. UTC | #2
On Thu, Mar 30, 2017 at 02:23:11PM +0200, wm4 wrote:
> On Thu, 30 Mar 2017 13:35:47 +0200
> Matthieu Bouron <matthieu.bouron@gmail.com> wrote:
> 
> > From e9e5b3e679a12fdd9495c53177ade51c3dee7ba2 Mon Sep 17 00:00:00 2001
> > From: Matthieu Bouron <matthieu.bouron@gmail.com>
> > Date: Wed, 29 Mar 2017 14:58:01 +0200
> > Subject: [PATCH] doc/examples/filtering_video: switch to new decoding API
> > 
> > ---
> >  doc/examples/filtering_video.c | 46 +++++++++++++++++++++++++-----------------
> >  1 file changed, 27 insertions(+), 19 deletions(-)
> > 
> > diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c
> > index 15116d3881..4d973024f1 100644
> > --- a/doc/examples/filtering_video.c
> > +++ b/doc/examples/filtering_video.c
> > @@ -213,7 +213,6 @@ int main(int argc, char **argv)
> >      AVPacket packet;
> >      AVFrame *frame = av_frame_alloc();
> >      AVFrame *filt_frame = av_frame_alloc();
> > -    int got_frame;
> >  
> >      if (!frame || !filt_frame) {
> >          perror("Could not allocate frame");
> > @@ -238,33 +237,42 @@ int main(int argc, char **argv)
> >              break;
> >  
> >          if (packet.stream_index == video_stream_index) {
> > -            got_frame = 0;
> > -            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet);
> > +            ret = avcodec_send_packet(dec_ctx, &packet);
> 
> I assume the "flush" packet makes it to this code as well...
> 
> >              if (ret < 0) {
> > -                av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");
> > +                av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");
> >                  break;
> >              }
> >  
> > -            if (got_frame) {
> > -                frame->pts = av_frame_get_best_effort_timestamp(frame);
> > -
> > -                /* push the decoded frame into the filtergraph */
> > -                if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
> > -                    av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
> > +            while (ret >= 0) {
> > +                ret = avcodec_receive_frame(dec_ctx, frame);
> > +                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
> >                      break;
> 
> On EOF this assumes the demuxer takes care of it, and if the demuxer is
> unexpectedly not EOF, the send call will error. So LGTM.
> 
> > +                } else if (ret < 0) {
> > +                    av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");
> > +                    goto end;
> >                  }
> >  
> > -                /* pull filtered frames from the filtergraph */
> > -                while (1) {
> > -                    ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
> > -                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
> > +                if (ret >= 0) {
> > +                    frame->pts = av_frame_get_best_effort_timestamp(frame);
> > +
> > +                    /* push the decoded frame into the filtergraph */
> > +                    if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
> > +                        av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
> >                          break;
> > -                    if (ret < 0)
> > -                        goto end;
> > -                    display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
> > -                    av_frame_unref(filt_frame);
> > +                    }
> > +
> > +                    /* pull filtered frames from the filtergraph */
> > +                    while (1) {
> > +                        ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
> > +                        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
> > +                            break;
> > +                        if (ret < 0)
> > +                            goto end;
> > +                        display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
> > +                        av_frame_unref(filt_frame);
> > +                    }
> > +                    av_frame_unref(frame);
> >                  }
> > -                av_frame_unref(frame);
> >              }
> >          }
> >          av_packet_unref(&packet);
> 
> LGTM.

Patch applied.

> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
diff mbox

Patch

From e9e5b3e679a12fdd9495c53177ade51c3dee7ba2 Mon Sep 17 00:00:00 2001
From: Matthieu Bouron <matthieu.bouron@gmail.com>
Date: Wed, 29 Mar 2017 14:58:01 +0200
Subject: [PATCH] doc/examples/filtering_video: switch to new decoding API

---
 doc/examples/filtering_video.c | 46 +++++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/doc/examples/filtering_video.c b/doc/examples/filtering_video.c
index 15116d3881..4d973024f1 100644
--- a/doc/examples/filtering_video.c
+++ b/doc/examples/filtering_video.c
@@ -213,7 +213,6 @@  int main(int argc, char **argv)
     AVPacket packet;
     AVFrame *frame = av_frame_alloc();
     AVFrame *filt_frame = av_frame_alloc();
-    int got_frame;
 
     if (!frame || !filt_frame) {
         perror("Could not allocate frame");
@@ -238,33 +237,42 @@  int main(int argc, char **argv)
             break;
 
         if (packet.stream_index == video_stream_index) {
-            got_frame = 0;
-            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet);
+            ret = avcodec_send_packet(dec_ctx, &packet);
             if (ret < 0) {
-                av_log(NULL, AV_LOG_ERROR, "Error decoding video\n");
+                av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");
                 break;
             }
 
-            if (got_frame) {
-                frame->pts = av_frame_get_best_effort_timestamp(frame);
-
-                /* push the decoded frame into the filtergraph */
-                if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
-                    av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
+            while (ret >= 0) {
+                ret = avcodec_receive_frame(dec_ctx, frame);
+                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                     break;
+                } else if (ret < 0) {
+                    av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");
+                    goto end;
                 }
 
-                /* pull filtered frames from the filtergraph */
-                while (1) {
-                    ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
-                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+                if (ret >= 0) {
+                    frame->pts = av_frame_get_best_effort_timestamp(frame);
+
+                    /* push the decoded frame into the filtergraph */
+                    if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
+                        av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
                         break;
-                    if (ret < 0)
-                        goto end;
-                    display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
-                    av_frame_unref(filt_frame);
+                    }
+
+                    /* pull filtered frames from the filtergraph */
+                    while (1) {
+                        ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
+                        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+                            break;
+                        if (ret < 0)
+                            goto end;
+                        display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base);
+                        av_frame_unref(filt_frame);
+                    }
+                    av_frame_unref(frame);
                 }
-                av_frame_unref(frame);
             }
         }
         av_packet_unref(&packet);
-- 
2.12.0