summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGyan Doshi <ffmpeg@gyani.pro>2019-04-14 22:12:25 +0530
committerGyan Doshi <ffmpeg@gyani.pro>2019-04-20 10:38:01 +0530
commit3153a6502a28b20a0da822daf32bcd8f7c90d721 (patch)
treef3673539f54af82ab363d813eb42cd72048105e8
parentd93e44332f1bd2be90eb637268385a5acd8f6c10 (diff)
avcodec: add AV_CODEC_FLAG_DROPCHANGED to flags
Discard decoded frames which differ from first decoded frame in stream.
-rw-r--r--doc/codecs.texi2
-rw-r--r--libavcodec/avcodec.h8
-rw-r--r--libavcodec/decode.c47
-rw-r--r--libavcodec/internal.h8
-rw-r--r--libavcodec/options_table.h1
-rw-r--r--libavcodec/version.h2
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
+@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
@@ -860,6 +860,11 @@ typedef struct RcOverride{
*/
#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.
*/
#define AV_CODEC_FLAG_PASS1 (1 << 9)
@@ -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, \