Skip to content
Snippets Groups Projects

Draft: Clock context to handle PTS/PCR discontinuity

Closed Thomas Guillem requested to merge tguillem/vlc:clock-context-id into master
7 unresolved threads

Cf. discussion during Workshop 2021-12-06/07 #26378 (closed)

The issue

The goal is to keep the data related to the PTS as long as possible inside the playback workflow. To do that, the clock internal state needs to be kept through the whole pipeline, and not scratched synchronously.

As an example scenario: during a media player playback:

  • a change in the clock (discontinuity) is performed
  • currently, the clock internal state is reset, so every picture that has been decoded and not displayed has now an invalid PTS (because the PTS cannot be converted to the system time anymore). So they are discarded, or the output might wait a huge amount of time before displaying them (depending if the new PTS increase or decrease)
  • however, if we could keep the current state for these pictures (and not for the future ones), we could be able to display them.

Sample with a PCR discontinuity: https://streams.videolan.org/issues/26378/intentional_pcr_discontinuity-short.ts

The solution

The es_out can trigger the creation of a new clock_context via vlc_clock_main_SetFirstPCR. For now, it is only triggered when the input_clock detect a discontinuity, but we could also let demux modules send a new es_out control to trigger it.

The clock_id will be propagated from the main clock owned by the es_out to the output modules, held by block_t or picture_t , and passed from packetizers to decoders to filters to outputs

TODO

It's a draft, if the solution is accepted, I will have to :

  • Fix all decoders to forward the clock_id
  • Fix all packetizers to forward the clock_id
  • Handle clock_id in subpicture_t and spu renderer
  • Fix some aout modules to send PTS directly from aout_TimingReport (and not a ts based on 0)
  • Fix some aout modules to send the clock_id from aout_TimingReport
Edited by Thomas Guillem

Merge request reports

Merge request pipeline #452977 failed

Merge request pipeline failed for 275db3af

Approval is optional

Closed by Thomas GuillemThomas Guillem 9 months ago (Jun 27, 2024 11:26am UTC)

