* [FFmpeg-devel] [PATCH v3 1/4] avcodec: Add new side data type to contain original PTS value
2023-07-21 20:37 [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
@ 2023-07-21 20:37 ` Devin Heitmueller
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 2/4] mpegts: Stash original PTS for SCTE-35 sections for processing later Devin Heitmueller
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Devin Heitmueller @ 2023-07-21 20:37 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
In order to properly process SCTE-35 packets, we need the original
PTS value from the demux (i.e. not mangled by the application or
reclocked for the output). This allows us to set the pts_adjustment
field in an BSF on the output side.
Introduce a new side data type to store the original PTS.
Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
libavcodec/defs.h | 12 ++++++++++++
libavcodec/packet.h | 11 +++++++++++
2 files changed, 23 insertions(+)
diff --git a/libavcodec/defs.h b/libavcodec/defs.h
index fbe3254..ff50d25 100644
--- a/libavcodec/defs.h
+++ b/libavcodec/defs.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include "libavutil/rational.h"
/**
* @ingroup lavc_decoding
@@ -119,6 +120,17 @@ typedef struct AVPanScan {
} AVPanScan;
/**
+ * Original Transport Timestamp. Provides the original timestamp
+ * of the packet as specified by the libavformat source This allows that
+ * data to be used in calculations even if the clocks have been
+ * rebased or otherwise modified.
+ */
+typedef struct AVTransportTimestamp {
+ int64_t pts;
+ AVRational time_base;
+} AVTransportTimestamp;
+
+/**
* This structure describes the bitrate properties of an encoded bitstream. It
* roughly corresponds to a subset the VBV parameters for MPEG-2 or HRD
* parameters for H.264/HEVC.
diff --git a/libavcodec/packet.h b/libavcodec/packet.h
index f28e7e7..8b650a8 100644
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -300,6 +300,17 @@ enum AVPacketSideDataType {
AV_PKT_DATA_DYNAMIC_HDR10_PLUS,
/**
+ * Provides the original PTS when passed through the demux. This can
+ * be used to offset any subsequent changes made by the caller to
+ * adjust PTS values (such as pts_offset). We need this for SCTE-35,
+ * since by the time the packets reach the output the PTS values have
+ * already been re-written, and we cannot calculate pre-roll values
+ * using the PTS values embedded in the packet content
+ * Format for this data can be found in AVTransportTimestamp struct
+ */
+ AV_PKT_DATA_TRANSPORT_TIMESTAMP,
+
+ /**
* The number of side data types.
* This is not part of the public API/ABI in the sense that it may
* change when new side data types are added.
--
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".
^ permalink raw reply [flat|nested] 7+ messages in thread
* [FFmpeg-devel] [PATCH v3 2/4] mpegts: Stash original PTS for SCTE-35 sections for processing later
2023-07-21 20:37 [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 1/4] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
@ 2023-07-21 20:37 ` Devin Heitmueller
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 3/4] mpegtsenc: Add support for output of SCTE-35 streams over TS Devin Heitmueller
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Devin Heitmueller @ 2023-07-21 20:37 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
We need the original PTS value in order to do subsequent processing,
so set it as packet side data.
Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
libavformat/mpegts.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 0b3edda..a1b2420 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -1783,8 +1783,17 @@ static void scte_data_cb(MpegTSFilter *filter, const uint8_t *section,
prg = av_find_program_from_stream(ts->stream, NULL, idx);
if (prg && prg->pcr_pid != -1 && prg->discard != AVDISCARD_ALL) {
MpegTSFilter *f = ts->pids[prg->pcr_pid];
- if (f && f->last_pcr != -1)
+ if (f && f->last_pcr != -1) {
+ AVTransportTimestamp *transport_ts;
ts->pkt->pts = ts->pkt->dts = f->last_pcr/300;
+ transport_ts = (AVTransportTimestamp *) av_packet_new_side_data(ts->pkt,
+ AV_PKT_DATA_TRANSPORT_TIMESTAMP,
+ sizeof(AVTransportTimestamp));
+ if (transport_ts) {
+ transport_ts->pts = ts->pkt->pts;
+ transport_ts->time_base = av_make_q(1, 90000);
+ }
+ }
}
ts->stop_parse = 1;
--
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".
^ permalink raw reply [flat|nested] 7+ messages in thread
* [FFmpeg-devel] [PATCH v3 3/4] mpegtsenc: Add support for output of SCTE-35 streams over TS
2023-07-21 20:37 [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 1/4] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 2/4] mpegts: Stash original PTS for SCTE-35 sections for processing later Devin Heitmueller
@ 2023-07-21 20:37 ` Devin Heitmueller
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 4/4] bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when reclocking Devin Heitmueller
2023-07-27 15:08 ` [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
4 siblings, 0 replies; 7+ messages in thread
From: Devin Heitmueller @ 2023-07-21 20:37 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
Introduce the ability to pass through SCTE-35 packets when creating
MPEG transport streams. Note that this patch makes no effort to
change the PTS values in the SCTE-35 packets, and thus only works
when not reclocking the stream (i.e. using -copyts). A subsequent
patch includes a BSF to recompute the PTS values.
Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
libavformat/mpegts.h | 1 +
libavformat/mpegtsenc.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++---
libavformat/mux.c | 6 ++--
3 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
index a48f14e..a7aaaba 100644
--- a/libavformat/mpegts.h
+++ b/libavformat/mpegts.h
@@ -137,6 +137,7 @@
#define STREAM_TYPE_AUDIO_AC3 0x81
#define STREAM_TYPE_AUDIO_DTS 0x82
#define STREAM_TYPE_AUDIO_TRUEHD 0x83
+#define STREAM_TYPE_SCTE_35 0x86
#define STREAM_TYPE_AUDIO_EAC3 0x87
/* ISO/IEC 13818-1 Table 2-22 */
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 700fc54..c6cd1fd 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -425,6 +425,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st)
case AV_CODEC_ID_SMPTE_2038:
stream_type = STREAM_TYPE_PRIVATE_DATA;
break;
+ case AV_CODEC_ID_SCTE_35:
+ stream_type = STREAM_TYPE_SCTE_35;
+ break;
case AV_CODEC_ID_DVB_SUBTITLE:
case AV_CODEC_ID_DVB_TELETEXT:
case AV_CODEC_ID_ARIB_CAPTION:
@@ -522,6 +525,16 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
*q++ = 0xfc; // private_data_byte
}
+ /* If there is an SCTE-35 stream, we need a registration descriptor
+ at the program level (SCTE 35 2016 Sec 8.1) */
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ if (st->codecpar->codec_id == AV_CODEC_ID_SCTE_35) {
+ put_registration_descriptor(&q, MKTAG('C', 'U', 'E', 'I'));
+ break;
+ }
+ }
+
val = 0xf000 | (q - program_info_length_ptr - 2);
program_info_length_ptr[0] = val >> 8;
program_info_length_ptr[1] = val;
@@ -533,6 +546,14 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
const char default_language[] = "und";
const char *language = lang && strlen(lang->value) >= 3 ? lang->value : default_language;
enum AVCodecID codec_id = st->codecpar->codec_id;
+ uint16_t pid;
+
+ if (st->codecpar->codec_id == AV_CODEC_ID_SCTE_35) {
+ MpegTSSection *sect = st->priv_data;
+ pid = sect->pid;
+ } else {
+ pid = ts_st->pid;
+ }
if (s->nb_programs) {
int k, found = 0;
@@ -556,7 +577,7 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
stream_type = ts->m2ts_mode ? get_m2ts_stream_type(s, st) : get_dvb_stream_type(s, st);
*q++ = stream_type;
- put16(&q, 0xe000 | ts_st->pid);
+ put16(&q, 0xe000 | pid);
desc_length_ptr = q;
q += 2; /* patched after */
@@ -819,6 +840,10 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
putbuf(&q, tag, strlen(tag));
*q++ = 0; /* metadata service ID */
*q++ = 0xF; /* metadata_locator_record_flag|MPEG_carriage_flags|reserved */
+ } else if (st->codecpar->codec_id == AV_CODEC_ID_SCTE_35) {
+ *q++ = 0x8a; /* Cue Identifier Descriptor */
+ *q++ = 0x01; /* length */
+ *q++ = 0x01; /* Cue Stream Type (see Sec 8.2) */
}
break;
}
@@ -1159,6 +1184,33 @@ static int mpegts_init(AVFormatContext *s)
AVStream *st = s->streams[i];
MpegTSWriteStream *ts_st;
+ if (st->codecpar->codec_id == AV_CODEC_ID_SCTE_35) {
+ struct MpegTSSection *sect;
+ sect = av_mallocz(sizeof(MpegTSSection));
+ if (!sect) {
+ ret = AVERROR(ENOMEM);
+ continue;
+ }
+
+ if (st->id < 16) {
+ sect->pid = ts->start_pid + i;
+ } else if (st->id < 0x1FFF) {
+ sect->pid = st->id;
+ } else {
+ av_log(s, AV_LOG_ERROR,
+ "Invalid stream id %d, must be less than 8191\n", st->id);
+ ret = AVERROR(EINVAL);
+ continue;
+ }
+
+ sect->write_packet = section_write_packet;
+ sect->opaque = s;
+ sect->cc = 15;
+ sect->discontinuity= ts->flags & MPEGTS_FLAG_DISCONT;
+ st->priv_data = sect;
+ continue;
+ }
+
ts_st = av_mallocz(sizeof(MpegTSWriteStream));
if (!ts_st) {
return AVERROR(ENOMEM);
@@ -1877,6 +1929,19 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
dts += delay;
}
+ if (st->codecpar->codec_id == AV_CODEC_ID_SCTE_35) {
+ MpegTSSection *s = st->priv_data;
+ uint8_t data[SECTION_LENGTH];
+
+ if (size > SECTION_LENGTH) {
+ av_log(s, AV_LOG_ERROR, "SCTE-35 section too long\n");
+ return AVERROR_INVALIDDATA;
+ }
+ memcpy(data, buf, size);
+ mpegts_write_section(s, data, size);
+ return 0;
+ }
+
if (!ts_st->first_timestamp_checked && (pts == AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE)) {
av_log(s, AV_LOG_ERROR, "first pts and dts value must be set\n");
return AVERROR_INVALIDDATA;
@@ -2149,7 +2214,8 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
return 0;
}
- if (ts_st->payload_size && (ts_st->payload_size + size > ts->pes_payload_size ||
+ if (st->codecpar->codec_id != AV_CODEC_ID_SCTE_35 &&
+ ts_st->payload_size && (ts_st->payload_size + size > ts->pes_payload_size ||
(dts != AV_NOPTS_VALUE && ts_st->payload_dts != AV_NOPTS_VALUE &&
dts - ts_st->payload_dts >= max_audio_delay) ||
ts_st->opus_queued_samples + opus_samples >= 5760 /* 120ms */)) {
@@ -2194,7 +2260,7 @@ static void mpegts_write_flush(AVFormatContext *s)
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
MpegTSWriteStream *ts_st = st->priv_data;
- if (ts_st->payload_size > 0) {
+ if (st->codecpar->codec_id != AV_CODEC_ID_SCTE_35 && ts_st->payload_size > 0) {
mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size,
ts_st->payload_pts, ts_st->payload_dts,
ts_st->payload_flags & AV_PKT_FLAG_KEY, -1);
@@ -2237,7 +2303,7 @@ static void mpegts_deinit(AVFormatContext *s)
for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
MpegTSWriteStream *ts_st = st->priv_data;
- if (ts_st) {
+ if (ts_st && st->codecpar->codec_id != AV_CODEC_ID_SCTE_35) {
av_freep(&ts_st->dvb_ac3_desc);
av_freep(&ts_st->payload);
if (ts_st->amux) {
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 415bd39..55bec25 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -307,7 +307,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT &&
- par->codec_id != AV_CODEC_ID_SMPTE_2038)
+ par->codec_id != AV_CODEC_ID_SMPTE_2038 &&
+ par->codec_id != AV_CODEC_ID_SCTE_35)
si->nb_interleaved_streams++;
}
si->interleave_packet = of->interleave_packet;
@@ -946,7 +947,8 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt,
} else if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT &&
par->codec_id != AV_CODEC_ID_VP8 &&
par->codec_id != AV_CODEC_ID_VP9 &&
- par->codec_id != AV_CODEC_ID_SMPTE_2038) {
+ par->codec_id != AV_CODEC_ID_SMPTE_2038 &&
+ par->codec_id != AV_CODEC_ID_SCTE_35) {
++noninterleaved_count;
}
}
--
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".
^ permalink raw reply [flat|nested] 7+ messages in thread
* [FFmpeg-devel] [PATCH v3 4/4] bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when reclocking
2023-07-21 20:37 [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
` (2 preceding siblings ...)
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 3/4] mpegtsenc: Add support for output of SCTE-35 streams over TS Devin Heitmueller
@ 2023-07-21 20:37 ` Devin Heitmueller
2023-07-27 15:33 ` James Almer
2023-07-27 15:08 ` [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
4 siblings, 1 reply; 7+ messages in thread
From: Devin Heitmueller @ 2023-07-21 20:37 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
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 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 | 103 +++++++++++++++++++++++++++++++++++++++
libavformat/mpegtsenc.c | 2 +
5 files changed, 116 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 1b0226c..4c1b312 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..9870737
--- /dev/null
+++ b/libavcodec/scte35ptsadjust_bsf.c
@@ -0,0 +1,103 @@
+/*
+ * 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] & (int64_t) 0x01 << 32) |
+ ((int64_t) pkt->data[5] << 24) |
+ ((int64_t) pkt->data[6] << 16) |
+ ((int64_t) pkt->data[7] << 8) |
+ ((int64_t) pkt->data[8] );
+
+ 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 &= (int64_t) 0x1ffffffff;
+
+ 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".
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 4/4] bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when reclocking
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 4/4] bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when reclocking Devin Heitmueller
@ 2023-07-27 15:33 ` James Almer
0 siblings, 0 replies; 7+ messages in thread
From: James Almer @ 2023-07-27 15:33 UTC (permalink / raw)
To: ffmpeg-devel
On 7/21/2023 5:37 PM, Devin Heitmueller wrote:
> 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 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 | 103 +++++++++++++++++++++++++++++++++++++++
> libavformat/mpegtsenc.c | 2 +
> 5 files changed, 116 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 1b0226c..4c1b312 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..9870737
> --- /dev/null
> +++ b/libavcodec/scte35ptsadjust_bsf.c
> @@ -0,0 +1,103 @@
> +/*
> + * 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] & (int64_t) 0x01 << 32) |
> + ((int64_t) pkt->data[5] << 24) |
> + ((int64_t) pkt->data[6] << 16) |
> + ((int64_t) pkt->data[7] << 8) |
> + ((int64_t) pkt->data[8] );
I think this is cleaner:
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 &= (int64_t) 0x1ffffffff;
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;
_______________________________________________
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] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35
2023-07-21 20:37 [FFmpeg-devel] [PATCH v3 0/4] Add passthrough support for SCTE-35 Devin Heitmueller
` (3 preceding siblings ...)
2023-07-21 20:37 ` [FFmpeg-devel] [PATCH v3 4/4] bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when reclocking Devin Heitmueller
@ 2023-07-27 15:08 ` Devin Heitmueller
4 siblings, 0 replies; 7+ messages in thread
From: Devin Heitmueller @ 2023-07-27 15:08 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
On Fri, Jul 21, 2023 at 4:38 PM Devin Heitmueller
<devin.heitmueller@ltnglobal.com> wrote:
>
> Properly set up the MPEG-TS mux and recalculate the pts_adjust field
> in SCTE_35 packets, such that a user can transparently pass through
> SCTE-35 streams when both the input and output are MPEG-TS.
>
> This patch series rebased against master and a patch to hack around
> periodic PCR retransmission has been dropped as the behavior is
> no longer reproducible in master.
>
> Devin Heitmueller (4):
> avcodec: Add new side data type to contain original PTS value
> mpegts: Stash original PTS for SCTE-35 sections for processing later
> mpegtsenc: Add support for output of SCTE-35 streams over TS
> bsf: Add new bitstream filter to set SCTE-35 pts_adjustment when
> reclocking
>
> doc/bitstream_filters.texi | 9 ++++
> libavcodec/Makefile | 1 +
> libavcodec/bitstream_filters.c | 1 +
> libavcodec/defs.h | 12 +++++
> libavcodec/packet.h | 11 +++++
> libavcodec/scte35ptsadjust_bsf.c | 103 +++++++++++++++++++++++++++++++++++++++
> libavformat/mpegts.c | 11 ++++-
> libavformat/mpegts.h | 1 +
> libavformat/mpegtsenc.c | 76 +++++++++++++++++++++++++++--
> libavformat/mux.c | 6 ++-
> 10 files changed, 224 insertions(+), 7 deletions(-)
> create mode 100644 libavcodec/scte35ptsadjust_bsf.c
>
> --
> 1.8.3.1
>
Given all the comments/feedback has been addressed and there haven't
been any further comments, is there any reason this can't be merged by
someone?
Thank you,
Devin
--
Devin Heitmueller, Senior Software Engineer
LTN Global Communications
o: +1 (301) 363-1001
w: https://ltnglobal.com e: devin.heitmueller@ltnglobal.com
_______________________________________________
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] 7+ messages in thread