[FFmpeg-devel,v2,1/1] libavformat/dashenc: add webm support

Submitted by Peter Große on Jan. 21, 2017, 6:53 p.m.

Details

Message ID 20170121185332.4508-1-pegro@friiks.de
State New
Headers show

Commit Message

Peter Große Jan. 21, 2017, 6:53 p.m.
Use webm muxer for VP8, VP9 and Opus codec, mp4 muxer otherwise.

Signed-off-by: Peter Große <pegro@friiks.de>
---
 libavformat/dashenc.c | 46 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index bd6bb88..186c175 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -114,6 +114,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)
@@ -500,14 +517,14 @@  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\" bandwidth=\"%d\" width=\"%d\" height=\"%d\"",
-                i, os->codec_str, os->bit_rate, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\" bandwidth=\"%d\" width=\"%d\" height=\"%d\"",
+                i, os->ctx->oformat->name, os->codec_str, os->bit_rate, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
             if (s->streams[i]->avg_frame_rate.num)
                 avio_printf(out, " frameRate=\"%d/%d\"", s->streams[i]->avg_frame_rate.num, s->streams[i]->avg_frame_rate.den);
             avio_printf(out, ">\n");
         } else {
-            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/mp4\" codecs=\"%s\" bandwidth=\"%d\" audioSamplingRate=\"%d\">\n",
-                i, os->codec_str, os->bit_rate, s->streams[i]->codecpar->sample_rate);
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\" bandwidth=\"%d\" audioSamplingRate=\"%d\">\n",
+                i, os->ctx->oformat->name, os->codec_str, os->bit_rate, 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);
         }
@@ -790,7 +807,14 @@  static int dash_init(AVFormatContext *s)
         dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
         dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
 
-        ret = avformat_alloc_output_context2(&ctx, NULL, "mp4", NULL);
+        // 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) {
+            ret = avformat_alloc_output_context2(&ctx, NULL, "webm", NULL);
+        } else {
+            ret = avformat_alloc_output_context2(&ctx, NULL, "mp4", NULL);
+        }
         if (ret < 0)
             return AVERROR(ENOMEM);
         os->ctx = ctx;
@@ -829,7 +853,14 @@  static int dash_init(AVFormatContext *s)
             return ret;
         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 {
+            av_dict_set_int(&opts, "dash", 1, 0);
+            av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000 + 100 , 0);
+            av_dict_set_int(&opts, "live", 1, 0);
+            av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
+        }
         if ((ret = avformat_init_output(ctx, &opts)) < 0)
             return ret;
         os->ctx_inited = 1;
@@ -1047,7 +1078,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)) {