/*****************************************************************************
* ts.c: Transport Stream input module for VLC.
*****************************************************************************
- * Copyright (C) 2004-2005 the VideoLAN team
+ * Copyright (C) 2004-2005 VideoLAN (Centrale Réseaux) and its contributors
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
const vlc_bool_t b_adaptation = p[3]&0x20;
const vlc_bool_t b_payload = p[3]&0x10;
const int i_cc = p[3]&0x0f; /* continuity counter */
+ vlc_bool_t b_discontinuity = VLC_FALSE;/* discontinuity */
/* transport_scrambling_control is ignored */
-
int i_skip = 0;
vlc_bool_t i_ret = VLC_FALSE;
int i_diff;
msg_Warn( p_demux, "discontinuity_indicator (pid=%d) "
"ignored", pid->i_pid );
}
+ /* discontinuity indicator found in stream */
+ b_discontinuity = p[5]&0x80 ? VLC_TRUE : VLC_FALSE;
+ if( p[5]&0x40 )
+ msg_Dbg( p_demux, "random access indicator (pid=%d) ", pid->i_pid );
}
}
* diff == 0 and duplicate packet (playload != 0) <- should we
* test the content ?
*/
-
i_diff = ( i_cc - pid->i_cc )&0x0f;
if( b_payload && i_diff == 1 )
{
pid->i_pid, i_cc );
pid->i_cc = i_cc;
}
- else if( i_diff != 0 )
+ else if( i_diff != 0 && !b_discontinuity )
{
/* FIXME what to do when discontinuity_indicator is set ? */
msg_Warn( p_demux, "discontinuity received 0x%x instead of 0x%x (pid=%d)",
i_cc, ( pid->i_cc + 1 )&0x0f, pid->i_pid );
pid->i_cc = i_cc;
-
if( pid->es->p_pes && pid->es->fmt.i_cat != VIDEO_ES )
{
/* Small video artifacts are usually better then
}
}
}
-
+
+ if( b_discontinuity && pid->es->p_pes )
+ {
+ msg_Warn( p_demux, "discontinuity indicator (pid=%d) ",
+ pid->i_pid );
+ pid->es->p_pes->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+ }
return i_ret;
}
#endif
if( i_iod_tag != 0x02 )
{
+#ifdef DEBUG
fprintf( stderr, "\n ERR: tag %02x != 0x02", i_iod_tag );
+#endif
return p_iod;
}
/*****************************************************************************
* ts.c: MPEG-II TS Muxer
*****************************************************************************
- * Copyright (C) 2001, 2002 the VideoLAN team
+ * Copyright (C) 2001-2005 VideoLAN (Centrale Réseaux) and its contributors
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
int i_stream_type;
int i_stream_id;
int i_continuity_counter;
+ vlc_bool_t b_discontinuity;
/* to be used for carriege of DIV3 */
vlc_fourcc_t i_bih_codec;
p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
p_stream->i_codec = p_input->p_fmt->i_codec;
p_stream->i_continuity_counter = 0;
+ p_stream->b_discontinuity = VLC_FALSE;
p_stream->i_decoder_specific_info = 0;
p_stream->p_decoder_specific_info = NULL;
p_stream->i_continuity_counter;
p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
+ p_stream->b_discontinuity = (p_pes->i_flags & BLOCK_FLAG_DISCONTINUITY);
if( b_adaptation_field )
{
p_ts->p_buffer[4] = 7 + i_stuffing;
p_ts->p_buffer[5] = 0x10; /* flags */
+ if( p_stream->b_discontinuity )
+ {
+ p_ts->p_buffer[5] |= 0x80; /* flag TS dicontinuity */
+ p_stream->b_discontinuity = VLC_FALSE;
+ }
p_ts->p_buffer[6] = ( 0 )&0xff;
p_ts->p_buffer[7] = ( 0 )&0xff;
p_ts->p_buffer[8] = ( 0 )&0xff;
return p_ts;
}
-
static void TSSetPCR( block_t *p_ts, mtime_t i_dts )
{
mtime_t i_pcr = 9 * i_dts / 100;
if( i_stuffing > 1 )
{
p_ts->p_buffer[5] = 0x00;
+ if( p_stream->b_discontinuity )
+ {
+ p_ts->p_buffer[5] |= 0x80;
+ p_stream->b_discontinuity = VLC_FALSE;
+ }
for( i = 6; i < 6 + i_stuffing - 2; i++ )
{
p_ts->p_buffer[i] = 0xff;
/*****************************************************************************
* mpegvideo.c: parse and packetize an MPEG1/2 video stream
*****************************************************************************
- * Copyright (C) 2001, 2002 the VideoLAN team
+ * Copyright (C) 2001-2005 VideoLAN (Centrale Réseaux) and its contributors
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
* Gildas Bazin <gbazin@videolan.org>
+ * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "vlc_block_helper.h"
+#define SYNC_INTRAFRAME_TEXT N_("Sync on intraframe")
+#define SYNC_INTRAFRAME_LONGTEXT N_("Normally the packetizer would " \
+ "sync on the next full frame. This flags instructs the packetizer " \
+ "to sync on the first intraframe found.")
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
set_description( _("MPEG-I/II video packetizer") );
set_capability( "packetizer", 50 );
set_callbacks( Open, Close );
+
+ add_bool( "packetizer-mpegvideo-sync-iframe", 1, NULL, SYNC_INTRAFRAME_TEXT,
+ SYNC_INTRAFRAME_LONGTEXT, VLC_TRUE );
vlc_module_end();
/*****************************************************************************
/* Number of pictures since last sequence header */
int i_seq_old;
-
+
+ /* Sync behaviour */
+ vlc_bool_t b_sync_on_intra_frame;
+ vlc_bool_t b_discontinuity;
};
enum {
p_sys->i_old_duration = 0;
p_sys->i_last_ref_pts = 0;
+ p_sys->b_discontinuity = VLC_FALSE;
+ p_sys->b_sync_on_intra_frame = var_CreateGetBool( p_dec, "packetizer-mpegvideo-sync-iframe" );
+ if( p_sys->b_sync_on_intra_frame )
+ msg_Dbg( p_dec, "syncing happens on intraframe now." );
+
return VLC_SUCCESS;
}
{
block_ChainRelease( p_sys->p_frame );
}
+
+ var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
free( p_sys );
}
if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
{
p_sys->i_state = STATE_NOSYNC;
- if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
+ p_sys->b_discontinuity = VLC_TRUE;
+ if( p_sys->p_frame )
+ block_ChainRelease( p_sys->p_frame );
p_sys->p_frame = NULL;
p_sys->pp_last = &p_sys->p_frame;
p_sys->b_frame_slice = VLC_FALSE;
break;
}
+ /* If a discontinuity has been encountered, then wait till
+ * the next Intra frame before continuing with packetizing */
+ if( p_sys->b_discontinuity &&
+ p_sys->b_sync_on_intra_frame )
+ {
+ if( p_pic->i_flags & BLOCK_FLAG_TYPE_I )
+ {
+ msg_Dbg( p_dec, "synced on Intra frame" );
+ p_sys->b_discontinuity = VLC_FALSE;
+ p_pic->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+ }
+ else
+ {
+ p_sys->i_state = STATE_NOSYNC;
+ break;
+ }
+ }
+
/* We've just started the stream, wait for the first PTS.
* We discard here so we can still get the sequence header. */
if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 &&
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
int i_id;
es_out_pgrm_t *p_pgrm;
- /* */
+ /* Signal a discontinuity in the timeline for every PID */
+ vlc_bool_t b_discontinuity;
+
+ /* Misc. */
int64_t i_preroll_end;
/* Channel in the track type */
for( i = 0; i < p_sys->i_es; i++ )
{
es_out_id_t *es = p_sys->es[i];
-
+ es->b_discontinuity = VLC_TRUE; /* signal discontinuity */
+
/* Send a dummy block to let decoder know that
* there is a discontinuity */
if( es->p_dec && ( !b_audio || es->fmt.i_cat == AUDIO_ES ) )
es->p_pgrm = p_pgrm;
es_format_Copy( &es->fmt, fmt );
es->i_preroll_end = -1;
+ es->b_discontinuity = VLC_FALSE;
switch( fmt->i_cat )
{
}
p_block->i_rate = p_input->i_rate;
+ if( es->b_discontinuity )
+ {
+ p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+ es->b_discontinuity = VLC_FALSE;
+ }
/* TODO handle mute */
if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES ||