Skip to content

Commit

Permalink
transcode: pcr_sync: switch assert to runtime error
Browse files Browse the repository at this point in the history
This assertion was too severe and deserve actual runtime handling.

The `pcr_helper` should just fail in case of inconsistent
input/output. This can happen in various case such as bogus encoder or
simply internal error in the `pcr_helper` code.

This patch is making sure the `pcr_helper` user can disable it in case
of failure.

Refs #27730
  • Loading branch information
AlaricSenat authored and tmatth committed Jan 26, 2023
1 parent 68a9ddd commit ec5e344
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 24 deletions.
20 changes: 13 additions & 7 deletions modules/stream_out/transcode/pcr_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,21 @@ int transcode_track_pcr_helper_SignalEnteringFrame(transcode_track_pcr_helper_t
return VLC_SUCCESS;
}

vlc_tick_t transcode_track_pcr_helper_SignalLeavingFrame(transcode_track_pcr_helper_t *pcr_helper,
const vlc_frame_t *frame)
int transcode_track_pcr_helper_SignalLeavingFrame(transcode_track_pcr_helper_t *pcr_helper,
const vlc_frame_t *frame,
vlc_tick_t *pcr)
{
assert(!vlc_list_is_empty(&pcr_helper->delayed_frames_data));
*pcr = VLC_TICK_INVALID;

if (vlc_list_is_empty(&pcr_helper->delayed_frames_data))
return VLC_EGENERIC;

pcr_helper->last_dts_output = frame->i_dts;

pcr_helper->held_media_time -= frame->i_length;
const vlc_tick_t output_media_time =
pcr_helper->input_media_time - pcr_helper->held_media_time;

vlc_tick_t pcr = VLC_TICK_INVALID;
delayed_frame_data_t *frame_data;
vlc_list_foreach(frame_data, &pcr_helper->delayed_frames_data, node)
{
Expand All @@ -176,11 +179,14 @@ vlc_tick_t transcode_track_pcr_helper_SignalLeavingFrame(transcode_track_pcr_hel
const vlc_tick_t current_pcr =
transcode_track_pcr_helper_GetFramePCR(pcr_helper, frame_data->dts);
if (current_pcr != VLC_TICK_INVALID)
pcr = current_pcr;
*pcr = current_pcr;

vlc_list_remove(&frame_data->node);
free(frame_data);
}
return (pcr == VLC_TICK_INVALID) ? VLC_TICK_INVALID
: __MIN(frame->i_dts, pcr);

if (*pcr != VLC_TICK_INVALID)
*pcr = __MIN(frame->i_dts, *pcr);

return VLC_SUCCESS;
}
11 changes: 7 additions & 4 deletions modules/stream_out/transcode/pcr_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,14 @@ int transcode_track_pcr_helper_SignalEnteringFrame(transcode_track_pcr_helper_t
* \note This can be called multiple times to handle multiple following PCR's.
* \note If the frame output has seen its timestamp altered, this helper will synthetise a new PCR.
*
* \param frame The leaving frame (will be treated as a single frame).
* \param[in] frame The leaving frame (will be treated as a single frame).
* \param[out] pcr The PCR value following the frame or VLC_TICK_INVALID if no PCR is following.
*
* \return The PCR value following the frame or VLC_TICK_INVALID if no PCR is following.
* \retval VLC_SUCCESS On success (even if no PCR is to be forwarded).
* \retval VLC_EGENERIC On fatal frame mismatch error.
*/
vlc_tick_t transcode_track_pcr_helper_SignalLeavingFrame(transcode_track_pcr_helper_t *,
const vlc_frame_t *frame);
int transcode_track_pcr_helper_SignalLeavingFrame(transcode_track_pcr_helper_t *,
const vlc_frame_t *frame,
vlc_tick_t *pcr);

#endif
3 changes: 2 additions & 1 deletion modules/stream_out/transcode/transcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,8 @@ static int Send( sout_stream_t *p_stream, void *_id, block_t *p_buffer )

vlc_tick_t pcr = VLC_TICK_INVALID;
if( sys->pcr_forwarding_enabled )
pcr = transcode_track_pcr_helper_SignalLeavingFrame( id->pcr_helper, it );
transcode_track_pcr_helper_SignalLeavingFrame(
id->pcr_helper, it, &pcr );

if( sout_StreamIdSend( p_stream->p_next, id->downstream_id, it ) != VLC_SUCCESS )
{
Expand Down
38 changes: 26 additions & 12 deletions test/modules/stream_out/pcr_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,10 @@ static void test_PCRHelperSimple(vlc_pcr_sync_t *sync,
assert(vlc_pcr_sync_SignalPCR(sync, 10u) == VLC_SUCCESS);

const vlc_frame_t out_frame = {.i_dts = 2000u, .i_length = 10u};
const vlc_tick_t pcr =
transcode_track_pcr_helper_SignalLeavingFrame(pcr_helper, &out_frame);
vlc_tick_t pcr;
const int status = transcode_track_pcr_helper_SignalLeavingFrame(
pcr_helper, &out_frame, &pcr);
assert(status == VLC_SUCCESS);
assert(pcr == 10u);
}

Expand Down Expand Up @@ -380,19 +382,24 @@ test_PCRHelperMultipleTracks(vlc_pcr_sync_t *sync,
assert(vlc_pcr_sync_SignalPCR(sync, 101) == VLC_SUCCESS);
}

vlc_tick_t pcr;
// Unqueue the audio frames first to mimic fast decoding
for (vlc_tick_t dts = 0; dts < 200; dts += 10)
{
const vlc_frame_t a_frame = {.i_dts = dts + 1, .i_length = 10u};
const vlc_tick_t pcr = transcode_track_pcr_helper_SignalLeavingFrame(audio, &a_frame);
const int status = transcode_track_pcr_helper_SignalLeavingFrame(
audio, &a_frame, &pcr);
assert(status == VLC_SUCCESS);
assert(pcr == VLC_TICK_INVALID);
}

for (vlc_tick_t dts = 0; dts < 100; dts += 10)
{
const vlc_frame_t v_frame = {.i_dts = (dts * 2) - 10 + 1,
.i_length = 20u};
const vlc_tick_t pcr = transcode_track_pcr_helper_SignalLeavingFrame(video, &v_frame);
const int status = transcode_track_pcr_helper_SignalLeavingFrame(
video, &v_frame, &pcr);
assert(status == VLC_SUCCESS);
if (dts != 50)
assert(pcr == VLC_TICK_INVALID);
else
Expand All @@ -416,11 +423,15 @@ test_PCRHelperSplitFrameOutput(vlc_pcr_sync_t *sync,

const vlc_frame_t out_frame1 = {.i_dts = 2000u, .i_length = 5u};
const vlc_frame_t out_frame2 = {.i_dts = 2005u, .i_length = 5u};
vlc_tick_t pcr =
transcode_track_pcr_helper_SignalLeavingFrame(pcr_helper, &out_frame1);
vlc_tick_t pcr;
int status = transcode_track_pcr_helper_SignalLeavingFrame(
pcr_helper, &out_frame1, &pcr);
assert(status == VLC_SUCCESS);
assert(pcr == VLC_TICK_INVALID);
pcr =
transcode_track_pcr_helper_SignalLeavingFrame(pcr_helper, &out_frame2);

status = transcode_track_pcr_helper_SignalLeavingFrame(
pcr_helper, &out_frame2, &pcr);
assert(status == VLC_SUCCESS);
assert(pcr == 10u);
}

Expand All @@ -446,13 +457,16 @@ test_PCRHelperSplitFrameInput(vlc_pcr_sync_t *sync,
assert(dropped_frame_pcr == VLC_TICK_INVALID);

const vlc_frame_t out_frame1 = {.i_dts = 1u, .i_length = 20u};
vlc_tick_t pcr =
transcode_track_pcr_helper_SignalLeavingFrame(pcr_helper, &out_frame1);
vlc_tick_t pcr;
int status = transcode_track_pcr_helper_SignalLeavingFrame(
pcr_helper, &out_frame1, &pcr);
assert(status == VLC_SUCCESS);
// PCR should be re-synthetized.
assert(pcr == 1u);
const vlc_frame_t out_frame2 = {.i_dts = 21u, .i_length = 10u};
pcr =
transcode_track_pcr_helper_SignalLeavingFrame(pcr_helper, &out_frame2);
status = transcode_track_pcr_helper_SignalLeavingFrame(
pcr_helper, &out_frame2, &pcr);
assert(status == VLC_SUCCESS);
assert(pcr == VLC_TICK_INVALID);
}

Expand Down

0 comments on commit ec5e344

Please sign in to comment.