diff mbox series

[FFmpeg-devel,2/2] avcodec/noise: allow various cadence for dropping packets

Message ID 20210723093341.2000-2-ffmpeg@gyani.pro
State New
Headers show
Series [FFmpeg-devel,1/2] avcodec/noise: don't force non-zero value for amount
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate fail Make fate failed
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate warning Make fate failed

Commit Message

Gyan Doshi July 23, 2021, 9:33 a.m. UTC
Packets can now be dropped at fixed intervals or
with varying degrees of irregularity
---
 doc/bitstream_filters.texi | 22 +++++++++++++
 libavcodec/noise_bsf.c     | 65 ++++++++++++++++++++++++++++++--------
 libavcodec/version.h       |  2 +-
 3 files changed, 74 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index 2b84bda1fc..4ab6cc15ab 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -539,6 +539,22 @@  with @var{1} meaning every byte is modified. Default is @var{0}.
 @item dropamount
 Accepts a positive integer. Lower the value, more frequently packets will be dropped,
 with @var{1} meaning every packet is dropped. Default is @var{0}.
+@item drop_pattern
+Regulate how packets are dropped, starting with packet index of @var{drop_offset}.
+Possible values are
+@table @option
+@item 0 (@emph{default})
+Drop at fixed intervals of @var{dropamount}, e.g. with dropamount @var{5} and drop_offset @var{2},
+packets no. @code{2, 7, 12...} will be dropped.
+@item 1
+Drop a random packet in each interval of size @var{dropamount}.
+@item 2
+Drop a random packet in roughly inverse frequency to @var{dropamount}. Over a short range of packets,
+the drop frequency is less stable than pattern value @var{1}.
+@end table
+@item drop_offset
+Accepts a positive integer. Represents the index of the first packet at which drop evaluations
+start. Default is @var{0}.
 @end table
 
 The following example applies the modification to every byte but does not drop
@@ -547,6 +563,12 @@  any packets.
 ffmpeg -i INPUT -c copy -bsf noise=amount=1 output.mkv
 @end example
 
+The following example drops one random packet every 5 packets starting with packet #2 and modifies
+roughly every 3rd byte of remaining packets.
+@example
+ffmpeg -i INPUT -c copy -bsf noise=amount=3:dropamount=5:drop_pattern=1:drop_offset=2 output.mkv
+@end example
+
 @section null
 This bitstream filter passes the packets through unchanged.
 
diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c
index c1b0203442..83118c12cf 100644
--- a/libavcodec/noise_bsf.c
+++ b/libavcodec/noise_bsf.c
@@ -30,7 +30,12 @@  typedef struct NoiseContext {
     const AVClass *class;
     int amount;
     int dropamount;
+    int drop_pattern;
+    int drop_offset;
+
     unsigned int state;
+    unsigned int pkt_idx;
+    unsigned int drop_idx;
 } NoiseContext;
 
 static int noise_init(AVBSFContext *ctx)
@@ -48,31 +53,61 @@  static int noise_init(AVBSFContext *ctx)
 static int noise(AVBSFContext *ctx, AVPacket *pkt)
 {
     NoiseContext *s = ctx->priv_data;
-    int i, ret;
+    int i, ret, interval_pos, drop;
 
     ret = ff_bsf_get_packet_ref(ctx, pkt);
     if (ret < 0)
         return ret;
 
-    if (s->dropamount && s->state % s->dropamount == 0) {
-        s->state++;
-        av_packet_unref(pkt);
-        return AVERROR(EAGAIN);
+    if (s->dropamount && s->pkt_idx >= s->drop_offset) {
+
+        interval_pos = (s->pkt_idx - s->drop_offset) % s->dropamount;
+
+        switch (s->drop_pattern) {
+        case 0:
+            drop = interval_pos == 0;
+            break;
+        case 1:
+            if (interval_pos == 0)
+                s->drop_idx = s->pkt_idx + s->state % s->dropamount;
+            drop = s->pkt_idx == s->drop_idx;
+            break;
+        case 2:
+            drop = s->state % s->dropamount == 0;
+            break;
+        }
+
+        if (drop) {
+            av_log(ctx, AV_LOG_VERBOSE, "Stream #%d packet #%d with pts %"PRId64" dropped.\n", pkt->stream_index, s->pkt_idx, pkt->pts);
+            s->state++;
+            av_packet_unref(pkt);
+            ret = AVERROR(EAGAIN);
+            goto done;
+        }
     }
 
-    ret = av_packet_make_writable(pkt);
-    if (ret < 0) {
-        av_packet_unref(pkt);
-        return ret;
+    if (s->amount) {
+        ret = av_packet_make_writable(pkt);
+        if (ret < 0) {
+            av_packet_unref(pkt);
+            goto done;
+        }
     }
 
-    for (i = 0; i < pkt->size; i++) {
-        s->state += pkt->data[i] + 1;
-        if (s->amount && s->state % s->amount == 0)
-            pkt->data[i] = s->state;
+    if (s->amount || s->drop_pattern) {
+
+        for (i = 0; i < pkt->size; i++) {
+            s->state += pkt->data[i] + 1;
+            if (s->amount && s->state % s->amount == 0)
+                pkt->data[i] = s->state;
+        }
     }
 
-    return 0;
+    ret = 0;
+
+done:
+    s->pkt_idx++;
+    return ret;
 }
 
 #define OFFSET(x) offsetof(NoiseContext, x)
@@ -80,6 +115,8 @@  static int noise(AVBSFContext *ctx, AVPacket *pkt)
 static const AVOption options[] = {
     { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
     { "dropamount", NULL, OFFSET(dropamount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
+    { "drop_pattern",  NULL, OFFSET(drop_pattern),  AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2,       FLAGS },
+    { "drop_offset",  NULL,  OFFSET(drop_offset),   AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
     { NULL },
 };
 
diff --git a/libavcodec/version.h b/libavcodec/version.h
index c660f70669..91325ce4e7 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@ 
 
 #define LIBAVCODEC_VERSION_MAJOR  59
 #define LIBAVCODEC_VERSION_MINOR   3
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MICRO 102
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \