[FFmpeg-trac] #8501(avformat:new): Speedup init times of DASH streams

FFmpeg trac at avcodec.org
Wed Jan 29 22:42:51 EET 2020

#8501: Speedup init times of DASH streams
             Reporter:  lukasf    |                     Type:  enhancement
               Status:  new       |                 Priority:  normal
            Component:  avformat  |                  Version:  unspecified
             Keywords:  DASH      |               Blocked By:
             Blocking:            |  Reproduced by developer:  0
Analyzed by developer:  0         |
 Summary of the bug:

 Initialization of the AVFormatContext is painfully slow when opening a
 DASH stream. On my 100MBit/s connection, opening DASH streams usually
 takes ~7-8 seconds, and that is before I even start reading packets. On
 slower connections the times are even higher, often more than 20 seconds.
 When opening the same stream with VLC, it only takes half the time (3-4
 seconds on my connection, ~10 seconds on slow connections). And when
 opening in a browser player, it takes below one second even on slow
 connections. When using FFmpeg as a decoder library in a video player
 scenario, these slow connection times are unacceptable.

 This is a good free sample stream to work with:

 There are three reasons for slow init times:

 1. The DASH MPD header contains pretty detailed information about each
 stream. But that information is not used. Instead, every stream is opened
 and probed.

 2. Each DASH stream usually has one init section, followed by the actual
 data sections. The init section is supposed to be enough to prepare the
 decoder. But currently, a probe buffer of a fixed size is filled and
 probing is done on that buffer. That buffer includes the small init
 section, plus some part of the actual data section. That means, two tcp
 connections are created for every stream, sequentially. Theoretically, it
 would be enough to do the probing on only the init section, saving the
 time to open and read parts of the first data section.

 3. All streams are opened and probed sequentially. For DASH, we often have
 about 7-10 streams, sometimes even more. For every stream, usually two tcp
 connections are opened and read. This gets very very slow.

 I am not sure if point 1 could be solved, because of how libavformat works
 internally. But I have created experimental patches for point 2 and 3.
 Solving point 2 will roughly cut init times in half. It requires changes
 to both "dashdec.c" and "mov.c". Point 3 will even more drastically reduce
 connection times, usually by factor "numberOfStreams". Solving point 2 and
 3 together would lead to init times very well below 1 second on most

 I will submit patches to the mailing list when I am ready. But I already
 wanted to create awareness of the problem here and maybe start a
 discussion. Any feedback is appreciated.

 Approach for point 2:

 Use av_probe_input_format2() directly on the init buffer for probing. Only
 if that fails, use the normal probing with fixed/increasing buffer size.

 Additionally, this needs a change in mov.c: In mov_read_header(), the mov
 decoder searches for both moov and mdat atoms. But for the initialization,
 only moov is really required. The mdat is the following atom that holds
 the actual data packets. I have changed this so that duing
 mov_read_header, only moov is searched and evaluated. Then later in
 mov_read_packet, the mdat is searched.

 These two changes together will prevent opening of the DASH stream data

 Approach for point 3:

 Create threads for each stream to do the initialization in parallel. It is
 not a big issue to open multiple threads here, since they will only wait
 for tcp connection to open and data to arrive. Still, I would make this a
 configurable parameter. Not sure if this should be on or off by default.

 How to reproduce:
 ffprobe started on 2020-01-29 at 20:37:38
 Report written to "ffprobe-20200129-203738.log"
 Command line:
 "C:\\Program Files\\ffmpeg\\ffprobe.exe"
 http://www.bok.net/dash/tears_of_steel/cleartext/stream.mpd -report
 ffprobe version 4.2.1 Copyright (c) 2007-2019 the FFmpeg developers
   built with gcc 9.1.1 (GCC) 20190807
   configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-
 fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-
 libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame
 --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
 --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr
 --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack
 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2
 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-
 libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa
 --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx
 --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-
 nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
   libavutil      56. 31.100 / 56. 31.100
   libavcodec     58. 54.100 / 58. 54.100
   libavformat    58. 29.100 / 58. 29.100
   libavdevice    58.  8.100 / 58.  8.100
   libavfilter     7. 57.100 /  7. 57.100
   libswscale      5.  5.100 /  5.  5.100
   libswresample   3.  5.100 /  3.  5.100
   libpostproc    55.  5.100 / 55.  5.100
 [NULL @ 000001243588d340] Opening
 'http://www.bok.net/dash/tears_of_steel/cleartext/stream.mpd' for reading
 [http @ 000001243588dcc0] Setting default whitelist
 [tcp @ 0000012435890380] Original list of addresses:
 [tcp @ 0000012435890380] Address port 80
 [tcp @ 0000012435890380] Interleaved list of addresses:
 [tcp @ 0000012435890380] Address port 80
 [tcp @ 0000012435890380] Starting connection attempt to
 port 80
 [tcp @ 0000012435890380] Successfully connected to port 80
 [http @ 000001243588dcc0] request: GET
 /dash/tears_of_steel/cleartext/stream.mpd HTTP/1.1


Ticket URL: <https://trac.ffmpeg.org/ticket/8501>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker

More information about the FFmpeg-trac mailing list