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