Commit 29be1e00 authored by Gildas Bazin's avatar Gildas Bazin

* modules/mux/mpeg/ps.c: make sure the data blocks containing the pack and...

* modules/mux/mpeg/ps.c: make sure the data blocks containing the pack and system headers are timestamped correctly. Added an --sout-ps-dts-delay option.
parent 60568b2c
......@@ -7,8 +7,7 @@
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
* Gildas Bazin <gbazin@netcourrier.com>
*
* Gildas Bazin <gbazin@videolan.org>
*
* 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
......@@ -38,25 +37,31 @@
#include "bits.h"
#include "pes.h"
/* TODO:
* - test support of DTS, LPCM
*
*/
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define DTS_TEXT N_("DTS delay (ms)")
#define DTS_LONGTEXT N_("This option will delay the DTS (decoding time " \
"stamps) and PTS (presentation timestamps) of the data in the " \
"stream, compared to the SCRs. This allows for some buffering inside " \
"the client decoder.")
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
#define SOUT_CFG_PREFIX "sout-ps-"
vlc_module_begin();
set_description( _("PS muxer") );
set_capability( "sout mux", 50 );
add_shortcut( "ps" );
add_shortcut( "mpeg1" );
add_shortcut( "dvd" );
set_callbacks( Open, Close );
vlc_module_end();
add_integer( SOUT_CFG_PREFIX "dts-delay", 200, NULL, DTS_TEXT,
DTS_LONGTEXT, VLC_TRUE );
vlc_module_end();
/*****************************************************************************
* Exported prototypes
......@@ -66,14 +71,13 @@ static int AddStream( sout_mux_t *, sout_input_t * );
static int DelStream( sout_mux_t *, sout_input_t * );
static int Mux ( sout_mux_t * );
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int MuxGetStream ( sout_mux_t *, int *, mtime_t * );
static void MuxWritePackHeader ( sout_mux_t *, block_t **, mtime_t );
static void MuxWriteSystemHeader( sout_mux_t *, block_t ** );
static void MuxWriteSystemHeader( sout_mux_t *, block_t **, mtime_t );
static void StreamIdInit ( vlc_bool_t *id, int i_range );
static int StreamIdGet ( vlc_bool_t *id, int i_id_min, int i_id_max );
......@@ -95,26 +99,30 @@ struct sout_mux_sys_t
vlc_bool_t stream_id_dts[8]; /* 0x88 -> 0x8f */
vlc_bool_t stream_id_lpcm[16]; /* 0xa0 -> 0xaf */
int i_audio_bound;
int i_video_bound;
int i_audio_bound;
int i_video_bound;
int i_pes_count;
int i_system_header;
int i_dts_delay;
int i_pes_count;
int i_system_header;
vlc_bool_t b_mpeg2;
vlc_bool_t b_mpeg2;
};
static const char *ppsz_sout_options[] = {
"dts-delay", NULL
};
/*****************************************************************************
* Open:
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys;
sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys;
vlc_value_t val;
msg_Info( p_mux, "Open" );
sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
p_mux->pf_control = Control;
p_mux->pf_addstream = AddStream;
......@@ -137,6 +145,9 @@ static int Open( vlc_object_t *p_this )
p_sys->b_mpeg2 = !(p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mpeg1" ));
var_Get( p_mux, SOUT_CFG_PREFIX "dts-delay", &val );
p_sys->i_dts_delay = (int64_t)val.i_int * 1000;
return VLC_SUCCESS;
}
......@@ -199,9 +210,10 @@ static int Control( sout_mux_t *p_mux, int i_query, va_list args )
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_sys_t *p_sys = p_mux->p_sys;
ps_stream_t *p_stream;
ps_stream_t *p_stream;
msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_codec );
msg_Dbg( p_mux, "adding input codec=%4.4s",
(char*)&p_input->p_fmt->i_codec );
p_input->p_sys = p_stream = malloc( sizeof( ps_stream_t ) );
......@@ -209,22 +221,28 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
switch( p_input->p_fmt->i_codec )
{
case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
p_stream->i_stream_id = StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
p_stream->i_stream_id =
StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
break;
case VLC_FOURCC( 'l', 'p', 'c', 'm' ):
p_stream->i_stream_id = 0xbd00|StreamIdGet( p_sys->stream_id_lpcm, 0xa0, 0xaf );
p_stream->i_stream_id =
0xbd00 | StreamIdGet( p_sys->stream_id_lpcm, 0xa0, 0xaf );
break;
case VLC_FOURCC( 'd', 't', 's', ' ' ):
p_stream->i_stream_id = 0xbd00|StreamIdGet( p_sys->stream_id_dts, 0x88, 0x8f );
p_stream->i_stream_id =
0xbd00 | StreamIdGet( p_sys->stream_id_dts, 0x88, 0x8f );
break;
case VLC_FOURCC( 'a', '5', '2', ' ' ):
p_stream->i_stream_id = 0xbd00|StreamIdGet( p_sys->stream_id_a52, 0x80, 0x87 );
p_stream->i_stream_id =
0xbd00 | StreamIdGet( p_sys->stream_id_a52, 0x80, 0x87 );
break;
case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
p_stream->i_stream_id = StreamIdGet( p_sys->stream_id_mpga, 0xc0, 0xcf );
p_stream->i_stream_id =
StreamIdGet( p_sys->stream_id_mpga, 0xc0, 0xcf );
break;
case VLC_FOURCC( 's', 'p', 'u', ' ' ):
p_stream->i_stream_id = 0xbd00|StreamIdGet( p_sys->stream_id_spu, 0x20, 0x3f );
p_stream->i_stream_id =
0xbd00 | StreamIdGet( p_sys->stream_id_spu, 0x20, 0x3f );
break;
default:
goto error;
......@@ -256,29 +274,35 @@ error:
*****************************************************************************/
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{
sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_mux_sys_t *p_sys = p_mux->p_sys;
ps_stream_t *p_stream =(ps_stream_t*)p_input->p_sys;
msg_Dbg( p_mux, "removing input" );
switch( p_input->p_fmt->i_codec )
{
case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
StreamIdRelease( p_sys->stream_id_mpgv, 0xe0, p_stream->i_stream_id);
StreamIdRelease( p_sys->stream_id_mpgv, 0xe0,
p_stream->i_stream_id );
break;
case VLC_FOURCC( 'l', 'p', 'c', 'm' ):
StreamIdRelease( p_sys->stream_id_lpcm, 0xa0, p_stream->i_stream_id&0xff );
StreamIdRelease( p_sys->stream_id_lpcm, 0xa0,
p_stream->i_stream_id&0xff );
break;
case VLC_FOURCC( 'd', 't', 's', ' ' ):
StreamIdRelease( p_sys->stream_id_dts, 0x88, p_stream->i_stream_id&0xff );
StreamIdRelease( p_sys->stream_id_dts, 0x88,
p_stream->i_stream_id&0xff );
break;
case VLC_FOURCC( 'a', '5', '2', ' ' ):
StreamIdRelease( p_sys->stream_id_a52, 0x80, p_stream->i_stream_id&0xff );
StreamIdRelease( p_sys->stream_id_a52, 0x80,
p_stream->i_stream_id&0xff );
break;
case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
StreamIdRelease( p_sys->stream_id_mpga, 0xc0, p_stream->i_stream_id );
StreamIdRelease( p_sys->stream_id_mpga, 0xc0,
p_stream->i_stream_id );
break;
case VLC_FOURCC( 's', 'p', 'u', ' ' ):
StreamIdRelease( p_sys->stream_id_spu, 0x20, p_stream->i_stream_id&0xff );
StreamIdRelease( p_sys->stream_id_spu, 0x20,
p_stream->i_stream_id&0xff );
break;
default:
/* Never reached */
......@@ -320,6 +344,7 @@ static int Mux( sout_mux_t *p_mux )
{
return VLC_SUCCESS;
}
p_input = p_mux->pp_inputs[i_stream];
p_stream = (ps_stream_t*)p_input->p_sys;
p_ps = NULL;
......@@ -335,7 +360,7 @@ static int Mux( sout_mux_t *p_mux )
{
block_t *p_pk;
MuxWriteSystemHeader( p_mux, &p_ps );
MuxWriteSystemHeader( p_mux, &p_ps, i_dts );
/* For MPEG1 streaming, set HEADER flag */
for( p_pk = p_ps; p_pk != NULL; p_pk = p_pk->p_next )
......@@ -346,12 +371,11 @@ static int Mux( sout_mux_t *p_mux )
/* Get and mux a packet */
p_data = block_FifoGet( p_input->p_fifo );
E_( EStoPES )( p_mux->p_sout,
&p_data, p_data,
p_stream->i_stream_id,
E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id,
p_mux->p_sys->b_mpeg2 );
block_ChainAppend( &p_ps, p_data );
sout_AccessOutWrite( p_mux->p_access, p_ps );
/* Increase counter */
......@@ -361,11 +385,10 @@ static int Mux( sout_mux_t *p_mux )
return VLC_SUCCESS;
}
/*****************************************************************************
*
*****************************************************************************/
static void StreamIdInit ( vlc_bool_t *id, int i_range )
static void StreamIdInit( vlc_bool_t *id, int i_range )
{
int i;
......@@ -374,7 +397,7 @@ static void StreamIdInit ( vlc_bool_t *id, int i_range )
id[i] = VLC_TRUE;
}
}
static int StreamIdGet ( vlc_bool_t *id, int i_id_min, int i_id_max )
static int StreamIdGet( vlc_bool_t *id, int i_id_min, int i_id_max )
{
int i;
......@@ -395,19 +418,21 @@ static void StreamIdRelease( vlc_bool_t *id, int i_id_min, int i_id )
}
static void MuxWritePackHeader( sout_mux_t *p_mux, block_t **p_buf,
mtime_t i_dts )
mtime_t i_dts )
{
block_t *p_hdr;
bits_buffer_t bits;
mtime_t i_src;
sout_mux_sys_t *p_sys = p_mux->p_sys;
bits_buffer_t bits;
block_t *p_hdr;
mtime_t i_scr;
i_src = i_dts * 9 / 100;
i_scr = (i_dts - p_sys->i_dts_delay) * 9 / 100;
p_hdr = block_New( p_mux, 18 );
p_hdr->i_pts = p_hdr->i_dts = i_dts;
bits_initwrite( &bits, 14, p_hdr->p_buffer );
bits_write( &bits, 32, 0x01ba );
if( p_mux->p_sys->b_mpeg2 )
if( p_sys->b_mpeg2 )
{
bits_write( &bits, 2, 0x01 );
}
......@@ -416,14 +441,14 @@ static void MuxWritePackHeader( sout_mux_t *p_mux, block_t **p_buf,
bits_write( &bits, 4, 0x02 );
}
bits_write( &bits, 3, ( i_src >> 30 )&0x07 );
bits_write( &bits, 3, ( i_scr >> 30 )&0x07 );
bits_write( &bits, 1, 1 );
bits_write( &bits, 15, ( i_src >> 15 )&0x7fff );
bits_write( &bits, 15, ( i_scr >> 15 )&0x7fff );
bits_write( &bits, 1, 1 );
bits_write( &bits, 15, i_src&0x7fff );
bits_write( &bits, 15, i_scr&0x7fff );
bits_write( &bits, 1, 1 );
if( p_mux->p_sys->b_mpeg2 )
if( p_sys->b_mpeg2 )
{
bits_write( &bits, 9, 0 ); // src extention
}
......@@ -432,19 +457,20 @@ static void MuxWritePackHeader( sout_mux_t *p_mux, block_t **p_buf,
bits_write( &bits, 22, 1000/8/50); // FIXME mux rate
bits_write( &bits, 1, 1 );
if( p_mux->p_sys->b_mpeg2 )
if( p_sys->b_mpeg2 )
{
bits_write( &bits, 1, 1 );
bits_write( &bits, 5, 0x1f ); // FIXME reserved
bits_write( &bits, 3, 0 ); // stuffing bytes
}
p_hdr->i_buffer = p_mux->p_sys->b_mpeg2 ? 14: 12;
p_hdr->i_buffer = p_sys->b_mpeg2 ? 14: 12;
block_ChainAppend( p_buf, p_hdr );
}
static void MuxWriteSystemHeader( sout_mux_t *p_mux, block_t **p_buf )
static void MuxWriteSystemHeader( sout_mux_t *p_mux, block_t **p_buf,
mtime_t i_dts )
{
sout_mux_sys_t *p_sys = p_mux->p_sys;
block_t *p_hdr;
......@@ -467,9 +493,11 @@ static void MuxWriteSystemHeader( sout_mux_t *p_mux, block_t **p_buf )
}
/* Private stream are declared only one time */
i_nb_stream = p_mux->i_nb_inputs - ( i_nb_private > 0 ? i_nb_private - 1 : 0 );
i_nb_stream = p_mux->i_nb_inputs -
( i_nb_private > 0 ? i_nb_private - 1 : 0 );
p_hdr = block_New( p_mux, 12 + i_nb_stream * 3 );
p_hdr->i_dts = p_hdr->i_pts = i_dts;
bits_initwrite( &bits, 12 + i_nb_stream * 3, p_hdr->p_buffer );
bits_write( &bits, 32, 0x01bb );
......@@ -539,9 +567,7 @@ static void MuxWriteSystemHeader( sout_mux_t *p_mux, block_t **p_buf )
/*
* Find stream to be muxed.
*/
static int MuxGetStream( sout_mux_t *p_mux,
int *pi_stream,
mtime_t *pi_dts )
static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
{
mtime_t i_dts;
int i_stream;
......@@ -549,7 +575,7 @@ static int MuxGetStream( sout_mux_t *p_mux,
for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
{
sout_input_t *p_input = p_mux->pp_inputs[i];
sout_input_t *p_input = p_mux->pp_inputs[i];
block_t *p_data;
if( p_input->p_fifo->i_depth <= 0 )
......@@ -560,13 +586,13 @@ static int MuxGetStream( sout_mux_t *p_mux,
/* We need that audio+video fifo contain at least 1 packet */
return VLC_EGENERIC;
}
/* SPU */
continue;
}
p_data = block_FifoShow( p_input->p_fifo );
if( i_stream == -1 ||
p_data->i_dts < i_dts )
if( i_stream == -1 || p_data->i_dts < i_dts )
{
i_stream = i;
i_dts = p_data->i_dts;
......@@ -578,4 +604,3 @@ static int MuxGetStream( sout_mux_t *p_mux,
return VLC_SUCCESS;
}
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