Merge details

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
44 44 double rate;
45 45 double coeff;
46 46 vlc_tick_t offset;
47 vlc_tick_t first_pcr_ts;
  • Denis Charmet
  • Denis Charmet
    Denis Charmet @typx started a thread on commit 9786ca15
  • 129 129
    130 130 uint32_t i_flags;
    131 131 unsigned i_nb_samples; /* Used for audio */
    132 uint32_t clock_id;
    • Not a big fan of extending the whole frame structure for a fringe case. Why not use ancillaries and only attach them to the blocks starting a new timeline. Just like a new SPS for a new sequence.

      It would also prevent doing the same for pictures.

      Edited by Denis Charmet
    • Please register or sign in to reply
  • Denis Charmet
    Denis Charmet @typx started a thread on commit d98786bd
  • 62 62
    63 63 /* Display date
    64 64 * cf. decoder_GetDisplayDate */
    65 vlc_tick_t (*get_display_date)( decoder_t *, vlc_tick_t, vlc_tick_t );
    65 vlc_tick_t (*get_display_date)( decoder_t *, uint32_t clock_id,
  • Denis Charmet
    Denis Charmet @typx started a thread on commit 011d77cc
  • 188 188 }
    189 189 p_pic->i_pts = p_block_bytestream->i_pts;
    190 190 p_pic->i_dts = p_block_bytestream->i_dts;
    191 p_pic->clock_id = p_block_bytestream->clock_id;
  • Denis Charmet
    Denis Charmet @typx started a thread on commit 275db3af
  • 413 415 if (unlikely(first == NULL))
    414 416 return written;
    415 417
    418 if (first->clock_id != sys->clock_id)
    419 {
    420 const pa_sample_spec *ss = pa_stream_get_sample_spec(s);
    421 pa_usec_t written_usec = pa_bytes_to_usec(sys->written_bytes, ss);
    422 sys->first_pts = first->i_pts - written_usec;
    • I don't understand this substraction.

    • Author Maintainer

      It's a stitch between the old pts base and the new pts. We subtract the amount of written samples to the new time base because the timing report will continue to increase and include this amount of written samples.

    • Please register or sign in to reply
    • I struggle to understand the actual problem you are trying to fix TBH. Care to share an example?

      For now a PCR discontinuity or a seek will trigger a flush in the core anyway.

    • Author Maintainer

      I struggle to understand the actual problem you are trying to fix TBH. Care to share an example?

      I just added in the MR description: https://streams.videolan.org/issues/26378/intentional_pcr_discontinuity-short.ts

      PCR discontinuity at 16sec. Works with VLC 3.0. Video "freeze" in VLC 4.0 (since the vout will wait for an invalid date)

      For now a PCR discontinuity or a seek will trigger a flush in the core anyway.

      A seek, yes, but not a PCR discontinuity. The demux can set the block flags as DISCONTINUITY, but it won't be handled by the clock or the es_out.

      We don't want to flush in that case since there are no input discontinuity, the video and audio decoders can continue to decoder (and we don't want to lose output frames).

      I think @fcartegnie has some other valid use case.

    • In general terms, this MR fix the fact that clock changes are currently synchronous whereas the pipeline is asynchronously using it.

    • Author Maintainer

      One alternative could have been to handle a sort drain midstream, but it is not possible (and will never be) since:

      • You need to flush after a drain (since most decoders and output can't handle a resume from a drain). Therefore, you might lose some context and will need to send a key frame first.
      • Re-buffering midstream after a drain, not impossible but we don't want to handle that
    • or now a PCR discontinuity or a seek will trigger a flush in the core anyway.

      only RESET_PCR does

      Edited by François Cartegnie
    • Please register or sign in to reply
  • Thomas Guillem changed the description

    changed the description

    • TBH, I don't understand why we need a new clock ID, and I have the same prejudice against adding a field in so many objects for a corner case. But if we really need this, I would expect a reference counted object rather than an integer.

      AFAICT, if we want to retain timestamps from before a clock reset after clock reset, it is necessary and sufficient to ensure that the timestamp ranges across resets do not overlap. Sufficiency is kind of obvious. Necessity stems from how stream output modules are (not) going to like timestamps going backwards.

      Easier said than done, of course.

    • Author Maintainer

      TBH, I don't understand why we need a new clock ID, and I have the same prejudice against adding a field in so many objects for a corner case.

      I have a version where the clock chooses the correct context where the difference output_ts - clock_context->first_pcr is the smallest. It's definitely the simplest solution, but maybe too naive ?

      But if we really need this, I would expect a reference counted object rather than an integer.

      It will increase the complexity. With this MR, the clock retains all contexts, and remove a specific one when all clocks passed to the next context.

    • It will increase the complexity. With this MR, the clock retains all contexts, and remove a specific one when all clocks passed to the next context.

      Not if we use ancillaries that are naturally refcounted and we share the clock context directly :smile:

    • Author Maintainer

      We will need to add ancillaries support in subpictures too.

    • Author Maintainer

      For now, ancillaries are mostly created by decoders. No decoders or packetizer modules will copy the ancillaries from the input block to the output.

    • I have a version where the clock chooses the correct context where the difference output_ts - clock_context->first_pcr is the smallest. It's definitely the simplest solution, but maybe too naive ?

      I'm personally not a big fan of this because we have no way to ensure that a stream will not have a PCR going backward. This would only fix one use case.

    • For now, ancillaries are mostly created by decoders. No decoders or packetizer modules will copy the ancillaries from the input block to the output.

      They do copy ICC though. It's not really different of how you would copy the clock id from the frame to the picture.

      Edited by Denis Charmet
    • Author Maintainer

      I could try the ancillary approach, if we all agree on the great picture: are you OK to add support for PCR discontinuity without data discontinuity ?

      Note that it is already handled (OK, maybe by luck) in VLC 3.0.

    • Necessity stems from how stream output modules are (not) going to like timestamps going backwards.

      Going too far forward to trigger an $enteranybigvaluehere wait doesn't help either

    • I have a version where the clock chooses the correct context where the difference output_ts - clock_context->first_pcr is the smallest. It's definitely the simplest solution, but maybe too naive ?

      Open GOPs have a long history of pts lower than dts with some containers

      Edited by François Cartegnie
    • Please register or sign in to reply
  • Since there's lots of duration computation using the non converted timestamps, this is going to be fun with still bogus durations.

  • Thomas Guillem mentioned in merge request !5202 (merged)

    mentioned in merge request !5202 (merged)

  • Thomas Guillem mentioned in merge request !5473 (closed)

    mentioned in merge request !5473 (closed)

  • Thomas Guillem mentioned in merge request !5626 (merged)

    mentioned in merge request !5626 (merged)

  • Thomas Guillem mentioned in merge request !5630 (merged)

    mentioned in merge request !5630 (merged)

  • Author Maintainer

    Superseded by !5630 (merged)

  • Please register or sign in to reply
    Loading