[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