Commit 2fb55089 authored by Marton Balint's avatar Marton Balint

avformat/mpegtsenc: get rid of packet counting for sdt/pat/pmt

The packet counting based approach caused excessive sdt/pat/pmt for VBR, so
let's use a timestamp based approach instead similar to how we emit PCRs.
SDT/PAT/PMT period should be consistent for both VBR and CBR from now on.

Also change the type of sdt_period and pat_period to AV_OPT_TYPE_DURATION so no
floating point math is necessary.

Fixes ticket #3714.
Signed-off-by: 's avatarMarton Balint <cus@passwd.hu>
parent 5c119bf1
......@@ -1624,11 +1624,11 @@ Override the default PCR retransmission time in milliseconds. Default is
20 ms is used for CBR streams, the highest multiple of the frame duration which
is less than 100 ms is used for VBR streams.
@item pat_period @var{double}
Maximum time in seconds between PAT/PMT tables.
@item pat_period @var{duration}
Maximum time in seconds between PAT/PMT tables. Default is @code{0.1}.
@item sdt_period @var{double}
Maximum time in seconds between SDT tables.
@item sdt_period @var{duration}
Maximum time in seconds between SDT tables. Default is @code{0.5}.
@item tables_version @var{integer}
Set PAT, PMT and SDT version (default @code{0}, valid values are from 0 to 31, inclusively).
......
......@@ -76,10 +76,8 @@ typedef struct MpegTSWrite {
MpegTSSection pat; /* MPEG-2 PAT table */
MpegTSSection sdt; /* MPEG-2 SDT table context */
MpegTSService **services;
int sdt_packet_count;
int sdt_packet_period;
int pat_packet_count;
int pat_packet_period;
int64_t sdt_period; /* SDT period in PCR time base */
int64_t pat_period; /* PAT/PMT period in PCR time base */
int nb_services;
int onid;
int tsid;
......@@ -106,8 +104,8 @@ typedef struct MpegTSWrite {
int flags;
int copyts;
int tables_version;
double pat_period;
double sdt_period;
int64_t pat_period_us;
int64_t sdt_period_us;
int64_t last_pat_ts;
int64_t last_sdt_ts;
......@@ -978,17 +976,6 @@ static int mpegts_init(AVFormatContext *s)
av_freep(&pids);
if (ts->mux_rate > 1) {
ts->sdt_packet_period = (int64_t)ts->mux_rate * SDT_RETRANS_TIME /
(TS_PACKET_SIZE * 8 * 1000);
ts->pat_packet_period = (int64_t)ts->mux_rate * PAT_RETRANS_TIME /
(TS_PACKET_SIZE * 8 * 1000);
} else {
/* Arbitrary values, PAT/PMT will also be written on video key frames */
ts->sdt_packet_period = 200;
ts->pat_packet_period = 40;
}
if (ts->copyts < 1)
ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
......@@ -996,24 +983,17 @@ static int mpegts_init(AVFormatContext *s)
ts->last_pat_ts = AV_NOPTS_VALUE;
ts->last_sdt_ts = AV_NOPTS_VALUE;
// The user specified a period, use only it
if (ts->pat_period < INT_MAX/2) {
ts->pat_packet_period = INT_MAX;
}
if (ts->sdt_period < INT_MAX/2) {
ts->sdt_packet_period = INT_MAX;
}
ts->pat_packet_count = ts->pat_packet_period - 1;
ts->sdt_packet_count = ts->sdt_packet_period - 1;
ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE);
ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE);
if (ts->mux_rate == 1)
av_log(s, AV_LOG_VERBOSE, "muxrate VBR, ");
else
av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
av_log(s, AV_LOG_VERBOSE,
"sdt every %d, pat/pmt every %d pkts\n",
ts->sdt_packet_period, ts->pat_packet_period);
"sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms\n",
av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE),
av_rescale(ts->pat_period, 1000, PCR_TIME_BASE));
if (ts->m2ts_mode == -1) {
if (av_match_ext(s->url, "m2ts")) {
......@@ -1031,27 +1011,24 @@ fail:
}
/* send SDT, PAT and PMT tables regularly */
static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts)
static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int64_t pcr)
{
MpegTSWrite *ts = s->priv_data;
int i;
if (++ts->sdt_packet_count == ts->sdt_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0)
if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
(pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) ||
force_sdt
) {
ts->sdt_packet_count = 0;
if (dts != AV_NOPTS_VALUE)
ts->last_sdt_ts = FFMAX(dts, ts->last_sdt_ts);
if (pcr != AV_NOPTS_VALUE)
ts->last_sdt_ts = FFMAX(pcr, ts->last_sdt_ts);
mpegts_write_sdt(s);
}
if (++ts->pat_packet_count == ts->pat_packet_period ||
(dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
(dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
if ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
(pcr != AV_NOPTS_VALUE && pcr - ts->last_pat_ts >= ts->pat_period) ||
force_pat) {
ts->pat_packet_count = 0;
if (dts != AV_NOPTS_VALUE)
ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts);
if (pcr != AV_NOPTS_VALUE)
ts->last_pat_ts = FFMAX(pcr, ts->last_pat_ts);
mpegts_write_pat(s);
for (i = 0; i < ts->nb_services; i++)
mpegts_write_pmt(s, ts->services[i]);
......@@ -1181,18 +1158,30 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
int afc_len, stuffing_len;
int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
int force_sdt = 0;
av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
force_pat = 1;
}
if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) {
force_pat = 1;
force_sdt = 1;
ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT;
}
is_start = 1;
while (payload_size > 0) {
int64_t pcr = -1; /* avoid warning */
int64_t pcr = AV_NOPTS_VALUE;
if (ts->mux_rate > 1)
pcr = get_pcr(ts, s->pb);
else if (dts != AV_NOPTS_VALUE)
pcr = (dts - delay) * 300;
retransmit_si_info(s, force_pat, dts);
retransmit_si_info(s, force_pat, force_sdt, pcr);
force_pat = 0;
force_sdt = 0;
write_pcr = 0;
if (ts->mux_rate > 1) {
......@@ -1230,8 +1219,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
/* recalculate write_pcr and possibly retransmit si_info */
continue;
}
} else if (ts_st->pcr_period && dts != AV_NOPTS_VALUE) {
pcr = (dts - delay) * 300;
} else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) {
if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) {
ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period);
write_pcr = 1;
......@@ -1555,12 +1543,6 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
if (side_data)
stream_id = side_data[0];
if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) {
ts->pat_packet_count = ts->pat_packet_period - 1;
ts->sdt_packet_count = ts->sdt_packet_period - 1;
ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT;
}
if (ts->copyts < 1) {
if (pts != AV_NOPTS_VALUE)
pts += delay;
......@@ -1965,11 +1947,11 @@ static const AVOption options[] = {
offsetof(MpegTSWrite, pcr_period_ms), AV_OPT_TYPE_INT,
{ .i64 = -1 }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
{ "pat_period", "PAT/PMT retransmission time limit in seconds",
offsetof(MpegTSWrite, pat_period), AV_OPT_TYPE_DOUBLE,
{ .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
offsetof(MpegTSWrite, pat_period_us), AV_OPT_TYPE_DURATION,
{ .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM },
{ "sdt_period", "SDT retransmission time limit in seconds",
offsetof(MpegTSWrite, sdt_period), AV_OPT_TYPE_DOUBLE,
{ .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
offsetof(MpegTSWrite, sdt_period_us), AV_OPT_TYPE_DURATION,
{ .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM },
{ NULL },
};
......
......@@ -33,7 +33,7 @@
// Also please add any ticket numbers that you believe might be affected here
#define LIBAVFORMAT_VERSION_MAJOR 58
#define LIBAVFORMAT_VERSION_MINOR 31
#define LIBAVFORMAT_VERSION_MICRO 101
#define LIBAVFORMAT_VERSION_MICRO 102
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
......
165d022ab86306d069797acff0c1e295 *tests/data/fate/acodec-s302m.mpegts
1589164 tests/data/fate/acodec-s302m.mpegts
0bf5457fd41a22fc5cdd99ae5ad4e273 *tests/data/fate/acodec-s302m.mpegts
1527688 tests/data/fate/acodec-s302m.mpegts
31f25a0020fd9017de9c3c608316854b *tests/data/fate/acodec-s302m.out.wav
stddev: 986.94 PSNR: 36.44 MAXDIFF:18571 bytes: 1058400/ 1056708
38f4b14d43a0e416be8d598628997cbc *tests/data/lavf/lavf.ts
407020 tests/data/lavf/lavf.ts
371dc016eb3155116bea27e3b4eeb928 *tests/data/lavf/lavf.ts
389160 tests/data/lavf/lavf.ts
tests/data/lavf/lavf.ts CRC=0x71287e25
......@@ -2,51 +2,51 @@ ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st:-1 flags:0 ts:-1.000000
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st:-1 flags:1 ts: 1.894167
ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.920000 pos: 189692 size: 24786
ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.920000 pos: 181420 size: 24786
ret: 0 st: 0 flags:0 ts: 0.788333
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 0 flags:1 ts:-0.317500
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 1 flags:0 ts: 2.576667
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209
ret: 0 st: 1 flags:1 ts: 1.470833
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208
ret: 0 st:-1 flags:0 ts: 0.365002
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st:-1 flags:1 ts:-0.740831
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 0 flags:0 ts: 2.153333
ret: 0 st: 1 flags:1 dts: 1.794811 pts: 1.794811 pos: 322608 size: 209
ret: 0 st: 1 flags:1 dts: 1.794811 pts: 1.794811 pos: 308508 size: 209
ret: 0 st: 0 flags:1 ts: 1.047500
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 1 flags:0 ts:-0.058333
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208
ret: 0 st: 1 flags:1 ts: 2.835833
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209
ret: 0 st:-1 flags:0 ts: 1.730004
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208
ret: 0 st:-1 flags:1 ts: 0.624171
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 0 flags:0 ts:-0.481667
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 0 flags:1 ts: 2.412500
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209
ret: 0 st: 1 flags:0 ts: 1.306667
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208
ret: 0 st: 1 flags:1 ts: 0.200844
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208
ret: 0 st:-1 flags:0 ts:-0.904994
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st:-1 flags:1 ts: 1.989173
ret: 0 st: 0 flags:0 dts: 1.960000 pts: 2.000000 pos: 235000 size: 15019
ret: 0 st: 0 flags:0 dts: 1.960000 pts: 2.000000 pos: 224848 size: 15019
ret: 0 st: 0 flags:0 ts: 0.883344
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 0 flags:1 ts:-0.222489
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st: 1 flags:0 ts: 2.671678
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209
ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209
ret: 0 st: 1 flags:1 ts: 1.565844
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208
ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208
ret: 0 st:-1 flags:0 ts: 0.460008
ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801
ret: 0 st:-1 flags:1 ts:-0.645825
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment