[vlc-devel] [PATCH] TS demux: get time and length
Laurent Aimar
fenrir at elivagar.org
Wed Oct 5 21:48:20 CEST 2011
Sorry for the delay.
On Fri, Sep 30, 2011 at 12:20:37AM +0900, Naohiro KORIYAMA wrote:
> 2011/9/25 Laurent Aimar <fenrir at elivagar.org>:
> > On Fri, Sep 23, 2011 at 11:17:57AM +0900, Naohiro KORIYAMA wrote:
> > There are two differents issues:
> > 1. Handle files that have PCR restarting without it being due to a PCR wrap.
> > 2. Handle files longer than 1 PCR wraps (more than ~ 26 hours).
>
> I added a table for checking PCR wrap around.
> This modification solved the issues and made a little bit improvement
> for Seek().
> @@ -336,6 +343,14 @@ struct demux_sys_t
> /* how many TS packet we read at once */
> int i_ts_read;
>
> + /* to determine length and time */
> + int i_pid_ref_pcr;
> + mtime_t i_first_pcr;
> + mtime_t i_current_pcr;
> + mtime_t i_last_pcr;
> + bool b_force_seek_per_percent;
> + mtime_t i_pcrs[10];
You could also store and use the exact position to:
- improve the precision of the seek, and maybe (I am unsure) to avoid
failling seeking in case the PCR was not too close of the byte position.
- prepare for support when the file size change while playing. I know it
won't work as is yet (and not needed in this patch).
If you prefer to do that in another patch later, I am fine with it.
> @@ -788,6 +810,18 @@ static int Open( vlc_object_t *p_this )
> p_sys->b_silent = var_CreateGetBool( p_demux, "ts-silent" );
> p_sys->b_split_es = var_InheritBool( p_demux, "ts-split-es" );
>
> + p_sys->i_first_pcr = -1;
> + p_sys->i_last_pcr = -1;
> + p_sys->b_force_seek_per_percent = false;
It would be simpler to initialize it with var_InheritBool("ts-seek-percent")
and it would avoid to call it at each seek.
> + bool can_seek = false;
> + stream_Control( p_demux->s, STREAM_CAN_SEEK, &can_seek );
> + if( can_seek )
> + {
> + GetFirstPCR( p_demux );
> + CheckPCRWrapAround( p_demux );
> + GetLastPCR( p_demux );
You could also set b_force_seek_per_percent to true here if
i_first_pcr/i_last_pcr are not valid (will simplify later code).
> case DEMUX_SET_POSITION:
> f = (double) va_arg( args, double );
> - i64 = stream_Size( p_demux->s );
>
> - if( stream_Seek( p_demux->s, (int64_t)(i64 * f) ) )
> + if( f < 0.0 || f > 1.0 )
> + {
> return VLC_EGENERIC;
> + }
You don't need to check the value of f, it is guaranted to be valid.
> +static void GetFirstPCR( demux_t *p_demux )
> +{
> + demux_sys_t *p_sys = p_demux->p_sys;
> +
> + p_sys->i_pid_ref_pcr = -1;
> + p_sys->i_first_pcr = -1;
> +
> + int64_t i_initial_pos = stream_Tell( p_demux->s );
> +
> + if( stream_Seek( p_demux->s, 0 ) )
> + return;
> +
> + while( vlc_object_alive (p_demux) )
> + {
> + block_t *p_pkt;
> + if( !( p_pkt = ReadTSPacket( p_demux ) ) )
> + {
> + break;
> + }
> + mtime_t i_pcr = GetPCR( p_pkt );
> + if( i_pcr >= 0 )
> + {
> + p_sys->i_pid_ref_pcr = PIDGet( p_pkt );
> + p_sys->i_first_pcr = i_pcr;
Setting i_current_pcr here will avoid having GET_TIME failing
at the beginning.
> + }
> + block_Release( p_pkt );
> + if( p_sys->i_first_pcr >= 0 )
> + break;
> + }
> + stream_Seek( p_demux->s, i_initial_pos );
> +}
> +static void CheckPCRWrapAround( demux_t *p_demux )
> +{
> + demux_sys_t *p_sys = p_demux->p_sys;
> +
> + int64_t i_initial_pos = stream_Tell( p_demux->s );
> +
> + p_sys->b_force_seek_per_percent = false;
> +
> + int i = 0;
> + p_sys->i_pcrs[0] = p_sys->i_first_pcr;
> +
> + for(int i = 1; i < 10 && vlc_object_alive( p_demux ); ++i )
> + {
> + int64_t i_pos = stream_Size( p_demux->s ) * 0.1 * i;
> + if( SeekToPCR( p_demux, i_pos ) )
> + {
> + p_sys->b_force_seek_per_percent = true;
> + break;
> + }
> + p_sys->i_pcrs[i] = p_sys->i_current_pcr;
> + if( p_sys->i_pcrs[i-1] > p_sys->i_pcrs[i] )
> + {
> + msg_Dbg( p_demux, "PCR Wrap Around found between %d%% and %d%% (pcr:%lld(%09llx) pcr:%lld(%09llx))",
> + (i-1)*10, i*10, p_sys->i_pcrs[i-1], p_sys->i_pcrs[i-1], p_sys->i_pcrs[i], p_sys->i_pcrs[i] );
> + }
> + }
> +
> + stream_Seek( p_demux->s, i_initial_pos );
> +}
I think that it might be worth to reject (ie b_force_seek_per_percent = true)
when they are too much PCR wraps. It will catch most of the file that have
arbitrary PCR reset.
Again, that can be added later, as you prefer.
Regards,
--
fenrir
More information about the vlc-devel
mailing list