Commit 09a858da authored by Fredrik Axelsson's avatar Fredrik Axelsson Committed by Michael Niedermayer

Add support for BDAV/m2ts-mode muxing

Signed-off-by: 's avatarFredrik Axelsson <fraxbe@gmail.com>
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent b118255e
...@@ -75,6 +75,7 @@ typedef struct MpegTSWrite { ...@@ -75,6 +75,7 @@ typedef struct MpegTSWrite {
int pmt_start_pid; int pmt_start_pid;
int start_pid; int start_pid;
int m2ts_mode;
} MpegTSWrite; } MpegTSWrite;
static const AVOption options[] = { static const AVOption options[] = {
...@@ -88,6 +89,9 @@ static const AVOption options[] = { ...@@ -88,6 +89,9 @@ static const AVOption options[] = {
offsetof(MpegTSWrite, pmt_start_pid), FF_OPT_TYPE_INT, {.dbl = 0x1000 }, 0x1000, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM}, offsetof(MpegTSWrite, pmt_start_pid), FF_OPT_TYPE_INT, {.dbl = 0x1000 }, 0x1000, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM},
{ "mpegts_start_pid", "Set the first pid.", { "mpegts_start_pid", "Set the first pid.",
offsetof(MpegTSWrite, start_pid), FF_OPT_TYPE_INT, {.dbl = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM}, offsetof(MpegTSWrite, start_pid), FF_OPT_TYPE_INT, {.dbl = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM},
{"mpegts_m2ts_mode", "Enable m2ts mode.",
offsetof(MpegTSWrite, m2ts_mode), FF_OPT_TYPE_INT, {.dbl = -1 },
-1,1, AV_OPT_FLAG_ENCODING_PARAM},
{ NULL }, { NULL },
}; };
...@@ -434,9 +438,28 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts, ...@@ -434,9 +438,28 @@ static MpegTSService *mpegts_add_service(MpegTSWrite *ts,
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);
} }
...@@ -584,6 +607,14 @@ static int mpegts_write_header(AVFormatContext *s) ...@@ -584,6 +607,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;
...@@ -616,12 +647,6 @@ static void retransmit_si_info(AVFormatContext *s) ...@@ -616,12 +647,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;
...@@ -648,6 +673,7 @@ static void mpegts_insert_null_packet(AVFormatContext *s) ...@@ -648,6 +673,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);
} }
...@@ -673,6 +699,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st) ...@@ -673,6 +699,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);
} }
...@@ -909,6 +936,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, ...@@ -909,6 +936,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);
...@@ -1054,7 +1082,7 @@ AVOutputFormat ff_mpegts_muxer = { ...@@ -1054,7 +1082,7 @@ AVOutputFormat ff_mpegts_muxer = {
.name = "mpegts", .name = "mpegts",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"), .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"),
.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 = CODEC_ID_MP2, .audio_codec = CODEC_ID_MP2,
.video_codec = CODEC_ID_MPEG2VIDEO, .video_codec = CODEC_ID_MPEG2VIDEO,
......
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