int i_tk;
es_out_id_t **tk;
-
- int64_t i_pcr;
- int i_pcr_tk;
+ int64_t *tk_pcr;
+ int64_t i_pcr;
unsigned i_ssa_order;
static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order );
static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time );
+static void ResetTime( demux_t *p_demux, int64_t i_time );
/*****************************************************************************
* Open
p_sys->fmt = fmt;
p_sys->i_tk = 0;
p_sys->tk = NULL;
- p_sys->i_pcr_tk = -1;
- p_sys->i_pcr = -1;
+ p_sys->tk_pcr = NULL;
p_sys->i_ssa_order = 0;
TAB_INIT( p_sys->i_attachments, p_sys->attachments);
p_sys->p_title = NULL;
TAB_APPEND( p_sys->i_tk, p_sys->tk, es );
}
}
+ p_sys->tk_pcr = calloc( p_sys->i_tk, sizeof(*p_sys->tk_pcr) );
+
if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
i_start_time = p_sys->ic->start_time * 1000000 / AV_TIME_BASE;
TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
}
+ ResetTime( p_demux, 0 );
return VLC_SUCCESS;
}
demux_sys_t *p_sys = p_demux->p_sys;
FREENULL( p_sys->tk );
+ free( p_sys->tk_pcr );
if( p_sys->ic ) av_close_input_stream( p_sys->ic );
msg_Dbg( p_demux, "tk[%d] dts=%"PRId64" pts=%"PRId64,
pkt.stream_index, p_frame->i_dts, p_frame->i_pts );
#endif
+ if( p_frame->i_dts > VLC_TS_INVALID )
+ p_sys->tk_pcr[pkt.stream_index] = p_frame->i_dts;
- if( p_frame->i_dts > VLC_TS_INVALID &&
- ( pkt.stream_index == p_sys->i_pcr_tk || p_sys->i_pcr_tk < 0 ) )
- {
- p_sys->i_pcr_tk = pkt.stream_index;
- p_sys->i_pcr = p_frame->i_dts;
+ int64_t i_ts_max = INT64_MIN;
+ for( int i = 0; i < p_sys->i_tk; i++ )
+ i_ts_max = __MAX( i_ts_max, p_sys->tk_pcr[i] );
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
+ int64_t i_ts_min = INT64_MAX;
+ for( int i = 0; i < p_sys->i_tk; i++ )
+ {
+ if( p_sys->tk_pcr[i] > VLC_TS_INVALID && p_sys->tk_pcr[i] + 10 * CLOCK_FREQ >= i_ts_max )
+ i_ts_min = __MIN( i_ts_min, p_sys->tk_pcr[i] );
+ }
+ if( i_ts_min >= p_sys->i_pcr )
+ {
+ p_sys->i_pcr = i_ts_min;
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
+ UpdateSeekPoint( p_demux, p_sys->i_pcr );
}
es_out_Send( p_demux->out, p_sys->tk[pkt.stream_index], p_frame );
- UpdateSeekPoint( p_demux, p_sys->i_pcr);
av_free_packet( &pkt );
return 1;
}
}
}
+static void ResetTime( demux_t *p_demux, int64_t i_time )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ if( p_sys->ic->start_time == (int64_t)AV_NOPTS_VALUE || i_time < 0 )
+ i_time = VLC_TS_INVALID;
+ else if( i_time == 0 )
+ i_time = 1;
+
+ p_sys->i_pcr = i_time;
+ for( int i = 0; i < p_sys->i_tk; i++ )
+ p_sys->tk_pcr[i] = i_time;
+
+ if( i_time > VLC_TS_INVALID )
+ {
+ es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_time );
+ UpdateSeekPoint( p_demux, i_time );
+ }
+}
+
static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order )
{
if( p_pkt->size <= 0 )
static int Control( demux_t *p_demux, int i_query, va_list args )
{
demux_sys_t *p_sys = p_demux->p_sys;
+ const int64_t i_start_time = p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE ? p_sys->ic->start_time : 0;
double f, *pf;
int64_t i64, *pi64;
case DEMUX_SET_POSITION:
f = (double) va_arg( args, double );
- if( p_sys->i_pcr > 0 )
- {
- i64 = p_sys->ic->duration * f;
- if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
- i64 += p_sys->ic->start_time;
+ i64 = p_sys->ic->duration * f + i_start_time;
- msg_Warn( p_demux, "DEMUX_SET_POSITION: %"PRId64, i64 );
+ msg_Warn( p_demux, "DEMUX_SET_POSITION: %"PRId64, i64 );
- /* If we have a duration, we prefer to seek by time
- but if we don't, or if the seek fails, try BYTE seeking */
- if( p_sys->ic->duration == (int64_t)AV_NOPTS_VALUE ||
- (av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0) )
- {
- int64_t i_size = stream_Size( p_demux->s );
- i64 = (i_size * f);
+ /* If we have a duration, we prefer to seek by time
+ but if we don't, or if the seek fails, try BYTE seeking */
+ if( p_sys->ic->duration == (int64_t)AV_NOPTS_VALUE ||
+ (av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0) )
+ {
+ int64_t i_size = stream_Size( p_demux->s );
+ i64 = (i_size * f);
- msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
- return VLC_EGENERIC;
- }
- else
- {
- UpdateSeekPoint( p_demux, i64 );
- }
- p_sys->i_pcr = -1; /* Invalidate time display */
+ msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
+ return VLC_EGENERIC;
+
+ ResetTime( p_demux, -1 );
+ }
+ else
+ {
+ ResetTime( p_demux, i64 - i_start_time );
}
return VLC_SUCCESS;
return VLC_SUCCESS;
case DEMUX_SET_TIME:
+ {
i64 = (int64_t)va_arg( args, int64_t );
- i64 = i64 *AV_TIME_BASE / 1000000;
- if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
- i64 += p_sys->ic->start_time;
+ i64 = i64 *AV_TIME_BASE / 1000000 + i_start_time;
msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0 )
{
return VLC_EGENERIC;
}
- p_sys->i_pcr = -1; /* Invalidate time display */
- UpdateSeekPoint( p_demux, i64 );
+ ResetTime( p_demux, i64 - i_start_time );
return VLC_SUCCESS;
+ }
case DEMUX_HAS_UNSUPPORTED_META:
{
if( !p_sys->p_title )
return VLC_EGENERIC;
- i64 = p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset *AV_TIME_BASE / 1000000;
- if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
- i64 += p_sys->ic->start_time;
+ i64 = p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset *
+ AV_TIME_BASE / 1000000 + i_start_time;
msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0 )
{
return VLC_EGENERIC;
}
- p_sys->i_pcr = -1; /* Invalidate time display */
- UpdateSeekPoint( p_demux, i64 );
+ ResetTime( p_demux, i64 - i_start_time );
return VLC_SUCCESS;
}