diff mbox

[FFmpeg-devel] avcodec: add delayer bitstream filter

Message ID S-RssmRpbmjJMApUgnVet5XSTifeJXb4hW0kzJSXau3qpSqFunFZS15NBQtwMsZt96Azn9R_atdbajAvCpLAyHC4jCdeXYDn7E_Uoj2kZhs=@protonmail.com
State New
Headers show

Commit Message

Andreas Håkon June 25, 2019, 7:17 p.m. UTC
Example of use:

ffmpeg -f mpegts -i INPUT.ts -map i:101 -c:v copy -map i:102 -bsf:a delayer=offset=3600 -c:a copy -f mpegts OUTPUT.ts

You can use it with VIDEO, AUDIO or DATA streams.

Regards.
A.H.

---
From 414a3c78dfa208b8253448d5c09fde9a8bee56cb Mon Sep 17 00:00:00 2001
From: Andreas Hakon <andreas.hakon@protonmail.com>
Date: Tue, 25 Jun 2019 20:03:48 +0100
Subject: [PATCH] avcodec: add delayer bitstream filter

This implements a new delayer bitstream filter.

Signed-off-by: Andreas Hakon <andreas.hakon@protonmail.com>
---
 doc/bitstream_filters.texi     |    4 ++
 libavcodec/Makefile            |    1 +
 libavcodec/bitstream_filters.c |    1 +
 libavcodec/delayer_bsf.c       |   81 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+)
 create mode 100644 libavcodec/delayer_bsf.c

Comments

Andreas Rheinhardt June 25, 2019, 7:26 p.m. UTC | #1
Andreas Håkon:
> Example of use:
> 
> ffmpeg -f mpegts -i INPUT.ts -map i:101 -c:v copy -map i:102 -bsf:a delayer=offset=3600 -c:a copy -f mpegts OUTPUT.ts
> 
> You can use it with VIDEO, AUDIO or DATA streams.
> 
> Regards.
> A.H.
> 
> ---
> 
> 
> _______________________________________________
> 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".
> 

The delay applied here depends on the timebase. Wouldn't it be more
user-friendly to let the user input the delay in (say) microseconds
and convert it appropriately?
And ff_delayer_bsf isn't properly aligned.

- Andreas Rheinhardt
Gyan Doshi June 25, 2019, 7:28 p.m. UTC | #2
On 26-06-2019 12:47 AM, Andreas Håkon wrote:
> Example of use:
>
> ffmpeg -f mpegts -i INPUT.ts -map i:101 -c:v copy -map i:102 -bsf:a delayer=offset=3600 -c:a copy -f mpegts OUTPUT.ts
>
> You can use it with VIDEO, AUDIO or DATA streams.

What's the advantage over output_ts_offset?

Gyan
Gyan Doshi June 25, 2019, 7:36 p.m. UTC | #3
On 26-06-2019 12:58 AM, Gyan wrote:
>
>
> On 26-06-2019 12:47 AM, Andreas Håkon wrote:
>> Example of use:
>>
>> ffmpeg -f mpegts -i INPUT.ts -map i:101 -c:v copy -map i:102 -bsf:a 
>> delayer=offset=3600 -c:a copy -f mpegts OUTPUT.ts
>>
>> You can use it with VIDEO, AUDIO or DATA streams.
>
> What's the advantage over output_ts_offset?

To answer that partially, this can be applied per-stream.

Wouldn't this be better if extended to be a BSF version of setpts? In 
addition to delays, rescaling as well as other ops could be carried out 
on TS.

Gyan
Andreas Håkon June 26, 2019, 7:06 a.m. UTC | #4
Hi,


> -   Andreas Rheinhardt:

> > Example of use:
> > ffmpeg -f mpegts -i INPUT.ts -map i:101 -c:v copy -map i:102 -bsf:a delayer=offset=3600 -c:a copy -f mpegts OUTPUT.ts
>
> The delay applied here depends on the timebase. Wouldn't it be more
> user-friendly to let the user input the delay in (say) microseconds
> and convert it appropriately?

You can see that inside the TODO comments there is something similar pointed.
In the future you will be able to use Frames, Seconds or Absolute values.
However, the first step would be to include the plugin as it is, don't you think?


> And ff_delayer_bsf isn't properly aligned.

