Some implementations do not probe the streams for codecs.
---

Tested with our demuxer and vlc's and works as expected.

 libavformat/mpegenc.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c
index 500ea48..45db2a6 100644
--- a/libavformat/mpegenc.c
+++ b/libavformat/mpegenc.c
@@ -27,6 +27,7 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavcodec/put_bits.h"
+#include "avio_internal.h"
 #include "avformat.h"
 #include "internal.h"
 #include "mpeg.h"
@@ -82,6 +83,7 @@ typedef struct {
     int64_t vcd_padding_bytes_written;

     int preload;
+    int stream_map;
 } MpegMuxContext;

 extern AVOutputFormat ff_mpeg1vcd_muxer;
@@ -293,6 +295,66 @@ static int get_system_header_size(AVFormatContext *ctx)
     return buf_index;
 }

+static int get_type(AVFormatContext *ctx, int codec_id)
+{
+    switch (codec_id) {
+    case AV_CODEC_ID_MPEG1VIDEO:
+        return STREAM_TYPE_VIDEO_MPEG1;
+    case AV_CODEC_ID_MPEG2VIDEO:
+        return STREAM_TYPE_VIDEO_MPEG2;
+    case AV_CODEC_ID_MPEG4:
+        return STREAM_TYPE_VIDEO_MPEG4;
+    case AV_CODEC_ID_H264:
+        return STREAM_TYPE_VIDEO_H264;
+    case AV_CODEC_ID_MP2:
+        return STREAM_TYPE_AUDIO_MPEG1;
+    case AV_CODEC_ID_AAC:
+        return STREAM_TYPE_AUDIO_AAC;
+    case AV_CODEC_ID_AC3:
+        return STREAM_TYPE_AUDIO_AC3;
+    default: {
+        const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
+        if (desc)
+            avpriv_report_missing_feature(ctx, "Codec %s", desc->name);
+        else
+            av_log(ctx, AV_LOG_ERROR, "Codec Id %d does not exist.\n",
+                   codec_id);
+        return 0;
+        }
+    }
+}
+
+static int output_stream_map(AVFormatContext *ctx)
+{
+    AVIOContext *pb   = ctx->pb;
+    int es_map_length = ctx->nb_streams * 4;
+    int psm_length    = 1 + 1 + 2 + 2 + es_map_length + 4;
+    uint8_t buf[128];
+    int len = put_pack_header(ctx, buf, 0);
+    int i;
+
+    avio_write(pb, buf, len);
+    avio_wb32(pb, PROGRAM_STREAM_MAP);
+    avio_wb16(pb, psm_length);
+    ffio_init_checksum(pb, ff_crc04C11DB7_update, 0);
+    avio_w8(pb, 128); // current_next_indicator and version 0
+    avio_w8(pb, 1);   // marker_bit
+    avio_wb16(pb, 0); // info_length
+    avio_wb16(pb, ctx->nb_streams * 4);
+    for (i = 0; i < ctx->nb_streams; i++) {
+        AVStream *st = ctx->streams[i];
+        StreamInfo *stream = st->priv_data;
+        int type = get_type(ctx, st->codec->codec_id);
+
+        avio_w8(pb, type);
+        avio_w8(pb, stream->id);
+        avio_wb16(pb, 0); // es_info_length
+    }
+    avio_wb32(pb, ffio_get_checksum(pb));
+
+    return 0;
+}
+
 static av_cold int mpeg_mux_init(AVFormatContext *ctx)
 {
     MpegMuxContext *s = ctx->priv_data;
@@ -484,6 +546,8 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
     }
     s->system_header_size = get_system_header_size(ctx);
     s->last_scr = 0;
+    if (s->stream_map)
+        return output_stream_map(ctx);
     return 0;
 fail:
     for (i = 0; i < ctx->nb_streams; i++)
@@ -1151,6 +1215,7 @@ static int mpeg_mux_end(AVFormatContext *ctx)
 static const AVOption options[] = {
     { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 
INT_MAX, E },
     { "preload", "Initial demux-decode delay in microseconds.", 
OFFSET(preload),  AV_OPT_TYPE_INT, {.i64 = 500000}, 0, INT_MAX, E},
+    { "stream_map", "Output a stream map.", OFFSET(stream_map),  
AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E},
     { NULL },
 };

--
1.9.0

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to