Commit 4558d9ca authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont Committed by Jean-Baptiste Kempf

smf: avoid arbitrarily long (PCR wise) Demux calls

Always return after one tick or one events timestamp.
parent 0e9fdd2a
...@@ -93,14 +93,15 @@ static int ReadDeltaTime (stream_t *s, mtrk_t *track) ...@@ -93,14 +93,15 @@ static int ReadDeltaTime (stream_t *s, mtrk_t *track)
struct demux_sys_t struct demux_sys_t
{ {
es_out_id_t *es; es_out_id_t *es;
date_t pts; date_t pts; /*< Play timestamp */
uint64_t pulse; /* Pulses counter */ uint64_t pulse; /*< Pulses counter */
mtime_t tick; /*< Last tick timestamp */
unsigned ppqn; /* Pulses Per Quarter Note */ unsigned ppqn; /*< Pulses Per Quarter Note */
/* by the way, "quarter note" is "noire" in French */ /* by the way, "quarter note" is "noire" in French */
unsigned trackc; /* Number of tracks */ unsigned trackc; /*< Number of tracks */
mtrk_t trackv[]; /* Track states */ mtrk_t trackv[]; /*< Track states */
}; };
/** /**
...@@ -359,55 +360,53 @@ skip: ...@@ -359,55 +360,53 @@ skip:
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
*****************************************************************************/ *****************************************************************************/
static int Demux (demux_t *p_demux) static int Demux (demux_t *demux)
{ {
stream_t *s = p_demux->s; demux_sys_t *sys = demux->p_sys;
demux_sys_t *p_sys = p_demux->p_sys;
uint64_t pulse = p_sys->pulse, next_pulse = UINT64_MAX;
if (pulse == UINT64_MAX) /* MIDI Tick emulation (ping the decoder every 10ms) */
return 0; /* all tracks are done */ if (sys->tick <= date_Get (&sys->pts))
{
block_t *tick = block_Alloc (1);
if (unlikely(tick == NULL))
return VLC_ENOMEM;
es_out_Control (p_demux->out, ES_OUT_SET_PCR, date_Get (&p_sys->pts)); tick->p_buffer[0] = 0xF9;
tick->i_dts = tick->i_pts = sys->tick;
for (unsigned i = 0; i < p_sys->trackc; i++) es_out_Send (demux->out, sys->es, tick);
es_out_Control (demux->out, ES_OUT_SET_PCR, sys->tick);
sys->tick += CLOCK_FREQ / 100;
return 1;
}
/* MIDI events in chronological order across all tracks */
uint64_t cur_pulse = sys->pulse, next_pulse = UINT64_MAX;
for (unsigned i = 0; i < sys->trackc; i++)
{ {
mtrk_t *track = p_sys->trackv + i; mtrk_t *track = sys->trackv + i;
while (track->next == pulse) while (track->next == cur_pulse)
{ {
if (HandleMessage (p_demux, track) if (HandleMessage (demux, track)
|| ReadDeltaTime (s, track)) || ReadDeltaTime (demux->s, track))
{ {
msg_Err (p_demux, "fatal parsing error"); msg_Err (demux, "fatal parsing error");
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
if (track->next < next_pulse) if (next_pulse > track->next)
next_pulse = track->next; next_pulse = track->next;
} }
mtime_t cur_tick = (date_Get (&p_sys->pts) + 9999) / 10000, last_tick; if (next_pulse == UINT64_MAX)
if (next_pulse != UINT64_MAX) return 0; /* all tracks are done */
last_tick = date_Increment (&p_sys->pts, next_pulse - pulse) / 10000;
else
last_tick = cur_tick + 1;
/* MIDI Tick emulation (ping the decoder every 10ms) */
while (cur_tick < last_tick)
{
block_t *tick = block_Alloc (1);
if (tick == NULL)
break;
tick->p_buffer[0] = 0xF9;
tick->i_dts = tick->i_pts = VLC_TS_0 + cur_tick++ * 10000;
es_out_Send (p_demux->out, p_sys->es, tick);
}
p_sys->pulse = next_pulse;
date_Increment (&sys->pts, next_pulse - cur_pulse);
sys->pulse = next_pulse;
return 1; return 1;
} }
...@@ -416,15 +415,13 @@ static int Demux (demux_t *p_demux) ...@@ -416,15 +415,13 @@ static int Demux (demux_t *p_demux)
*****************************************************************************/ *****************************************************************************/
static int Control (demux_t *p_demux, int i_query, va_list args) static int Control (demux_t *p_demux, int i_query, va_list args)
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *sys = p_demux->p_sys;
switch (i_query) switch (i_query)
{ {
case DEMUX_GET_TIME: case DEMUX_GET_TIME:
{ *va_arg (args, int64_t *) = sys->tick - VLC_TS_0;
*(va_arg (args, int64_t *)) = date_Get (&p_sys->pts);
return 0; return 0;
}
#if 0 #if 0
/* TODO: */ /* TODO: */
case DEMUX_SET_TIME: case DEMUX_SET_TIME:
...@@ -544,6 +541,7 @@ static int Open (vlc_object_t *obj) ...@@ -544,6 +541,7 @@ static int Open (vlc_object_t *obj)
date_Init (&sys->pts, ppqn * 2, 1); date_Init (&sys->pts, ppqn * 2, 1);
date_Set (&sys->pts, VLC_TS_0); date_Set (&sys->pts, VLC_TS_0);
sys->pulse = 0; sys->pulse = 0;
sys->tick = VLC_TS_0;
sys->ppqn = ppqn; sys->ppqn = ppqn;
sys->trackc = tracks; sys->trackc = tracks;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment