mirror of https://git.ffmpeg.org/ffmpeg.git
Add support for BDAV/m2ts-mode muxing
Signed-off-by: Fredrik Axelsson <fraxbe@gmail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
26e20dfd06
commit
8f8caca224
|
@ -78,6 +78,7 @@ typedef struct MpegTSWrite {
|
||||||
|
|
||||||
int pmt_start_pid;
|
int pmt_start_pid;
|
||||||
int start_pid;
|
int start_pid;
|
||||||
|
int m2ts_mode;
|
||||||
|
|
||||||
int reemit_pat_pmt; // backward compatibility
|
int reemit_pat_pmt; // backward compatibility
|
||||||
|
|
||||||
|
@ -465,9 +466,28 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts, int sid,
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
|
||||||
|
{
|
||||||
|
return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
|
||||||
|
ts->first_pcr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mpegts_prefix_m2ts_header(AVFormatContext *s)
|
||||||
|
{
|
||||||
|
MpegTSWrite *ts = s->priv_data;
|
||||||
|
if (ts->m2ts_mode) {
|
||||||
|
int64_t pcr = get_pcr(s->priv_data, s->pb);
|
||||||
|
uint32_t tp_extra_header = pcr % 0x3fffffff;
|
||||||
|
tp_extra_header = AV_RB32(&tp_extra_header);
|
||||||
|
avio_write(s->pb, (unsigned char *) &tp_extra_header,
|
||||||
|
sizeof(tp_extra_header));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void section_write_packet(MpegTSSection *s, const uint8_t *packet)
|
static void section_write_packet(MpegTSSection *s, const uint8_t *packet)
|
||||||
{
|
{
|
||||||
AVFormatContext *ctx = s->opaque;
|
AVFormatContext *ctx = s->opaque;
|
||||||
|
mpegts_prefix_m2ts_header(ctx);
|
||||||
avio_write(ctx->pb, packet, TS_PACKET_SIZE);
|
avio_write(ctx->pb, packet, TS_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,6 +685,14 @@ static int mpegts_write_header(AVFormatContext *s)
|
||||||
service->pcr_packet_period,
|
service->pcr_packet_period,
|
||||||
ts->sdt_packet_period, ts->pat_packet_period);
|
ts->sdt_packet_period, ts->pat_packet_period);
|
||||||
|
|
||||||
|
if (ts->m2ts_mode == -1) {
|
||||||
|
if (av_match_ext(s->filename, "m2ts")) {
|
||||||
|
ts->m2ts_mode = 1;
|
||||||
|
} else {
|
||||||
|
ts->m2ts_mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
avio_flush(s->pb);
|
avio_flush(s->pb);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -705,12 +733,6 @@ static void retransmit_si_info(AVFormatContext *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
|
|
||||||
{
|
|
||||||
return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
|
|
||||||
ts->first_pcr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int write_pcr_bits(uint8_t *buf, int64_t pcr)
|
static int write_pcr_bits(uint8_t *buf, int64_t pcr)
|
||||||
{
|
{
|
||||||
int64_t pcr_low = pcr % 300, pcr_high = pcr / 300;
|
int64_t pcr_low = pcr % 300, pcr_high = pcr / 300;
|
||||||
|
@ -737,6 +759,7 @@ static void mpegts_insert_null_packet(AVFormatContext *s)
|
||||||
*q++ = 0xff;
|
*q++ = 0xff;
|
||||||
*q++ = 0x10;
|
*q++ = 0x10;
|
||||||
memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf));
|
memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf));
|
||||||
|
mpegts_prefix_m2ts_header(s);
|
||||||
avio_write(s->pb, buf, TS_PACKET_SIZE);
|
avio_write(s->pb, buf, TS_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,6 +785,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
|
||||||
|
|
||||||
/* stuffing bytes */
|
/* stuffing bytes */
|
||||||
memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
|
memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
|
||||||
|
mpegts_prefix_m2ts_header(s);
|
||||||
avio_write(s->pb, buf, TS_PACKET_SIZE);
|
avio_write(s->pb, buf, TS_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,6 +1017,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
|
||||||
memcpy(buf + TS_PACKET_SIZE - len, payload, len);
|
memcpy(buf + TS_PACKET_SIZE - len, payload, len);
|
||||||
payload += len;
|
payload += len;
|
||||||
payload_size -= len;
|
payload_size -= len;
|
||||||
|
mpegts_prefix_m2ts_header(s);
|
||||||
avio_write(s->pb, buf, TS_PACKET_SIZE);
|
avio_write(s->pb, buf, TS_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
avio_flush(s->pb);
|
avio_flush(s->pb);
|
||||||
|
@ -1206,6 +1231,9 @@ static const AVOption options[] = {
|
||||||
{ "mpegts_start_pid", "Set the first pid.",
|
{ "mpegts_start_pid", "Set the first pid.",
|
||||||
offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
|
offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
|
||||||
{ .i64 = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
|
{ .i64 = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
|
||||||
|
{"mpegts_m2ts_mode", "Enable m2ts mode.",
|
||||||
|
offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_INT,
|
||||||
|
{ .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
|
||||||
{ "muxrate", NULL,
|
{ "muxrate", NULL,
|
||||||
offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT,
|
offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT,
|
||||||
{ .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
|
{ .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
|
||||||
|
@ -1242,7 +1270,7 @@ AVOutputFormat ff_mpegts_muxer = {
|
||||||
.name = "mpegts",
|
.name = "mpegts",
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"),
|
.long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"),
|
||||||
.mime_type = "video/x-mpegts",
|
.mime_type = "video/x-mpegts",
|
||||||
.extensions = "ts,m2t",
|
.extensions = "ts,m2t,m2ts",
|
||||||
.priv_data_size = sizeof(MpegTSWrite),
|
.priv_data_size = sizeof(MpegTSWrite),
|
||||||
.audio_codec = AV_CODEC_ID_MP2,
|
.audio_codec = AV_CODEC_ID_MP2,
|
||||||
.video_codec = AV_CODEC_ID_MPEG2VIDEO,
|
.video_codec = AV_CODEC_ID_MPEG2VIDEO,
|
||||||
|
|
Loading…
Reference in New Issue