Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Devin Heitmueller <devin.heitmueller@ltnglobal.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Devin Heitmueller <dheitmueller@ltnglobal.com>
Subject: [FFmpeg-devel] [PATCH v4 4/4] bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when reclocking
Date: Mon, 31 Jul 2023 09:38:06 -0400
Message-ID: <1690810686-4723-5-git-send-email-dheitmueller@ltnglobal.com> (raw)
In-Reply-To: <1690810686-4723-1-git-send-email-dheitmueller@ltnglobal.com>

Because SCTE-35 messages are represented in TS streams as sections
rather than PES packets, we cannot rely on ffmpeg's standard
mechanisms to adjust PTS values if reclocking the stream.
This filter will leverage the SCTE-35 pts_adjust field to
compensate for any change in the PTS values in the stream.

See SCTE-35 2019 Sec 9.6 for information about the use of
the pts_adjust field.

This filter also tweaks the mpegtsenc mux to automatically
add it so the user doesn't have to include it manually.

Thanks to Andreas Rheinhardt and James Almer for providing
feedback/suggestions on improving the patch.

Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
 doc/bitstream_filters.texi       |   9 ++++
 libavcodec/Makefile              |   1 +
 libavcodec/bitstream_filters.c   |   1 +
 libavcodec/scte35ptsadjust_bsf.c | 100 +++++++++++++++++++++++++++++++++++++++
 libavformat/mpegtsenc.c          |   2 +
 5 files changed, 113 insertions(+)
 create mode 100644 libavcodec/scte35ptsadjust_bsf.c

diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index c63c203..068b0c9 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -797,6 +797,15 @@ Remove extradata from all frames.
 @end table
 @end table
 
+@section scte35ptsadjust
+This bitstream filter makes use of side data injected by the MPEG-TS demux
+in order to rewrite the PTS adjust field within SCTE-35 packets.  This
+ensures the pts_adjust field contains a valid value if the caller changes
+the timebase of the stream.
+
+The bitstream filter is added automatically by the mpegtsenc mux, and no
+action is required on the part of the user.
+
 @section setts
 Set PTS and DTS in packets.
 
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 3c16b51..efe0ae9 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1253,6 +1253,7 @@ OBJS-$(CONFIG_PCM_RECHUNK_BSF)            += pcm_rechunk_bsf.o
 OBJS-$(CONFIG_PGS_FRAME_MERGE_BSF)        += pgs_frame_merge_bsf.o
 OBJS-$(CONFIG_PRORES_METADATA_BSF)        += prores_metadata_bsf.o
 OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF)       += remove_extradata_bsf.o av1_parse.o
+OBJS-$(CONFIG_SCTE35PTSADJUST_BSF)        += scte35ptsadjust_bsf.o
 OBJS-$(CONFIG_SETTS_BSF)                  += setts_bsf.o
 OBJS-$(CONFIG_TEXT2MOVSUB_BSF)            += movsub_bsf.o
 OBJS-$(CONFIG_TRACE_HEADERS_BSF)          += trace_headers_bsf.o
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 1e9a676..60ed164 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -57,6 +57,7 @@ extern const FFBitStreamFilter ff_pcm_rechunk_bsf;
 extern const FFBitStreamFilter ff_pgs_frame_merge_bsf;
 extern const FFBitStreamFilter ff_prores_metadata_bsf;
 extern const FFBitStreamFilter ff_remove_extradata_bsf;
+extern const FFBitStreamFilter ff_scte35ptsadjust_bsf;
 extern const FFBitStreamFilter ff_setts_bsf;
 extern const FFBitStreamFilter ff_text2movsub_bsf;
 extern const FFBitStreamFilter ff_trace_headers_bsf;
