diff mbox

[FFmpeg-devel] ffprobe: port to new decode API

Message ID 20170330150536.13390-1-nfxjfg@googlemail.com
State Accepted
Commit 2a88ebd096f3c748a2d99ed1b60b22879b3c567c
Headers show

Commit Message

wm4 March 30, 2017, 3:05 p.m. UTC
Not sure if it behaves ideally in presence of decoding errors.
---
The original version of this patch is actually 1 year old.
---
 ffprobe.c | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

Comments

Michael Niedermayer March 31, 2017, 1:49 a.m. UTC | #1
On Thu, Mar 30, 2017 at 05:05:36PM +0200, wm4 wrote:
> Not sure if it behaves ideally in presence of decoding errors.
> ---
> The original version of this patch is actually 1 year old.
> ---
>  ffprobe.c | 42 +++++++++++++++++++++++++++++-------------
>  1 file changed, 29 insertions(+), 13 deletions(-)

changes:
http://samples.mplayerhq.hu/A-codecs/WMA/wav/FLCL_Ending_My.wav
./ffprobe -v 0 -show_frames -of compact=nk=1:p=0 ~/tickets/1905/FLCL_Ending_My.wav

after the patch there are alot of "N/A" in the output where numbers
where before

[...]
wm4 March 31, 2017, 11:28 a.m. UTC | #2
On Fri, 31 Mar 2017 03:49:16 +0200
Michael Niedermayer <michael@niedermayer.cc> wrote:

> On Thu, Mar 30, 2017 at 05:05:36PM +0200, wm4 wrote:
> > Not sure if it behaves ideally in presence of decoding errors.
> > ---
> > The original version of this patch is actually 1 year old.
> > ---
> >  ffprobe.c | 42 +++++++++++++++++++++++++++++-------------
> >  1 file changed, 29 insertions(+), 13 deletions(-)  
> 
> changes:
> http://samples.mplayerhq.hu/A-codecs/WMA/wav/FLCL_Ending_My.wav
> ./ffprobe -v 0 -show_frames -of compact=nk=1:p=0 ~/tickets/1905/FLCL_Ending_My.wav
> 
> after the patch there are alot of "N/A" in the output where numbers
> where before

This is just what the API returns. It has nothing to do with this
patch. One packet results in multiple frames in this case, and with the
new decode API, the timestamp fields in subsequent frames have the
timestamp fields unset, while the old API duplicates the ones from the
first frame of a packet.

This in turn happens because the "emulation" code in utils.c resets the
timestamps on subsequent frames explicitly:

        avctx->internal->buffer_pkt->pts   = AV_NOPTS_VALUE;
        avctx->internal->buffer_pkt->dts   = AV_NOPTS_VALUE;

So this is very much by design, and I think the result with the new API
is better too. (Old API users probably had to explicitly handle this
case themselves, because nobody wants non-increasing timestamps.)
wm4 April 4, 2017, 6:28 a.m. UTC | #3
On Fri, 31 Mar 2017 03:49:16 +0200
Michael Niedermayer <michael@niedermayer.cc> wrote:

> On Thu, Mar 30, 2017 at 05:05:36PM +0200, wm4 wrote:
> > Not sure if it behaves ideally in presence of decoding errors.
> > ---
> > The original version of this patch is actually 1 year old.
> > ---
> >  ffprobe.c | 42 +++++++++++++++++++++++++++++-------------
> >  1 file changed, 29 insertions(+), 13 deletions(-)  
> 
> changes:
> http://samples.mplayerhq.hu/A-codecs/WMA/wav/FLCL_Ending_My.wav
> ./ffprobe -v 0 -show_frames -of compact=nk=1:p=0 ~/tickets/1905/FLCL_Ending_My.wav
> 
> after the patch there are alot of "N/A" in the output where numbers
> where before
> 
> [...]

Pushed.
diff mbox

Patch

diff --git a/ffprobe.c b/ffprobe.c
index fa60894833..c35d4cfcd9 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -2134,7 +2134,8 @@  static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
 
 static av_always_inline int process_frame(WriterContext *w,
                                           InputFile *ifile,
-                                          AVFrame *frame, AVPacket *pkt)
+                                          AVFrame *frame, AVPacket *pkt,
+                                          int *packet_new)
 {
     AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     AVCodecContext *dec_ctx = ifile->streams[pkt->stream_index].dec_ctx;
@@ -2146,24 +2147,39 @@  static av_always_inline int process_frame(WriterContext *w,
     if (dec_ctx && dec_ctx->codec) {
         switch (par->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
-            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, pkt);
-            break;
-
         case AVMEDIA_TYPE_AUDIO:
-            ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt);
+            if (*packet_new) {
+                ret = avcodec_send_packet(dec_ctx, pkt);
+                if (ret == AVERROR(EAGAIN)) {
+                    ret = 0;
+                } else if (ret >= 0 || ret == AVERROR_EOF) {
+                    ret = 0;
+                    *packet_new = 0;
+                }
+            }
+            if (ret >= 0) {
+                ret = avcodec_receive_frame(dec_ctx, frame);
+                if (ret >= 0) {
+                    got_frame = 1;
+                } else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+                    ret = 0;
+                }
+            }
             break;
 
         case AVMEDIA_TYPE_SUBTITLE:
             ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt);
+            *packet_new = 0;
             break;
+        default:
+            *packet_new = 0;
         }
+    } else {
+        *packet_new = 0;
     }
 
     if (ret < 0)
         return ret;
-    ret = FFMIN(ret, pkt->size); /* guard against bogus return values */
-    pkt->data += ret;
-    pkt->size -= ret;
     if (got_frame) {
         int is_sub = (par->codec_type == AVMEDIA_TYPE_SUBTITLE);
         nb_streams_frames[pkt->stream_index]++;
@@ -2175,7 +2191,7 @@  static av_always_inline int process_frame(WriterContext *w,
         if (is_sub)
             avsubtitle_free(&sub);
     }
-    return got_frame;
+    return got_frame || *packet_new;
 }
 
 static void log_read_interval(const ReadInterval *interval, void *log_ctx, int log_level)
@@ -2206,7 +2222,7 @@  static int read_interval_packets(WriterContext *w, InputFile *ifile,
                                  const ReadInterval *interval, int64_t *cur_ts)
 {
     AVFormatContext *fmt_ctx = ifile->fmt_ctx;
-    AVPacket pkt, pkt1;
+    AVPacket pkt;
     AVFrame *frame = NULL;
     int ret = 0, i = 0, frame_count = 0;
     int64_t start = -INT64_MAX, end = interval->end;
@@ -2283,8 +2299,8 @@  static int read_interval_packets(WriterContext *w, InputFile *ifile,
                 nb_streams_packets[pkt.stream_index]++;
             }
             if (do_read_frames) {
-                pkt1 = pkt;
-                while (pkt1.size && process_frame(w, ifile, frame, &pkt1) > 0);
+                int packet_new = 1;
+                while (process_frame(w, ifile, frame, &pkt, &packet_new) > 0);
             }
         }
         av_packet_unref(&pkt);
@@ -2296,7 +2312,7 @@  static int read_interval_packets(WriterContext *w, InputFile *ifile,
     for (i = 0; i < fmt_ctx->nb_streams; i++) {
         pkt.stream_index = i;
         if (do_read_frames)
-            while (process_frame(w, ifile, frame, &pkt) > 0);
+            while (process_frame(w, ifile, frame, &pkt, &(int){1}) > 0);
     }
 
 end: