Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] lavfi/vf_decimate: add mixed option to process input only partially to be decimated
@ 2022-11-09 12:07 mail
  0 siblings, 0 replies; 3+ messages in thread
From: mail @ 2022-11-09 12:07 UTC (permalink / raw)
  To: ffmpeg-devel

Enabling the option will only decimate frames below dupthresh and output at
variable frame rate.

Signed-off-by: lovesyk <lovesyk@users.noreply.github.com>
---
 libavfilter/vf_decimate.c | 42 +++++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c
index f61e501c96..dbeca427f1 100644
--- a/libavfilter/vf_decimate.c
+++ b/libavfilter/vf_decimate.c
@@ -44,6 +44,7 @@ typedef struct DecimateContext {
     AVFrame **clean_src;    ///< frame queue for the clean source
     int got_frame[2];       ///< frame request flag for each input stream
     int64_t last_pts;       ///< last output timestamp
+    int64_t last_duration;  ///< last output duration
     int64_t start_pts;      ///< base for output timestamps
     uint32_t eof;           ///< bitmask for end of stream
     int hsub, vsub;         ///< chroma subsampling values
@@ -51,6 +52,9 @@ typedef struct DecimateContext {
     int nxblocks, nyblocks;
     int bdiffsize;
     int64_t *bdiffs;
+    AVRational in_tb;       // input time-base
+    AVRational nondec_tb;   // non-decimated time-base
+    AVRational dec_tb;      // decimated time-base
 
     /* options */
     int cycle;
@@ -61,6 +65,7 @@ typedef struct DecimateContext {
     int blockx, blocky;
     int ppsrc;
     int chroma;
+    int mixed;
 } DecimateContext;
 
 #define OFFSET(x) offsetof(DecimateContext, x)
@@ -74,6 +79,7 @@ static const AVOption decimate_options[] = {
     { "blocky",    "set the size of the y-axis blocks used during metric
calculations", OFFSET(blocky), AV_OPT_TYPE_INT, {.i64 = 32}, 4, 1<<9, FLAGS
},
     { "ppsrc",     "mark main input as a pre-processed input and activate
clean source input stream", OFFSET(ppsrc), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,
FLAGS },
     { "chroma",    "set whether or not chroma is considered in the metric
calculations", OFFSET(chroma), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
+    { "mixed",     "set whether or not the input only partially contains
content to be decimated", OFFSET(mixed), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,
FLAGS },
     { NULL }
 };
 
@@ -193,7 +199,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
*in)
         }
         if (dm->queue[lowest].maxbdiff < dm->dupthresh)
             duppos = lowest;
-        drop = scpos >= 0 && duppos < 0 ? scpos : lowest;
+
+        if (dm->mixed && duppos < 0) {
+            drop = -1; // no drop if mixed content + no frame in cycle
below threshold
+        } else {
+            drop = scpos >= 0 && duppos < 0 ? scpos : lowest;
+        }
     }
 
     /* metrics debug */
@@ -212,7 +223,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
*in)
     /* push all frames except the drop */
     ret = 0;
     for (i = 0; i < dm->cycle && dm->queue[i].frame; i++) {
-        AVRational in_tb = ctx->inputs[INPUT_MAIN]->time_base;
         if (i == drop) {
             if (dm->ppsrc)
                 av_frame_free(&dm->clean_src[i]);
@@ -221,7 +231,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
*in)
             AVFrame *frame = dm->queue[i].frame;
             dm->queue[i].frame = NULL;
             if (frame->pts != AV_NOPTS_VALUE && dm->start_pts ==
AV_NOPTS_VALUE)
-                dm->start_pts = av_rescale_q(frame->pts, in_tb,
outlink->time_base);
+                dm->start_pts = av_rescale_q(frame->pts, dm->in_tb,
outlink->time_base);
 
             if (dm->ppsrc) {
                 av_frame_free(&frame);
@@ -230,9 +240,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
*in)
                     continue;
                 dm->clean_src[i] = NULL;
             }
-            frame->pts = outlink->frame_count_in +
+
+            frame->pts = dm->last_duration ? dm->last_pts +
dm->last_duration :
                          (dm->start_pts == AV_NOPTS_VALUE ? 0 :
dm->start_pts);
-            frame->duration = 1;
+            frame->duration = dm->mixed ? av_div_q(drop < 0 ? dm->nondec_tb
: dm->dec_tb, outlink->time_base).num : 1;
+            dm->last_duration = frame->duration;
             dm->last_pts = frame->pts;
             ret = ff_filter_frame(outlink, frame);
             if (ret < 0)
@@ -329,6 +341,7 @@ static av_cold int decimate_init(AVFilterContext *ctx)
     }
 
     dm->start_pts = AV_NOPTS_VALUE;
+    dm->last_duration = 0;
 
     return 0;
 }
@@ -388,6 +401,9 @@ static int config_output(AVFilterLink *outlink)
     dm->bdiffsize = dm->nxblocks * dm->nyblocks;
     dm->bdiffs    = av_malloc_array(dm->bdiffsize, sizeof(*dm->bdiffs));
     dm->queue     = av_calloc(dm->cycle, sizeof(*dm->queue));
+    dm->in_tb     = inlink->time_base;
+    dm->nondec_tb = av_inv_q(fps);
+    dm->dec_tb    = av_mul_q(dm->nondec_tb, (AVRational){dm->cycle,
dm->cycle - 1});
 
     if (!dm->bdiffs || !dm->queue)
         return AVERROR(ENOMEM);
