[FFmpeg-trac] #8009(avformat:new): hls demuxer does not handle pid changes after EXT-X-DISCONTINUITY
FFmpeg
trac at avcodec.org
Thu Jan 19 22:15:08 EET 2023
#8009: hls demuxer does not handle pid changes after EXT-X-DISCONTINUITY
------------------------------------+------------------------------------
Reporter: Aman | Owner: (none)
Type: defect | Status: new
Priority: normal | Component: avformat
Version: git-master | Resolution:
Keywords: hls | Blocked By:
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
------------------------------------+------------------------------------
Comment (by Vraz):
Ran into a variation of this while adding OTT live playback (like Pluto)
to my player using 4.3.2 libs. During playback, the hls demuxer
concatenates segments and passes to the subdemuxer as continuous media. At
least for mpegts, concatenating segments is only valid for media that was
mastered together. mpegts does not support the arbitrary concatenation of
random segments and that is what happens at a discontinuity.
If you crack the log level up, you will likely see:
"Continuity check failed for pid %d expected %d got %d" at transitions of
non-related segments.
You can find the corresponding code in mpegts.c by searching on the
ironically wrong comment: /* continuity check (currently not used) */
(which is very much used). Once the corruption occurs, all kinds of "bad
things" happen to the streams. Most common seems to be -1 stream types
that eventually overflow the stream table.
The workaround is changing hls to advertise segment boundaries to mpegts
so the latter can prepare for the change. In my experiments, making mpegts
detect a seek between discontinuous segments solved the issue. My proof of
concept triggers the mpegts seek code between every segment though don't
think that is fully hls compliant.
In hls.c/read_data:
{{{
ret = read_from_url(v, seg, buf, buf_size);
if (ret > 0) { ... }
+ if (avio_feof(v->input))
+ v->ctx->io_repositioned = (v->pb.pos+ret) & 0x7fffffff;
}}}
In mpegts.c/handle_packets:
{{{
ts->last_pos = avio_tell(s->pb);
+ if (s->io_repositioned == (ts->last_pos & 0x7fffffff))
+ ts->last_pos = 0;
return ret;
}}}
Reusing AVFormatContext::io_repositioned required stripping the stream
position to 31-bits. With a couple extra lines of code, setting the
advertisement could be conditional on a prior #EXT-X-DISCONTINUITY to be
more standards compliant. Your app must disable
AVFormatContext::ts_overflow (else it will trigger improperly) and the app
must performs its own DTS/PTS resequencing.
Also, additional streams will get added during playback. After a couple
hours of Pluto and its commercials, there were 16 h264 streams, 1 aac and
1 timed_id3. The "merge_pmt_versions" might help, though its non-trivial
to set as hls does not pass options down to the subdemuxer.
--
Ticket URL: <https://trac.ffmpeg.org/ticket/8009#comment:6>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list