diff --git a/libavcodec/scte35ptsadjust_bsf.c b/libavcodec/scte35ptsadjust_bsf.c
new file mode 100644
index 0000000..b8bf48d
--- /dev/null
+++ b/libavcodec/scte35ptsadjust_bsf.c
@@ -0,0 +1,100 @@
+/*
+ * SCTE-35 PTS fixup bitstream filter
+ * Copyright (c) 2023 LTN Global Communications, Inc.
+ *
+ * Author: Devin Heitmueller <dheitmueller@ltnglobal.com>
+ *
+ * Because SCTE-35 messages are represented in TS streams as sections
+ * rather than PES packets, we cannot rely on ffmpeg's standard
+ * mechanisms to adjust PTS values if reclocking the stream.
+ * This filter will leverage the SCTE-35 pts_adjust field to
+ * compensate for any change in the PTS values in the stream.
+ *
+ * See SCTE-35 2019 Sec 9.6 for information about the use of
+ * the pts_adjust field.
+ *
+ * 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
+ */
+
+#include "bsf.h"
+#include "bsf_internal.h"
+#include "defs.h"
+#include "libavutil/intreadwrite.h"
+
+static int scte35ptsadjust_filter(AVBSFContext *ctx, AVPacket *pkt)
+{
+    const AVTransportTimestamp *transport_ts;
+    int64_t cur_pts_adjust;
+    int ret = 0;
+
+    ret = ff_bsf_get_packet_ref(ctx, pkt);
+    if (ret < 0)
+        return ret;
+
+    /* Retrieve the original PTS, which will be used to calculate the pts_adjust */
+    transport_ts = (AVTransportTimestamp *) av_packet_get_side_data(pkt, AV_PKT_DATA_TRANSPORT_TIMESTAMP, NULL);
+    if (transport_ts == NULL) {
+        /* No original PTS specified, so just pass the packet through */
+        return 0;
+    }
+
+    /* The pts_adjust field is logically buf[4]-buf[8] of the payload */
+    if (pkt->size < 9) {
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+
+    /* Extract the current pts_adjust value from the packet */
+    cur_pts_adjust = ((int64_t)(pkt->data[4] & 1) << 32 ) |
+	    AV_RB32(pkt->data + 5);
+
+    av_log(ctx, AV_LOG_DEBUG, "pts=%" PRId64 "(%d/%d) orig_pts=%" PRId64 "(%d/%d) pts_adjust=%" PRId64 "\n",
+           pkt->pts, pkt->time_base.num, pkt->time_base.den,
+           transport_ts->pts, transport_ts->time_base.num, transport_ts->time_base.den, cur_pts_adjust);
+
+    /* Compute the new PTS adjust value */
+    cur_pts_adjust -= av_rescale_q(transport_ts->pts, transport_ts->time_base, (AVRational){1, 90000});
+    cur_pts_adjust += av_rescale_q(pkt->pts, pkt->time_base, (AVRational){1, 90000});
+    cur_pts_adjust &= 0x1FFFFFFFFLL;
+
+    av_log(ctx, AV_LOG_DEBUG, "new pts_adjust=%" PRId64 "\n", cur_pts_adjust);
+
+    ret = av_packet_make_writable(pkt);
+    if (ret < 0)
+        goto fail;
+
+    /* Insert the updated pts_adjust value */
+    pkt->data[4] &= 0xfe; /* Preserve top 7 unrelated bits */
+    pkt->data[4] |= cur_pts_adjust >> 32;
+    AV_WB32(pkt->data + 5, cur_pts_adjust);
+
+fail:
+    if (ret < 0)
+        av_packet_unref(pkt);
+
+    return ret;
+}
+
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_SCTE_35, AV_CODEC_ID_NONE,
+};
+
+const FFBitStreamFilter ff_scte35ptsadjust_bsf = {
+    .p.name         = "scte35ptsadjust",
+    .p.codec_ids    = codec_ids,
+    .filter         = scte35ptsadjust_filter,
+};
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index c6cd1fd..48d7833 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -2337,6 +2337,8 @@ static int mpegts_check_bitstream(AVFormatContext *s, AVStream *st,
                               (st->codecpar->extradata_size > 0 &&
                                st->codecpar->extradata[0] == 1)))
             ret = ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL);
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_SCTE_35) {
+        ret = ff_stream_add_bitstream_filter(st, "scte35ptsadjust", NULL);
     }
 
     return ret;
-- 
1.8.3.1

_______________________________________________
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".

  parent reply	other threads:[~2023-07-31 13:38 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-31 13:38 [FFmpeg-devel] [PATCH v4 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
2023-07-31 13:38 ` [FFmpeg-devel] [PATCH v4 1/4] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
2023-07-31 13:38 ` [FFmpeg-devel] [PATCH v4 2/4] mpegts: Stash original PTS for SCTE-35 sections for processing later Devin Heitmueller
2023-08-09 13:54   ` Kieran Kunhya
2023-08-09 16:36     ` Devin Heitmueller
2023-08-10 12:12       ` Kieran Kunhya
2023-08-10 12:20         ` Devin Heitmueller
2023-08-10 12:41           ` Kieran Kunhya
2023-08-10 12:48             ` Kieran Kunhya
2023-08-10 12:58               ` Devin Heitmueller
2023-08-10 13:08                 ` Kieran Kunhya
2023-08-10 15:12                   ` Devin Heitmueller
2023-08-10 15:53                     ` Kieran Kunhya
2023-07-31 13:38 ` [FFmpeg-devel] [PATCH v4 3/4] mpegtsenc: Add support for output of SCTE-35 streams over TS Devin Heitmueller
2023-07-31 13:38 ` Devin Heitmueller [this message]
2023-08-04 11:16 ` [FFmpeg-devel] [PATCH v4 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
2023-08-08 14:31   ` Devin Heitmueller
2023-08-08 15:30     ` Dennis Mungai
2023-09-01  9:29       ` Dennis Mungai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1690810686-4723-5-git-send-email-dheitmueller@ltnglobal.com \
    --to=devin.heitmueller@ltnglobal.com \
    --cc=dheitmueller@ltnglobal.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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