@@ -403,11 +419,17 @@ static int config_output(AVFilterLink *outlink)
                "current rate of %d/%d is invalid\n", fps.num, fps.den);
         return AVERROR(EINVAL);
     }
-    fps = av_mul_q(fps, (AVRational){dm->cycle - 1, dm->cycle});
-    av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
-           inlink->frame_rate.num, inlink->frame_rate.den, fps.num,
fps.den);
-    outlink->time_base  = av_inv_q(fps);
-    outlink->frame_rate = fps;
+
+    if (dm->mixed) {
+        outlink->time_base = av_gcd_q(dm->nondec_tb, dm->dec_tb,
AV_TIME_BASE / 2, AV_TIME_BASE_Q);
+        av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> VFR (use %d/%d if CFR
required)\n",
+            fps.num, fps.den, outlink->time_base.den,
outlink->time_base.num);
+    } else {
+        outlink->time_base = dm->dec_tb;
+        outlink->frame_rate = av_inv_q(outlink->time_base);
+        av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
+            fps.num, fps.den, outlink->frame_rate.num,
outlink->frame_rate.den);
+    }
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     if (dm->ppsrc) {
         outlink->w = ctx->inputs[INPUT_CLEANSRC]->w;
-- 
2.34.2


_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [FFmpeg-devel] [PATCH] lavfi/vf_decimate: add mixed option to process input only partially to be decimated
  2022-11-09 12:08 mail
@ 2022-12-19 15:27 ` Paul B Mahol
  0 siblings, 0 replies; 3+ messages in thread
From: Paul B Mahol @ 2022-12-19 15:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On 11/9/22, mail@nodoa.me <mail@nodoa.me> wrote:
> The purpose of this new option is to enable processing of mixed content
> such
> as TV recordings or even movies which have some cuts in telecined 24fps and
> others in 30p.
>
> Enabling it (mixed=1) will calculate a common timebase between decimated
> and
> non-decimated content and set frame duration according to whether the
> current cycle contains a frame deemed to be a duplicate or not.
>
> The default is disabled (mixed=0) and keeping it disabled will keep the PTS
> as before (verified using ffprobe).
>
>
>
> Regarding setting frame->pts, I had to adjust this part a bit as it is no
> longer possible to assume all frames counted by frame_count_in have the
> same
> duration.
>
> As for outlink->frame_rate, I have removed the assignment in the case of
> mixed content as the output will be of variable frame rate. Please tell me
> in case this is not sufficient to signalize VFR content.
>
>
>
> An example for verifying the result is
> http://samples.ffmpeg.org/HDTV/Hellboy.ts
>
> ffmpeg -i Hellboy.ts -map 0:v -c:v libx264 -vf
> fps=fps=30000/1001,fieldmatch,decimate=mixed=1,fps=fps=120000/1001 -preset
> veryfast -crf 10 Hellboy.mp4
>
> The source has a frame rate of 30000/1001 -> timebase 1001/30000 which with
> a decimation cycle of 5 results in a decimated timebase of 24000/1001 and a
> common timebase of 1001/120000.
>
> The source contains 24fps interlaced content which will result in a
> duration
> of 5 frames at the output frame rate of 120000/1001.
>
> The source also contains 30p content which in the output will have a
> duration of 4 frames.
>
> This particular source requires the frame rate to be set to constant
> 30000/1001. I haven't looked into why but I have verified this to also be
> required if not applying this patch.
>

Applied
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [FFmpeg-devel] [PATCH] lavfi/vf_decimate: add mixed option to process input only partially to be decimated
@ 2022-11-09 12:08 mail
  2022-12-19 15:27 ` Paul B Mahol
  0 siblings, 1 reply; 3+ messages in thread
From: mail @ 2022-11-09 12:08 UTC (permalink / raw)
  To: ffmpeg-devel

The purpose of this new option is to enable processing of mixed content such
as TV recordings or even movies which have some cuts in telecined 24fps and
others in 30p.

Enabling it (mixed=1) will calculate a common timebase between decimated and
non-decimated content and set frame duration according to whether the
current cycle contains a frame deemed to be a duplicate or not.

The default is disabled (mixed=0) and keeping it disabled will keep the PTS
as before (verified using ffprobe).

 

Regarding setting frame->pts, I had to adjust this part a bit as it is no
longer possible to assume all frames counted by frame_count_in have the same
duration.

As for outlink->frame_rate, I have removed the assignment in the case of
mixed content as the output will be of variable frame rate. Please tell me
in case this is not sufficient to signalize VFR content.

 

An example for verifying the result is
http://samples.ffmpeg.org/HDTV/Hellboy.ts

ffmpeg -i Hellboy.ts -map 0:v -c:v libx264 -vf
fps=fps=30000/1001,fieldmatch,decimate=mixed=1,fps=fps=120000/1001 -preset
veryfast -crf 10 Hellboy.mp4

The source has a frame rate of 30000/1001 -> timebase 1001/30000 which with
a decimation cycle of 5 results in a decimated timebase of 24000/1001 and a
common timebase of 1001/120000.

The source contains 24fps interlaced content which will result in a duration
of 5 frames at the output frame rate of 120000/1001.

The source also contains 30p content which in the output will have a
duration of 4 frames.

This particular source requires the frame rate to be set to constant
30000/1001. I haven't looked into why but I have verified this to also be
required if not applying this patch.

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-12-19 15:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-09 12:07 [FFmpeg-devel] [PATCH] lavfi/vf_decimate: add mixed option to process input only partially to be decimated mail
2022-11-09 12:08 mail
2022-12-19 15:27 ` Paul B Mahol

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git