/*****************************************************************************
* ts.c: MPEG-II TS Muxer
*****************************************************************************
- * Copyright (C) 2001-2005 VideoLAN (Centrale Réseaux) and its contributors
+ * Copyright (C) 2001-2005 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
/*****************************************************************************
* Preamble
*****************************************************************************/
-#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
#include <vlc/vlc.h>
-#include <vlc/input.h>
-#include <vlc/sout.h>
+#include <vlc_sout.h>
+#include <vlc_codecs.h>
+#include <vlc_block.h>
#include "iso_lang.h"
static void Close ( vlc_object_t * );
#define VPID_TEXT N_("Video PID")
-#define VPID_LONGTEXT N_("Assigns a fixed PID to the video stream. The PCR " \
+#define VPID_LONGTEXT N_("Assign a fixed PID to the video stream. The PCR " \
"PID will automatically be the video.")
#define APID_TEXT N_("Audio PID")
-#define APID_LONGTEXT N_("Assigns a fixed PID to the audio stream.")
+#define APID_LONGTEXT N_("Assign a fixed PID to the audio stream.")
#define SPUPID_TEXT N_("SPU PID")
-#define SPUPID_LONGTEXT N_("Assigns a fixed PID to the SPU.")
+#define SPUPID_LONGTEXT N_("Assign a fixed PID to the SPU.")
#define PMTPID_TEXT N_("PMT PID")
-#define PMTPID_LONGTEXT N_("Assigns a fixed PID to the PMT")
+#define PMTPID_LONGTEXT N_("Assign a fixed PID to the PMT")
#define TSID_TEXT N_("TS ID")
-#define TSID_LONGTEXT N_("Assigns a fixed Transport Stream ID.")
+#define TSID_LONGTEXT N_("Assign a fixed Transport Stream ID.")
#define NETID_TEXT N_("NET ID")
-#define NETID_LONGTEXT N_("Assigns a fixed Network ID (for SDT table)")
-#define PMTPROG_TEXT N_("PMT Program numbers (requires --sout-ts-es-id-pid)")
-#define PMTPROG_LONGTEXT N_("Assigns a program number to each PMT")
+#define NETID_LONGTEXT N_("Assign a fixed Network ID (for SDT table)")
+
+#define PMTPROG_TEXT N_("PMT Program numbers")
+#define PMTPROG_LONGTEXT N_("Assign a program number to each PMT. This " \
+ "requires \"Set PID to ID of ES\" to be enabled." )
+
#define MUXPMT_TEXT N_("Mux PMT (requires --sout-ts-es-id-pid)")
-#define MUXPMT_LONGTEXT N_("Defines the pids to add to each pmt." )
+#define MUXPMT_LONGTEXT N_("Define the pids to add to each pmt. This " \
+ "requires \"Set PID to ID of ES\" to be enabled." )
#define SDTDESC_TEXT N_("SDT Descriptors (requires --sout-ts-es-id-pid)")
-#define SDTDESC_LONGTEXT N_("Defines the descriptors of each SDT" )
+#define SDTDESC_LONGTEXT N_("Defines the descriptors of each SDT. This" \
+ "requires \"Set PID to ID of ES\" to be enabled." )
#define PID_TEXT N_("Set PID to ID of ES")
#define PID_LONGTEXT N_("Sets PID to the ID if the incoming ES. This is for " \
#define ALIGNMENT_TEXT N_("Data alignment")
#define ALIGNMENT_LONGTEXT N_("Enforces alignment of all access units on " \
- "PES boundaries. This is a waste of bandwidth.")
+ "PES boundaries. Disabling this might save some bandwidth but introduce incompatibilities.")
#define SHAPING_TEXT N_("Shaping delay (ms)")
-#define SHAPING_LONGTEXT N_("If enabled, the TS muxer will cut the " \
+#define SHAPING_LONGTEXT N_("Cut the " \
"stream in slices of the given duration, and ensure a constant bitrate " \
- "between the two boundaries. This avoids having huge bitrate peaks for " \
- "reference frames, in particular.")
+ "between the two boundaries. This avoids having huge bitrate peaks, " \
+ "especially for reference frames." )
+
#define KEYF_TEXT N_("Use keyframes")
#define KEYF_LONGTEXT N_("If enabled, and shaping is specified, " \
"the TS muxer will place the boundaries at the end of I pictures. In " \
"frames in the stream.")
#define PCR_TEXT N_("PCR delay (ms)")
-#define PCR_LONGTEXT N_("This option allows you to set at which interval " \
- "PCRs (Program Clock Reference) will be sent. " \
- "This value should be below 100ms. (default is 70)")
+#define PCR_LONGTEXT N_("Set at which interval " \
+ "PCRs (Program Clock Reference) will be sent (in milliseconds). " \
+ "This value should be below 100ms. (default is 70ms).")
#define BMIN_TEXT N_( "Minimum B (deprecated)")
#define BMIN_LONGTEXT N_( "This setting is deprecated and not used anymore" )
#define BMAX_LONGTEXT N_( "This setting is deprecated and not used anymore")
#define DTS_TEXT N_("DTS delay (ms)")
-#define DTS_LONGTEXT N_("This option will delay the DTS (decoding time " \
+#define DTS_LONGTEXT N_("Delay the DTS (decoding time " \
"stamps) and PTS (presentation timestamps) of the data in the " \
"stream, compared to the PCRs. This allows for some buffering inside " \
"the client decoder.")
#define VCRYPT_LONGTEXT N_("Crypt video using CSA")
#define CK_TEXT N_("CSA Key")
-#define CK_LONGTEXT N_("Defines the CSA encryption key. This must be a " \
+#define CK_LONGTEXT N_("CSA encryption key. This must be a " \
"16 char string (8 hexadecimal bytes).")
#define CPKT_TEXT N_("Packet size in bytes to encrypt")
-#define CPKT_LONGTEXT N_("Specify the size of the TS packet to encrypt. " \
+#define CPKT_LONGTEXT N_("Size of the TS packet to encrypt. " \
"The encryption routines subtract the TS-header from the value before " \
- "encrypting. " )
+ "encrypting." )
#define SOUT_CFG_PREFIX "sout-ts-"
#ifdef HAVE_BSEARCH
#ifdef HAVE_DVBPSI_SDT
add_string( SOUT_CFG_PREFIX "sdtdesc", NULL, NULL, SDTDESC_TEXT, SDTDESC_LONGTEXT, VLC_TRUE );
#endif
- add_bool( SOUT_CFG_PREFIX "alignment", 0, NULL, ALIGNMENT_TEXT,
+ add_bool( SOUT_CFG_PREFIX "alignment", VLC_TRUE, NULL, ALIGNMENT_TEXT,
ALIGNMENT_LONGTEXT, VLC_TRUE );
add_integer( SOUT_CFG_PREFIX "shaping", 200, NULL,SHAPING_TEXT,
return b;
}
-static inline void BufferChainClean( sout_instance_t *p_sout,
- sout_buffer_chain_t *c )
+static inline void BufferChainClean( sout_buffer_chain_t *c )
{
block_t *b;
uint8_t *p_decoder_specific_info;
/* language is iso639-2T */
- uint8_t lang[3];
+ int i_langs;
+ uint8_t *lang;
sout_buffer_chain_t chain_pes;
mtime_t i_pes_dts;
vlc_value_t val;
int i;
- sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
+ config_ChainParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
p_sys = malloc( sizeof( sout_mux_sys_t ) );
if( !p_sys )
*****************************************************************************/
static int Control( sout_mux_t *p_mux, int i_query, va_list args )
{
+ VLC_UNUSED(p_mux);
vlc_bool_t *pb_bool;
char **ppsz;
- switch( i_query )
- {
- case MUX_CAN_ADD_STREAM_WHILE_MUXING:
- pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
- *pb_bool = VLC_TRUE;
- return VLC_SUCCESS;
+ switch( i_query )
+ {
+ case MUX_CAN_ADD_STREAM_WHILE_MUXING:
+ pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
+ *pb_bool = VLC_TRUE;
+ return VLC_SUCCESS;
- case MUX_GET_ADD_STREAM_WAIT:
- pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
- *pb_bool = VLC_FALSE;
- return VLC_SUCCESS;
+ case MUX_GET_ADD_STREAM_WAIT:
+ pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
+ *pb_bool = VLC_FALSE;
+ return VLC_SUCCESS;
- case MUX_GET_MIME:
- ppsz = (char**)va_arg( args, char ** );
- *ppsz = strdup( "video/mpeg" ); /* FIXME not sure */
- return VLC_SUCCESS;
+ case MUX_GET_MIME:
+ ppsz = (char**)va_arg( args, char ** );
+ *ppsz = strdup( "video/mpeg" ); /* FIXME not sure */
+ return VLC_SUCCESS;
default:
return VLC_EGENERIC;
- }
+ }
}
/*****************************************************************************
{
sout_mux_sys_t *p_sys = p_mux->p_sys;
ts_stream_t *p_stream;
+ int i;
p_input->p_sys = p_stream = malloc( sizeof( ts_stream_t ) );
+ if( !p_input->p_sys )
+ return VLC_ENOMEM;
/* Init this new stream */
if ( p_sys->b_es_id_pid )
switch( p_input->p_fmt->i_codec )
{
case VLC_FOURCC( 'm', 'p','g', 'a' ):
+ case VLC_FOURCC( 'm', 'p', '3', ' ' ):
p_stream->i_stream_type =
p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
p_stream->i_stream_id = 0xc0;
return VLC_EGENERIC;
}
+ p_stream->i_langs = 1+p_input->p_fmt->i_extra_languages;
+ p_stream->lang = malloc(p_stream->i_langs*3);
+ if( !p_stream->lang )
+ {
+ p_stream->i_langs = 0;
+ free( p_stream );
+ return VLC_ENOMEM;
+ }
+ i = 1;
p_stream->lang[0] =
p_stream->lang[1] =
p_stream->lang[2] = '\0';
p_stream->lang[2] = pl->psz_iso639_2T[2];
msg_Dbg( p_mux, " - lang=%c%c%c",
- p_stream->lang[0], p_stream->lang[1], p_stream->lang[2] );
+ p_stream->lang[0], p_stream->lang[1],
+ p_stream->lang[2] );
}
}
+ while( i < p_stream->i_langs ) {
+ if( p_input->p_fmt->p_extra_languages[i-1].psz_language )
+ {
+ char *psz = p_input->p_fmt->p_extra_languages[i-1].psz_language;
+ const iso639_lang_t *pl = NULL;
- /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
- p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
- if( p_stream->i_decoder_specific_info > 0 )
- {
- p_stream->p_decoder_specific_info =
- malloc( p_stream->i_decoder_specific_info );
- memcpy( p_stream->p_decoder_specific_info,
- p_input->p_fmt->p_extra,
- p_input->p_fmt->i_extra );
+ if( strlen( psz ) == 2 )
+ {
+ pl = GetLang_1( psz );
+ }
+ else if( strlen( psz ) == 3 )
+ {
+ pl = GetLang_2B( psz );
+ if( !strcmp( pl->psz_iso639_1, "??" ) )
+ {
+ pl = GetLang_2T( psz );
+ }
+ }
+ if( pl && strcmp( pl->psz_iso639_1, "??" ) )
+ {
+ p_stream->lang[i*3+0] = pl->psz_iso639_2T[0];
+ p_stream->lang[i*3+1] = pl->psz_iso639_2T[1];
+ p_stream->lang[i*3+2] = pl->psz_iso639_2T[2];
+
+ msg_Dbg( p_mux, " - lang=%c%c%c",
+ p_stream->lang[i*3+0], p_stream->lang[i*3+1],
+ p_stream->lang[i*3+2] );
+ }
+ }
+ i++;
}
/* Create decoder specific info for subt */
p_stream->i_decoder_specific_info = 55;
p_stream->p_decoder_specific_info = p =
malloc( p_stream->i_decoder_specific_info );
-
- p[0] = 0x10; /* textFormat, 0x10 for 3GPP TS 26.245 */
- p[1] = 0x00; /* flags: 1b: associated video info flag
- 3b: reserved
- 1b: duration flag
- 3b: reserved */
- p[2] = 52; /* remaining size */
-
- p += 3;
-
- p[0] = p[1] = p[2] = p[3] = 0; p+=4; /* display flags */
- *p++ = 0; /* horizontal justification (-1: left, 0 center, 1 right) */
- *p++ = 1; /* vertical justification (-1: top, 0 center, 1 bottom) */
-
- p[0] = p[1] = p[2] = 0x00; p+=3;/* background rgb */
- *p++ = 0xff; /* background a */
-
- p[0] = p[1] = 0; p += 2; /* text box top */
- p[0] = p[1] = 0; p += 2; /* text box left */
- p[0] = p[1] = 0; p += 2; /* text box bottom */
- p[0] = p[1] = 0; p += 2; /* text box right */
-
- p[0] = p[1] = 0; p += 2; /* start char */
- p[0] = p[1] = 0; p += 2; /* end char */
- p[0] = p[1] = 0; p += 2; /* default font id */
-
- *p++ = 0; /* font style flags */
- *p++ = 12; /* font size */
-
- p[0] = p[1] = p[2] = 0x00; p+=3;/* foreground rgb */
- *p++ = 0x00; /* foreground a */
-
- p[0] = p[1] = p[2] = 0; p[3] = 22; p += 4;
- memcpy( p, "ftab", 4 ); p += 4;
- *p++ = 0; *p++ = 1; /* entry count */
- p[0] = p[1] = 0; p += 2; /* font id */
- *p++ = 9; /* font name length */
- memcpy( p, "Helvetica", 9 ); /* font name */
+ if( p )
+ {
+ p[0] = 0x10; /* textFormat, 0x10 for 3GPP TS 26.245 */
+ p[1] = 0x00; /* flags: 1b: associated video info flag
+ 3b: reserved
+ 1b: duration flag
+ 3b: reserved */
+ p[2] = 52; /* remaining size */
+
+ p += 3;
+
+ p[0] = p[1] = p[2] = p[3] = 0; p+=4; /* display flags */
+ *p++ = 0; /* horizontal justification (-1: left, 0 center, 1 right) */
+ *p++ = 1; /* vertical justification (-1: top, 0 center, 1 bottom) */
+
+ p[0] = p[1] = p[2] = 0x00; p+=3;/* background rgb */
+ *p++ = 0xff; /* background a */
+
+ p[0] = p[1] = 0; p += 2; /* text box top */
+ p[0] = p[1] = 0; p += 2; /* text box left */
+ p[0] = p[1] = 0; p += 2; /* text box bottom */
+ p[0] = p[1] = 0; p += 2; /* text box right */
+
+ p[0] = p[1] = 0; p += 2; /* start char */
+ p[0] = p[1] = 0; p += 2; /* end char */
+ p[0] = p[1] = 0; p += 2; /* default font id */
+
+ *p++ = 0; /* font style flags */
+ *p++ = 12; /* font size */
+
+ p[0] = p[1] = p[2] = 0x00; p+=3;/* foreground rgb */
+ *p++ = 0x00; /* foreground a */
+
+ p[0] = p[1] = p[2] = 0; p[3] = 22; p += 4;
+ memcpy( p, "ftab", 4 ); p += 4;
+ *p++ = 0; *p++ = 1; /* entry count */
+ p[0] = p[1] = 0; p += 2; /* font id */
+ *p++ = 9; /* font name length */
+ memcpy( p, "Helvetica", 9 ); /* font name */
+ }
+ else p_stream->i_decoder_specific_info = 0;
+ }
+ else
+ {
+ /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
+ p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
+ if( p_stream->i_decoder_specific_info > 0 )
+ {
+ p_stream->p_decoder_specific_info =
+ malloc( p_stream->i_decoder_specific_info );
+ if( p_stream->p_decoder_specific_info )
+ {
+ memcpy( p_stream->p_decoder_specific_info,
+ p_input->p_fmt->p_extra,
+ p_input->p_fmt->i_extra );
+ }
+ else p_stream->i_decoder_specific_info = 0;
+ }
}
/* Init pes chain */
}
/* Empty all data in chain_pes */
- BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
+ BufferChainClean( &p_stream->chain_pes );
+ if( p_stream->lang )
+ {
+ free(p_stream->lang);
+ }
if( p_stream->p_decoder_specific_info )
{
free( p_stream->p_decoder_specific_info );
if( p_sys->i_pcr_pid == 0x1fff )
{
+ int i;
+ for( i = 0; i < p_mux->i_nb_inputs; i++ )
+ {
+ block_FifoEmpty( p_mux->pp_inputs[i]->p_fifo );
+ }
msg_Dbg( p_mux, "waiting for PCR streams" );
msleep( 1000 );
return VLC_SUCCESS;
p_input = p_mux->pp_inputs[i];
p_stream = (ts_stream_t*)p_input->p_sys;
- if( ( p_stream == p_pcr_stream &&
- p_stream->i_pes_length < i_shaping_delay ) ||
- p_stream->i_pes_dts + p_stream->i_pes_length <
- p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
+ if( ( ( p_stream == p_pcr_stream ) &&
+ ( p_stream->i_pes_length < i_shaping_delay ) ) ||
+ ( p_stream->i_pes_dts + p_stream->i_pes_length <
+ p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) )
{
/* Need more data */
- if( p_input->p_fifo->i_depth <= 1 )
+ if( block_FifoCount( p_input->p_fifo ) <= 1 )
{
- if( p_input->p_fmt->i_cat == AUDIO_ES ||
- p_input->p_fmt->i_cat == VIDEO_ES )
+ if( ( p_input->p_fmt->i_cat == AUDIO_ES ) ||
+ ( p_input->p_fmt->i_cat == VIDEO_ES ) )
{
/* We need more data */
return VLC_SUCCESS;
}
- else if( p_input->p_fifo->i_depth <= 0 )
+ else if( block_FifoCount( p_input->p_fifo ) <= 0 )
{
/* spu, only one packet is needed */
continue;
}
- else
+ else if( p_input->p_fmt->i_cat == SPU_ES )
{
/* Don't mux the SPU yet if it is too early */
block_t *p_spu = block_FifoShow( p_input->p_fifo );
i_spu_delay =
p_spu->i_dts - p_pcr_stream->i_pes_dts;
- if( i_spu_delay > i_shaping_delay &&
- i_spu_delay < I64C(100000000) )
+ if( ( i_spu_delay > i_shaping_delay ) &&
+ ( i_spu_delay < I64C(100000000) ) )
continue;
- if ( i_spu_delay >= I64C(100000000)
- || i_spu_delay < 10000 )
+ if ( ( i_spu_delay >= I64C(100000000) ) ||
+ ( i_spu_delay < I64C(10000) ) )
{
- BufferChainClean( p_mux->p_sout,
- &p_stream->chain_pes );
+ BufferChainClean( &p_stream->chain_pes );
p_stream->i_pes_dts = 0;
p_stream->i_pes_used = 0;
p_stream->i_pes_length = 0;
else
p_data = FixPES( p_mux, p_input->p_fifo );
- if( p_input->p_fifo->i_depth > 0 &&
+ if( block_FifoCount( p_input->p_fifo ) > 0 &&
p_input->p_fmt->i_cat != SPU_ES )
{
block_t *p_next = block_FifoShow( p_input->p_fifo );
p_pcr_stream->i_pes_dts );
block_Release( p_data );
- BufferChainClean( p_mux->p_sout,
- &p_stream->chain_pes );
+ BufferChainClean( &p_stream->chain_pes );
p_stream->i_pes_dts = 0;
p_stream->i_pes_used = 0;
p_stream->i_pes_length = 0;
if( p_input->p_fmt->i_cat != SPU_ES )
{
- BufferChainClean( p_mux->p_sout,
- &p_pcr_stream->chain_pes );
+ BufferChainClean( &p_pcr_stream->chain_pes );
p_pcr_stream->i_pes_dts = 0;
p_pcr_stream->i_pes_used = 0;
p_pcr_stream->i_pes_length = 0;
i_header_size = 0x24;
b_data_alignment = 1;
}
+ else if( p_input->p_fmt->i_codec ==
+ VLC_FOURCC('d','v','b','s') )
+ {
+ /* EN 300 743 */
+ b_data_alignment = 1;
+ }
}
else if( p_data->i_length < 0 ||
p_data->i_length > 2000000 )
if( p_stream->i_stream_id == 0xa0 &&
p_data->i_pts <= 0 )
{
- /* XXX yes I know, it's awfull, but it's needed,
+ /* XXX yes I know, it's awful, but it's needed,
* so don't remove it ... */
p_data->i_pts = p_data->i_dts;
}
/* Select stream (lowest dts) */
for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
{
- p_input = p_mux->pp_inputs[i];
p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
if( p_stream->i_pes_dts == 0 )
break;
}
p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
+ p_input = p_mux->pp_inputs[i_stream];
/* do we need to issue pcr */
b_pcr = VLC_FALSE;
else if( i_size > STD_PES_PAYLOAD )
{
block_t *p_new = block_New( p_mux, STD_PES_PAYLOAD );
- p_mux->p_vlc->pf_memcpy( p_new->p_buffer, p_data->p_buffer, STD_PES_PAYLOAD );
+ p_mux->p_libvlc->pf_memcpy( p_new->p_buffer, p_data->p_buffer, STD_PES_PAYLOAD );
p_new->i_pts = p_data->i_pts;
p_new->i_dts = p_data->i_dts;
p_new->i_length = p_data->i_length * STD_PES_PAYLOAD
}
i_copy = __MIN( STD_PES_PAYLOAD - i_size, p_next->i_buffer );
- p_mux->p_vlc->pf_memcpy( &p_data->p_buffer[i_size], p_next->p_buffer,
+ p_mux->p_libvlc->pf_memcpy( &p_data->p_buffer[i_size], p_next->p_buffer,
i_copy );
p_next->i_pts += p_next->i_length * i_copy / p_next->i_buffer;
p_next->i_dts += p_next->i_length * i_copy / p_next->i_buffer;
{
sout_mux_sys_t *p_sys = p_mux->p_sys;
block_t *p_pmt[MAX_PMT];
- block_t *p_sdt;
- dvbpsi_sdt_t sdt;
dvbpsi_pmt_es_t *p_es;
- dvbpsi_psi_section_t *p_section[MAX_PMT], *p_section2;
- dvbpsi_sdt_service_t *p_service;
- char *psz_sdt_desc;
- int i_pidinput;
+ dvbpsi_psi_section_t *p_section[MAX_PMT];
+ int i_pidinput;
int i_stream;
int i;
int *p_usepid = NULL;
+#ifdef HAVE_DVBPSI_SDT
+ block_t *p_sdt;
+ dvbpsi_sdt_t sdt;
+
+ dvbpsi_psi_section_t* p_section2;
+ dvbpsi_sdt_service_t *p_service;
+
+ uint8_t *psz_sdt_desc;
+#endif
+
if( p_sys->dvbpmt == NULL )
+ {
p_sys->dvbpmt = malloc( p_sys->i_num_pmt * sizeof(dvbpsi_pmt_t) );
+ if( !p_sys->dvbpmt )
+ {
+ return;
+ }
+ }
#ifdef HAVE_DVBPSI_SDT
if( p_sys->b_sdt )
dvbpsi_InitSDT( &sdt, p_sys->i_tsid, 1, 1, p_sys->i_netid );
#define psz_sdtserv p_sys->sdt_descriptors[i].psz_service_name
/* FIXME: Ineffecient malloc's & ugly code...... */
- if( psz_sdtprov != NULL && psz_sdtserv != NULL )
+ if( ( psz_sdtprov != NULL ) && ( psz_sdtserv != NULL ) )
{
psz_sdt_desc = malloc( 3 + strlen(psz_sdtprov)
+ strlen(psz_sdtserv) );
- psz_sdt_desc[0] = 0x01; /* digital television service */
-
- /* service provider name length */
- psz_sdt_desc[1] = (char)strlen(psz_sdtprov);
- memcpy( &psz_sdt_desc[2], psz_sdtprov, strlen(psz_sdtprov) );
-
- /* service name length */
- psz_sdt_desc[ 2 + strlen(psz_sdtprov) ]
- = (char)strlen(psz_sdtserv);
- memcpy( &psz_sdt_desc[3+strlen(psz_sdtprov)], psz_sdtserv,
- strlen(psz_sdtserv) );
-
- dvbpsi_SDTServiceAddDescriptor( p_service, 0x48,
- 3 + strlen(psz_sdtprov) + strlen(psz_sdtserv),
- psz_sdt_desc );
- free( psz_sdt_desc );
+ if( psz_sdt_desc )
+ {
+ psz_sdt_desc[0] = 0x01; /* digital television service */
+
+ /* service provider name length */
+ psz_sdt_desc[1] = (char)strlen(psz_sdtprov);
+ memcpy( &psz_sdt_desc[2], psz_sdtprov, strlen(psz_sdtprov) );
+
+ /* service name length */
+ psz_sdt_desc[ 2 + strlen(psz_sdtprov) ]
+ = (char)strlen(psz_sdtserv);
+ memcpy( &psz_sdt_desc[3+strlen(psz_sdtprov)], psz_sdtserv,
+ strlen(psz_sdtserv) );
+
+ dvbpsi_SDTServiceAddDescriptor( p_service, 0x48,
+ 3 + strlen(psz_sdtprov) + strlen(psz_sdtserv),
+ (uint8_t *)psz_sdt_desc );
+ free( psz_sdt_desc );
+ psz_sdt_desc = NULL;
+ }
}
#undef psz_sdtprov
#undef psz_sdtserv
}
else if( p_stream->i_codec == VLC_FOURCC('t','e','l','x') )
{
- dvbpsi_PMTESAddDescriptor( p_es, 0x56,
- p_stream->i_decoder_specific_info,
- p_stream->p_decoder_specific_info );
+ if( p_stream->i_decoder_specific_info )
+ {
+ dvbpsi_PMTESAddDescriptor( p_es, 0x56,
+ p_stream->i_decoder_specific_info,
+ p_stream->p_decoder_specific_info );
+ }
+ continue;
}
-#ifdef _DVBPSI_DR_59_H_
else if( p_stream->i_codec == VLC_FOURCC('d','v','b','s') )
{
/* DVB subtitles */
- dvbpsi_subtitling_dr_t descr;
- dvbpsi_subtitle_t sub;
- dvbpsi_descriptor_t *p_descr;
-
- memcpy( sub.i_iso6392_language_code, p_stream->lang, 3 );
- sub.i_subtitling_type = 0x10; /* no aspect-ratio criticality */
- sub.i_composition_page_id = p_stream->i_es_id & 0xFF;
- sub.i_ancillary_page_id = p_stream->i_es_id >> 16;
-
- descr.i_subtitles_number = 1;
- descr.p_subtitle[0] = sub;
-
- p_descr = dvbpsi_GenSubtitlingDr( &descr, 0 );
- /* Work around bug in old libdvbpsi */ p_descr->i_length = 8;
- dvbpsi_PMTESAddDescriptor( p_es, p_descr->i_tag,
- p_descr->i_length, p_descr->p_data );
+ if( p_stream->i_decoder_specific_info )
+ {
+ /* pass-through from the TS demux */
+ dvbpsi_PMTESAddDescriptor( p_es, 0x59,
+ p_stream->i_decoder_specific_info,
+ p_stream->p_decoder_specific_info );
+ }
+#ifdef _DVBPSI_DR_59_H_
+ else
+ {
+ /* from the dvbsub transcoder */
+ dvbpsi_subtitling_dr_t descr;
+ dvbpsi_subtitle_t sub;
+ dvbpsi_descriptor_t *p_descr;
+
+ memcpy( sub.i_iso6392_language_code, p_stream->lang, 3 );
+ sub.i_subtitling_type = 0x10; /* no aspect-ratio criticality */
+ sub.i_composition_page_id = p_stream->i_es_id & 0xFF;
+ sub.i_ancillary_page_id = p_stream->i_es_id >> 16;
+
+ descr.i_subtitles_number = 1;
+ descr.p_subtitle[0] = sub;
+
+ p_descr = dvbpsi_GenSubtitlingDr( &descr, 0 );
+ /* Work around bug in old libdvbpsi */ p_descr->i_length = 8;
+ dvbpsi_PMTESAddDescriptor( p_es, p_descr->i_tag,
+ p_descr->i_length, p_descr->p_data );
+ }
+#endif /* _DVBPSI_DR_59_H_ */
continue;
}
-#endif /* _DVBPSI_DR_59_H_ */
if( p_stream->lang[0] != 0 )
{
- uint8_t data[4];
+ uint8_t data[4*p_stream->i_langs];
/* I construct the content myself, way faster than looking at
* over complicated/mind broken libdvbpsi way */
- data[0] = p_stream->lang[0];
- data[1] = p_stream->lang[1];
- data[2] = p_stream->lang[2];
- data[3] = 0x00; /* audio type: 0x00 undefined */
-
- dvbpsi_PMTESAddDescriptor( p_es, 0x0a, 4, data );
+ for(i = 0; i < p_stream->i_langs; i++ )
+ {
+ data[i*4+0] = p_stream->lang[i*3+0];
+ data[i*4+1] = p_stream->lang[i*3+1];
+ data[i*4+2] = p_stream->lang[i*3+2];
+ data[i*4+3] = 0x00; /* audio type: 0x00 undefined */
+ }
+ dvbpsi_PMTESAddDescriptor( p_es, 0x0a, 4*p_stream->i_langs, data );
}
}