Use webm muxer for VP8, VP9 and Opus codec, mp4 muxer otherwise.
Also copy stream metadata to output stream.

Signed-off-by: Peter Große <pe...@friiks.de>
---
 libavformat/dashenc.c | 68 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 54 insertions(+), 14 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 86b454e..24665cd 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -113,6 +113,23 @@ static void set_codec_str(AVFormatContext *s, 
AVCodecParameters *par,
 {
     const AVCodecTag *tags[2] = { NULL, NULL };
     uint32_t tag;
+
+    // common Webm codecs are not part of RFC 6381
+    switch (par->codec_id) {
+    case AV_CODEC_ID_VP8:
+        snprintf(str, size, "vp8");
+        return;
+    case AV_CODEC_ID_VP9:
+        snprintf(str, size, "vp9");
+        return;
+    case AV_CODEC_ID_VORBIS:
+        snprintf(str, size, "vorbis");
+        return;
+    case AV_CODEC_ID_OPUS:
+        snprintf(str, size, "opus");
+        return;
+    }
+
     if (par->codec_type == AVMEDIA_TYPE_VIDEO)
         tags[0] = ff_codec_movvideo_tags;
     else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
@@ -495,11 +512,11 @@ static int write_adaptation_set(AVFormatContext *s, 
AVIOContext *out, int as_ind
             continue;
 
         if (as->media_type == AVMEDIA_TYPE_VIDEO) {
-            avio_printf(out, "\t\t\t<Representation id=\"%d\" 
mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\">\n",
-                i, os->codec_str, os->bandwidth_str, 
s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" 
mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\">\n",
+                i, os->ctx->oformat->name, os->codec_str, os->bandwidth_str, 
s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
         } else {
-            avio_printf(out, "\t\t\t<Representation id=\"%d\" 
mimeType=\"audio/mp4\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
-                i, os->codec_str, os->bandwidth_str, 
s->streams[i]->codecpar->sample_rate);
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" 
mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
+                i, os->ctx->oformat->name, os->codec_str, os->bandwidth_str, 
s->streams[i]->codecpar->sample_rate);
             avio_printf(out, "\t\t\t\t<AudioChannelConfiguration 
schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" 
value=\"%d\" />\n",
                 s->streams[i]->codecpar->channels);
         }
@@ -700,11 +717,18 @@ static int dict_copy_entry(AVDictionary **dst, const 
AVDictionary *src, const ch
     return 0;
 }
 
+static int dict_set_int(AVDictionary **pm, const char *key, int64_t value, int 
flags)
+{
+    char valuestr[22];
+    snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
+    flags &= ~AV_DICT_DONT_STRDUP_VAL;
+    return av_dict_set(pm, key, valuestr, flags);
+}
+
 static int dash_write_header(AVFormatContext *s)
 {
     DASHContext *c = s->priv_data;
     int ret = 0, i, range_length;
-    AVOutputFormat *oformat;
     char *ptr;
     char basename[1024];
 
@@ -727,12 +751,6 @@ static int dash_write_header(AVFormatContext *s)
     if (ptr)
         *ptr = '\0';
 
-    oformat = av_guess_format("mp4", NULL, NULL);
-    if (!oformat) {
-        ret = AVERROR_MUXER_NOT_FOUND;
-        goto fail;
-    }
-
     c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
     if (!c->streams) {
         ret = AVERROR(ENOMEM);
@@ -784,12 +802,25 @@ static int dash_write_header(AVFormatContext *s)
             ret = AVERROR(ENOMEM);
             goto fail;
         }
+
+        // choose muxer based on codec: webm for VP8/9 and opus, mp4 otherwise
+        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_VP8 ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_VP9 ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS) {
+            ctx->oformat = av_guess_format("webm", NULL, NULL);
+        } else {
+            ctx->oformat = av_guess_format("mp4", NULL, NULL);
+        }
+        if (!ctx->oformat) {
+            ret = AVERROR_MUXER_NOT_FOUND;
+            goto fail;
+        }
         os->ctx = ctx;
-        ctx->oformat = oformat;
         ctx->interrupt_callback = s->interrupt_callback;
         ctx->opaque             = s->opaque;
         ctx->io_close           = s->io_close;
         ctx->io_open            = s->io_open;
+        av_dict_copy(&ctx->metadata, s->metadata, 0);
 
         if (!(st = avformat_new_stream(ctx, NULL))) {
             ret = AVERROR(ENOMEM);
@@ -798,7 +829,10 @@ static int dash_write_header(AVFormatContext *s)
         avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
+        st->avg_frame_rate = s->streams[i]->avg_frame_rate;
         ctx->avoid_negative_ts = s->avoid_negative_ts;
+        ctx->flags = s->flags;
+        ctx->max_delay = s->max_delay;
 
         if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
             goto fail;
@@ -818,7 +852,12 @@ static int dash_write_header(AVFormatContext *s)
             goto fail;
         os->init_start_pos = 0;
 
-        av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
+        if (!strcmp(ctx->oformat->name, "mp4")) {
+            av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
+        } else {
+            dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 
1000, 0);
+            dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // 
set a large cluster size limit
+        }
         if ((ret = avformat_write_header(ctx, &opts)) < 0)
             goto fail;
 
@@ -1023,7 +1062,8 @@ static int dash_flush(AVFormatContext *s, int final, int 
stream)
         os->pos += range_length;
 
         // write chunk header
-        write_styp(os->ctx->pb);
+        if (!strcmp(os->ctx->oformat->name, "mp4"))
+            write_styp(os->ctx->pb);
     }
 
     if (c->window_size || (final && c->remove_at_exit)) {
-- 
2.10.2

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to