Le 17/05/2022 à 20:06, Alexis Murzeau a écrit :
> [...]

I've investigated a bit more on how the arte.tv stream is made.
I've found that ffmpeg v4 is using wrong timestamp information from the
input stream and that only ffmpeg v5 read the correct timestamps.
So the same conclusion as upstream.


Details of why (brain dump :-) ):

In fact, arte.tv is not using MPEGTS at all but fragmented MP4.
I've checked the original files 108210-039-B_v216.mp4 and 
108210-039-B_aud_VA.mp4
that are on arte.tv servers, and it is using the fragmented MP4 format
correctly, with this structure:

 - A "header" with metadata: ftyp + moov + sidx
 - Several fragments: moof + mdat
 - A closing header: mfra

In the aud_VA.m3u8 file:
 - The part referenced by #EXT-X-MAP matches exactly the first 1680 bytes
   of the .mp4 files which is the "header"(ftyp + moov + sidx)
 - One fragment in the m3u8 (#EXT-X-BYTERANGE) references 3 MP4 fragments
   (so 3x moof + mdat)

So when streamlink process this file, it will add the "header" every 3
MP4 fragments like this:
 - One "header" (EXT-X-MAP)
   - ftyp + moov + sidx
 - One HLS fragment (EXT-X-BYTERANGE) == 3 MP4 fragments
   - moof + mdat
   - moof + mdat
   - moof + mdat

 - One "header" (EXT-X-MAP)
   - ftyp + moov + sidx
 - One HLS fragment (EXT-X-BYTERANGE) == 3 MP4 fragments
   - moof + mdat
   - moof + mdat
   - moof + mdat
etc... until the last fragment (the "closing header" doesn't appear
anymore).

When checking with the HLS RFC, everything seems fine here.


The MP4 stream contains timestamp in both sidx and tfdt (which is inside
moof blocks).

The issue is that ffmpeg v4 sees the sidx block and decide to reset sample
timestamps (PTS and DTS, presentation and decoding timestamps) according
to that data in sidx.

The correct timestamps are in moof/tfdt which are not part
of the header, so their values are different for each fragments (and
correct). Timestamp in sidx are the same for all fragment as sidx is part
of the "header" which is copied before each HLS fragment.

As sidx appear for each HLS fragment, the behavior of ffmpeg v4 is to
ignore tfdt and resets timestamps instead (which is wrong here).
Then ffmpeg try to recover from that when writing the mpegts output file.

Unfortunately, this means the resulting output file has bad frame
timestamps and players try to follow them, which cause the glitches.


With ffmpeg v5.x, it uses the tfdt (a block in moof block) instead of sidx
and that tfdt contains correct data, that's why everything work fine with
that version.
There is a new option in ffmpeg called "use_tfdt" in that version, which
is enabled by default now.
This was implemented in parts, where the first is here:
https://github.com/FFmpeg/FFmpeg/commit/071930de724166bfb90fc6d368c748771188fd94
According to github, this commit is only in version v5.0 (tag n5.0) but
not earlier.

=> So really the only option to use ffmpeg v5.x



Relevant files:
https://arte-cmafhls.akamaized.net/am/cmaf/108000/108200/108210-039-B/220509185705/medias/108210-039-B_v216.m3u8
https://arte-cmafhls.akamaized.net/am/cmaf/108000/108200/108210-039-B/220509185705/medias/108210-039-B_v216.mp4
https://arte-cmafhls.akamaized.net/am/cmaf/108000/108200/108210-039-B/220509185705/medias/108210-039-B_aud_VA.m3u8
https://arte-cmafhls.akamaized.net/am/cmaf/108000/108200/108210-039-B/220509185705/medias/108210-039-B_aud_VA.mp4
https://arte-cmafhls.akamaized.net/am/cmaf/108000/108200/108210-039-B/220509185705/108210-039-B_VA_XQ.m3u8

Additional sources that helped me:
For MP4: https://bitmovin.com/fun-with-container-formats-2/
For MPEGTS: https://bitmovin.com/fun-with-container-formats-3/
HLS RFC: https://datatracker.ietf.org/doc/html/rfc8216#section-3.3
ffmpeg MP4 options: https://ffmpeg.org/ffmpeg-formats.html#Options-2
Raw MP4 file browser: https://github.com/sannies/isoviewer

-- 
Alexis Murzeau
PGP: B7E6 0EBB 9293 7B06 BDBC  2787 E7BD 1904 F480 937F                |

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to