Now, I see it... sorry!


Regards.
A.H.
Andreas Håkon June 26, 2019, 7:11 a.m. UTC | #5
Hi Gyan,


> > > Example of use:
> > > ffmpeg -f mpegts -i INPUT.ts -map i:101 -c:v copy -map i:102 -bsf:a
> > > delayer=offset=3600 -c:a copy -f mpegts OUTPUT.ts
> > > You can use it with VIDEO, AUDIO or DATA streams.
> >
> > What's the advantage over output_ts_offset?
>
> To answer that partially, this can be applied per-stream.

Yes! That's the key point. You can (manually) resynchronize streams
(video with audio, multiple video, audio tracks...) withtout any reencoding.


> Wouldn't this be better if extended to be a BSF version of setpts? In
> addition to delays, rescaling as well as other ops could be carried out
> on TS.

Maybe. But I prefer to include this "simple" SFB plugin first. I'm using it
and it works like a charm.


Regards.
A.H.

---
Moritz Barsnick June 26, 2019, 10:13 a.m. UTC | #6
On Wed, Jun 26, 2019 at 01:06:56 +0530, Gyan wrote:
> Wouldn't this be better if extended to be a BSF version of setpts? In
> addition to delays, rescaling as well as other ops could be carried out
> on TS.

I second that notion, or at least the suggestion of a setpts bsf.

IMO, there is probably some functionality in filters which could be
implemented in bitstream filters, to allow it to apply to stream copy.

Moritz
Andreas Håkon June 26, 2019, 11:15 a.m. UTC | #7
Hi Moritz,

> > Wouldn't this be better if extended to be a BSF version of setpts? In
> > addition to delays, rescaling as well as other ops could be carried out
> > on TS.
>
> I second that notion, or at least the suggestion of a setpts bsf.
>
> IMO, there is probably some functionality in filters which could be
> implemented in bitstream filters, to allow it to apply to stream copy.

I think it's a good idea.

Just to say that from my point of view, it would be easier if another
developer took care of including the functionality of other filters,
because my knowledge of the project is not so deep.
Still, I feel that it would be best to incorporate this BSF as it is
and later on add more features.

Do you agree?

Regards.
A.H.

---
Reimar Döffinger June 26, 2019, 6:45 p.m. UTC | #8
On 26.06.2019, at 13:15, Andreas Håkon <andreas.hakon@protonmail.com> wrote:

> Hi Moritz,
> 
>>> Wouldn't this be better if extended to be a BSF version of setpts? In
>>> addition to delays, rescaling as well as other ops could be carried out
>>> on TS.
>> 
>> I second that notion, or at least the suggestion of a setpts bsf.
>> 
>> IMO, there is probably some functionality in filters which could be
>> implemented in bitstream filters, to allow it to apply to stream copy.
> 
> I think it's a good idea.
> 
> Just to say that from my point of view, it would be easier if another
> developer took care of including the functionality of other filters,
> because my knowledge of the project is not so deep.
> Still, I feel that it would be best to incorporate this BSF as it is
> and later on add more features.

Minor note: I'd suggest a different name, "delayer" is too easily read as e.g. "de-layer".
Could be something like add_delay for example.
Andreas Håkon June 27, 2019, 3:14 p.m. UTC | #9
Hi Reimar,

> Minor note: I'd suggest a different name, "delayer" is too easily read as e.g. "de-layer".
> Could be something like add_delay for example.

Good point! Or perhaps "timer" will be preferable. Ideas?

Regards.
A.H.

---
Marton Balint June 27, 2019, 6:50 p.m. UTC | #10
On Thu, 27 Jun 2019, Andreas Håkon wrote:

> Hi Reimar,
>
>> Minor note: I'd suggest a different name, "delayer" is too easily read as e.g. "de-layer".
>> Could be something like add_delay for example.
>
> Good point! Or perhaps "timer" will be preferable. Ideas?

Maybe it's too much work for little benefit, but instead of this a more 
generic "setts" bitstream filter might be implemented which can be used to 
set both PTS and DTS similar to how the setpts/asetpts filter works for 
frames.

Regards,
Marton
Andreas Håkon June 28, 2019, 8:46 a.m. UTC | #11
Hi Marton,

> Maybe it's too much work for little benefit, but instead of this a more
> generic "setts" bitstream filter might be implemented which can be used to
> set both PTS and DTS similar to how the setpts/asetpts filter works for
> frames.

New version (ready to merge) is here:
https://patchwork.ffmpeg.org/patch/13743/

As for improvements, they can be made after the first version is accepted.

Regards.
A.H.


---
diff mbox

Patch

diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index 40e8ada..563dfa9 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -96,6 +96,10 @@  Deletes Padding OBUs.
 
 Remove zero padding at the end of a packet.
 
+@section delayer
+
+Apply an offset to the PTS/DTS timestamps.
+
 @section dca_core
 
 Extract the core from a DCA/DTS stream, dropping extensions such as
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index edccd73..e723e62 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1071,6 +1071,7 @@  OBJS-$(CONFIG_AAC_ADTSTOASC_BSF)          += aac_adtstoasc_bsf.o mpeg4audio.o
 OBJS-$(CONFIG_AV1_METADATA_BSF)           += av1_metadata_bsf.o
 OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF)        += av1_frame_split_bsf.o
 OBJS-$(CONFIG_CHOMP_BSF)                  += chomp_bsf.o
+OBJS-$(CONFIG_DELAYER_BSF)                += delayer_bsf.o
 OBJS-$(CONFIG_DUMP_EXTRADATA_BSF)         += dump_extradata_bsf.o
 OBJS-$(CONFIG_DCA_CORE_BSF)               += dca_core_bsf.o
 OBJS-$(CONFIG_EAC3_CORE_BSF)              += eac3_core_bsf.o
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 4630039..a3c509a 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -28,6 +28,7 @@  extern const AVBitStreamFilter ff_aac_adtstoasc_bsf;
 extern const AVBitStreamFilter ff_av1_frame_split_bsf;
 extern const AVBitStreamFilter ff_av1_metadata_bsf;
 extern const AVBitStreamFilter ff_chomp_bsf;
+extern const AVBitStreamFilter ff_delayer_bsf;
 extern const AVBitStreamFilter ff_dump_extradata_bsf;
 extern const AVBitStreamFilter ff_dca_core_bsf;
 extern const AVBitStreamFilter ff_eac3_core_bsf;
diff --git a/libavcodec/delayer_bsf.c b/libavcodec/delayer_bsf.c
new file mode 100644
index 0000000..81ef625
--- /dev/null
+++ b/libavcodec/delayer_bsf.c
@@ -0,0 +1,81 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * This bitstream filter applies an offset to the PTS/DTS timestamps.
+ *
+ */
+
+// TODO: Control time wrapping
+// TODO: Instead of using absolute timestamp offsets, use frame numbers
+// TODO: Advance in time? (aka negative offset)
+
+#include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/opt.h"
+
+typedef struct DelayerContext {
+    const AVClass *class;
+    int offset;
+} DelayerContext;
+
+static int delayer_filter(AVBSFContext *ctx, AVPacket *pkt)
+{
+    int ret;
+    DelayerContext *s = ctx->priv_data;
+    int64_t opts,odts;
+
+    ret = ff_bsf_get_packet_ref(ctx, pkt);
+    if (ret < 0)
+        return ret;
+
+    opts = pkt->pts;
+    if (pkt->pts != AV_NOPTS_VALUE) {
+        pkt->pts += s->offset;
+    }
+    odts = pkt->dts;
+    if (pkt->dts != AV_NOPTS_VALUE) {
+        pkt->dts += s->offset;
+    }
+    av_log(ctx, AV_LOG_DEBUG, "Updated PTS/DTS (%"PRId64"/%"PRId64" : %"PRId64"/%"PRId64") with offset:%d\n", pkt->pts,pkt->dts, opts,odts, s->offset );
+
+    return 0;
+}
+
+#define OFFSET(x) offsetof(DelayerContext, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM)
+static const AVOption options[] = {
+    { "offset", NULL, OFFSET(offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
+    { NULL },
+};
+
+static const AVClass delayer_class = {
+    .class_name = "delayer",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_delayer_bsf = {
+    .name   = "delayer",
+    .priv_data_size = sizeof(DelayerContext),
+    .priv_class     = &delayer_class,
+    .filter = delayer_filter,
+};