better framework for specific mpeg mux options such as vcd - added (incomplete) mpeg2...
authorFabrice Bellard <fabrice@bellard.org>
Tue, 15 Oct 2002 10:22:23 +0000 (10:22 +0000)
committerFabrice Bellard <fabrice@bellard.org>
Tue, 15 Oct 2002 10:22:23 +0000 (10:22 +0000)
Originally committed as revision 1042 to svn://svn.ffmpeg.org/ffmpeg/trunk

libav/mpeg.c

index 8820c6e..e0770ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * MPEG1 mux/demux
+ * MPEG1/2 mux/demux
  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
  *
  * This library is free software; you can redistribute it and/or
@@ -43,6 +43,8 @@ typedef struct {
     /* stream info */
     int audio_bound;
     int video_bound;
+    int is_mpeg2;
+    int is_vcd;
 } MpegMuxContext;
 
 #define PACK_START_CODE             ((unsigned int)0x000001ba)
@@ -62,6 +64,10 @@ typedef struct {
 #define AUDIO_ID 0xc0
 #define VIDEO_ID 0xe0
 
+extern AVOutputFormat mpeg1system_mux;
+extern AVOutputFormat mpeg1vcd_mux;
+extern AVOutputFormat mpeg2vob_mux;
+
 static int put_pack_header(AVFormatContext *ctx, 
                            UINT8 *buf, INT64 timestamp)
 {
@@ -154,9 +160,10 @@ static int mpeg_mux_init(AVFormatContext *ctx)
     StreamInfo *stream;
 
     s->packet_number = 0;
-
-    /* XXX: hardcoded */
-    if (ctx->flags & AVF_FLAG_VCD)
+    s->is_vcd = (ctx->oformat == &mpeg1vcd_mux);
+    s->is_mpeg2 = (ctx->oformat == &mpeg2vob_mux);
+    
+    if (s->is_vcd)
         s->packet_size = 2324; /* VCD packet size */
     else
         s->packet_size = 2048;
@@ -203,14 +210,14 @@ static int mpeg_mux_init(AVFormatContext *ctx)
     }
     s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50);
     
-    if (ctx->flags & AVF_FLAG_VCD)
+    if (s->is_vcd || s->is_mpeg2)
         /* every packet */
         s->pack_header_freq = 1;
     else
         /* every 2 seconds */
         s->pack_header_freq = 2 * bitrate / s->packet_size / 8;
     
-    if (ctx->flags & AVF_FLAG_VCD)
+    if (s->is_vcd)
         /* every 40 packets, this is my invention */
         s->system_header_freq = s->pack_header_freq * 40;
     else
@@ -255,7 +262,7 @@ static void flush_packet(AVFormatContext *ctx, int stream_index, int last_pkt)
     MpegMuxContext *s = ctx->priv_data;
     StreamInfo *stream = ctx->streams[stream_index]->priv_data;
     UINT8 *buf_ptr;
-    int size, payload_size, startcode, id, len, stuffing_size, i;
+    int size, payload_size, startcode, id, len, stuffing_size, i, header_len;
     INT64 timestamp;
     UINT8 buffer[128];
     int last = last_pkt ? 4 : 0;
@@ -282,7 +289,12 @@ static void flush_packet(AVFormatContext *ctx, int stream_index, int last_pkt)
     put_buffer(&ctx->pb, buffer, size);
 
     /* packet header */
-    payload_size = s->packet_size - (size + 6 + 5 + last);
+    if (s->is_mpeg2) {
+        header_len = 8;
+    } else {
+        header_len = 5;
+    }
+    payload_size = s->packet_size - (size + 6 + header_len + last);
     if (id < 0xc0) {
         startcode = PRIVATE_STREAM_1;
         payload_size -= 4;
@@ -295,12 +307,16 @@ static void flush_packet(AVFormatContext *ctx, int stream_index, int last_pkt)
 
     put_be32(&ctx->pb, startcode);
 
-    put_be16(&ctx->pb, payload_size + 5);
+    put_be16(&ctx->pb, payload_size + header_len);
     /* stuffing */
     for(i=0;i<stuffing_size;i++)
         put_byte(&ctx->pb, 0xff);
-    
-    /* presentation time stamp */
+
+    if (s->is_mpeg2) {
+        put_byte(&ctx->pb, 0x80); /* mpeg2 id */
+        put_byte(&ctx->pb, 0x80); /* flags */
+        put_byte(&ctx->pb, 0x05); /* header len (only pts is included) */
+    }
     put_byte(&ctx->pb, 
              (0x02 << 4) | 
              (((timestamp >> 30) & 0x07) << 1) | 
@@ -626,11 +642,37 @@ static int mpegps_read_close(AVFormatContext *s)
     return 0;
 }
 
-static AVOutputFormat mpegps_mux = {
+static AVOutputFormat mpeg1system_mux = {
     "mpeg",
-    "MPEG PS format",
+    "MPEG1 System format",
+    "video/x-mpeg",
+    "mpg,mpeg",
+    sizeof(MpegMuxContext),
+    CODEC_ID_MP2,
+    CODEC_ID_MPEG1VIDEO,
+    mpeg_mux_init,
+    mpeg_mux_write_packet,
+    mpeg_mux_end,
+};
+
+static AVOutputFormat mpeg1vcd_mux = {
+    "vcd",
+    "MPEG1 System format (VCD)",
+    "video/x-mpeg",
+    NULL,
+    sizeof(MpegMuxContext),
+    CODEC_ID_MP2,
+    CODEC_ID_MPEG1VIDEO,
+    mpeg_mux_init,
+    mpeg_mux_write_packet,
+    mpeg_mux_end,
+};
+
+static AVOutputFormat mpeg2vob_mux = {
+    "vob",
+    "MPEG2 PS format (VOB)",
     "video/x-mpeg",
-    "mpg,mpeg,vob",
+    "vob",
     sizeof(MpegMuxContext),
     CODEC_ID_MP2,
     CODEC_ID_MPEG1VIDEO,
@@ -652,7 +694,9 @@ static AVInputFormat mpegps_demux = {
 
 int mpegps_init(void)
 {
-    av_register_output_format(&mpegps_mux);
+    av_register_output_format(&mpeg1system_mux);
+    av_register_output_format(&mpeg1vcd_mux);
+    av_register_output_format(&mpeg2vob_mux);
     av_register_input_format(&mpegps_demux);
     return 0;
 }