Commit ca44fe14 authored by Christophe Massiot's avatar Christophe Massiot

* ALL: Add a way to specify per-output options (239.1.0.1:1234/tsid=42). *...

* ALL: Add a way to specify per-output options (239.1.0.1:1234/tsid=42). * dvblast.c: Fix reinitialization of existing inputs, creating discontinuities. * demux.c: Print NIT table; always print DVB tables. * demux.c: Only check the CRC when needed. * demux.c: Use biTStream built-in print functions. * demux.c: Allow the same PID to be declared twice in PMT; allow the same service to be declared twice in SDT.
parent 527bda5e
...@@ -55,6 +55,9 @@ EITp/f, TOT, TDT). If you also want to pass-through the EIT schedule tables, ...@@ -55,6 +55,9 @@ EITp/f, TOT, TDT). If you also want to pass-through the EIT schedule tables,
use the -e switch. It is considered a good practice to configure the name use the -e switch. It is considered a good practice to configure the name
of the network (for the NIT) with the -M option. of the network (for the NIT) with the -M option.
If you don't want to set these options on a general basis, you can set them
per output - see below.
Other rarely used options are available - run dvblast -h for more Other rarely used options are available - run dvblast -h for more
information. information.
...@@ -83,7 +86,7 @@ Configuring outputs ...@@ -83,7 +86,7 @@ Configuring outputs
DVBlast reads a configuration file containing one or several lines in the DVBlast reads a configuration file containing one or several lines in the
format : format :
<IP>[:<port>][/udp] <always on> <SID> [<PID>,]* <IP>[:<port>][/<option>]* <always on> <SID> [<PID>,]*
For instance : For instance :
239.255.0.1:1234 1 10750 1234,1235,1236 239.255.0.1:1234 1 10750 1234,1235,1236
...@@ -108,6 +111,18 @@ regularly reset the CAM module if it fails to descramble the service, ...@@ -108,6 +111,18 @@ regularly reset the CAM module if it fails to descramble the service,
assuming the module is dead. Every time it is reset a few TS packets assuming the module is dead. Every time it is reset a few TS packets
will be lost, that is why this feature is optional. will be lost, that is why this feature is optional.
Other options can be set by appending / to the multicast address definition.
Available options include :
/udp (turns on -U for a specific output)
/dvb (turns on -C for a specific output)
/epg (turns on -C -e for a specific output)
/tsid=XXX (sets the transport stream ID)
/retention=XXX (see -E)
/latency=XXX (see -L)
Several options can be appended, for instance:
239.255.0.1:1234/udp/epg/tsid=42
The optional "/udp" parameter can be used to force DVBlast to output The optional "/udp" parameter can be used to force DVBlast to output
raw UDP stream. This functionality is provided for backwards compatibility raw UDP stream. This functionality is provided for backwards compatibility
with IPTV set top boxes that don't support RTP and should only be used with IPTV set top boxes that don't support RTP and should only be used
......
This diff is collapsed.
/***************************************************************************** /*****************************************************************************
* dvblast.c * dvblast.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2004, 2008-2009 VideoLAN * Copyright (C) 2004, 2008-2010 VideoLAN
* $Id$ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
...@@ -63,14 +63,9 @@ int b_tone = 0; ...@@ -63,14 +63,9 @@ int b_tone = 0;
int i_bandwidth = 8; int i_bandwidth = 8;
char *psz_modulation = NULL; char *psz_modulation = NULL;
int b_budget_mode = 0; int b_budget_mode = 0;
int b_output_udp = 0; int b_random_tsid = 0;
int b_dvb_compliance = 0;
int b_enable_epg = 0;
int b_unique_tsid = 0;
uint16_t i_network_id = 0xffff; uint16_t i_network_id = 0xffff;
const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html"; const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html";
mtime_t i_output_latency = DEFAULT_OUTPUT_LATENCY;
mtime_t i_max_retention = DEFAULT_MAX_RETENTION;
volatile int b_hup_received = 0; volatile int b_hup_received = 0;
int i_verbose = DEFAULT_VERBOSITY; int i_verbose = DEFAULT_VERBOSITY;
int i_syslog = 0; int i_syslog = 0;
...@@ -79,6 +74,12 @@ in_addr_t i_src_addr = { 0 }; ...@@ -79,6 +74,12 @@ in_addr_t i_src_addr = { 0 };
int b_src_rawudp = 0; int b_src_rawudp = 0;
int i_asi_adapter = 0; int i_asi_adapter = 0;
static int b_udp_global = 0;
static int b_dvb_global = 0;
static int b_epg_global = 0;
static mtime_t i_latency_global = DEFAULT_OUTPUT_LATENCY;
static mtime_t i_retention_global = DEFAULT_MAX_RETENTION;
void (*pf_Open)( void ) = NULL; void (*pf_Open)( void ) = NULL;
block_t * (*pf_Read)( mtime_t i_poll_timeout ) = NULL; block_t * (*pf_Read)( mtime_t i_poll_timeout ) = NULL;
int (*pf_SetFilter)( uint16_t i_pid ) = NULL; int (*pf_SetFilter)( uint16_t i_pid ) = NULL;
...@@ -108,7 +109,7 @@ static void ReadConfiguration( char *psz_file ) ...@@ -108,7 +109,7 @@ static void ReadConfiguration( char *psz_file )
while ( fgets( psz_line, sizeof(psz_line), p_file ) != NULL ) while ( fgets( psz_line, sizeof(psz_line), p_file ) != NULL )
{ {
output_t *p_output = NULL; output_t *p_output = NULL;
char *psz_parser, *psz_token, *psz_token2, *psz_token3; char *psz_parser, *psz_token, *psz_token2;
struct addrinfo *p_addr; struct addrinfo *p_addr;
struct addrinfo ai_hints; struct addrinfo ai_hints;
char sz_port[6]; char sz_port[6];
...@@ -116,7 +117,12 @@ static void ReadConfiguration( char *psz_file ) ...@@ -116,7 +117,12 @@ static void ReadConfiguration( char *psz_file )
uint16_t i_sid = 0; uint16_t i_sid = 0;
uint16_t *pi_pids = NULL; uint16_t *pi_pids = NULL;
int i_nb_pids = 0; int i_nb_pids = 0;
uint8_t i_config = 0; uint8_t i_config = (b_udp_global ? OUTPUT_UDP : 0) |
(b_dvb_global ? OUTPUT_DVB : 0) |
(b_epg_global ? OUTPUT_EPG : 0);
mtime_t i_retention = i_retention_global;
mtime_t i_latency = i_latency_global;
int i_tsid = -1;
snprintf( sz_port, sizeof( sz_port ), "%d", DEFAULT_PORT ); snprintf( sz_port, sizeof( sz_port ), "%d", DEFAULT_PORT );
...@@ -127,11 +133,24 @@ static void ReadConfiguration( char *psz_file ) ...@@ -127,11 +133,24 @@ static void ReadConfiguration( char *psz_file )
if ( psz_token == NULL ) if ( psz_token == NULL )
continue; continue;
if ( (psz_token3 = strrchr( psz_token, '/' )) != NULL ) psz_token2 = psz_token;
while ( (psz_token2 = strchr( psz_token2, '/' )) != NULL )
{ {
*psz_token3 = '\0'; *psz_token2++ = '\0';
if( strncasecmp( psz_token3 + 1, "udp", 3 ) == 0 ) if ( !strncasecmp( psz_token2, "udp", 3 ) )
i_config |= OUTPUT_UDP; i_config |= OUTPUT_UDP;
else if ( !strncasecmp( psz_token2, "dvb", 3 ) )
i_config |= OUTPUT_DVB;
else if ( !strncasecmp( psz_token2, "epg", 3 ) )
i_config |= OUTPUT_EPG;
else if ( !strncasecmp( psz_token2, "tsid=", 5 ) )
i_tsid = strtol( psz_token2 + 5, NULL, 0 );
else if ( !strncasecmp( psz_token2, "retention=", 10 ) )
i_retention = strtoll( psz_token2 + 10, NULL, 0 ) * 1000;
else if ( !strncasecmp( psz_token2, "latency=", 8 ) )
i_latency = strtoll( psz_token2 + 8, NULL, 0 ) * 1000;
else
msg_Warn( NULL, "unrecognized option %s", psz_token2 );
} }
if ( !strncmp( psz_token, "[", 1 ) ) if ( !strncmp( psz_token, "[", 1 ) )
...@@ -227,9 +246,8 @@ static void ReadConfiguration( char *psz_file ) ...@@ -227,9 +246,8 @@ static void ReadConfiguration( char *psz_file )
} }
} }
msg_Dbg( NULL, "conf: %s w=%d sid=%d pids[%d]=%d,%d,%d,%d,%d...", msg_Dbg( NULL, "conf: %s config=0x%x sid=%d pids[%d]=%d,%d,%d,%d,%d...",
psz_displayname, psz_displayname, i_config, i_sid, i_nb_pids,
( i_config & OUTPUT_WATCH ) ? 1 : 0, i_sid, i_nb_pids,
i_nb_pids < 1 ? -1 : pi_pids[0], i_nb_pids < 1 ? -1 : pi_pids[0],
i_nb_pids < 2 ? -1 : pi_pids[1], i_nb_pids < 2 ? -1 : pi_pids[1],
i_nb_pids < 3 ? -1 : pi_pids[2], i_nb_pids < 3 ? -1 : pi_pids[2],
...@@ -247,7 +265,6 @@ static void ReadConfiguration( char *psz_file ) ...@@ -247,7 +265,6 @@ static void ReadConfiguration( char *psz_file )
( p_esad->sin_port == p_nsad->sin_port ) ) ( p_esad->sin_port == p_nsad->sin_port ) )
{ {
p_output = pp_outputs[i]; p_output = pp_outputs[i];
output_Init( p_output, i_config, psz_displayname, (void *)p_addr );
break; break;
} }
} }
...@@ -263,19 +280,20 @@ static void ReadConfiguration( char *psz_file ) ...@@ -263,19 +280,20 @@ static void ReadConfiguration( char *psz_file )
( p_esad->sin6_port == p_nsad->sin6_port ) ) ( p_esad->sin6_port == p_nsad->sin6_port ) )
{ {
p_output = pp_outputs[i]; p_output = pp_outputs[i];
output_Init( p_output, i_config, psz_displayname, (void *)p_addr );
break; break;
} }
} }
} }
if ( i == i_nb_outputs ) if ( i == i_nb_outputs )
p_output = output_Create( i_config, psz_displayname, (void *)p_addr ); p_output = output_Create( psz_displayname, p_addr );
if ( p_output != NULL ) if ( p_output != NULL )
{ {
demux_Change( p_output, i_sid, pi_pids, i_nb_pids ); p_output->i_config = OUTPUT_VALID | OUTPUT_STILL_PRESENT | i_config;
p_output->i_config |= OUTPUT_STILL_PRESENT; p_output->i_output_latency = i_latency;
p_output->i_max_retention = i_retention;
demux_Change( p_output, i_tsid, i_sid, pi_pids, i_nb_pids );
} }
free( psz_displayname ); free( psz_displayname );
...@@ -287,11 +305,13 @@ static void ReadConfiguration( char *psz_file ) ...@@ -287,11 +305,13 @@ static void ReadConfiguration( char *psz_file )
for ( i = 0; i < i_nb_outputs; i++ ) for ( i = 0; i < i_nb_outputs; i++ )
{ {
if ( ( pp_outputs[i]->i_config & OUTPUT_VALID ) && output_t *p_output = pp_outputs[i];
!( pp_outputs[i]->i_config & OUTPUT_STILL_PRESENT ) )
if ( (p_output->i_config & OUTPUT_VALID) &&
!(p_output->i_config & OUTPUT_STILL_PRESENT) )
{ {
msg_Dbg( NULL, "closing %s", pp_outputs[i]->psz_displayname ); msg_Dbg( NULL, "closing %s", pp_outputs[i]->psz_displayname );
demux_Change( pp_outputs[i], 0, NULL, 0 ); demux_Change( pp_outputs[i], -1, 0, NULL, 0 );
output_Close( pp_outputs[i] ); output_Close( pp_outputs[i] );
} }
...@@ -530,15 +550,15 @@ int main( int i_argc, char **pp_argv ) ...@@ -530,15 +550,15 @@ int main( int i_argc, char **pp_argv )
break; break;
case 'U': case 'U':
b_output_udp = 1; b_udp_global = 1;
break; break;
case 'L': case 'L':
i_output_latency = strtoll( optarg, NULL, 0 ) * 1000; i_latency_global = strtoll( optarg, NULL, 0 ) * 1000;
break; break;
case 'E': case 'E':
i_max_retention = strtoll( optarg, NULL, 0 ) * 1000; i_retention_global = strtoll( optarg, NULL, 0 ) * 1000;
break; break;
case 'd': case 'd':
...@@ -621,11 +641,16 @@ int main( int i_argc, char **pp_argv ) ...@@ -621,11 +641,16 @@ int main( int i_argc, char **pp_argv )
i_dup_config |= OUTPUT_VALID; i_dup_config |= OUTPUT_VALID;
} }
if ( i_dup_config &= OUTPUT_VALID ) { if ( i_dup_config & OUTPUT_VALID )
output_Init( &output_dup, i_dup_config, psz_displayname, p_daddr ); {
output_dup.i_config = i_dup_config;
output_dup.i_output_latency = i_latency_global;
output_dup.i_max_retention = i_retention_global;
output_Init( &output_dup, psz_displayname, p_daddr );
} }
else else
msg_Err( NULL, "Invalid configuration for -d switch: %s" , optarg); msg_Err( NULL, "Invalid configuration for -d switch: %s" ,
optarg);
free( psz_displayname ); free( psz_displayname );
freeaddrinfo( p_daddr ); freeaddrinfo( p_daddr );
...@@ -681,11 +706,11 @@ int main( int i_argc, char **pp_argv ) ...@@ -681,11 +706,11 @@ int main( int i_argc, char **pp_argv )
break; break;
case 'C': case 'C':
b_dvb_compliance = 1; b_dvb_global = 1;
break; break;
case 'e': case 'e':
b_enable_epg = 1; b_epg_global = 1;
break; break;
case 'M': case 'M':
...@@ -701,7 +726,7 @@ int main( int i_argc, char **pp_argv ) ...@@ -701,7 +726,7 @@ int main( int i_argc, char **pp_argv )
break; break;
case 'T': case 'T':
b_unique_tsid = 1; b_random_tsid = 1;
break; break;
case 'V': case 'V':
...@@ -721,16 +746,16 @@ int main( int i_argc, char **pp_argv ) ...@@ -721,16 +746,16 @@ int main( int i_argc, char **pp_argv )
msg_Warn( NULL, "restarting" ); msg_Warn( NULL, "restarting" );
if ( b_output_udp ) if ( b_udp_global )
{ {
msg_Warn( NULL, "raw UDP output is deprecated. Please consider using RTP." ); msg_Warn( NULL, "raw UDP output is deprecated. Please consider using RTP." );
msg_Warn( NULL, "for DVB-IP compliance you should use RTP." ); msg_Warn( NULL, "for DVB-IP compliance you should use RTP." );
} }
if ( b_enable_epg && !b_dvb_compliance ) if ( b_epg_global && !b_dvb_global )
{ {
msg_Dbg( NULL, "turning on DVB compliance, required by EPG information" ); msg_Dbg( NULL, "turning on DVB compliance, required by EPG information" );
b_dvb_compliance = 1; b_dvb_global = 1;
} }
signal( SIGHUP, SigHandler ); signal( SIGHUP, SigHandler );
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
* Bit 2 : Set if output is valid (replaces m_addr != 0 tests) * Bit 2 : Set if output is valid (replaces m_addr != 0 tests)
* Bit 3 : Set for UDP, otherwise use RTP if a network stream * Bit 3 : Set for UDP, otherwise use RTP if a network stream
* Bit 4 : Set for file / FIFO output, unset for network (future use) * Bit 4 : Set for file / FIFO output, unset for network (future use)
* Bit 5 : Set if DVB conformance tables are inserted
* Bit 6 : Set if DVB EIT schedule tables are forwarded
*****************************************************************************/ *****************************************************************************/
#define OUTPUT_WATCH 0x01 #define OUTPUT_WATCH 0x01
...@@ -54,6 +56,8 @@ ...@@ -54,6 +56,8 @@
#define OUTPUT_VALID 0x04 #define OUTPUT_VALID 0x04
#define OUTPUT_UDP 0x08 #define OUTPUT_UDP 0x08
#define OUTPUT_FILE 0x10 #define OUTPUT_FILE 0x10
#define OUTPUT_DVB 0x20
#define OUTPUT_EPG 0x40
typedef int64_t mtime_t; typedef int64_t mtime_t;
...@@ -96,12 +100,16 @@ typedef struct output_t ...@@ -96,12 +100,16 @@ typedef struct output_t
uint8_t i_sdt_version, i_sdt_cc; uint8_t i_sdt_version, i_sdt_cc;
block_t *p_eit_ts_buffer; block_t *p_eit_ts_buffer;
uint8_t i_eit_ts_buffer_offset, i_eit_cc; uint8_t i_eit_ts_buffer_offset, i_eit_cc;
uint16_t i_ts_id;
/* configuration */ /* configuration */
uint16_t i_sid; /* 0 if raw mode */ uint16_t i_sid; /* 0 if raw mode */
uint16_t *pi_pids; uint16_t *pi_pids;
int i_nb_pids; int i_nb_pids;
int i_ttl;
in_addr_t i_ssrc;
uint16_t i_tsid;
bool b_fixed_tsid;
mtime_t i_output_latency, i_max_retention;
uint8_t i_config; uint8_t i_config;
} output_t; } output_t;
...@@ -125,14 +133,9 @@ extern int b_tone; ...@@ -125,14 +133,9 @@ extern int b_tone;
extern int i_bandwidth; extern int i_bandwidth;
extern char *psz_modulation; extern char *psz_modulation;
extern int b_budget_mode; extern int b_budget_mode;
extern int b_output_udp; extern int b_random_tsid;
extern int b_dvb_compliance;
extern int b_enable_epg;
extern int b_unique_tsid;
extern uint16_t i_network_id; extern uint16_t i_network_id;
extern const char *psz_network_name; extern const char *psz_network_name;
extern mtime_t i_output_latency;
extern mtime_t i_max_retention;
extern mtime_t i_wallclock; extern mtime_t i_wallclock;
extern volatile int b_hup_received; extern volatile int b_hup_received;
extern int i_comm_fd; extern int i_comm_fd;
...@@ -185,15 +188,14 @@ void asi_UnsetFilter( int i_fd, uint16_t i_pid ); ...@@ -185,15 +188,14 @@ void asi_UnsetFilter( int i_fd, uint16_t i_pid );
void demux_Open( void ); void demux_Open( void );
void demux_Run( block_t *p_ts ); void demux_Run( block_t *p_ts );
void demux_Change( output_t *p_output, uint16_t i_sid, void demux_Change( output_t *p_output, int i_tsid, uint16_t i_sid,
uint16_t *pi_pids, int i_nb_pids ); uint16_t *pi_pids, int i_nb_pids );
void demux_ResendCAPMTs( void ); void demux_ResendCAPMTs( void );
bool demux_PIDIsSelected( uint16_t i_pid ); bool demux_PIDIsSelected( uint16_t i_pid );
output_t *output_Create( uint8_t i_config, const char *psz_displayname, output_t *output_Create( const char *psz_displayname, struct addrinfo *p_ai );
void *p_init_data ); int output_Init( output_t *p_output, const char *psz_displayname,
int output_Init( output_t *p_output, uint8_t i_config, struct addrinfo *p_ai );
const char *psz_displayname, void *p_init_data );
void output_Close( output_t *p_output ); void output_Close( output_t *p_output );
void output_Put( output_t *p_output, block_t *p_block ); void output_Put( output_t *p_output, block_t *p_block );
mtime_t output_Send( void ); mtime_t output_Send( void );
......
...@@ -77,8 +77,7 @@ static void rtp_SetHdr( output_t *p_output, packet_t *p_packet, ...@@ -77,8 +77,7 @@ static void rtp_SetHdr( output_t *p_output, packet_t *p_packet,
/***************************************************************************** /*****************************************************************************
* output_Create : called from main thread * output_Create : called from main thread
*****************************************************************************/ *****************************************************************************/
output_t *output_Create( uint8_t i_config, const char *psz_displayname, output_t *output_Create( const char *psz_displayname, struct addrinfo *p_ai )
void *p_init_data )
{ {
int i; int i;
output_t *p_output = NULL; output_t *p_output = NULL;
...@@ -101,7 +100,7 @@ output_t *output_Create( uint8_t i_config, const char *psz_displayname, ...@@ -101,7 +100,7 @@ output_t *output_Create( uint8_t i_config, const char *psz_displayname,
pp_outputs[i] = p_output; pp_outputs[i] = p_output;
} }
if ( output_Init( p_output, i_config, psz_displayname, p_init_data ) < 0 ) if ( output_Init( p_output, psz_displayname, p_ai ) < 0 )
return NULL; return NULL;
return p_output; return p_output;
...@@ -110,8 +109,8 @@ output_t *output_Create( uint8_t i_config, const char *psz_displayname, ...@@ -110,8 +109,8 @@ output_t *output_Create( uint8_t i_config, const char *psz_displayname,
/***************************************************************************** /*****************************************************************************
* output_Init * output_Init
*****************************************************************************/ *****************************************************************************/
int output_Init( output_t *p_output, uint8_t i_config, int output_Init( output_t *p_output, const char *psz_displayname,
const char *psz_displayname, void *p_init_data ) struct addrinfo *p_ai )
{ {
p_output->i_sid = 0; p_output->i_sid = 0;
p_output->p_packets = p_output->p_last_packet = NULL; p_output->p_packets = p_output->p_last_packet = NULL;
...@@ -135,15 +134,22 @@ int output_Init( output_t *p_output, uint8_t i_config, ...@@ -135,15 +134,22 @@ int output_Init( output_t *p_output, uint8_t i_config,
p_output->p_sdt_section = NULL; p_output->p_sdt_section = NULL;
p_output->p_eit_ts_buffer = NULL; p_output->p_eit_ts_buffer = NULL;
p_output->i_eit_ts_buffer_offset = 0; p_output->i_eit_ts_buffer_offset = 0;
if ( b_unique_tsid ) if ( b_random_tsid )
p_output->i_ts_id = rand() & 0xffff; {
p_output->i_tsid = rand() & 0xffff;
p_output->b_fixed_tsid = true;
}
else
{
p_output->i_tsid = 0;
p_output->b_fixed_tsid = false;
}
p_output->i_ref_timestamp = 0; p_output->i_ref_timestamp = 0;
p_output->i_ref_wallclock = 0; p_output->i_ref_wallclock = 0;
p_output->i_config = i_config; p_output->i_config = 0;
p_output->psz_displayname = strdup( psz_displayname ); p_output->psz_displayname = strdup( psz_displayname );
struct addrinfo *p_ai = (struct addrinfo *)p_init_data;
p_output->i_addrlen = p_ai->ai_addrlen; p_output->i_addrlen = p_ai->ai_addrlen;
p_output->p_addr = malloc( p_output->i_addrlen ); p_output->p_addr = malloc( p_output->i_addrlen );
memcpy( p_output->p_addr, p_ai->ai_addr, memcpy( p_output->p_addr, p_ai->ai_addr,
...@@ -205,7 +211,7 @@ static void output_Flush( output_t *p_output ) ...@@ -205,7 +211,7 @@ static void output_Flush( output_t *p_output )
NB_BLOCKS_IPV6 : NB_BLOCKS; NB_BLOCKS_IPV6 : NB_BLOCKS;
int i_iov, i_block; int i_iov, i_block;
if ( !b_output_udp && !(p_output->i_config & OUTPUT_UDP) ) if ( !(p_output->i_config & OUTPUT_UDP) )
{ {
p_iov[0].iov_base = p_rtp_hdr; p_iov[0].iov_base = p_rtp_hdr;
p_iov[0].iov_len = sizeof(p_rtp_hdr); p_iov[0].iov_len = sizeof(p_rtp_hdr);
...@@ -262,7 +268,8 @@ void output_Put( output_t *p_output, block_t *p_block ) ...@@ -262,7 +268,8 @@ void output_Put( output_t *p_output, block_t *p_block )
if ( p_output->p_last_packet != NULL if ( p_output->p_last_packet != NULL
&& p_output->p_last_packet->i_depth < i_block_cnt && p_output->p_last_packet->i_depth < i_block_cnt
&& p_output->p_last_packet->i_dts + i_max_retention > p_block->i_dts ) && p_output->p_last_packet->i_dts + p_output->i_max_retention
> p_block->i_dts )
{ {
p_packet = p_output->p_last_packet; p_packet = p_output->p_last_packet;
if ( ts_has_adaptation( p_block->p_ts ) if ( ts_has_adaptation( p_block->p_ts )
...@@ -298,7 +305,7 @@ mtime_t output_Send( void ) ...@@ -298,7 +305,7 @@ mtime_t output_Send( void )
if ( output_dup.i_config & OUTPUT_VALID ) if ( output_dup.i_config & OUTPUT_VALID )
{ {
while ( output_dup.p_packets != NULL while ( output_dup.p_packets != NULL
&& output_dup.p_packets->i_dts + i_output_latency && output_dup.p_packets->i_dts + output_dup.i_output_latency
<= i_wallclock ) <= i_wallclock )
output_Flush( &output_dup ); output_Flush( &output_dup );
...@@ -313,18 +320,19 @@ mtime_t output_Send( void ) ...@@ -313,18 +320,19 @@ mtime_t output_Send( void )
continue; continue;
while ( p_output->p_packets != NULL while ( p_output->p_packets != NULL
&& p_output->p_packets->i_dts + i_output_latency && p_output->p_packets->i_dts + p_output->i_output_latency
<= i_wallclock ) <= i_wallclock )
output_Flush( p_output ); output_Flush( p_output );
if ( p_output->p_packets != NULL if ( p_output->p_packets != NULL
&& (p_output->p_packets->i_dts < i_earliest_dts && (p_output->p_packets->i_dts + p_output->i_output_latency
< i_earliest_dts
|| i_earliest_dts == -1) ) || i_earliest_dts == -1) )
i_earliest_dts = p_output->p_packets->i_dts; i_earliest_dts = p_output->p_packets->i_dts
+ p_output->i_output_latency;
} }
return i_earliest_dts == -1 ? -1 : return i_earliest_dts == -1 ? -1 : i_earliest_dts - i_wallclock;
i_earliest_dts + i_output_latency - i_wallclock;
} }
/***************************************************************************** /*****************************************************************************
......
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