[FFmpeg-devel] [PATCH] adding support for writing m2ts bluray container
Herr Sven Alisch BSc.
svenali
Sat Feb 12 00:23:38 CET 2011
Dear developer,
sorry, if I am making mistakes. I am a beginner, who want to offer a patch that adding support for m2ts (MPEG 2 Transport Streams). I know that ffmpeg can read such files but not write them. I needed this feature for my app. So I want to share my code. I hope it is ok.
I had to modify the Makefile, allformats.c and mpegtsenc.c under /libavformat.
Here he is:
diff --git a/libavformat/Makefile b/libavformat/Makefile
index f408ad9..1d4e75e 100644
--- a/a/libavformat/Makefile
+++ b/b/libavformat/Makefile
@@ -145,7 +145,6 @@ OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += rawenc.o
OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o
OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o isom.o
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o adtsenc.o
-OBJS-$(CONFIG_MPEG2TS_MUXER) += mpegtsenc.o adtsenc.o
OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += mpegvideodec.o rawdec.o
OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o
OBJS-$(CONFIG_MSNWC_TCP_DEMUXER) += msnwc_tcp.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 55045f0..0ff4b5a 100644
--- a/a/libavformat/allformats.c
+++ b/b/libavformat/allformats.c
@@ -135,7 +135,6 @@ void av_register_all(void)
REGISTER_MUXER (MPEG2VOB, mpeg2vob);
REGISTER_DEMUXER (MPEGPS, mpegps);
REGISTER_MUXDEMUX (MPEGTS, mpegts);
- REGISTER_MUXER (MPEG2TS, mpeg2ts);
REGISTER_DEMUXER (MPEGTSRAW, mpegtsraw);
REGISTER_DEMUXER (MPEGVIDEO, mpegvideo);
REGISTER_MUXER (MPJPEG, mpjpeg);
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 39a6bee..b1bccd1 100644
--- a/a/libavformat/mpegtsenc.c
+++ b/b/libavformat/mpegtsenc.c
@@ -1,7 +1,6 @@
/*
* MPEG2 transport stream (aka DVB) muxer
* Copyright (c) 2003 Fabrice Bellard
- * M2TS patches Copyright (c) 2011 Sven Alisch
*
* This file is part of FFmpeg.
*
@@ -67,11 +66,6 @@ typedef struct MpegTSWrite {
int64_t first_pcr;
int mux_rate; ///< set to 1 when VBR
- int64_t last_arrival_time_stamp; /* contains the last written arrival timestamp */
- int counted_null_packets; /* Null Packets were not written into m2ts streams. But the pcr has to calculate with the bytes not written. */
- int last_null_packets; /* To calculate the exact arrival_time_stamp, we have to get the number of last counted null packets. */
- int m2ts_mode; /* 0, if not, 1 if yes */
-
int transport_stream_id;
int original_network_id;
int service_id;
@@ -101,29 +95,6 @@ static const AVClass mpegts_muxer_class = {
LIBAVUTIL_VERSION_INT,
};
-/* generates a arrival time stamp for the m2ts header */
-static int64_t get_arrival_time_stamp(MpegTSWrite *ts, ByteIOContext *pb)
-{
- int64_t pcr_diff = (ts->last_null_packets + 1) * av_rescale(188 * 8, PCR_TIME_BASE, ts->mux_rate);
-
- ts->last_arrival_time_stamp += pcr_diff;
- return ts->last_arrival_time_stamp;
-}
-
-/* The arrival_time_stamp consists of 4 byte. The first two bits are reserved for a copyright and should set to 11 (binary) */
-static void write_starttime_code(uint8_t* q, int64_t arrival_time_stamp)
-{
- *q = 3 << 6;
- int val = (arrival_time_stamp >> 24) & 0xFF;
- *q++ |= val;
- val = (arrival_time_stamp >> 16) & 0xFF;
- *q++ = val;
- val = (arrival_time_stamp >> 8) & 0xFF;
- *q++ = val;
- val = arrival_time_stamp;
- *q++ = val;
-}
-
/* NOTE: 4 bytes must be left at the end for the crc32 */
static void mpegts_write_section(MpegTSSection *s, uint8_t *buf, int len)
{
@@ -440,20 +411,6 @@ static void section_write_packet(MpegTSSection *s, const uint8_t *packet)
put_buffer(ctx->pb, packet, TS_PACKET_SIZE);
}
-/* a version for m2ts streams */
-static void section_write_packet2(MpegTSSection *s, const uint8_t *packet)
-{
- AVFormatContext *ctx = s->opaque;
- MpegTSWrite *ts = ctx->priv_data;
- uint8_t buf[TS_PACKET_SIZE + 4];
- int64_t arrival_time_stamp = get_arrival_time_stamp(ctx->priv_data, ctx->pb);
-
- write_starttime_code(buf, arrival_time_stamp);
- memcpy(&buf[4], packet, TS_PACKET_SIZE);
-
- put_buffer(ctx->pb, buf, TS_PACKET_SIZE + 4);
-}
-
static int mpegts_write_header(AVFormatContext *s)
{
MpegTSWrite *ts = s->priv_data;
@@ -466,13 +423,8 @@ static int mpegts_write_header(AVFormatContext *s)
const char *provider_name;
int *pids;
- if (ts->m2ts_mode != 1) /* if mpeg2ts_write_header is not called first */
- ts->m2ts_mode = 0;
ts->tsid = ts->transport_stream_id;
ts->onid = ts->original_network_id;
- /* Initializing the m2ts parameters. Not important for normal ts streams! */
- ts->counted_null_packets = 0;
- ts->last_null_packets = 0;
/* allocate a single DVB service */
title = av_metadata_get(s->metadata, "service_name", NULL, 0);
if (!title)
@@ -481,27 +433,18 @@ static int mpegts_write_header(AVFormatContext *s)
provider = av_metadata_get(s->metadata, "service_provider", NULL, 0);
provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME;
service = mpegts_add_service(ts, ts->service_id, provider_name, service_name);
- if (ts->m2ts_mode == 1)
- service->pmt.write_packet = section_write_packet2;
- else
- service->pmt.write_packet = section_write_packet;
+ service->pmt.write_packet = section_write_packet;
service->pmt.opaque = s;
service->pmt.cc = 15;
ts->pat.pid = PAT_PID;
ts->pat.cc = 15; // Initialize at 15 so that it wraps and be equal to 0 for the first packet we write
- if (ts->m2ts_mode == 1)
- ts->pat.write_packet = section_write_packet2;
- else
- ts->pat.write_packet = section_write_packet;
+ ts->pat.write_packet = section_write_packet;
ts->pat.opaque = s;
ts->sdt.pid = SDT_PID;
ts->sdt.cc = 15;
- if (ts->m2ts_mode == 1)
- ts->sdt.write_packet = section_write_packet2;
- else
- ts->sdt.write_packet = section_write_packet;
+ ts->sdt.write_packet = section_write_packet;
ts->sdt.opaque = s;
pids = av_malloc(s->nb_streams * sizeof(*pids));
@@ -645,12 +588,7 @@ static void retransmit_si_info(AVFormatContext *s)
static int64_t get_pcr(const MpegTSWrite *ts, ByteIOContext *pb)
{
- /* if a m2ts is build, an offset is possible (depends on the muxrate), because
- the null packets are only counted and NOT written! So url_ftell gives not the correct
- written bytes. We have to add an offset of 192 multiplied by counted null packets. */
- int byteoffset = (TS_PACKET_SIZE + 4) * ts->counted_null_packets;
-
- return av_rescale(url_ftell(pb) + byteoffset + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
+ return av_rescale(url_ftell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
ts->first_pcr;
}
@@ -690,7 +628,6 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
MpegTSWriteStream *ts_st = st->priv_data;
uint8_t *q;
uint8_t buf[TS_PACKET_SIZE];
- uint8_t source_packet[TS_PACKET_SIZE + 4];
q = buf;
*q++ = 0x47;
@@ -706,16 +643,7 @@ static void mpegts_insert_pcr_only(AVFormatContext *s, AVStream *st)
/* stuffing bytes */
memset(q, 0xFF, TS_PACKET_SIZE - (q - buf));
-
- if (ts->m2ts_mode == 1) {
- memcpy(&source_packet[4], buf, TS_PACKET_SIZE);
- int64_t arrival_time_stamp = get_arrival_time_stamp(ts, s->pb);
- write_starttime_code(source_packet, arrival_time_stamp);
-
- put_buffer(s->pb, source_packet, TS_PACKET_SIZE + 4);
- }
- else
- put_buffer(s->pb, buf, TS_PACKET_SIZE);
+ put_buffer(s->pb, buf, TS_PACKET_SIZE);
}
static void write_pts(uint8_t *q, int fourbits, int64_t pts)
@@ -744,7 +672,6 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
MpegTSWriteStream *ts_st = st->priv_data;
MpegTSWrite *ts = s->priv_data;
uint8_t buf[TS_PACKET_SIZE];
- uint8_t source_packet[TS_PACKET_SIZE + 4]; /* we copy the content from buf into source_packet if m2ts mode :-) */
uint8_t *q;
int val, is_start, len, header_len, write_pcr, private_code, flags;
int afc_len, stuffing_len;
@@ -771,14 +698,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
/* pcr insert gets priority over null packet insert */
if (write_pcr)
mpegts_insert_pcr_only(s, st);
- else {
- if (ts->m2ts_mode == 1) {
- ts->counted_null_packets++;
- ts->last_null_packets++;
- }
- else
- mpegts_insert_null_packet(s);
- }
+ else
+ mpegts_insert_null_packet(s);
continue; /* recalculate write_pcr and possibly retransmit si_info */
}
@@ -916,19 +837,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
memcpy(buf + TS_PACKET_SIZE - len, payload, len);
payload += len;
payload_size -= len;
- if (ts->m2ts_mode == 1) {
- memcpy(&source_packet[4], buf, TS_PACKET_SIZE);
- int64_t arrival_time_stamp = get_arrival_time_stamp(s->priv_data, s->pb);
-
- if (ts->last_null_packets > 0) {
- ts->last_null_packets = 0;
- }
-
- write_starttime_code(source_packet, arrival_time_stamp);
- put_buffer(s->pb, source_packet, TS_PACKET_SIZE + 4);
- }
- else
- put_buffer(s->pb, buf, TS_PACKET_SIZE);
+ put_buffer(s->pb, buf, TS_PACKET_SIZE);
}
put_flush_packet(s->pb);
}
@@ -1066,14 +975,6 @@ static int mpegts_write_end(AVFormatContext *s)
return 0;
}
-/* resetting the function pointer */
-static int mpeg2ts_write_header(AVFormatContext *s)
-{
- MpegTSWrite *ts = s->priv_data;
- ts->m2ts_mode = 1;
- return mpegts_write_header(s);
-}
-
AVOutputFormat ff_mpegts_muxer = {
"mpegts",
NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"),
@@ -1087,17 +988,3 @@ AVOutputFormat ff_mpegts_muxer = {
mpegts_write_end,
.priv_class = &mpegts_muxer_class,
};
-
-AVOutputFormat ff_mpeg2ts_muxer = {
- "mpeg2ts",
- NULL_IF_CONFIG_SMALL("BDAV MPEG-2 transport stream format"),
- "video/x-mpeg2ts",
- "m2ts",
- sizeof(MpegTSWrite),
- CODEC_ID_MP2,
- CODEC_ID_MPEG2VIDEO,
- mpeg2ts_write_header,
- mpegts_write_packet,
- mpegts_write_end,
- .priv_class = &mpegts_muxer_class,
-};
regards,
Sven
PS: I wish you a nice weekend!
More information about the ffmpeg-devel
mailing list