Commit c958b137 authored by Christophe Massiot's avatar Christophe Massiot

* dvblast.c: Add options --system-charset and --dvb-charset for charset...

* dvblast.c: Add options --system-charset and --dvb-charset for charset conversion via iconv. * dvblast.c: Add support for charset conversion of the network name. * demux.c: Add support for biTStream charset conversion. * demux.c: Add missing stream types for AAC audio. * en50221.c: Validate descriptors before accessing them. * en50221.c: Implement MMI string charset conversion.
parent e3e4ade7
......@@ -27,6 +27,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
......@@ -34,6 +35,10 @@
#include "dvblast.h"
#include "en50221.h"
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#include <bitstream/mpeg/ts.h>
#include <bitstream/mpeg/pes.h>
#include <bitstream/mpeg/psi.h>
......@@ -1060,13 +1065,18 @@ static void NewNIT( output_t *p_output )
psi_set_section( p, 0 );
psi_set_lastsection( p, 0 );
if ( p_network_name != NULL )
{
nit_set_desclength( p, DESCS_MAX_SIZE );
p_descs = nit_get_descs( p );
p_desc = descs_get_desc( p_descs, 0 );
desc40_init( p_desc );
desc40_set_networkname( p_desc, psz_network_name );
desc40_set_networkname( p_desc, p_network_name, i_network_name_size );
p_desc = descs_get_desc( p_descs, 1 );
descs_set_length( p_descs, p_desc - p_descs - DESCS_HEADER_SIZE );
}
else
nit_set_desclength( p, 0 );
p_header2 = nit_get_header2( p );
nith_init( p_header2 );
......@@ -1232,7 +1242,9 @@ static bool PIDWouldBeSelected( uint8_t *p_es )
case 0x2: /* video */
case 0x3: /* audio MPEG-1 */
case 0x4: /* audio */
case 0xf: /* audio AAC */
case 0xf: /* audio AAC ADTS */
case 0x10: /* video MPEG-4 */
case 0x11: /* audio AAC LATM */
case 0x1b: /* video H264 */
return true;
break;
......@@ -1247,9 +1259,13 @@ static bool PIDWouldBeSelected( uint8_t *p_es )
uint8_t i_tag = desc_get_tag( p_desc );
j++;
if( i_tag == 0x56 /* ttx */
if( i_tag == 0x46 /* VBI + teletext */
|| i_tag == 0x56 /* teletext */
|| i_tag == 0x59 /* dvbsub */
|| i_tag == 0x6a /* A/52 */ )
|| i_tag == 0x6a /* A/52 */
|| i_tag == 0x7a /* Enhanced A/52 */
|| i_tag == 0x7b /* DCA */
|| i_tag == 0x7c /* AAC */ )
return true;
}
break;
......@@ -1278,6 +1294,8 @@ static bool PIDCarriesPES( const uint8_t *p_es )
case 0x4: /* audio */
case 0x6: /* private PES data */
case 0xf: /* audio AAC */
case 0x10: /* video MPEG-4 */
case 0x11: /* audio AAC LATM */
case 0x1b: /* video H264 */
return true;
break;
......@@ -1388,6 +1406,67 @@ static void DeleteProgram( uint16_t i_sid, uint16_t i_pid )
}
}
/*****************************************************************************
* demux_Iconv
*****************************************************************************
* This code is from biTStream's examples and is under the WTFPL (see
* LICENSE.WTFPL).
*****************************************************************************/
static char *iconv_append_null(const char *p_string, size_t i_length)
{
char *psz_string = malloc(i_length + 1);
memcpy(psz_string, p_string, i_length);
psz_string[i_length] = '\0';
return psz_string;
}
char *demux_Iconv(void *_unused, const char *psz_encoding,
char *p_string, size_t i_length)
{
#ifdef HAVE_ICONV
static const char *psz_current_encoding = "";
static iconv_t iconv_handle = (iconv_t)-1;
char *psz_string, *p;
size_t i_out_length;
if (!strcmp(psz_encoding, psz_native_charset))
return iconv_append_null(p_string, i_length);
if (iconv_handle != (iconv_t)-1 &&
strcmp(psz_encoding, psz_current_encoding)) {
iconv_close(iconv_handle);
iconv_handle = (iconv_t)-1;
}
if (iconv_handle == (iconv_t)-1)
iconv_handle = iconv_open(psz_native_charset, psz_encoding);
if (iconv_handle == (iconv_t)-1) {
msg_Warn(NULL, "couldn't convert from %s to %s (%m)", psz_encoding,
psz_native_charset);
return iconv_append_null(p_string, i_length);
}
/* converted strings can be up to six times larger */
i_out_length = i_length * 6;
p = psz_string = malloc(i_out_length);
if (iconv(iconv_handle, &p_string, &i_length, &p, &i_out_length) == -1) {
msg_Warn(NULL, "couldn't convert from %s to %s (%m)", psz_encoding,
psz_native_charset);
free(psz_string);
return iconv_append_null(p_string, i_length);
}
if (i_length)
msg_Warn(NULL, "partial conversion from %s to %s", psz_encoding,
psz_native_charset);
*p = '\0';
return psz_string;
#else
return iconv_append_null(p_string, i_length);
#endif
}
/*****************************************************************************
* HandlePAT
*****************************************************************************/
......@@ -1686,7 +1765,7 @@ static void HandlePMT( uint16_t i_pid, uint8_t *p_pmt, mtime_t i_dts )
UpdatePMT( i_sid );
pmt_print( p_pmt, msg_Dbg, NULL );
pmt_print( p_pmt, msg_Dbg, NULL, demux_Iconv, NULL );
}
out_pmt:
......@@ -1727,7 +1806,8 @@ static void HandleNIT( mtime_t i_dts )
psi_table_init( pp_next_nit_sections );
if ( b_display )
nit_table_print( pp_current_nit_sections, msg_Dbg, NULL );
nit_table_print( pp_current_nit_sections, msg_Dbg, NULL,
demux_Iconv, NULL );
out_nit:
;
......@@ -1842,7 +1922,8 @@ static void HandleSDT( mtime_t i_dts )
}
if ( b_change )
sdt_table_print( pp_current_sdt_sections, msg_Dbg, NULL );
sdt_table_print( pp_current_sdt_sections, msg_Dbg, NULL,
demux_Iconv, NULL );
out_sdt:
SendSDT( i_dts );
......
......@@ -26,6 +26,7 @@
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <pthread.h>
......@@ -39,6 +40,12 @@
#include "dvblast.h"
#include "version.h"
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#include <bitstream/dvb/si.h>
/*****************************************************************************
* Local declarations
*****************************************************************************/
......@@ -64,7 +71,8 @@ char *psz_modulation = NULL;
int b_budget_mode = 0;
int b_random_tsid = 0;
uint16_t i_network_id = 0xffff;
const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html";
uint8_t *p_network_name;
size_t i_network_name_size;
volatile int b_hup_received = 0;
int i_verbose = DEFAULT_VERBOSITY;
int i_syslog = 0;
......@@ -72,6 +80,8 @@ uint16_t i_src_port = DEFAULT_PORT;
in_addr_t i_src_addr = { 0 };
int b_src_rawudp = 0;
int i_asi_adapter = 0;
const char *psz_native_charset = "UTF-8";
const char *psz_dvb_charset = "ISO_8859-1";
static int b_udp_global = 0;
static int b_dvb_global = 0;
......@@ -347,7 +357,7 @@ static void DisplayVersion()
*****************************************************************************/
void usage()
{
msg_Raw( NULL, "Usage: dvblast [-q] [-c <config file>] [-r <remote socket>] [-t <ttl>] [-o <SSRC IP>] [-i <RT priority>] [-a <adapter>] [-n <frontend number>] [-S <diseqc>] [-f <frequency>|-D <src mcast>:<port>|-A <ASI adapter>] [-F <fec inner>] [-R <rolloff>] [-s <symbol rate>] [-v <0|13|18>] [-p] [-b <bandwidth>] [-m <modulation] [-u] [-U] [-L <latency>] [-E <retention>] [-d <dest IP:port>] [-C [-e] [-M <network name] [-N <network ID>]] [-T]" );
msg_Raw( NULL, "Usage: dvblast [-q] [-c <config file>] [-r <remote socket>] [-t <ttl>] [-o <SSRC IP>] [-i <RT priority>] [-a <adapter>] [-n <frontend number>] [-S <diseqc>] [-f <frequency>|-D <src mcast>:<port>|-A <ASI adapter>] [-F <fec inner>] [-R <rolloff>] [-s <symbol rate>] [-v <0|13|18>] [-p] [-b <bandwidth>] [-m <modulation] [-u] [-U] [-L <latency>] [-E <retention>] [-d <dest IP:port>] [-C [-e] [-M <network name] [-N <network ID>]] [-T] [-j <system charset>] [-J <DVB charset>]" );
msg_Raw( NULL, "Input:" );
msg_Raw( NULL, " -a --adapter <adapter>" );
......@@ -386,16 +396,21 @@ void usage()
msg_Raw( NULL, "Misc:" );
msg_Raw( NULL, " -h --help display this full help" );
msg_Raw( NULL, " -i --priority <RT pritority>" );
msg_Raw( NULL, " -i --priority <RT priority>" );
msg_Raw( NULL, " -j --system-charset character set used for printing messages (default UTF-8)" );
msg_Raw( NULL, " -J --dvb-charset character set used in output DVB tables (default ISO_8859-1)" );
msg_Raw( NULL, " -l --logger use syslog for logging messages instead of stderr" );
msg_Raw( NULL, " -q be quiet (less verbosity, repeat or use number for even quieter)" );
msg_Raw( NULL, " -r --remote-socket <remote socket>" );
msg_Raw( NULL, " -l --logger use syslog for logging messages instead of stderr" );
msg_Raw( NULL, " -V --version only display the version" );
exit(1);
}
int main( int i_argc, char **pp_argv )
{
const char *psz_network_name = "DVBlast - http://www.videolan.org/projects/dvblast.html";
char *p_network_name_tmp = NULL;
size_t i_network_name_tmp_size;
mtime_t i_poll_timeout = MAX_POLL_TIMEOUT;
struct sched_param param;
int i_error;
......@@ -438,13 +453,15 @@ int main( int i_argc, char **pp_argv )
{ "epg-passthrough", no_argument, NULL, 'e' },
{ "network-name", no_argument, NULL, 'M' },
{ "network-id", no_argument, NULL, 'N' },
{ "system-charset", required_argument, NULL, 'j' },
{ "dvb-charset", required_argument, NULL, 'J' },
{ "logger", no_argument, NULL, 'l' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ 0, 0, 0, 0}
{ 0, 0, 0, 0 }
};
while ( ( c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:F:R:s:S:v:pb:m:uUTL:E:d:D:A:lCeM:N:hV", long_options, NULL)) != -1 )
while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:f:F:R:s:S:v:pb:m:uUTL:E:d:D:A:lCeM:N:j:J:hV", long_options, NULL)) != -1 )
{
switch ( c )
{
......@@ -727,6 +744,14 @@ int main( int i_argc, char **pp_argv )
i_network_id = strtoul( optarg, NULL, 0 );
break;
case 'j':
psz_native_charset = optarg;
break;
case 'J':
psz_dvb_charset = optarg;
break;
case 'l':
b_enable_syslog = 1;
break;
......@@ -764,6 +789,43 @@ int main( int i_argc, char **pp_argv )
b_dvb_global = 1;
}
if ( strcasecmp( psz_native_charset, psz_dvb_charset ) )
{
#ifdef HAVE_ICONV
iconv_t iconv_system = iconv_open( psz_dvb_charset,
psz_native_charset );
if ( iconv_system != (iconv_t)-1 )
{
size_t i = strlen( psz_network_name );
char *p, *psz_string;
i_network_name_tmp_size = i * 6;
p = psz_string = malloc(i_network_name_tmp_size);
if ( iconv( iconv_system, (char **)&psz_network_name, &i, &p,
&i_network_name_tmp_size ) == -1 )
free( psz_string );
else
{
p_network_name_tmp = psz_string;
i_network_name_tmp_size = p - psz_string;
}
iconv_close( iconv_system );
}
#else
msg_Warn( NULL,
"unable to convert from %s to %s (iconv is not available)",
psz_native_charset, psz_dvb_charset );
#endif
}
if ( p_network_name_tmp == NULL )
{
p_network_name_tmp = strdup(psz_network_name);
i_network_name_tmp_size = strlen(psz_network_name);
}
p_network_name = dvb_string_set( (uint8_t *)p_network_name_tmp,
i_network_name_tmp_size, psz_dvb_charset,
&i_network_name_size );
free( p_network_name_tmp );
signal( SIGHUP, SigHandler );
srand( time(NULL) * getpid() );
......
......@@ -25,6 +25,9 @@
#include <netdb.h>
#include <sys/socket.h>
#define HAVE_CLOCK_NANOSLEEP
#define HAVE_ICONV
#define DEFAULT_PORT 3001
#define TS_SIZE 188
#define NB_BLOCKS 7
......@@ -134,7 +137,8 @@ extern char *psz_modulation;
extern int b_budget_mode;
extern int b_random_tsid;
extern uint16_t i_network_id;
extern const char *psz_network_name;
extern uint8_t *p_network_name;
extern size_t i_network_name_size;
extern mtime_t i_wallclock;
extern volatile int b_hup_received;
extern int i_comm_fd;
......@@ -142,6 +146,8 @@ extern uint16_t i_src_port;
extern in_addr_t i_src_addr;
extern int b_src_rawudp;
extern int i_asi_adapter;
extern const char *psz_native_charset;
extern const char *psz_dvb_charset;
extern void (*pf_Open)( void );
extern block_t * (*pf_Read)( mtime_t i_poll_timeout );
......@@ -191,6 +197,9 @@ void demux_Change( output_t *p_output, int i_tsid, uint16_t i_sid,
uint16_t *pi_pids, int i_nb_pids );
void demux_ResendCAPMTs( void );
bool demux_PIDIsSelected( uint16_t i_pid );
char *demux_Iconv(void *_unused, const char *psz_encoding,
char *p_string, size_t i_length);
output_t *output_Create( const char *psz_displayname, struct addrinfo *p_ai );
int output_Init( output_t *p_output, const char *psz_displayname,
......
......@@ -25,10 +25,11 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
......@@ -48,6 +49,7 @@
#include <bitstream/mpeg/psi.h>
#include <bitstream/dvb/ci.h>
#include <bitstream/dvb/si.h>
#include "dvblast.h"
#include "en50221.h"
......@@ -1090,7 +1092,7 @@ static bool HasCADescriptors( system_ids_t *p_ids, uint8_t *p_descs )
uint8_t i_tag = desc_get_tag( p_desc );
j++;
if ( i_tag == 0x9
if ( i_tag == 0x9 && desc09_validate( p_desc )
&& CheckSystemID( p_ids, desc09_get_sysid( p_desc ) ) )
return true;
}
......@@ -1113,7 +1115,7 @@ static void CopyCADescriptors( system_ids_t *p_ids, uint8_t i_cmd,
uint8_t i_tag = desc_get_tag( p_desc );
j++;
if ( i_tag == 0x9
if ( i_tag == 0x9 && desc09_validate( p_desc )
&& CheckSystemID( p_ids, desc09_get_sysid( p_desc ) ) )
{
uint8_t *p_info = capmti_get_info( p_infos, k );
......@@ -1657,7 +1659,6 @@ static void MMIDisplayReply( access_t *p_access, int i_session_id )
static char *MMIGetText( access_t *p_access, uint8_t **pp_apdu, int *pi_size )
{
int i_tag = APDUGetTag( *pp_apdu, *pi_size );
char *psz_text;
int l;
uint8_t *d;
......@@ -1669,14 +1670,11 @@ static char *MMIGetText( access_t *p_access, uint8_t **pp_apdu, int *pi_size )
}
d = APDUGetLength( *pp_apdu, &l );
psz_text = malloc( l + 1 );
strncpy( psz_text, (char *)d, l );
psz_text[l] = '\0';
*pp_apdu += l + 4;
*pi_size -= l + 4;
return psz_text;
return dvb_string_get( d, l, demux_Iconv, p_access );
}
/*****************************************************************************
......
......@@ -37,8 +37,6 @@
#include "dvblast.h"
#define HAVE_CLOCK_NANOSLEEP
/*****************************************************************************
* Local declarations
*****************************************************************************/
......
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