void initTimes() { if( demux_Control( p_demux->p_next, DEMUX_GET_TIME, &m_start_time ) != VLC_SUCCESS ) m_start_time = -1; if( demux_Control( p_demux->p_next, DEMUX_GET_POSITION, &m_start_pos ) != VLC_SUCCESS ) m_start_pos = -1.0f; m_last_time = m_start_time; m_last_pos = m_start_pos; }
static void* DStreamThread( void *obj ) { stream_t *s = (stream_t *)obj; stream_sys_t *p_sys = s->p_sys; demux_t *p_demux; /* Create the demuxer */ p_demux = demux_New( s, s->p_input, "", p_sys->psz_name, "", s, p_sys->out, false ); if( p_demux == NULL ) return NULL; /* stream_Demux cannot apply DVB filters. * Get all programs and let the E/S output sort them out. */ demux_Control( p_demux, DEMUX_SET_GROUP, -1, NULL ); /* Main loop */ mtime_t next_update = 0; while( atomic_load( &p_sys->active ) ) { if( p_demux->info.i_update || mdate() >= next_update ) { double newpos; int64_t newlen, newtime; if( demux_Control( p_demux, DEMUX_GET_POSITION, &newpos ) ) newpos = 0.; if( demux_Control( p_demux, DEMUX_GET_LENGTH, &newlen ) ) newlen = 0; if( demux_Control( p_demux, DEMUX_GET_TIME, &newtime ) ) newtime = 0; vlc_mutex_lock( &p_sys->lock ); p_sys->stats.position = newpos; p_sys->stats.length = newlen; p_sys->stats.time = newtime; vlc_mutex_unlock( &p_sys->lock ); p_demux->info.i_update = 0; next_update = mdate() + (CLOCK_FREQ / 4); } if( demux_Demux( p_demux ) <= 0 ) break; } /* Explicit kludge: the stream is destroyed by the owner of the * streamDemux, not here. */ p_demux->s = NULL; demux_Delete( p_demux ); return NULL; }
void seekBack( vlc_tick_t time, double pos ) { es_out_Control( p_demux->p_next->out, ES_OUT_RESET_PCR ); if( m_can_seek ) { int ret = VLC_EGENERIC; if( time >= 0 ) ret = demux_Control( p_demux->p_next, DEMUX_SET_TIME, time, false ); if( ret != VLC_SUCCESS && pos >= 0 ) demux_Control( p_demux->p_next, DEMUX_SET_POSITION, pos, false ); } }
/***************************************************************************** * input_ControlVarStop: *****************************************************************************/ void input_ControlVarStop( input_thread_t *p_input ) { demux_t* p_demux = input_priv(p_input)->master->p_demux; int i_cur_title; if( !input_priv(p_input)->b_preparsing ) InputDelCallbacks( p_input, p_input_callbacks ); if( input_priv(p_input)->i_title > 1 ) InputDelCallbacks( p_input, p_input_title_navigation_callbacks ); for( int i = 0; i < input_priv(p_input)->i_title; i++ ) { char name[sizeof("title ") + 3 * sizeof (int)]; sprintf( name, "title %2u", i ); var_DelCallback( p_input, name, NavigationCallback, (void *)(intptr_t)i ); } if( !demux_Control( p_demux, DEMUX_GET_TITLE, &i_cur_title ) ) { const input_title_t* t = input_priv(p_input)->title[ i_cur_title ]; if( t->i_seekpoint > 1 ) InputDelCallbacks( p_input, p_input_seekpoint_navigation_callbacks ); } }
static void *vlc_demux_chained_Thread(void *data) { vlc_demux_chained_t *dc = data; demux_t *demux = demux_New(VLC_OBJECT(dc->reader), dc->name, dc->reader, dc->out); if (demux == NULL) { vlc_stream_Delete(dc->reader); return NULL; } /* Stream FIFO cannot apply DVB filters. * Get all programs and let the E/S output sort them out. */ demux_Control(demux, DEMUX_SET_GROUP_ALL); /* Main loop */ vlc_tick_t next_update = 0; do if (demux_TestAndClearFlags(demux, UINT_MAX) || vlc_tick_now() >= next_update) { double newpos; vlc_tick_t newlen; vlc_tick_t newtime; if (demux_Control(demux, DEMUX_GET_POSITION, &newpos)) newpos = 0.; if (demux_Control(demux, DEMUX_GET_LENGTH, &newlen)) newlen = 0; if (demux_Control(demux, DEMUX_GET_TIME, &newtime)) newtime = 0; vlc_mutex_lock(&dc->lock); dc->stats.position = newpos; dc->stats.length = newlen; dc->stats.time = newtime; vlc_mutex_unlock(&dc->lock); next_update = vlc_tick_now() + VLC_TICK_FROM_MS(250); } while (demux_Demux(demux) > 0); demux_Delete(demux); return NULL; }
int Control( demux_t *p_demux_filter, int i_query, va_list args ) { if( !m_enabled && i_query != DEMUX_FILTER_ENABLE ) return demux_vaControl( p_demux_filter->p_next, i_query, args ); switch (i_query) { case DEMUX_GET_POSITION: { double pos = getPosition(); if( pos >= 0 ) { *va_arg( args, double * ) = pos; return VLC_SUCCESS; } return VLC_EGENERIC; } case DEMUX_GET_TIME: { vlc_tick_t time = getTime(); if( time >= 0 ) { *va_arg(args, vlc_tick_t *) = time; return VLC_SUCCESS; } return VLC_EGENERIC; } case DEMUX_GET_LENGTH: { int ret; va_list ap; va_copy( ap, args ); ret = demux_vaControl( p_demux_filter->p_next, i_query, args ); if( ret == VLC_SUCCESS ) m_length = *va_arg( ap, vlc_tick_t * ); va_end( ap ); return ret; } case DEMUX_CAN_SEEK: { int ret; va_list ap; va_copy( ap, args ); ret = demux_vaControl( p_demux_filter->p_next, i_query, args ); if( ret == VLC_SUCCESS ) m_can_seek = *va_arg( ap, bool* ); va_end( ap ); return ret; } case DEMUX_SET_POSITION: { double pos = va_arg( args, double ); /* Force unprecise seek */ int ret = demux_Control( p_demux->p_next, DEMUX_SET_POSITION, pos, false ); if( ret != VLC_SUCCESS ) return ret; resetTimes(); resetDemuxEof(); return VLC_SUCCESS; } case DEMUX_SET_TIME: { vlc_tick_t time = va_arg( args, vlc_tick_t ); /* Force unprecise seek */ int ret = demux_Control( p_demux->p_next, DEMUX_SET_TIME, time, false ); if( ret != VLC_SUCCESS ) return ret; resetTimes(); resetDemuxEof(); return VLC_SUCCESS; } case DEMUX_SET_PAUSE_STATE: { va_list ap; va_copy( ap, args ); int paused = va_arg( ap, int ); va_end( ap ); setPauseState( paused != 0 ); break; } case DEMUX_SET_ES: /* Seek back to the last known pos when changing tracks. This will * flush sout streams, make sout del/add called right away and * clear CC buffers. */ seekBack(m_last_time, m_last_pos); resetTimes(); resetDemuxEof(); break; case DEMUX_FILTER_ENABLE: p_renderer = static_cast<chromecast_common *>( var_InheritAddress( p_demux, CC_SHARED_VAR_NAME ) ); assert(p_renderer != NULL); m_enabled = true; init(); return VLC_SUCCESS; case DEMUX_FILTER_DISABLE: deinit(); /* Seek back to last known position. Indeed we don't want to resume * from the input position that can be more than 1 minutes forward * (depending on the CC buffering policy). */ seekBack(m_last_time, m_last_pos); m_enabled = false; p_renderer = NULL; return VLC_SUCCESS; } return demux_vaControl( p_demux_filter->p_next, i_query, args ); }
/***************************************************************************** * Control: *****************************************************************************/ static int Control( demux_t *p_demux, int i_query, va_list args ) { demux_sys_t *p_sys = p_demux->p_sys; double f, *pf; int64_t i64; int i_ret; switch( i_query ) { case DEMUX_CAN_SEEK: *va_arg( args, bool * ) = p_sys->b_seekable; return VLC_SUCCESS; case DEMUX_GET_TITLE: *va_arg( args, int * ) = p_sys->current_title; return VLC_SUCCESS; case DEMUX_GET_SEEKPOINT: *va_arg( args, int * ) = p_sys->current_seekpoint; return VLC_SUCCESS; case DEMUX_GET_POSITION: pf = va_arg( args, double * ); i64 = stream_Size( p_demux->s ) - p_sys->i_start_byte; if( i64 > 0 ) { double current = vlc_stream_Tell( p_demux->s ) - p_sys->i_start_byte; *pf = current / (double)i64; } else { *pf = 0.0; } return VLC_SUCCESS; case DEMUX_SET_POSITION: f = va_arg( args, double ); i64 = stream_Size( p_demux->s ) - p_sys->i_start_byte; p_sys->i_current_pts = VLC_TICK_INVALID; p_sys->i_scr = VLC_TICK_INVALID; if( p_sys->format == CDXA_PS ) { i64 = (int64_t)(i64 * f); /* Align to sector payload */ i64 = p_sys->i_start_byte + i64 - (i64 % CDXA_SECTOR_SIZE) + CDXA_SECTOR_HEADER_SIZE; } else { i64 = p_sys->i_start_byte + (int64_t)(i64 * f); } i_ret = vlc_stream_Seek( p_demux->s, i64 ); if( i_ret == VLC_SUCCESS ) { NotifyDiscontinuity( p_sys->tk, p_demux->out ); return i_ret; } break; case DEMUX_GET_TIME: if( p_sys->i_time_track_index >= 0 && p_sys->i_current_pts != VLC_TICK_INVALID ) { *va_arg( args, vlc_tick_t * ) = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track_index].i_first_pts; return VLC_SUCCESS; } if( p_sys->i_first_scr != VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID ) { vlc_tick_t i_time = p_sys->i_scr - p_sys->i_first_scr; /* H.222 2.5.2.2 */ if( p_sys->i_mux_rate > 0 && p_sys->b_have_pack ) { uint64_t i_offset = vlc_stream_Tell( p_demux->s ) - p_sys->i_lastpack_byte; i_time += vlc_tick_from_samples(i_offset, p_sys->i_mux_rate * 50); } *va_arg( args, vlc_tick_t * ) = i_time; return VLC_SUCCESS; } *va_arg( args, vlc_tick_t * ) = 0; break; case DEMUX_GET_LENGTH: if( p_sys->i_length > VLC_TICK_0 ) { *va_arg( args, vlc_tick_t * ) = p_sys->i_length; return VLC_SUCCESS; } else if( p_sys->i_mux_rate > 0 ) { *va_arg( args, vlc_tick_t * ) = vlc_tick_from_samples( stream_Size( p_demux->s ) - p_sys->i_start_byte / 50, p_sys->i_mux_rate ); return VLC_SUCCESS; } *va_arg( args, vlc_tick_t * ) = 0; break; case DEMUX_SET_TIME: { if( p_sys->i_time_track_index >= 0 && p_sys->i_current_pts != VLC_TICK_INVALID && p_sys->i_length > VLC_TICK_0) { vlc_tick_t i_time = va_arg( args, vlc_tick_t ); i_time -= p_sys->tk[p_sys->i_time_track_index].i_first_pts; return demux_Control( p_demux, DEMUX_SET_POSITION, (double) i_time / p_sys->i_length ); } break; } case DEMUX_GET_TITLE_INFO: { struct input_title_t ***v = va_arg( args, struct input_title_t*** ); int *c = va_arg( args, int * ); *va_arg( args, int* ) = 0; /* Title offset */ *va_arg( args, int* ) = 0; /* Chapter offset */ return vlc_stream_Control( p_demux->s, STREAM_GET_TITLE_INFO, v, c ); } case DEMUX_SET_TITLE: return vlc_stream_vaControl( p_demux->s, STREAM_SET_TITLE, args ); case DEMUX_SET_SEEKPOINT: return vlc_stream_vaControl( p_demux->s, STREAM_SET_SEEKPOINT, args ); case DEMUX_TEST_AND_CLEAR_FLAGS: { unsigned *restrict flags = va_arg(args, unsigned *); *flags &= p_sys->updates; p_sys->updates &= ~*flags; return VLC_SUCCESS; } case DEMUX_GET_META: return vlc_stream_vaControl( p_demux->s, STREAM_GET_META, args ); case DEMUX_GET_FPS: break; case DEMUX_CAN_PAUSE: case DEMUX_SET_PAUSE_STATE: case DEMUX_CAN_CONTROL_PACE: case DEMUX_GET_PTS_DELAY: return demux_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args ); default: break; } return VLC_EGENERIC; }