[FFmpeg-devel] [PATCH v3] avcodec: add AV_CODEC_FLAG_DROPCHANGED to flags

Gyan ffmpeg at gyani.pro
Tue Apr 16 10:42:20 EEST 2019


Patch revised as per 
http://www.ffmpeg.org/pipermail/ffmpeg-devel/2019-April/242591.html

Gyan
-------------- next part --------------
From d97a89d0335cc6d11f111a7a6bebc891501837d2 Mon Sep 17 00:00:00 2001
From: Gyan Doshi <ffmpeg at gyani.pro>
Date: Sun, 14 Apr 2019 22:12:25 +0530
Subject: [PATCH v3] avcodec: add AV_CODEC_FLAG_DROPCHANGED to flags

Discard decoded frames which differ from first decoded frame in stream.
---
 doc/codecs.texi            |  2 ++
 libavcodec/avcodec.h       |  8 +++++++
 libavcodec/decode.c        | 47 +++++++++++++++++++++++++++++++++++++-
 libavcodec/internal.h      |  8 +++++++
 libavcodec/options_table.h |  1 +
 libavcodec/version.h       |  2 +-
 6 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/doc/codecs.texi b/doc/codecs.texi
index 572e561c1a..0baafee2e1 100644
--- a/doc/codecs.texi
+++ b/doc/codecs.texi
@@ -55,6 +55,8 @@ Do not draw edges.
 @item psnr
 Set error[?] variables during encoding.
 @item truncated
+ at item drop_changed
+Don't output frames whose parameters differ from first decoded frame in stream.
 
 @item ildct
 Use interlaced DCT.
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 9e37466641..b749946633 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -859,6 +859,11 @@ typedef struct RcOverride{
  * Use qpel MC.
  */
 #define AV_CODEC_FLAG_QPEL            (1 <<  4)
+/**
+ * Don't output frames whose parameters differ from first
+ * decoded frame in stream.
+ */
+#define AV_CODEC_FLAG_DROPCHANGED     (1 <<  5)
 /**
  * Use internal 2pass ratecontrol in first pass mode.
  */
@@ -4918,6 +4923,9 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
  *      AVERROR_EOF:       the decoder has been fully flushed, and there will be
  *                         no more output frames
  *      AVERROR(EINVAL):   codec not opened, or it is an encoder
+ *      AVERROR_INPUT_CHANGED:   current decoded frame has changed parameters
+ *                               with respect to first decoded frame. Applicable
+ *                               when flag AV_CODEC_FLAG_DROPCHANGED is set.
  *      other negative values: legitimate decoding errors
  */
 int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index a32ff2fcd3..6c31166ec2 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -740,7 +740,7 @@ static int apply_cropping(AVCodecContext *avctx, AVFrame *frame)
 int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     AVCodecInternal *avci = avctx->internal;
-    int ret;
+    int ret, changed;
 
     av_frame_unref(frame);
 
@@ -765,6 +765,51 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr
 
     avctx->frame_number++;
 
+    if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) {
+
+        if (avctx->frame_number == 1) {
+            avci->initial_format = frame->format;
+            switch(avctx->codec_type) {
+            case AVMEDIA_TYPE_VIDEO:
+                avci->initial_width  = frame->width;
+                avci->initial_height = frame->height;
+                break;
+            case AVMEDIA_TYPE_AUDIO:
+                avci->initial_sample_rate = frame->sample_rate ? frame->sample_rate :
+                                                                 avctx->sample_rate;
+                avci->initial_channels       = frame->channels;
+                avci->initial_channel_layout = frame->channel_layout;
+                break;
+            }
+        }
+
+        if (avctx->frame_number > 1) {
+            changed = avci->initial_format != frame->format;
+
+           switch(avctx->codec_type) {
+            case AVMEDIA_TYPE_VIDEO:
+                changed |= avci->initial_width  != frame->width ||
+                           avci->initial_height != frame->height;
+                break;
+            case AVMEDIA_TYPE_AUDIO:
+                changed |= avci->initial_sample_rate    != frame->sample_rate ||
+                           avci->initial_sample_rate    != avctx->sample_rate ||
+                           avci->initial_channels       != frame->channels ||
+                           avci->initial_channel_layout != frame->channel_layout;
+                break;
+            }
+
+            if (changed) {
+                avci->changed_frames_dropped++;
+                av_log(avctx, AV_LOG_INFO, "dropped changed frame #%d pts %"PRId64
+                                            " drop count: %d \n",
+                                            avctx->frame_number, frame->pts,
+                                            avci->changed_frames_dropped);
+                av_frame_unref(frame);
+                return AVERROR_INPUT_CHANGED;
+            }
+        }
+    }
     return 0;
 }
 
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index f2e6f00ace..5096ffa1d9 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -218,6 +218,14 @@ typedef struct AVCodecInternal {
 
     /* to prevent infinite loop on errors when draining */
     int nb_draining_errors;
+
+    /* used when avctx flag AV_CODEC_FLAG_DROPCHANGED is set */
+    int changed_frames_dropped;
+    int initial_format;
+    int initial_width, initial_height;
+    int initial_sample_rate;
+    int initial_channels;
+    uint64_t initial_channel_layout;
 } AVCodecInternal;
 
 struct AVCodecDefault {
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index a3235bcd57..4a266eca16 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -67,6 +67,7 @@ static const AVOption avcodec_options[] = {
 {"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"},
 {"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"},
 {"output_corrupt", "Output even potentially corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_OUTPUT_CORRUPT }, INT_MIN, INT_MAX, V|D, "flags"},
+{"drop_changed", "Drop frames whose parameters differ from first decoded frame", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_DROPCHANGED }, INT_MIN, INT_MAX, A|V|D, "flags"},
 {"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"},
 {"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"},
 {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"},
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 1b60202dee..195e21bfbe 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,7 +28,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  58
-#define LIBAVCODEC_VERSION_MINOR  51
+#define LIBAVCODEC_VERSION_MINOR  52
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
-- 
2.21.0


More information about the ffmpeg-devel mailing list