Re: [FFmpeg-devel] [PATCH] ffmpeg.c: fix calculation of input file duration in seek_to_start()
On Sun, 29 Oct 2017 21:45:04 +0100 Peter Große wrote: > On Sun, 29 Oct 2017 21:33:10 +0100 > Michael Niedermayer wrote: > > > seems this doesnt apply > > > > Yeah, it depends on the patch I started the thread with. > > I can swap the order of the two patches if you want, so that the > style fix can go in first. But they will depend on each other either way, > since their contexts overlap. Which one do you prefer? Regards Peter pgplZ2OUs77IG.pgp Description: OpenPGP digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] ffmpeg.c: fix calculation of input file duration in seek_to_start()
On Sun, 29 Oct 2017 21:33:10 +0100 Michael Niedermayer wrote: > seems this doesnt apply > Yeah, it depends on the patch I started the thread with. I can swap the order of the two patches if you want, so that the style fix can go in first. But they will depend on each other either way, since their contexts overlap. Regards Peter pgpSF5H4zdVVN.pgp Description: OpenPGP digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v2 3/7] dashenc: set DASH related options for the subsequent matroska muxer when using webm
This patch is inspired by the ffmpeg webm_chunk muxer and fixes that all resulting tracks have the same track number. Signed-off-by: Peter Große --- v2: extended commit message libavformat/dashenc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index e25a660fbe..0ca7cf5aa3 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -778,6 +778,9 @@ static int dash_init(AVFormatContext *s) } else { av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit +av_dict_set_int(&opts, "dash", 1, 0); +av_dict_set_int(&opts, "dash_track_number", i + 1, 0); +av_dict_set_int(&opts, "live", 1, 0); } if ((ret = avformat_write_header(ctx, &opts)) < 0) return ret; -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v2 6/7] dashenc: Don't output frameRates at both AS and Representation-level. Only output maxFrameRate at AS-level.
From: Anton Schubert Fix conformance regarding section "3.2.4. Presence of Attributes and Element" of the "Guidelines for Implementation: DASH-IF Interoperability Points V4.1" (http://dashif.org/guidelines/) Signed-off-by: Anton Schubert Signed-off-by: Peter Große --- v2: extended commit message libavformat/dashenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index c55106c11d..82381b67a9 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -393,8 +393,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); -if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate) -avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); +if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) +avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den); lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v2 1/7] dashenc: fix bitrate estimation with correct scaling
From: Anton Schubert Signed-off-by: Anton Schubert Signed-off-by: Peter Große --- v2: Fixed double rescaling. libavformat/dashenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 04b0fd99e6..e25a660fbe 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -947,6 +947,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; +AVStream *st = s->streams[i]; char filename[1024] = "", full_path[1024], temp_path[1024]; int range_length, index_length = 0; @@ -1001,7 +1002,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (!os->bit_rate) { // calculate average bitrate of first segment -int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / (os->max_pts - os->start_pts); +int64_t bitrate = (int64_t) range_length * 8 / ((os->max_pts - os->start_pts) * av_q2d(st->time_base)); if (bitrate >= 0) { os->bit_rate = bitrate; snprintf(os->bandwidth_str, sizeof(os->bandwidth_str), -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] ffmpeg.c: fix calculation of input file duration in seek_to_start()
On Sun, 29 Oct 2017 14:56:20 +0100 Moritz Barsnick wrote: > On Sun, Oct 29, 2017 at 12:08:05 +0100, Peter Große wrote: > > } else duration = 1; > > For style/readability, the statement should be on a new line, perhaps > even with brackets. (Not necessarily as part of this patch though.) Sure. Regards Peter From 14032f4185a0824b819b062068f5777a33057ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Sun, 29 Oct 2017 15:07:12 +0100 Subject: [PATCH] ffmpeg.c: fix code style in seek_to_start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: ffmpeg-devel@ffmpeg.org Signed-off-by: Peter GroÃe --- fftools/ffmpeg.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 17b594bac8..1e43b959da 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4140,14 +4140,17 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) AVRational sample_rate = {1, avctx->sample_rate}; duration = av_rescale_q(ist->nb_samples, sample_rate, ist->st->time_base); -} else +} else { continue; +} } else { if (ist->framerate.num) { duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); } else if (ist->st->avg_frame_rate.num) { duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base); -} else duration = 1; +} else { +duration = 1; +} } if (!ifile->duration) ifile->time_base = ist->st->time_base; -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] libavformat/mov.c: use calculated dts offset when seeking in streams
From: Jonas Licht Subtract the calculated dts offset from the requested timestamp before seeking. This fixes an error "Error while filtering: Operation not permitted" observed with a short file which contains only one key frame and starts with negative timestamps. Then, av_index_search_timestamp() returns a valid negative timestamp, but mov_seek_stream bails out with AVERROR_INVALIDDATA. Fixes ticket #6139. Signed-off-by: Jonas Licht Signed-off-by: Peter Große --- Compared to the other seek results in this test, the values are not that far off. libavformat/mov.c| 6 -- tests/ref/seek/extra-mp4 | 16 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 2ee67561e4..60a0f4ccf4 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6882,10 +6882,12 @@ static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags) { MOVStreamContext *sc = st->priv_data; -int sample, time_sample; +int sample, time_sample, ret; unsigned int i; -int ret = mov_seek_fragment(s, st, timestamp); +timestamp -= sc->time_offset; + +ret = mov_seek_fragment(s, st, timestamp); if (ret < 0) return ret; diff --git a/tests/ref/seek/extra-mp4 b/tests/ref/seek/extra-mp4 index c25544c095..c17ce4003c 100644 --- a/tests/ref/seek/extra-mp4 +++ b/tests/ref/seek/extra-mp4 @@ -28,10 +28,10 @@ ret: 0 st: 0 flags:0 dts: 50.63 pts: 50.73 pos:5926157 size: 13 ret: 0 st: 0 flags:0 dts: 50.67 pts: 50.67 pos:5927464 size: 150 ret: 0 st: 0 flags:0 dts: 50.70 pts: 50.70 pos:5927614 size: 176 ret: 0 st:-1 flags:1 ts: 153.470835 -ret: 0 st: 0 flags:1 dts: 153.47 pts: 153.50 pos:15867700 size: 96169 -ret: 0 st: 0 flags:0 dts: 153.50 pts: 153.53 pos:15963869 size: 785 -ret: 0 st: 0 flags:0 dts: 153.53 pts: 153.63 pos:15964654 size: 3135 -ret: 0 st: 0 flags:0 dts: 153.57 pts: 153.57 pos:15967789 size: 859 +ret: 0 st: 0 flags:1 dts: 151.97 pts: 152.00 pos:15705355 size:146924 +ret: 0 st: 0 flags:0 dts: 152.00 pts: 152.10 pos:15852279 size: 1355 +ret: 0 st: 0 flags:0 dts: 152.03 pts: 152.03 pos:15853634 size: 211 +ret: 0 st: 0 flags:0 dts: 152.07 pts: 152.07 pos:15853845 size: 217 ret: 0 st: 0 flags:0 ts: 76.365000 ret: 0 st: 0 flags:1 dts: 77.83 pts: 77.87 pos:8659657 size: 41182 ret: 0 st: 0 flags:0 dts: 77.87 pts: 77.97 pos:8700839 size: 4197 @@ -83,10 +83,10 @@ ret: 0 st: 0 flags:0 dts: 101.33 pts: 101.43 pos:11049548 size: ret: 0 st: 0 flags:0 dts: 101.37 pts: 101.37 pos:11053072 size: 562 ret: 0 st: 0 flags:0 dts: 101.40 pts: 101.40 pos:11053634 size: 599 ret: 0 st:-1 flags:0 ts: 25.306672 -ret: 0 st: 0 flags:1 dts: 27.40 pts: 27.43 pos:2674605 size:127383 -ret: 0 st: 0 flags:0 dts: 27.43 pts: 27.47 pos:2801988 size: 68 -ret: 0 st: 0 flags:0 dts: 27.47 pts: 27.50 pos:2802268 size: 1754 -ret: 0 st: 0 flags:0 dts: 27.50 pts: 27.53 pos:2804022 size: 4071 +ret: 0 st: 0 flags:1 dts: 25.30 pts: 25.33 pos:2607246 size: 40273 +ret: 0 st: 0 flags:0 dts: 25.33 pts: 25.43 pos:2647519 size: 2959 +ret: 0 st: 0 flags:0 dts: 25.37 pts: 25.37 pos:2650478 size: 197 +ret: 0 st: 0 flags:0 dts: 25.40 pts: 25.40 pos:2650675 size: 230 ret: 0 st:-1 flags:1 ts: 128.200839 ret: 0 st: 0 flags:1 dts: 127.83 pts: 127.87 pos:13514072 size: 67382 ret: 0 st: 0 flags:0 dts: 127.87 pts: 127.97 pos:13581454 size: 2936 -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] ffmpeg.c: fix calculation of input file duration in seek_to_start()
Fixes looping files without audio or when using stream_copy, where ist->nb_samples is not set since no decoding is done. This fixes ticket #5719 and also fixes an endless loop with the sample in ticket #6139. Signed-off-by: Peter Große --- fftools/ffmpeg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index cabc6864e7..17b594bac8 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -4144,9 +4144,9 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is) continue; } else { if (ist->framerate.num) { -duration = av_rescale_q(1, ist->framerate, ist->st->time_base); +duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base); } else if (ist->st->avg_frame_rate.num) { -duration = av_rescale_q(1, ist->st->avg_frame_rate, ist->st->time_base); +duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base); } else duration = 1; } if (!ifile->duration) -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] DASH manifest conformance (was: Re: [PATCH 0/7] dashenc fixes)
On Thu, 26 Oct 2017 18:32:57 +0200 Carl Eugen Hoyos wrote: > 2017-10-26 18:28 GMT+02:00 Peter Große : > > On Thu, 26 Oct 2017 18:07:55 +0200 > > Carl Eugen Hoyos wrote: > > > >> Did you test our dash muxer lately with some validation tool? > >> Errors were reported in the past. > > > > No official validation tool, no. > > The following was mentioned in the past iirc: > http://www-itec.uni-klu.ac.at/dash/?page_id=605 With the attached patch and checking against the current conformance XSD [1] instead of their "Standard XSD", I get a "Your DASH-MPD is VALID" logo. Regards Peter [1] https://github.com/Dash-Industry-Forum/Conformance-and-reference-source/blob/master/conformance/MPDValidator/schemas/DASH-MPD.xsd >From 7a731e2d0d1fd9c771b0cc2730a812e84ae9981e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Gro=C3=9Fe?= Date: Fri, 27 Oct 2017 21:18:47 +0200 Subject: [PATCH 1/1] dashenc: move UTCTiming element to the end of the manifest To: ffmpeg-devel@ffmpeg.org Required by comformance XSD [1]. [1] https://github.com/Dash-Industry-Forum/Conformance-and-reference-source/blob/master/conformance/MPDValidator/schemas/DASH-MPD.xsd --- libavformat/dashenc.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d3b0464d79..8c216a3af8 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -647,8 +647,6 @@ static int write_manifest(AVFormatContext *s, int final) av_free(escaped); } avio_printf(out, "\t\n"); -if (c->utc_timing_url) -avio_printf(out, "\t\n", c->utc_timing_url); if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) { OutputStream *os = &c->streams[0]; @@ -666,6 +664,10 @@ static int write_manifest(AVFormatContext *s, int final) return ret; } avio_printf(out, "\t\n"); + +if (c->utc_timing_url) +avio_printf(out, "\t\n", c->utc_timing_url); + avio_printf(out, "\n"); avio_flush(out); ff_format_io_close(s, &out); -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/1] libavformat/mov.c: use calculated dts offset when seeking in streams
From: Jonas Licht Subtract the calculated dts offset from the requested timestamp before seeking. This fixes an error "Error while filtering: Operation not permitted" observed with a short file which contains only one key frame and starts with negative timestamps. Then, av_index_search_timestamp() returns a valid negative timestamp, but mov_seek_stream bails out with AVERROR_INVALIDDATA. Fixes ticket #6139. Signed-off-by: Jonas Licht --- libavformat/mov.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index a5177e8f91..029d6a152d 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6918,10 +6918,12 @@ static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags) { MOVStreamContext *sc = st->priv_data; -int sample, time_sample; +int sample, time_sample, ret; unsigned int i; -int ret = mov_seek_fragment(s, st, timestamp); +timestamp -= sc->time_offset; + +ret = mov_seek_fragment(s, st, timestamp); if (ret < 0) return ret; -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 0/7] dashenc fixes
On Thu, 26 Oct 2017 18:07:55 +0200 Carl Eugen Hoyos wrote: > Did you test our dash muxer lately with some validation tool? > Errors were reported in the past. No official validation tool, no. I tried to get remuxing working with a pre-encoded multi-bitrate mkv file, but the official reference player [1] wasn't able to play the stream without patch 1 and 7. Patch 3 is inspired by the ffmpeg webm_chunk muxer and fixes that all tracks have the same track number. Patch 6 is a minor fix regarding section "3.2.4. Presence of Attributes and Element" of the "Guidelines for Implementation: DASH-IF Interoperability Points V4.1" [2] The rest are more cosmetic changes. Does that answer your question? Regards Peter [1] http://reference.dashif.org/dash.js/ [2] http://dashif.org/guidelines/ ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 5/7] dashenc: allow AdaptationSets to have different average frame rates
Signed-off-by: Peter Große --- libavformat/dashenc.c | 19 +-- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index c09b22bf7b..f3a12462be 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -55,6 +55,8 @@ typedef struct AdaptationSet { char id[10]; enum AVMediaType media_type; AVDictionary *metadata; +AVRational min_frame_rate, max_frame_rate; +int ambiguous_frame_rate; } AdaptationSet; typedef struct OutputStream { @@ -97,8 +99,6 @@ typedef struct DASHContext { const char *single_file_name; const char *init_seg_name; const char *media_seg_name; -AVRational min_frame_rate, max_frame_rate; -int ambiguous_frame_rate; const char *utc_timing_url; } DASHContext; @@ -393,8 +393,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); -if (as->media_type == AVMEDIA_TYPE_VIDEO && c->max_frame_rate.num && !c->ambiguous_frame_rate) -avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den); +if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate) +avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); @@ -675,7 +675,6 @@ static int dash_init(AVFormatContext *s) c->single_file = 1; if (c->single_file) c->use_template = 0; -c->ambiguous_frame_rate = 0; av_strlcpy(c->dirname, s->filename, sizeof(c->dirname)); ptr = strrchr(c->dirname, '/'); @@ -803,12 +802,12 @@ static int dash_init(AVFormatContext *s) if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { AVRational avg_frame_rate = s->streams[i]->avg_frame_rate; if (avg_frame_rate.num > 0) { -if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0) -c->min_frame_rate = avg_frame_rate; -if (av_cmp_q(c->max_frame_rate, avg_frame_rate) < 0) -c->max_frame_rate = avg_frame_rate; +if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0) +as->min_frame_rate = avg_frame_rate; +if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0) +as->max_frame_rate = avg_frame_rate; } else { -c->ambiguous_frame_rate = 1; +as->ambiguous_frame_rate = 1; } c->has_video = 1; } -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 6/7] dashenc: Don't output frameRates at both AS and Representation-level. Only output maxFrameRate at AS-level.
From: Anton Schubert Signed-off-by: Anton Schubert --- libavformat/dashenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index f3a12462be..b12a37a2e5 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -393,8 +393,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); -if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate) -avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); +if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) +avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den); lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 7/7] dashenc: copy stream frame rate to output stream
Leads to setting of DefaultDuration in Matroska muxer based on frame rate instead of timebase. Fixes playback in Chrome. Signed-off-by: Peter Große --- libavformat/dashenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index b12a37a2e5..2e5cac2384 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -750,6 +750,7 @@ static int dash_init(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; -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 4/7] dashenc: don't write header data before the first packet arrives
Fixes: 1b8ef01f04ab ("dashenc: add webm support") Signed-off-by: Peter Große --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index bde093646f..c09b22bf7b 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -780,7 +780,7 @@ static int dash_init(AVFormatContext *s) av_dict_set_int(&opts, "dash_track_number", i + 1, 0); av_dict_set_int(&opts, "live", 1, 0); } -if ((ret = avformat_write_header(ctx, &opts)) < 0) +if ((ret = avformat_init_output(ctx, &opts)) < 0) return ret; os->ctx_inited = 1; avio_flush(ctx->pb); -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 3/7] dashenc: set DASH related options for the subsequent matroska muxer when using webm
Signed-off-by: Peter Große --- libavformat/dashenc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 1b3acb7ac9..bde093646f 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -776,6 +776,9 @@ static int dash_init(AVFormatContext *s) } else { av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit +av_dict_set_int(&opts, "dash", 1, 0); +av_dict_set_int(&opts, "dash_track_number", i + 1, 0); +av_dict_set_int(&opts, "live", 1, 0); } if ((ret = avformat_write_header(ctx, &opts)) < 0) return ret; -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 5/7] dashenc: allow AdaptaionSets to have different average frame rates
Signed-off-by: Peter Große --- libavformat/dashenc.c | 19 +-- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index c09b22bf7b..f3a12462be 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -55,6 +55,8 @@ typedef struct AdaptationSet { char id[10]; enum AVMediaType media_type; AVDictionary *metadata; +AVRational min_frame_rate, max_frame_rate; +int ambiguous_frame_rate; } AdaptationSet; typedef struct OutputStream { @@ -97,8 +99,6 @@ typedef struct DASHContext { const char *single_file_name; const char *init_seg_name; const char *media_seg_name; -AVRational min_frame_rate, max_frame_rate; -int ambiguous_frame_rate; const char *utc_timing_url; } DASHContext; @@ -393,8 +393,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); -if (as->media_type == AVMEDIA_TYPE_VIDEO && c->max_frame_rate.num && !c->ambiguous_frame_rate) -avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den); +if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate) +avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); @@ -675,7 +675,6 @@ static int dash_init(AVFormatContext *s) c->single_file = 1; if (c->single_file) c->use_template = 0; -c->ambiguous_frame_rate = 0; av_strlcpy(c->dirname, s->filename, sizeof(c->dirname)); ptr = strrchr(c->dirname, '/'); @@ -803,12 +802,12 @@ static int dash_init(AVFormatContext *s) if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { AVRational avg_frame_rate = s->streams[i]->avg_frame_rate; if (avg_frame_rate.num > 0) { -if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0) -c->min_frame_rate = avg_frame_rate; -if (av_cmp_q(c->max_frame_rate, avg_frame_rate) < 0) -c->max_frame_rate = avg_frame_rate; +if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0) +as->min_frame_rate = avg_frame_rate; +if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0) +as->max_frame_rate = avg_frame_rate; } else { -c->ambiguous_frame_rate = 1; +as->ambiguous_frame_rate = 1; } c->has_video = 1; } -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/7] dashenc: fix bitrate estimation with correct scaling
From: Anton Schubert Signed-off-by: Anton Schubert --- libavformat/dashenc.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 240ff41380..a4b37403d6 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -953,6 +953,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; +AVStream *st = s->streams[i]; char filename[1024] = "", full_path[1024], temp_path[1024]; int range_length, index_length = 0; @@ -1007,7 +1008,9 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (!os->bit_rate) { // calculate average bitrate of first segment -int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / (os->max_pts - os->start_pts); +int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts, + st->time_base, + AV_TIME_BASE_Q); if (bitrate >= 0) { os->bit_rate = bitrate; snprintf(os->bandwidth_str, sizeof(os->bandwidth_str), -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/7] dashenc: use av_dict_set_int instead of static function
Signed-off-by: Peter Große --- libavformat/dashenc.c | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index a4b37403d6..1b3acb7ac9 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -664,14 +664,6 @@ 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_init(AVFormatContext *s) { DASHContext *c = s->priv_data; @@ -782,8 +774,8 @@ static int dash_init(AVFormatContext *s) if (!strcmp(os->format_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 +av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0); +av_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) return ret; -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 0/7] dashenc fixes
Some DASH muxer fixes after commits from libav got merged. Anton Schubert (2): dashenc: fix bitrate estimation with correct scaling dashenc: Don't output frameRates at both AS and Representation-level. Only output maxFrameRate at AS-level. Peter Große (5): dashenc: use av_dict_set_int instead of static function dashenc: set DASH related options for the subsequent matroska muxer when using webm dashenc: don't write header data before the first packet arrives dashenc: allow AdaptaionSets to have different average frame rates dashenc: copy stream frame rate to output stream libavformat/dashenc.c | 42 -- 1 file changed, 20 insertions(+), 22 deletions(-) -- 2.13.6 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v2] fate: add vf_overlay test for main source with alpha channel
Signed-off-by: Peter Große --- This depends on patch "lavfi/testsrc2: fix completely transparent alpha." The test fails without the patch "avfilter/vf_overlay: fix alpha blending when main source has an alpha channel". tests/fate/filter-video.mak | 4 tests/filtergraphs/overlay_main_alpha| 4 tests/ref/fate/filter-overlay_main-alpha | 30 ++ 3 files changed, 38 insertions(+) create mode 100644 tests/filtergraphs/overlay_main_alpha create mode 100644 tests/ref/fate/filter-overlay_main-alpha diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 53fc7a6528..ee2e7aff50 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -379,6 +379,10 @@ fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/d FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER FPS_FILTER MPDECIMATE_FILTER) += fate-filter-mpdecimate fate-filter-mpdecimate: CMD = framecrc -lavfi testsrc2=r=2:d=10,fps=3,mpdecimate -r 3 -pix_fmt yuv420p +FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER, OVERLAY_FILTER) += fate-filter-overlay_main-alpha +fate-filter-overlay_main-alpha: tests/data/filtergraphs/overlay_main_alpha +fate-filter-overlay_main-alpha: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_main_alpha + FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER FPS_FILTER QTRLE_DECODER) += fate-filter-fps-cfr fate-filter-fps fate-filter-fps-r fate-filter-fps-cfr: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p fate-filter-fps-r: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p diff --git a/tests/filtergraphs/overlay_main_alpha b/tests/filtergraphs/overlay_main_alpha new file mode 100644 index 00..95cc1d4c61 --- /dev/null +++ b/tests/filtergraphs/overlay_main_alpha @@ -0,0 +1,4 @@ +sws_flags=+accurate_rnd+bitexact; +testsrc2=d=1:s=1024x768:alpha=255[a]; +testsrc2=d=1:alpha=128[b]; +[a][b]overlay=x=100:y=50 \ No newline at end of file diff --git a/tests/ref/fate/filter-overlay_main-alpha b/tests/ref/fate/filter-overlay_main-alpha new file mode 100644 index 00..071c7435ae --- /dev/null +++ b/tests/ref/fate/filter-overlay_main-alpha @@ -0,0 +1,30 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1024x768 +#sar 0: 1/1 +0, 0, 0,1, 1966080, 0xbb0752de +0, 1, 1,1, 1966080, 0x2eaa3ef1 +0, 2, 2,1, 1966080, 0x6159c6b2 +0, 3, 3,1, 1966080, 0x03403179 +0, 4, 4,1, 1966080, 0x905a86ce +0, 5, 5,1, 1966080, 0x5c95b051 +0, 6, 6,1, 1966080, 0xd0989f23 +0, 7, 7,1, 1966080, 0x2f345dc0 +0, 8, 8,1, 1966080, 0x2d854f97 +0, 9, 9,1, 1966080, 0xc589e999 +0, 10, 10,1, 1966080, 0x8c2d7938 +0, 11, 11,1, 1966080, 0x457b26ad +0, 12, 12,1, 1966080, 0x5ee36f1e +0, 13, 13,1, 1966080, 0x2947c30c +0, 14, 14,1, 1966080, 0x5a031a29 +0, 15, 15,1, 1966080, 0xc278a4d0 +0, 16, 16,1, 1966080, 0x849a0f9d +0, 17, 17,1, 1966080, 0xaea83654 +0, 18, 18,1, 1966080, 0xd3054386 +0, 19, 19,1, 1966080, 0x1fae5492 +0, 20, 20,1, 1966080, 0xc8b95b6b +0, 21, 21,1, 1966080, 0x8634fdf9 +0, 22, 22,1, 1966080, 0x3627c5cb +0, 23, 23,1, 1966080, 0x8c1c5b90 +0, 24, 24,1, 1966080, 0x2c54109d -- 2.13.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] fate: add vf_overlay test for main source with alpha channel
On Thu, 20 Jul 2017 17:19:36 +0200 Tobias Rapp wrote: > > When I re-add --disable-optimizations --enable-mmx --disable-stripping to my > > configure command line, the test succeeds. > > > > Any further comments to the patch and test case? > > Maybe try adding -sws_flags +accurate_rnd+bitexact to CMD? I tried that, but that didn't help. Regards Peter pgploqABGDVDY.pgp Description: OpenPGP digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] fate: add vf_overlay test for main source with alpha channel
On Wed, 19 Jul 2017 21:00:49 +0200 Peter Große wrote: > I was able to reproduce your checksums only after removing > > --disable-optimizations --disable-mmx --disable-stripping > > from my configure command. I thought optimizations should have no > impact on the result?! After some further tests, it seems swscale (used as the auto_scaler in the test) produces slightly different output depending on whether MMX is enabled or not. When I re-add --disable-optimizations --enable-mmx --disable-stripping to my configure command line, the test succeeds. Any further comments to the patch and test case? Regards Peter ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] fate: add vf_overlay test for main source with alpha channel
Signed-off-by: Peter Große --- Updated version of the test. I was able to reproduce your checksums only after removing --disable-optimizations --disable-mmx --disable-stripping from my configure command. I thought optimizations should have no impact on the result?! tests/fate/filter-video.mak | 5 + tests/ref/fate/filter-overlay-main-alpha | 15 +++ 2 files changed, 20 insertions(+) create mode 100644 tests/ref/fate/filter-overlay-main-alpha diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 53fc7a6528..b30d5b7b7c 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -351,6 +351,11 @@ FATE_FILTER_SAMPLES-$(call ALLYES, MATROSKA_DEMUXER OVERLAY_FILTER H264_DECODER fate-filter-overlay-dvdsub-2397: tests/data/filtergraphs/overlay-dvdsub-2397 fate-filter-overlay-dvdsub-2397: CMD = framecrc -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay-dvdsub-2397 -c:a copy +FATE_FILTER_SAMPLES-$(call ALLYES, MXF_DEMUXER OVERLAY_FILTER DNXHD_DECODER PNG_DECODER) += fate-filter-overlay-main-alpha +fate-filter-overlay-main-alpha: SRC = $(TARGET_SAMPLES)/mxf/track_01_v02.mxf +fate-filter-overlay-main-alpha: OVERLAY = $(TARGET_SAMPLES)/png1/lena-rgba.png +fate-filter-overlay-main-alpha: CMD = framecrc -flags bitexact -i $(SRC) -filter_complex "movie='$(OVERLAY)'[logo];[v:0][logo]overlay" -an + FATE_FILTER_HQX-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER HQX_FILTER) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_HQX-yes) fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=2 -pix_fmt bgra diff --git a/tests/ref/fate/filter-overlay-main-alpha b/tests/ref/fate/filter-overlay-main-alpha new file mode 100644 index 00..95bb59ea13 --- /dev/null +++ b/tests/ref/fate/filter-overlay-main-alpha @@ -0,0 +1,15 @@ +#tb 0: 1001/24000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1280x720 +#sar 0: 1/1 +0, 0, 0,1, 2304000, 0x49ef8134 +0, 1, 1,1, 2304000, 0x49ef8134 +0, 2, 2,1, 2304000, 0x49ef8134 +0, 3, 3,1, 2304000, 0x49ef8134 +0, 4, 4,1, 2304000, 0x49ef8134 +0, 5, 5,1, 2304000, 0x49ef8134 +0, 6, 6,1, 2304000, 0x49ef8134 +0, 7, 7,1, 2304000, 0x49ef8134 +0, 8, 8,1, 2304000, 0x49ef8134 +0, 9, 9,1, 2304000, 0x49ef8134 -- 2.13.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] fate: add vf_overlay test for main source with alpha channel
Signed-off-by: Peter Große --- tests/fate/filter-video.mak | 5 + tests/ref/fate/filter-overlay-main-alpha | 15 +++ 2 files changed, 20 insertions(+) create mode 100644 tests/ref/fate/filter-overlay-main-alpha diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 9186593c10..cbfee449b6 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -341,6 +341,11 @@ FATE_FILTER_SAMPLES-$(call ALLYES, MATROSKA_DEMUXER OVERLAY_FILTER H264_DECODER fate-filter-overlay-dvdsub-2397: tests/data/filtergraphs/overlay-dvdsub-2397 fate-filter-overlay-dvdsub-2397: CMD = framecrc -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay-dvdsub-2397 -c:a copy +FATE_FILTER_SAMPLES-$(call ALLYES, MXF_DEMUXER OVERLAY_FILTER DNXHD_DECODER PNG_DECODER) += fate-filter-overlay-main-alpha +fate-filter-overlay-main-alpha: SRC = $(TARGET_SAMPLES)/mxf/track_01_v02.mxf +fate-filter-overlay-main-alpha: OVERLAY = $(TARGET_SAMPLES)/png1/lena-rgba.png +fate-filter-overlay-main-alpha: CMD = framecrc -flags bitexact -i $(SRC) -filter_complex "movie='$(OVERLAY)'[logo];[v:0][logo]overlay" -an + FATE_FILTER_HQX-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER HQX_FILTER) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_HQX-yes) fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=2 -pix_fmt bgra diff --git a/tests/ref/fate/filter-overlay-main-alpha b/tests/ref/fate/filter-overlay-main-alpha new file mode 100644 index 00..5e5cdfd0d2 --- /dev/null +++ b/tests/ref/fate/filter-overlay-main-alpha @@ -0,0 +1,15 @@ +#tb 0: 1001/24000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1280x720 +#sar 0: 1/1 +0, 0, 0,1, 2304000, 0x72b48234 +0, 1, 1,1, 2304000, 0x72b48234 +0, 2, 2,1, 2304000, 0x72b48234 +0, 3, 3,1, 2304000, 0x72b48234 +0, 4, 4,1, 2304000, 0x72b48234 +0, 5, 5,1, 2304000, 0x72b48234 +0, 6, 6,1, 2304000, 0x72b48234 +0, 7, 7,1, 2304000, 0x72b48234 +0, 8, 8,1, 2304000, 0x72b48234 +0, 9, 9,1, 2304000, 0x72b48234 -- 2.13.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avfilter/vf_overlay: fix alpha blending when main source has an alpha channel
On Sun, 16 Jul 2017 18:33:33 +0200 Paul B Mahol wrote: > > how can one reproduce this bug? ffmpeg -i fate-suite/mfx/track_01_v02.mxf -filter_complex \ "movie=fate-suite/png1/lena-rgba.png[logo];[v:0][logo]overlay" -an -vframes 1 out.png In this example files from the fate suite are used. The source mxf file actually doesn't have an alpha channel, but the autoscaler adds one on adapting pixel formats: [auto_scaler_0 @ 0x2118440] w:1280 h:720 fmt:yuv422p sar:1/1 -> w:1280 h:720 fmt:yuva420p sar:1/1 flags:0x2 As seen here [1] the png file has a almost zero alpha value on the left side, but the output is way too bright without the patch. I hope this helps. Regards Peter [1] http://imgur.com/a/74ZF4 pgpGcQkvmntOo.pgp Description: OpenPGP digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] avfilter/vf_overlay: fix alpha blending when main source has an alpha channel
Use alpha value from alpha channel instead of selected component channel. Signed-off-by: Peter Große --- libavfilter/vf_overlay.c | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 5c9f590957..cde09f5fb3 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -508,7 +508,7 @@ static av_always_inline void blend_plane(AVFilterContext *ctx, int dst_hp = AV_CEIL_RSHIFT(dst_h, vsub); int yp = y>>vsub; int xp = x>>hsub; -uint8_t *s, *sp, *d, *dp, *a, *ap; +uint8_t *s, *sp, *d, *dp, *a, *ap, *da, *dap; int jmax, j, k, kmax; j = FFMAX(-yp, 0); @@ -517,12 +517,16 @@ static av_always_inline void blend_plane(AVFilterContext *ctx, + (yp+j)* dst->linesize[dst_plane] + dst_offset; ap = src->data[3] + (j<linesize[3]; +if (main_has_alpha) +dap = dst->data[3] + (j<linesize[3]; for (jmax = FFMIN(-yp + dst_hp, src_hp); j < jmax; j++) { k = FFMAX(-xp, 0); d = dp + (xp+k) * dst_step; s = sp + k; a = ap + (k<linesize[3]] + - d[1] + d[src->linesize[3]+1]) >> 2; +alpha_d = (da[0] + da[src->linesize[3]] + + da[1] + da[src->linesize[3]+1]) >> 2; } else if (hsub || vsub) { alpha_h = hsub && k+1 < src_wp ? -(d[0] + d[1]) >> 1 : d[0]; +(da[0] + da[1]) >> 1 : da[0]; alpha_v = vsub && j+1 < src_hp ? -(d[0] + d[src->linesize[3]]) >> 1 : d[0]; +(da[0] + da[src->linesize[3]]) >> 1 : da[0]; alpha_d = (alpha_v + alpha_h) >> 1; } else -alpha_d = d[0]; +alpha_d = da[0]; alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); } *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha); -- 2.13.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 1/8] libavformat/dashenc: use avio_dynbuf instead of packet_write callback
On Sat, 21 Jan 2017 22:53:56 +0100 Moritz Barsnick wrote: > When adding new code, please stick to "if (" with a space. (Also in > some of your other patches.) >... > Two different ways of doing the same thing. ;-) (Assignment to ret > embedded in the "if"-clause versus before it.) Thanks for pointing that out. The mess with "ret" exists already in the old code, so I'm not sure, whether I should fix it only in lines I touch or at all occurances. Another question: the patcheck tool "complains" about "non doxy comments". What is the correct way of annotating segments of code? Or is it not recommend at all? Regards, Peter pgpMYwLWNzyvM.pgp Description: OpenPGP digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/1] libavformat/dashenc: separate segments based on segment duration instead of total duration
The current implementation creates new segments comparing pkt->pts - first_pts > total_duration This works fine, but if the keyframe interval is smaller than "min_seg_duration" segments shorter than the minimum segment duration are created. Example: keyint=50, min_seg_duration=300 segment 1 contains keyframe 1 (duration=2s < total_duration=3s) and keyframe 2 (duration=4s >= total_duration=3s) segment 2 contains keyframe 3 (duration=6s >= total_duration=6s) segment 3 contains keyframe 4 (duration=8s < total_duration=9s) and keyframe 5 (duration=10s >= total_duration=9s) ... Segment 2 is only 2s long, shorter than min_seg_duration = 3s. To fix this, either rename "min_seg_duration" to something more accurate. Or apply this patch to create new segments based on the actual written duration. Signed-off-by: Peter Große --- libavformat/dashenc.c | 17 - 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index e4bb923..c3a5dc5 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -73,7 +73,7 @@ typedef struct OutputStream { AVFormatContext *ctx; int ctx_inited, as_idx; AVIOContext *out; -int packets_written; +int duration_written; char initfile[1024]; int64_t init_start_pos, pos; int init_range_length; @@ -1032,7 +1032,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) char filename[1024] = "", full_path[1024], temp_path[1024]; int range_length, index_length = 0; -if (!os->packets_written) +if (!os->duration_written) continue; // Flush the single stream that got a keyframe right now. @@ -1081,7 +1081,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, full_path); // set new position -os->packets_written = 0; +os->duration_written = 0; os->pos += range_length; // write chunk header @@ -1119,7 +1119,6 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) DASHContext *c = s->priv_data; AVStream *st = s->streams[pkt->stream_index]; OutputStream *os = &c->streams[pkt->stream_index]; -int64_t seg_end_duration = (os->segment_index) * (int64_t) c->min_seg_duration; int ret; ret = update_stream_extradata(s, os, st->codecpar); @@ -1148,9 +1147,9 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) os->first_pts = pkt->pts; if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && -pkt->flags & AV_PKT_FLAG_KEY && os->packets_written && -av_compare_ts(pkt->pts - os->first_pts, st->time_base, - seg_end_duration, AV_TIME_BASE_Q) >= 0) { +pkt->flags & AV_PKT_FLAG_KEY && os->duration_written && +av_compare_ts(os->duration_written + pkt->duration, st->time_base, + c->min_seg_duration, AV_TIME_BASE_Q) >= 0) { int64_t prev_duration = c->last_duration; c->last_duration = av_rescale_q(pkt->pts - os->start_pts, @@ -1173,7 +1172,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } -if (!os->packets_written) { +if (!os->duration_written) { // If we wrote a previous segment, adjust the start time of the segment // to the end of the previous one (which is the same as the mp4 muxer // does). This avoids gaps in the timeline. @@ -1186,7 +1185,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) os->max_pts = pkt->pts + pkt->duration; else os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration); -os->packets_written++; +os->duration_written += pkt->duration; return ff_write_chained(os->ctx, 0, pkt, s, 0); } -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v2 8/8] libavformat/dashenc: add support for assigning streams to AdaptationSets
This patch is based on the stream assignment code in webmdashenc. Additional changes: * Default to one AdaptationSet per stream Previously all mapped streams of a media type (video, audio) where assigned to a single AdaptationSet. Using the DASH live profile it is mandatory, that the segments of all representations are aligned, which is currently not enforced. This leads to problems when using video streams with different key frame intervals. So to play safe, default to one AdaptationSet per stream, unless overwritten by explicit assignment * Make sure all streams are assigned to exactly one AdaptationSet * Copy "language" and "role" metadata from streams assigned to the set * Stream assignment in "adaptation_sets" option supports stream identifier (e.g. v:0) * Since the "bandwidth" attribute on a Representation is mandatory, calculate bandwith based on the size and duration of the first segment Signed-off-by: Peter Große --- Changes in v2: * removed changes related to min_seg_duration, since they are unrelated --- libavformat/dashenc.c | 286 +++--- 1 file changed, 227 insertions(+), 59 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 522a0eb..a5c4970 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -24,8 +24,10 @@ #include #endif +#include "libavutil/avutil.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/eval.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -59,9 +61,17 @@ typedef struct Segment { int n; } Segment; +typedef struct AdaptationSet { +char id[10]; +enum AVMediaType media_type; +AVRational min_frame_rate, max_frame_rate; +int ambiguous_frame_rate; +AVDictionary *metadata; +} AdaptationSet; + typedef struct OutputStream { AVFormatContext *ctx; -int ctx_inited; +int ctx_inited, as_idx; AVIOContext *out; int packets_written; char initfile[1024]; @@ -72,13 +82,14 @@ typedef struct OutputStream { int64_t first_pts, start_pts, max_pts; int64_t last_dts; int bit_rate; -char bandwidth_str[64]; - char codec_str[100]; } OutputStream; typedef struct DASHContext { const AVClass *class; /* Class for private options. */ +char *adaptation_sets; +AdaptationSet *as; +int nb_as; int window_size; int extra_window_size; int min_seg_duration; @@ -87,7 +98,7 @@ typedef struct DASHContext { int use_timeline; int single_file; OutputStream *streams; -int has_video, has_audio; +int has_video; int64_t last_duration; int64_t total_duration; char availability_start_time[100]; @@ -96,8 +107,6 @@ typedef struct DASHContext { const char *init_seg_name; const char *media_seg_name; const char *utc_timing_url; -AVRational min_frame_rate, max_frame_rate; -int ambiguous_frame_rate; } DASHContext; // RFC 6381 @@ -171,7 +180,7 @@ static int flush_dynbuf(OutputStream *os, int *range_length) uint8_t *buffer; int ret; -if(!os->ctx->pb) { +if (!os->ctx->pb) { return AVERROR(EINVAL); } @@ -193,6 +202,16 @@ static void dash_free(AVFormatContext *s) { DASHContext *c = s->priv_data; int i, j; + +if (c->as) { +for (i = 0; i < c->nb_as; i++) { +if (&c->as[i].metadata) +av_dict_free(&c->as[i].metadata); +} +av_freep(&c->as); +c->nb_as = 0; +} + if (!c->streams) return; for (i = 0; i < s->nb_streams; i++) { @@ -453,12 +472,165 @@ static void format_date_now(char *buf, int size) } } +static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index) +{ +DASHContext *c = s->priv_data; +AdaptationSet *as = &c->as[as_index]; +AVDictionaryEntry *lang, *role; +int i; + +avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); + +lang = av_dict_get(as->metadata, "language", NULL, 0); +if (lang) +avio_printf(out, " lang=\"%s\"", lang->value); + +if (as->max_frame_rate.num && !as->ambiguous_frame_rate) +avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); +avio_printf(out, ">\n"); + +role = av_dict_get(as->metadata, "role", NULL, 0); +if (role) +avio_printf(out, "\t\t\t\n", role->value); + +for (i = 0; i < s->nb_s
[FFmpeg-devel] [PATCH v2 1/1] libavformat/dashenc: add webm support
Use webm muxer for VP8, VP9 and Opus codec, mp4 muxer otherwise. Signed-off-by: Peter Große --- libavformat/dashenc.c | 46 +++--- 1 file changed, 39 insertions(+), 7 deletions(-) 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\tcodec_str, os->bit_rate, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height); +avio_printf(out, "\t\t\tctx->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\n", -i, os->codec_str, os->bit_rate, s->streams[i]->codecpar->sample_rate); +avio_printf(out, "\t\t\t\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\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)) { -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/1] libavformat/dashenc: add webm support
Use webm muxer for VP8, VP9 and Opus codec, mp4 muxer otherwise. Signed-off-by: Peter Große --- libavformat/dashenc.c | 46 +++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index bd6bb88..29920fa 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\tcodec_str, os->bit_rate, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height); +avio_printf(out, "\t\t\tctx->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\n", -i, os->codec_str, os->bit_rate, s->streams[i]->codecpar->sample_rate); +avio_printf(out, "\t\t\t\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\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)) { -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 7/8] libavformat/dashenc: support for hinting stream bandwidth using metadata option
Bandwidth information is required in the manifest, but not always provided by the demuxer. So enable hinting the stream bandwidth via a metadata field, supports same values as codec bitrate setting. Example: -metadata:s:v:0 bitrate=3500k Signed-off-by: Peter Große --- libavformat/dashenc.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 0c0248f..522a0eb 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -607,6 +607,17 @@ static int dash_init(AVFormatContext *s) char filename[1024]; os->bit_rate = s->streams[i]->codecpar->bit_rate; +// if no bit rate detected, try whether bitrates are provided via metadata +if(!os->bit_rate) { +AVDictionaryEntry *bitrate; +bitrate = av_dict_get(s->streams[i]->metadata, "bitrate", NULL, 0); +if(bitrate) { +char *tail; +os->bit_rate = av_strtod(bitrate->value, &tail); +if (*tail) +os->bit_rate = 0; +} +} if (os->bit_rate) { snprintf(os->bandwidth_str, sizeof(os->bandwidth_str), " bandwidth=\"%d\"", os->bit_rate); -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 8/8] libavformat/dashenc: add support for assigning streams to AdaptationSets
This patch is based on the stream assignment code in webmdashenc. Additional changes: * Default to one AdaptationSet per stream Previously all mapped streams of a media type (video, audio) where assigned to a single AdaptationSet. Using the DASH live profile it is mandatory, that the segments of all representations are aligned, which is currently not enforced. This leads to problems when using video streams with different key frame intervals. So to play safe, default to one AdaptationSet per stream, unless overwritten by explicit assignment * Make sure all streams are assigned to exactly one AdaptationSet * Copy "language" and "role" metadata from streams assigned to the set * Stream assignment in "adaptation_sets" option supports stream identifier (e.g. v:0) * If "min_seg_duration" option is set, audio segments will be created independently from occurance of video key frames when exceeding given segment duration * Since the "bandwidth" attribute on a Representation is mandatory, calculate bandwith based on the size and duration of the first segment Signed-off-by: Peter Große --- libavformat/dashenc.c | 295 ++ 1 file changed, 228 insertions(+), 67 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 522a0eb..bd6bb88 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -24,8 +24,10 @@ #include #endif +#include "libavutil/avutil.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/eval.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -59,9 +61,17 @@ typedef struct Segment { int n; } Segment; +typedef struct AdaptationSet { +char id[10]; +enum AVMediaType media_type; +AVRational min_frame_rate, max_frame_rate; +int ambiguous_frame_rate; +AVDictionary *metadata; +} AdaptationSet; + typedef struct OutputStream { AVFormatContext *ctx; -int ctx_inited; +int ctx_inited, as_idx; AVIOContext *out; int packets_written; char initfile[1024]; @@ -72,13 +82,14 @@ typedef struct OutputStream { int64_t first_pts, start_pts, max_pts; int64_t last_dts; int bit_rate; -char bandwidth_str[64]; - char codec_str[100]; } OutputStream; typedef struct DASHContext { const AVClass *class; /* Class for private options. */ +char *adaptation_sets; +AdaptationSet *as; +int nb_as; int window_size; int extra_window_size; int min_seg_duration; @@ -87,7 +98,6 @@ typedef struct DASHContext { int use_timeline; int single_file; OutputStream *streams; -int has_video, has_audio; int64_t last_duration; int64_t total_duration; char availability_start_time[100]; @@ -96,8 +106,6 @@ typedef struct DASHContext { const char *init_seg_name; const char *media_seg_name; const char *utc_timing_url; -AVRational min_frame_rate, max_frame_rate; -int ambiguous_frame_rate; } DASHContext; // RFC 6381 @@ -193,6 +201,16 @@ static void dash_free(AVFormatContext *s) { DASHContext *c = s->priv_data; int i, j; + +if (c->as) { +for (i = 0; i < c->nb_as; i++) { +if(&c->as[i].metadata) +av_dict_free(&c->as[i].metadata); +} +av_freep(&c->as); +c->nb_as = 0; +} + if (!c->streams) return; for (i = 0; i < s->nb_streams; i++) { @@ -453,12 +471,165 @@ static void format_date_now(char *buf, int size) } } +static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index) +{ +DASHContext *c = s->priv_data; +AdaptationSet *as = &c->as[as_index]; +AVDictionaryEntry *lang, *role; +int i; + +avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); + +lang = av_dict_get(as->metadata, "language", NULL, 0); +if (lang) +avio_printf(out, " lang=\"%s\"", lang->value); + +if (as->max_frame_rate.num && !as->ambiguous_frame_rate) +avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", as->max_frame_rate.num, as->max_frame_rate.den); +avio_printf(out, ">\n"); + +role = av_dict_get(as->metadata, "role", NULL, 0); +if (role) +avio_printf(out, "\t\t\t\n", role->value); + +for (i = 0; i < s->nb_streams; i++) { +OutputStream *os = &c->streams[i]; + +if (os->as_idx != as_index) +continue; + +if (as->media_type == A
[FFmpeg-devel] [PATCH 5/8] libavformat/dashenc: add option to provide UTC timing source
If set, adds a UTCTime tag in the manifest. See http://vm2.dashif.org/dash.js/docs/jsdocs/MediaPlayer.html#addUTCTimingSource for more information. Usable default: "https://time.akamai.com/?iso"; Signed-off-by: Peter Große --- libavformat/dashenc.c | 4 1 file changed, 4 insertions(+) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 054d0c0..fd1a304 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -95,6 +95,7 @@ typedef struct DASHContext { const char *single_file_name; const char *init_seg_name; const char *media_seg_name; +const char *utc_timing_url; AVRational min_frame_rate, max_frame_rate; int ambiguous_frame_rate; } DASHContext; @@ -508,6 +509,8 @@ static int write_manifest(AVFormatContext *s, int final) av_free(escaped); } avio_printf(out, "\t\n"); +if(c->utc_timing_url) +avio_printf(out, "\t\n", c->utc_timing_url); if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) { OutputStream *os = &c->streams[0]; int start_index = FFMAX(os->nb_segments - c->window_size, 0); @@ -1048,6 +1051,7 @@ static const AVOption options[] = { { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E }, { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E }, +{ "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/8] libavformat/dashenc: use avio_dynbuf instead of packet_write callback
The dash_write function drops data, if no IOContext is initialized. This might happen when a subordinate muxer calls avio_flush(). Using a dynamic buffer fixes that. Signed-off-by: Peter Große --- libavformat/dashenc.c | 86 +++ 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 534fa75..d0a2ab5 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -62,11 +62,10 @@ typedef struct Segment { typedef struct OutputStream { AVFormatContext *ctx; int ctx_inited; -uint8_t iobuf[32768]; AVIOContext *out; int packets_written; char initfile[1024]; -int64_t init_start_pos; +int64_t init_start_pos, pos; int init_range_length; int nb_segments, segments_size, segment_index; Segment **segments; @@ -100,14 +99,6 @@ typedef struct DASHContext { int ambiguous_frame_rate; } DASHContext; -static int dash_write(void *opaque, uint8_t *buf, int buf_size) -{ -OutputStream *os = opaque; -if (os->out) -avio_write(os->out, buf, buf_size); -return buf_size; -} - // RFC 6381 static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, char *str, int size) @@ -174,6 +165,29 @@ static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, } } +static int flush_dynbuf(OutputStream *os, int *range_length) +{ +uint8_t *buffer; +int ret; + +if(!os->ctx->pb) { +return AVERROR(EINVAL); +} + +// flush everything +av_write_frame(os->ctx, NULL); +avio_flush(os->ctx->pb); + +// write to output +*range_length = avio_close_dyn_buf(os->ctx->pb, &buffer); +avio_write(os->out, buffer, *range_length); +av_free(buffer); + +// re-open buffer +ret = avio_open_dyn_buf(&os->ctx->pb); +return ret; +} + static void dash_free(AVFormatContext *s) { DASHContext *c = s->priv_data; @@ -185,7 +199,7 @@ static void dash_free(AVFormatContext *s) if (os->ctx && os->ctx_inited) av_write_trailer(os->ctx); if (os->ctx && os->ctx->pb) -av_free(os->ctx->pb); +ffio_free_dyn_buf(&os->ctx->pb); ff_format_io_close(s, &os->out); if (os->ctx) avformat_free_context(os->ctx); @@ -624,9 +638,10 @@ static int dash_init(AVFormatContext *s) ctx->avoid_negative_ts = s->avoid_negative_ts; ctx->flags = s->flags; -ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, dash_write, NULL); -if (!ctx->pb) -return AVERROR(ENOMEM); +ret = avio_open_dyn_buf(&ctx->pb); +if (ret < 0) +return ret; +ctx->pb->seekable = 0; if (c->single_file) { if (c->single_file_name) @@ -646,7 +661,6 @@ static int dash_init(AVFormatContext *s) if ((ret = avformat_init_output(ctx, &opts)) < 0) return ret; os->ctx_inited = 1; -avio_flush(ctx->pb); av_dict_free(&opts); av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename); @@ -688,13 +702,24 @@ static int dash_init(AVFormatContext *s) static int dash_write_header(AVFormatContext *s) { DASHContext *c = s->priv_data; -int i, ret; +int i, ret, range_length; for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; if ((ret = avformat_write_header(os->ctx, NULL)) < 0) { dash_free(s); return ret; } + +if ((ret = flush_dynbuf(os, &range_length)) < 0) { +dash_free(s); +return ret; +} + +if (!c->single_file) { +ff_format_io_close(s, &os->out); +} + +os->pos = os->init_range_length = range_length; } ret = write_manifest(s, 0); if (!ret) @@ -803,7 +828,6 @@ static int dash_flush(AVFormatContext *s, int final, int stream) for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; char filename[1024] = "", full_path[1024], temp_path[1024]; -int64_t start_pos; int range_length, index_length = 0; if (!os->packets_written) @@ -821,15 +845,6 @@ static int dash_flush(AVFormatContext *s, int final, int stream) continue; } -if (!os->init_range_length) { -av_write_frame(os->ctx, NULL); -os->init_range_length = avio_tell(os->ctx->pb); -if (!c->single_file) -ff_format_io_close(s, &os->out); -} - -start_pos = avio_tel
[FFmpeg-devel] [PATCH 3/8] libavformat/dashenc: add mandatory id attribute to AdaptationSet and Period in manifest
Signed-off-by: Peter Große --- libavformat/dashenc.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 3286c36..7273997 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -457,7 +457,7 @@ static int write_manifest(AVFormatContext *s, int final) DASHContext *c = s->priv_data; AVIOContext *out; char temp_filename[1024]; -int ret, i; +int ret, i, as_id = 0; AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0); snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename); @@ -512,15 +512,15 @@ static int write_manifest(AVFormatContext *s, int final) OutputStream *os = &c->streams[0]; int start_index = FFMAX(os->nb_segments - c->window_size, 0); int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q); -avio_printf(out, "\t\n"); } else { -avio_printf(out, "\t\n"); +avio_printf(out, "\t\n"); } if (c->has_video) { -avio_printf(out, "\t\tmax_frame_rate.num && !c->ambiguous_frame_rate) avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den); avio_printf(out, ">\n"); @@ -543,7 +543,7 @@ static int write_manifest(AVFormatContext *s, int final) avio_printf(out, "\t\t\n"); } if (c->has_audio) { -avio_printf(out, "\t\t\n"); +avio_printf(out, "\t\t\n", as_id++); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; OutputStream *os = &c->streams[i]; -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 6/8] libavformat/dashenc: use avformat_alloc_output_context2 for initializing context
Also copy stream metadata to output stream. Signed-off-by: Peter Große --- libavformat/dashenc.c | 13 + 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index fd1a304..0c0248f 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -572,7 +572,6 @@ static int dash_init(AVFormatContext *s) { DASHContext *c = s->priv_data; int ret = 0, i; -AVOutputFormat *oformat; char *ptr; char basename[1024]; @@ -596,10 +595,6 @@ static int dash_init(AVFormatContext *s) if (ptr) *ptr = '\0'; -oformat = av_guess_format("mp4", NULL, NULL); -if (!oformat) -return AVERROR_MUXER_NOT_FOUND; - c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams); if (!c->streams) return AVERROR(ENOMEM); @@ -623,23 +618,25 @@ static int dash_init(AVFormatContext *s) return AVERROR(EINVAL); } -ctx = avformat_alloc_context(); -if (!ctx) +ret = avformat_alloc_output_context2(&ctx, NULL, "mp4", NULL); +if (ret < 0) return AVERROR(ENOMEM); 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))) return AVERROR(ENOMEM); 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; ret = avio_open_dyn_buf(&ctx->pb); if (ret < 0) -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH RFC 0/8] libavformat/dashenc: improvements to MPEG-DASH muxer
Some bugfixes and improvements to the MPEG-DASH [1] muxer. Most importantly it adds support for explicitly assigning streams to AdaptationSets, which is in part based on the code of webmdashenc. TODO: add documentation and FATE tests [1] http://standards.iso.org/ittf/PubliclyAvailableStandards/c065274_ISO_IEC_23009-1_2014.zip Anton Schubert (2): libavformat/dashenc: add Z to localtime to force correct UTC parsing libavformat/dashenc: increase buffer time hints in the manifest Peter Große (6): libavformat/dashenc: use avio_dynbuf instead of packet_write callback libavformat/dashenc: add mandatory id attribute to AdaptationSet and Period in manifest libavformat/dashenc: add option to provide UTC timing source libavformat/dashenc: use avformat_alloc_output_context2 for initializing context libavformat/dashenc: support for hinting stream bandwidth using metadata option libavformat/dashenc: add support for assigning streams to AdaptationSets libavformat/dashenc.c | 417 -- 1 file changed, 305 insertions(+), 112 deletions(-) -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 4/8] libavformat/dashenc: increase buffer time hints in the manifest
From: Anton Schubert Signed-off-by: Anton Schubert --- libavformat/dashenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 7273997..054d0c0 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -483,7 +483,7 @@ static int write_manifest(AVFormatContext *s, int final) if (c->use_template && !c->use_timeline) update_period = 500; avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period); -avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE); +avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", 5 * c->last_duration / AV_TIME_BASE); if (!c->availability_start_time[0] && s->nb_streams > 0 && c->streams[0].nb_segments > 0) { format_date_now(c->availability_start_time, sizeof(c->availability_start_time)); } @@ -499,7 +499,7 @@ static int write_manifest(AVFormatContext *s, int final) } } avio_printf(out, "\tminBufferTime=\""); -write_time(out, c->last_duration); +write_time(out, c->last_duration * 2); avio_printf(out, "\">\n"); avio_printf(out, "\t\n"); if (title) { -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/8] libavformat/dashenc: add Z to localtime to force correct UTC parsing
From: Anton Schubert Signed-off-by: Anton Schubert --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index d0a2ab5..3286c36 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -447,7 +447,7 @@ static void format_date_now(char *buf, int size) struct tm *ptm, tmbuf; ptm = gmtime_r(&t, &tmbuf); if (ptm) { -if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) +if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%SZ", ptm)) buf[0] = '\0'; } } -- 2.10.2 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel