Commit 396d7713 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Flagging BLOCK_FLAG_DISCONTINUITY for every PID in the input when the slider...

Flagging BLOCK_FLAG_DISCONTINUITY for every PID in the input when the slider is moved on the GUI or a jump in the stream is made. It is also propagated to the mpegvideo packetizer. The packetizer has a new mode to sync on I-frame boundary after such a jump. It avoids sending some broken frames to the client. (Forward port of branches/0.8.1-jpsaman-thedj revision 11067 and 11842.)
parent af44196e
/***************************************************************************** /*****************************************************************************
* ts.c: Transport Stream input module for VLC. * 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$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
...@@ -1613,9 +1613,9 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1613,9 +1613,9 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
const vlc_bool_t b_adaptation = p[3]&0x20; const vlc_bool_t b_adaptation = p[3]&0x20;
const vlc_bool_t b_payload = p[3]&0x10; const vlc_bool_t b_payload = p[3]&0x10;
const int i_cc = p[3]&0x0f; /* continuity counter */ const int i_cc = p[3]&0x0f; /* continuity counter */
vlc_bool_t b_discontinuity = VLC_FALSE;/* discontinuity */
/* transport_scrambling_control is ignored */ /* transport_scrambling_control is ignored */
int i_skip = 0; int i_skip = 0;
vlc_bool_t i_ret = VLC_FALSE; vlc_bool_t i_ret = VLC_FALSE;
int i_diff; int i_diff;
...@@ -1660,6 +1660,10 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1660,6 +1660,10 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
msg_Warn( p_demux, "discontinuity_indicator (pid=%d) " msg_Warn( p_demux, "discontinuity_indicator (pid=%d) "
"ignored", pid->i_pid ); "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 );
} }
} }
...@@ -1670,7 +1674,6 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1670,7 +1674,6 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
* diff == 0 and duplicate packet (playload != 0) <- should we * diff == 0 and duplicate packet (playload != 0) <- should we
* test the content ? * test the content ?
*/ */
i_diff = ( i_cc - pid->i_cc )&0x0f; i_diff = ( i_cc - pid->i_cc )&0x0f;
if( b_payload && i_diff == 1 ) if( b_payload && i_diff == 1 )
{ {
...@@ -1684,14 +1687,13 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1684,14 +1687,13 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
pid->i_pid, i_cc ); pid->i_pid, i_cc );
pid->i_cc = 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 ? */ /* FIXME what to do when discontinuity_indicator is set ? */
msg_Warn( p_demux, "discontinuity received 0x%x instead of 0x%x (pid=%d)", msg_Warn( p_demux, "discontinuity received 0x%x instead of 0x%x (pid=%d)",
i_cc, ( pid->i_cc + 1 )&0x0f, pid->i_pid ); i_cc, ( pid->i_cc + 1 )&0x0f, pid->i_pid );
pid->i_cc = i_cc; pid->i_cc = i_cc;
if( pid->es->p_pes && pid->es->fmt.i_cat != VIDEO_ES ) if( pid->es->p_pes && pid->es->fmt.i_cat != VIDEO_ES )
{ {
/* Small video artifacts are usually better then /* Small video artifacts are usually better then
...@@ -1757,7 +1759,13 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ) ...@@ -1757,7 +1759,13 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
} }
} }
} }
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; return i_ret;
} }
...@@ -1949,7 +1957,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ) ...@@ -1949,7 +1957,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
#endif #endif
if( i_iod_tag != 0x02 ) if( i_iod_tag != 0x02 )
{ {
#ifdef DEBUG
fprintf( stderr, "\n ERR: tag %02x != 0x02", i_iod_tag ); fprintf( stderr, "\n ERR: tag %02x != 0x02", i_iod_tag );
#endif
return p_iod; return p_iod;
} }
......
/***************************************************************************** /*****************************************************************************
* ts.c: MPEG-II TS Muxer * 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$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
...@@ -270,6 +270,7 @@ typedef struct ts_stream_t ...@@ -270,6 +270,7 @@ typedef struct ts_stream_t
int i_stream_type; int i_stream_type;
int i_stream_id; int i_stream_id;
int i_continuity_counter; int i_continuity_counter;
vlc_bool_t b_discontinuity;
/* to be used for carriege of DIV3 */ /* to be used for carriege of DIV3 */
vlc_fourcc_t i_bih_codec; vlc_fourcc_t i_bih_codec;
...@@ -653,6 +654,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -653,6 +654,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat ); 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_codec = p_input->p_fmt->i_codec;
p_stream->i_continuity_counter = 0; p_stream->i_continuity_counter = 0;
p_stream->b_discontinuity = VLC_FALSE;
p_stream->i_decoder_specific_info = 0; p_stream->i_decoder_specific_info = 0;
p_stream->p_decoder_specific_info = NULL; p_stream->p_decoder_specific_info = NULL;
...@@ -1568,6 +1570,7 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, ...@@ -1568,6 +1570,7 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream,
p_stream->i_continuity_counter; p_stream->i_continuity_counter;
p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16; 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 ) if( b_adaptation_field )
{ {
...@@ -1581,6 +1584,11 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, ...@@ -1581,6 +1584,11 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream,
p_ts->p_buffer[4] = 7 + i_stuffing; p_ts->p_buffer[4] = 7 + i_stuffing;
p_ts->p_buffer[5] = 0x10; /* flags */ 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[6] = ( 0 )&0xff;
p_ts->p_buffer[7] = ( 0 )&0xff; p_ts->p_buffer[7] = ( 0 )&0xff;
p_ts->p_buffer[8] = ( 0 )&0xff; p_ts->p_buffer[8] = ( 0 )&0xff;
...@@ -1646,7 +1654,6 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, ...@@ -1646,7 +1654,6 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream,
return p_ts; return p_ts;
} }
static void TSSetPCR( block_t *p_ts, mtime_t i_dts ) static void TSSetPCR( block_t *p_ts, mtime_t i_dts )
{ {
mtime_t i_pcr = 9 * i_dts / 100; mtime_t i_pcr = 9 * i_dts / 100;
...@@ -1800,6 +1807,11 @@ static void PEStoTS( sout_instance_t *p_sout, ...@@ -1800,6 +1807,11 @@ static void PEStoTS( sout_instance_t *p_sout,
if( i_stuffing > 1 ) if( i_stuffing > 1 )
{ {
p_ts->p_buffer[5] = 0x00; 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++ ) for( i = 6; i < 6 + i_stuffing - 2; i++ )
{ {
p_ts->p_buffer[i] = 0xff; p_ts->p_buffer[i] = 0xff;
......
/***************************************************************************** /*****************************************************************************
* mpegvideo.c: parse and packetize an MPEG1/2 video stream * 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$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
* Gildas Bazin <gbazin@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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -48,6 +49,11 @@ ...@@ -48,6 +49,11 @@
#include "vlc_block_helper.h" #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 * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -60,6 +66,9 @@ vlc_module_begin(); ...@@ -60,6 +66,9 @@ vlc_module_begin();
set_description( _("MPEG-I/II video packetizer") ); set_description( _("MPEG-I/II video packetizer") );
set_capability( "packetizer", 50 ); set_capability( "packetizer", 50 );
set_callbacks( Open, Close ); set_callbacks( Open, Close );
add_bool( "packetizer-mpegvideo-sync-iframe", 1, NULL, SYNC_INTRAFRAME_TEXT,
SYNC_INTRAFRAME_LONGTEXT, VLC_TRUE );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
...@@ -112,7 +121,10 @@ struct decoder_sys_t ...@@ -112,7 +121,10 @@ struct decoder_sys_t
/* Number of pictures since last sequence header */ /* Number of pictures since last sequence header */
int i_seq_old; int i_seq_old;
/* Sync behaviour */
vlc_bool_t b_sync_on_intra_frame;
vlc_bool_t b_discontinuity;
}; };
enum { enum {
...@@ -174,6 +186,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -174,6 +186,11 @@ static int Open( vlc_object_t *p_this )
p_sys->i_old_duration = 0; p_sys->i_old_duration = 0;
p_sys->i_last_ref_pts = 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; return VLC_SUCCESS;
} }
...@@ -199,6 +216,8 @@ static void Close( vlc_object_t *p_this ) ...@@ -199,6 +216,8 @@ static void Close( vlc_object_t *p_this )
{ {
block_ChainRelease( p_sys->p_frame ); block_ChainRelease( p_sys->p_frame );
} }
var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
free( p_sys ); free( p_sys );
} }
...@@ -219,7 +238,9 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) ...@@ -219,7 +238,9 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) if( (*pp_block)->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
{ {
p_sys->i_state = STATE_NOSYNC; 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->p_frame = NULL;
p_sys->pp_last = &p_sys->p_frame; p_sys->pp_last = &p_sys->p_frame;
p_sys->b_frame_slice = VLC_FALSE; p_sys->b_frame_slice = VLC_FALSE;
...@@ -294,6 +315,24 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) ...@@ -294,6 +315,24 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
break; 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've just started the stream, wait for the first PTS.
* We discard here so we can still get the sequence header. */ * We discard here so we can still get the sequence header. */
if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 && if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 &&
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -63,7 +64,10 @@ struct es_out_id_t ...@@ -63,7 +64,10 @@ struct es_out_id_t
int i_id; int i_id;
es_out_pgrm_t *p_pgrm; 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; int64_t i_preroll_end;
/* Channel in the track type */ /* Channel in the track type */
...@@ -276,7 +280,8 @@ void input_EsOutDiscontinuity( es_out_t *out, vlc_bool_t b_audio ) ...@@ -276,7 +280,8 @@ void input_EsOutDiscontinuity( es_out_t *out, vlc_bool_t b_audio )
for( i = 0; i < p_sys->i_es; i++ ) for( i = 0; i < p_sys->i_es; i++ )
{ {
es_out_id_t *es = p_sys->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 /* Send a dummy block to let decoder know that
* there is a discontinuity */ * there is a discontinuity */
if( es->p_dec && ( !b_audio || es->fmt.i_cat == AUDIO_ES ) ) if( es->p_dec && ( !b_audio || es->fmt.i_cat == AUDIO_ES ) )
...@@ -669,6 +674,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt ) ...@@ -669,6 +674,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
es->p_pgrm = p_pgrm; es->p_pgrm = p_pgrm;
es_format_Copy( &es->fmt, fmt ); es_format_Copy( &es->fmt, fmt );
es->i_preroll_end = -1; es->i_preroll_end = -1;
es->b_discontinuity = VLC_FALSE;
switch( fmt->i_cat ) switch( fmt->i_cat )
{ {
...@@ -1031,6 +1037,11 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block ) ...@@ -1031,6 +1037,11 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
} }
p_block->i_rate = p_input->i_rate; 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 */ /* TODO handle mute */
if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES || if( es->p_dec && ( es->fmt.i_cat != AUDIO_ES ||
......
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