* [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35
@ 2023-07-03 18:15 Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 1/5] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-03 18:15 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
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 updated to add a time_base field to the new side-data
type, as well as various improvements suggested by Andreas Rheinhardt
to the BSF filter.
Devin Heitmueller (5):
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
mpegtsenc: Don't periodically announce PCR on SCTE-35 streams
bsf: Add new bitstream filter to set 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 | 78 +++++++++++++++++++++++++++--
libavformat/mux.c | 6 ++-
10 files changed, 225 insertions(+), 8 deletions(-)
create mode 100644 libavcodec/scte35ptsadjust_bsf.c
--
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] 8+ messages in thread
* [FFmpeg-devel] [PATCH v2 1/5] avcodec: Add new side data type to contain original PTS value
2023-07-03 18:15 [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35 Devin Heitmueller
@ 2023-07-03 18:15 ` Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 2/5] mpegts: Stash original PTS for SCTE-35 sections for processing later Devin Heitmueller
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-03 18:15 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 deadfe7..173020f 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
@@ -131,6 +132,17 @@ typedef struct AVBarData {
} AVBarData;
/**
+ * 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 bdad21e..6c39a45 100644
--- a/libavcodec/packet.h
+++ b/libavcodec/packet.h
@@ -306,6 +306,17 @@ enum AVPacketSideDataType {
AV_PKT_DATA_BARDATA,
/**
+ * 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] 8+ messages in thread
* [FFmpeg-devel] [PATCH v2 2/5] mpegts: Stash original PTS for SCTE-35 sections for processing later
2023-07-03 18:15 [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35 Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 1/5] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
@ 2023-07-03 18:15 ` Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 3/5] mpegtsenc: Add support for output of SCTE-35 streams over TS Devin Heitmueller
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-03 18:15 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] 8+ messages in thread
* [FFmpeg-devel] [PATCH v2 3/5] mpegtsenc: Add support for output of SCTE-35 streams over TS
2023-07-03 18:15 [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35 Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 1/5] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 2/5] mpegts: Stash original PTS for SCTE-35 sections for processing later Devin Heitmueller
@ 2023-07-03 18:15 ` Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 5/5] bsf: Add new bitstream filter to set pts_adjustment when reclocking Devin Heitmueller
4 siblings, 0 replies; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-03 18:15 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] 8+ messages in thread
* [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams
2023-07-03 18:15 [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35 Devin Heitmueller
` (2 preceding siblings ...)
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 3/5] mpegtsenc: Add support for output of SCTE-35 streams over TS Devin Heitmueller
@ 2023-07-03 18:15 ` Devin Heitmueller
2023-07-03 19:17 ` Marton Balint
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 5/5] bsf: Add new bitstream filter to set pts_adjustment when reclocking Devin Heitmueller
4 siblings, 1 reply; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-03 18:15 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Devin Heitmueller
Changes were made between in the last two years to periodically
send PCR-only packets on all PIDs, but for cases where the stream
may send packets very infrequently (like SCTE-35), this results in
extra TR101290 errors because it fails the PCR interval test.
I am not quite sure what the "right" fix should be for this, but
for now just disable all periodic sending of PCR-only packets on
SCTE-35 streams.
Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
---
libavformat/mpegtsenc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index c6cd1fd..ba60582 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -1579,7 +1579,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
int st2_index = i < st->index ? i : (i + 1 == s->nb_streams ? st->index : i + 1);
AVStream *st2 = s->streams[st2_index];
MpegTSWriteStream *ts_st2 = st2->priv_data;
- if (ts_st2->pcr_period) {
+ if (ts_st2->pcr_period && st2->codecpar->codec_id != AV_CODEC_ID_SCTE_35) {
if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) {
ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period);
if (st2 != st) {
--
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] 8+ messages in thread
* [FFmpeg-devel] [PATCH v2 5/5] bsf: Add new bitstream filter to set pts_adjustment when reclocking
2023-07-03 18:15 [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35 Devin Heitmueller
` (3 preceding siblings ...)
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams Devin Heitmueller
@ 2023-07-03 18:15 ` Devin Heitmueller
4 siblings, 0 replies; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-03 18:15 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 ba60582..728057e 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] 8+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams Devin Heitmueller
@ 2023-07-03 19:17 ` Marton Balint
2023-07-05 15:29 ` Devin Heitmueller
0 siblings, 1 reply; 8+ messages in thread
From: Marton Balint @ 2023-07-03 19:17 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Mon, 3 Jul 2023, Devin Heitmueller wrote:
> Changes were made between in the last two years to periodically
> send PCR-only packets on all PIDs, but for cases where the stream
> may send packets very infrequently (like SCTE-35), this results in
> extra TR101290 errors because it fails the PCR interval test.
>
> I am not quite sure what the "right" fix should be for this, but
> for now just disable all periodic sending of PCR-only packets on
> SCTE-35 streams.
Hmm, only one PID per service should generate PCR, and if there is a video
stream in the service, then that is preferred for PCR generation. An SCTE
stream should only get selected for PCR if there are no video streams in a
service. Or are you seeing something else?
And it is also strange that not sending PCR for any stream improves the
PCR interval test, it should make it worse, because less PCRs are
provided, no?
Thanks,
Marton
>
> Signed-off-by: Devin Heitmueller <dheitmueller@ltnglobal.com>
> ---
> libavformat/mpegtsenc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
> index c6cd1fd..ba60582 100644
> --- a/libavformat/mpegtsenc.c
> +++ b/libavformat/mpegtsenc.c
> @@ -1579,7 +1579,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
> int st2_index = i < st->index ? i : (i + 1 == s->nb_streams ? st->index : i + 1);
> AVStream *st2 = s->streams[st2_index];
> MpegTSWriteStream *ts_st2 = st2->priv_data;
> - if (ts_st2->pcr_period) {
> + if (ts_st2->pcr_period && st2->codecpar->codec_id != AV_CODEC_ID_SCTE_35) {
> if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) {
> ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period);
> if (st2 != st) {
> --
> 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".
>
_______________________________________________
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] 8+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams
2023-07-03 19:17 ` Marton Balint
@ 2023-07-05 15:29 ` Devin Heitmueller
0 siblings, 0 replies; 8+ messages in thread
From: Devin Heitmueller @ 2023-07-05 15:29 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Hi Marton,
On Mon, Jul 3, 2023 at 3:20 PM Marton Balint <cus@passwd.hu> wrote:
> Hmm, only one PID per service should generate PCR, and if there is a video
> stream in the service, then that is preferred for PCR generation. An SCTE
> stream should only get selected for PCR if there are no video streams in a
> service. Or are you seeing something else?
>
> And it is also strange that not sending PCR for any stream improves the
> PCR interval test, it should make it worse, because less PCRs are
> provided, no?
You make valid points. Admittedly this is a patch I wrote a couple of
years ago that has been ported to master, and it's entirely possible
that the description is incorrect. I definitely made the patch in
response to seeing that I was getting recurring PCR packets on the
SCTE-35 stream (which is contrary to SCTE-35's typical behavior where
you typically only get packets on the PID when there is an actual
trigger). Also, you generally don't have PCRs delivered on streams
that are composed only of sections (i.e. not containing PES packets),
although I haven't looked to see if that's technically illegal.
I will back out the patch and better document the behavior I am seeing
and update the patch description so it's more clear why it is needed.
Regards,
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] 8+ messages in thread
end of thread, other threads:[~2023-07-05 15:29 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-03 18:15 [FFmpeg-devel] [PATCH v2 0/5] Add passthrough support for SCTE-35 Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 1/5] avcodec: Add new side data type to contain original PTS value Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 2/5] mpegts: Stash original PTS for SCTE-35 sections for processing later Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 3/5] mpegtsenc: Add support for output of SCTE-35 streams over TS Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 4/5] mpegtsenc: Don't periodically announce PCR on SCTE-35 streams Devin Heitmueller
2023-07-03 19:17 ` Marton Balint
2023-07-05 15:29 ` Devin Heitmueller
2023-07-03 18:15 ` [FFmpeg-devel] [PATCH v2 5/5] bsf: Add new bitstream filter to set pts_adjustment when reclocking Devin Heitmueller
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