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.
*****************************************************************************
* 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>
......@@ -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_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;
......@@ -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) "
"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 )
* 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 )
{
......@@ -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_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
......@@ -1758,6 +1760,12 @@ 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;
}
......@@ -1949,7 +1957,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
#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>
......@@ -270,6 +270,7 @@ typedef struct ts_stream_t
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;
......@@ -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_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;
......@@ -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+1)%16;
p_stream->b_discontinuity = (p_pes->i_flags & BLOCK_FLAG_DISCONTINUITY);
if( b_adaptation_field )
{
......@@ -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[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;
......@@ -1646,7 +1654,6 @@ static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream,
return p_ts;
}
static void TSSetPCR( block_t *p_ts, mtime_t i_dts )
{
mtime_t i_pcr = 9 * i_dts / 100;
......@@ -1800,6 +1807,11 @@ static void PEStoTS( sout_instance_t *p_sout,
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
......@@ -48,6 +49,11 @@
#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
*****************************************************************************/
......@@ -60,6 +66,9 @@ vlc_module_begin();
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();
/*****************************************************************************
......@@ -113,6 +122,9 @@ struct decoder_sys_t
/* 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 {
......@@ -174,6 +186,11 @@ static int Open( vlc_object_t *p_this )
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;
}
......@@ -200,6 +217,8 @@ static void Close( vlc_object_t *p_this )
block_ChainRelease( p_sys->p_frame );
}
var_Destroy( p_dec, "packetizer-mpegvideo-sync-iframe" );
free( p_sys );
}
......@@ -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) )
{
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;
......@@ -294,6 +315,24 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
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 &&
......
......@@ -5,6 +5,7 @@
* $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
......@@ -63,7 +64,10 @@ struct es_out_id_t
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 */
......@@ -276,6 +280,7 @@ void input_EsOutDiscontinuity( es_out_t *out, vlc_bool_t b_audio )
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 */
......@@ -669,6 +674,7 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
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 )
{
......@@ -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;
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 ||
......
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