/*****************************************************************************
* ts.c: Transport Stream input module for VLC.
*****************************************************************************
- * Copyright (C) 2004-2005 VideoLAN (Centrale Réseaux) and its contributors
+ * Copyright (C) 2004-2005 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
/*****************************************************************************
* Preamble
*****************************************************************************/
+
+#include <vlc/vlc.h>
+
+#include <stdio.h>
#include <stdlib.h> /* malloc(), free() */
#include <ctype.h>
-#include <vlc/vlc.h>
#include <vlc/input.h>
#include "iso_lang.h"
#include "network.h"
+#include "charset.h"
#include "../mux/mpeg/csa.h"
# endif
#endif
+#undef TS_DEBUG
+
/* TODO:
* - XXX: do not mark options message to be translated, they are too osbcure for now ...
* - test it
* - ...
*/
+#define vlc_meta_Add(a,b,c) fprintf(stderr, "FIXME: TS demuxer meta is broken\n" )
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define PMT_TEXT N_("Extra PMT")
#define PMT_LONGTEXT N_( \
- "Allows a user to specify an extra pmt (pmt_pid=pid:stream_type[,...])" )
+ "Allows a user to specify an extra pmt (pmt_pid=pid:stream_type[,...])." )
#define PID_TEXT N_("Set id of ES to PID")
-#define PID_LONGTEXT N_("set id of es to pid")
+#define PID_LONGTEXT N_("Set the internal ID of each elementary stream" \
+ " handled by VLC to the same value as the PID in" \
+ " the TS stream, instead of 1, 2, 3, etc. Useful to" \
+ " do \'#duplicate{..., select=\"es=<pid>\"}\'.")
#define TSOUT_TEXT N_("Fast udp streaming")
#define TSOUT_LONGTEXT N_( \
- "Sends TS to specific ip:port by udp (you must know what you are doing)")
+ "Sends TS to specific ip:port by udp (you must know what you are doing).")
#define MTUOUT_TEXT N_("MTU for out mode")
-#define MTUOUT_LONGTEXT N_("MTU for out mode")
+#define MTUOUT_LONGTEXT N_("MTU for out mode.")
#define CSA_TEXT N_("CSA ck")
-#define CSA_LONGTEXT N_("CSA ck")
+#define CSA_LONGTEXT N_("Control word for the CSA encryption algorithm")
#define SILENT_TEXT N_("Silent mode")
-#define SILENT_LONGTEXT N_("do not complain on encrypted PES")
+#define SILENT_LONGTEXT N_("Do not complain on encrypted PES.")
#define CAPMT_SYSID_TEXT N_("CAPMT System ID")
-#define CAPMT_SYSID_LONGTEXT N_("only forward descriptors from this SysID to the CAM")
+#define CAPMT_SYSID_LONGTEXT N_("Only forward descriptors from this SysID to the CAM.")
#define CPKT_TEXT N_("Packet size in bytes to decrypt")
#define CPKT_LONGTEXT N_("Specify the size of the TS packet to decrypt. " \
"decrypting. " )
#define TSDUMP_TEXT N_("Filename of dump")
-#define TSDUMP_LONGTEXT N_("Specify a filename where to dump the TS in")
+#define TSDUMP_LONGTEXT N_("Specify a filename where to dump the TS in.")
#define APPEND_TEXT N_("Append")
#define APPEND_LONGTEXT N_( \
add_integer( "ts-out-mtu", 1500, NULL, MTUOUT_TEXT,
MTUOUT_LONGTEXT, VLC_TRUE );
add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, VLC_TRUE );
- add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, VLC_TRUE );
+ add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, VLC_TRUE );
add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, VLC_TRUE );
add_file( "ts-dump-file", NULL, NULL, TSDUMP_TEXT, TSDUMP_LONGTEXT, VLC_FALSE );
FILE *p_file; /* filehandle */
uint64_t i_write; /* bytes written */
vlc_bool_t b_file_out; /* dump mode enabled */
-
+
/* */
vlc_bool_t b_meta;
};
#define TS_PACKET_SIZE_192 192
#define TS_PACKET_SIZE_204 204
#define TS_PACKET_SIZE_MAX 204
+#define TS_TOPFIELD_HEADER 1320
/*****************************************************************************
* Open
ts_pid_t *pat;
char *psz_mode;
vlc_bool_t b_append;
+ vlc_bool_t b_topfield = VLC_FALSE;
vlc_value_t val;
if( stream_Peek( p_demux->s, &p_peek, TS_PACKET_SIZE_MAX ) <
TS_PACKET_SIZE_MAX ) return VLC_EGENERIC;
+ if( p_peek[0] == 'T' && p_peek[1] == 'F' &&
+ p_peek[2] == 'r' && p_peek[3] == 'c' )
+ {
+ b_topfield = VLC_TRUE;
+ msg_Dbg( p_demux, "this is a topfield file" );
+ }
+
/* Search first sync byte */
for( i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ )
{
if( p_peek[i_sync] == 0x47 ) break;
}
- if( i_sync >= TS_PACKET_SIZE_MAX )
+ if( i_sync >= TS_PACKET_SIZE_MAX && !b_topfield )
{
if( strcmp( p_demux->psz_demux, "ts" ) ) return VLC_EGENERIC;
msg_Warn( p_demux, "this does not look like a TS stream, continuing" );
}
- /* Check next 3 sync bytes */
- i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1;
+ if( b_topfield )
+ {
+ /* Read the entire Topfield header */
+ i_peek = TS_TOPFIELD_HEADER;
+ }
+ else
+ {
+ /* Check next 3 sync bytes */
+ i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1;
+ }
+
if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek )
{
msg_Err( p_demux, "cannot peek" );
{
i_packet_size = TS_PACKET_SIZE_188;
}
+ else if( b_topfield )
+ {
+ i_packet_size = TS_PACKET_SIZE_188;
+#if 0
+ /* I used the TF5000PVR 2004 Firmware .doc header documentation,
+ * http://www.i-topfield.com/data/product/firmware/Structure%20of%20Recorded%20File%20in%20TF5000PVR%20(Feb%2021%202004).doc
+ * but after the filename the offsets seem to be incorrect. - DJ */
+ int i_duration, i_name;
+ char *psz_name = malloc(25);
+ char *psz_event_name;
+ char *psz_event_text = malloc(130);
+ char *psz_ext_text = malloc(1025);
+
+ // 2 bytes version Uimsbf (4,5)
+ // 2 bytes reserved (6,7)
+ // 2 bytes duration in minutes Uimsbf (8,9(
+ i_duration = (int) (p_peek[8] << 8) | p_peek[9];
+ msg_Dbg( p_demux, "Topfield recording length: +/- %d minutes", i_duration);
+ // 2 bytes service number in channel list (10, 11)
+ // 2 bytes service type Bslbf 0=TV 1=Radio Bslb (12, 13)
+ // 4 bytes of reserved + tuner info (14,15,16,17)
+ // 2 bytes of Service ID Bslbf (18,19)
+ // 2 bytes of PMT PID Uimsbf (20,21)
+ // 2 bytes of PCR PID Uimsbf (22,23)
+ // 2 bytes of Video PID Uimsbf (24,25)
+ // 2 bytes of Audio PID Uimsbf (26,27)
+ // 24 bytes filename Bslbf
+ memcpy( psz_name, &p_peek[28], 24 );
+ psz_name[24] = '\0';
+ msg_Dbg( p_demux, "recordingname=%s", psz_name );
+ // 1 byte of sat index Uimsbf (52)
+ // 3 bytes (1 bit of polarity Bslbf +23 bits reserved)
+ // 4 bytes of freq. Uimsbf (56,57,58,59)
+ // 2 bytes of symbol rate Uimsbf (60,61)
+ // 2 bytes of TS stream ID Uimsbf (62,63)
+ // 4 bytes reserved
+ // 2 bytes reserved
+ // 2 bytes duration Uimsbf (70,71)
+ //i_duration = (int) (p_peek[70] << 8) | p_peek[71];
+ //msg_Dbg( p_demux, "Topfield 2nd duration field: +/- %d minutes", i_duration);
+ // 4 bytes EventID Uimsbf (72-75)
+ // 8 bytes of Start and End time info (76-83)
+ // 1 byte reserved (84)
+ // 1 byte event name length Uimsbf (89)
+ i_name = (int)(p_peek[89]&~0x81);
+ msg_Dbg( p_demux, "event name length = %d", i_name);
+ psz_event_name = malloc( i_name+1 );
+ // 1 byte parental rating (90)
+ // 129 bytes of event text
+ memcpy( psz_event_name, &p_peek[91], i_name );
+ psz_event_name[i_name] = '\0';
+ memcpy( psz_event_text, &p_peek[91+i_name], 129-i_name );
+ psz_event_text[129-i_name] = '\0';
+ msg_Dbg( p_demux, "event name=%s", psz_event_name );
+ msg_Dbg( p_demux, "event text=%s", psz_event_text );
+ // 12 bytes reserved (220)
+ // 6 bytes reserved
+ // 2 bytes Event Text Length Uimsbf
+ // 4 bytes EventID Uimsbf
+ // FIXME We just have 613 bytes. not enough for this entire text
+ // 1024 bytes Extended Event Text Bslbf
+ memcpy( psz_ext_text, p_peek+372, 1024 );
+ psz_ext_text[1024] = '\0';
+ msg_Dbg( p_demux, "extended event text=%s", psz_ext_text );
+ // 52 bytes reserved Bslbf
+#endif
+ }
else
{
msg_Warn( p_demux, "TS module discarded (lost sync)" );
msg_Info( p_demux, "dumping raw stream to standard output" );
p_sys->p_file = stdout;
}
- else if( ( p_sys->p_file = fopen( p_sys->psz_file, psz_mode ) ) == NULL )
+ else if( ( p_sys->p_file = utf8_fopen( p_sys->psz_file, psz_mode ) ) == NULL )
{
msg_Err( p_demux, "cannot create `%s' for writing", p_sys->psz_file );
p_sys->b_file_out = VLC_FALSE;
i_data = stream_Read( p_demux->s, p_sys->buffer, i_bufsize );
if( (i_data <= 0) && (i_data < p_sys->i_packet_size) )
{
- msg_Dbg( p_demux, "Error reading malformed packets" );
+ msg_Dbg( p_demux, "error reading malformed packets" );
return i_data;
}
i_diff = ( i_cc - p_pid->i_cc )&0x0f;
if( b_payload && i_diff == 1 )
{
- p_pid->i_cc++;
+ p_pid->i_cc = ( p_pid->i_cc + 1 ) & 0xf;
}
else
{
i_diff = ( i_cc - pid->i_cc )&0x0f;
if( b_payload && i_diff == 1 )
{
- pid->i_cc++;
+ pid->i_cc = ( pid->i_cc + 1 ) & 0xf;
}
else
{
case 0x92: /* DVD_SPU vls (sub) */
es_format_Init( fmt, SPU_ES, VLC_FOURCC( 's', 'p', 'u', 'b' ) );
break;
- case 0x93: /* LPCM vls (audio) */
- es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'l', 'p', 'c', 'b' ) );
- break;
+
case 0x94: /* SDDS (audio) */
es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 's', 'd', 'd', 'b' ) );
break;
p_iod = malloc( sizeof( iod_descriptor_t ) );
memset( p_iod, 0, sizeof( iod_descriptor_t ) );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n************ IOD ************" );
#endif
for( i = 0; i < 255; i++ )
byte1 = IODGetByte( &i_data, &p_data );
byte2 = IODGetByte( &i_data, &p_data );
byte3 = IODGetByte( &i_data, &p_data );
- if( byte2 == 0x02 ) //old vlc's buggy implementation of the IOD_descriptor
+ if( byte2 == 0x02 ) //old vlc's buggy implementation of the IOD_descriptor
{
p_iod->i_iod_label_scope = 0x11;
p_iod->i_iod_label = byte1;
i_iod_tag = byte2;
}
- else //correct implementation of the IOD_descriptor
+ else //correct implementation of the IOD_descriptor
{
p_iod->i_iod_label_scope = byte1;
p_iod->i_iod_label = byte2;
i_iod_tag = byte3;
}
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* iod_label:%d", p_iod->i_iod_label );
fprintf( stderr, "\n* ===========" );
fprintf( stderr, "\n* tag:0x%x", i_iod_tag );
#endif
if( i_iod_tag != 0x02 )
{
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n ERR: tag %02x != 0x02", i_iod_tag );
#endif
return p_iod;
}
i_iod_length = IODDescriptorLength( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* length:%d", i_iod_length );
#endif
if( i_iod_length > i_data )
i_flags = IODGetByte( &i_data, &p_data );
p_iod->i_od_id |= i_flags >> 6;
b_url = ( i_flags >> 5 )&0x01;
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* od_id:%d", p_iod->i_od_id );
fprintf( stderr, "\n* url flag:%d", b_url );
fprintf( stderr, "\n* includeInlineProfileLevel flag:%d", ( i_flags >> 4 )&0x01 );
if( b_url )
{
p_iod->psz_url = IODGetURL( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* url string:%s", p_iod->psz_url );
fprintf( stderr, "\n*****************************\n" );
#endif
p_iod->i_audioProfileLevelIndication = IODGetByte( &i_data, &p_data );
p_iod->i_visualProfileLevelIndication = IODGetByte( &i_data, &p_data );
p_iod->i_graphicsProfileLevelIndication = IODGetByte( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* ODProfileLevelIndication:%d", p_iod->i_ODProfileLevelIndication );
fprintf( stderr, "\n* sceneProfileLevelIndication:%d", p_iod->i_sceneProfileLevelIndication );
fprintf( stderr, "\n* audioProfileLevelIndication:%d", p_iod->i_audioProfileLevelIndication );
{
#define es_descr p_iod->es_descr[i_es_index]
int i_decoderConfigDescr_length;
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* - ES_Descriptor length:%d", i_length );
#endif
es_descr.b_ok = 1;
b_url = ( i_flags >> 6 )&0x01;
es_descr.b_OCRStreamFlag = ( i_flags >> 5 )&0x01;
es_descr.i_streamPriority = i_flags & 0x1f;
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* * streamDependenceFlag:%d", es_descr.b_streamDependenceFlag );
fprintf( stderr, "\n* * OCRStreamFlag:%d", es_descr.b_OCRStreamFlag );
fprintf( stderr, "\n* * streamPriority:%d", es_descr.i_streamPriority );
if( es_descr.b_streamDependenceFlag )
{
es_descr.i_dependOn_es_id = IODGetWord( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* * dependOn_es_id:%d", es_descr.i_dependOn_es_id );
#endif
}
if( b_url )
{
es_descr.psz_url = IODGetURL( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* url string:%s", es_descr.psz_url );
#endif
}
if( es_descr.b_OCRStreamFlag )
{
es_descr.i_OCR_es_id = IODGetWord( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* * OCR_es_id:%d", es_descr.i_OCR_es_id );
#endif
}
if( IODGetByte( &i_data, &p_data ) != 0x04 )
{
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* ERR missing DecoderConfigDescr" );
#endif
es_descr.b_ok = 0;
break;
}
i_decoderConfigDescr_length = IODDescriptorLength( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* - DecoderConfigDesc length:%d", i_decoderConfigDescr_length );
#endif
#define dec_descr es_descr.dec_descr
dec_descr.i_bufferSizeDB = IODGet3Bytes( &i_data, &p_data );
dec_descr.i_maxBitrate = IODGetDWord( &i_data, &p_data );
dec_descr.i_avgBitrate = IODGetDWord( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* * objectTypeIndication:0x%x", dec_descr.i_objectTypeIndication );
fprintf( stderr, "\n* * streamType:0x%x", dec_descr.i_streamType );
fprintf( stderr, "\n* * upStream:%d", dec_descr.b_upStream );
if( IODGetByte( &i_data, &p_data ) != 0x06 )
{
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* ERR missing SLConfigDescr" );
#endif
es_descr.b_ok = 0;
break;
}
i_SLConfigDescr_length = IODDescriptorLength( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* - SLConfigDescr length:%d", i_SLConfigDescr_length );
#endif
i_predefined = IODGetByte( &i_data, &p_data );
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* * i_predefined:0x%x", i_predefined );
#endif
switch( i_predefined )
}
break;
default:
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* ERR unsupported SLConfigDescr predefined" );
#endif
es_descr.b_ok = 0;
#undef sl_descr
#undef es_descr
default:
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n* - OD tag:0x%x length:%d (Unsupported)", i_tag, i_length );
#endif
break;
i_data = i_data_sav - i_length;
i_es_index++;
}
-#ifdef DEBUG
+#ifdef TS_DEBUG
fprintf( stderr, "\n*****************************\n" );
#endif
return p_iod;
{
if( p_dr->i_tag == 0x48 )
{
+#if 0
static const char *psz_type[0x11] = {
"Reserved",
"Digital television service",
"RCS FLS (see EN 301 790 [35])",
"DVB MHP service"
};
+#endif
dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
char str1[257];
char str2[257];
msg_Dbg( p_demux, " - type=%d provider=%s name=%s",
pD->i_service_type, str1, str2 );
- vlc_meta_Add( p_meta, "Name", str2 );
- vlc_meta_Add( p_meta, "Provider", str1 );
+ vlc_meta_SetTitle( p_meta, str2 );
+ vlc_meta_SetPublisher( p_meta, str1 );
if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 )
vlc_meta_Add( p_meta, "Type", psz_type[pD->i_service_type] );
}
else
vlc_meta_Add( p_meta, "Status", "Unknown" );
-
es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
p_srv->i_service_id, p_meta );
vlc_meta_Delete( p_meta );
* caracters encoding, for now lets skip it */
if( psz[0] >= 0x20 )
return;
- if( ( i_len = strlen( psz ) ) > 0 )
+ if( ( i_len = strlen( (char *) psz ) ) > 0 )
memmove( &psz[0], &psz[1], i_len ); /* Copy the \0 too */
}
static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
memcpy( psz_text, pE->i_text, pE->i_text_length );
psz_text[pE->i_text_length] = '\0';
- EITEventFixString(psz_name);
- EITEventFixString(psz_text);
+ EITEventFixString((unsigned char *)&psz_name);
+ EITEventFixString((unsigned char *)&psz_text);
msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'",
pE->i_iso_639_code, psz_name, psz_text );
}
memcpy( str1, pE->i_item_description[i],
pE->i_item_description_length[i] );
str1[pE->i_item_description_length[i]] = '\0';
- EITEventFixString(str1);
+ EITEventFixString((unsigned char *)&str1);
memcpy( str2, pE->i_item[i],
pE->i_item_length[i] );
str2[pE->i_item_length[i]] = '\0';
- EITEventFixString(str2);
+ EITEventFixString((unsigned char *)&str2);
msg_Dbg( p_demux, " - desc='%s' item='%s'", str1, str2 );
psz_extra = realloc( psz_extra,
memcpy( str1, pE->i_text, pE->i_text_length );
str1[pE->i_text_length] = '\0';
- EITEventFixString(str1);
+ EITEventFixString((unsigned char *)&str1);
msg_Dbg( p_demux, " - text='%s'", str1 );
psz_extra = realloc( psz_extra,
if( p_evt->i_running_status == 0x04 )
{
- vlc_meta_Add( p_meta, VLC_META_NOW_PLAYING, psz_name );
+ vlc_meta_SetNowPlaying( p_meta, psz_name );
b_event_active = VLC_TRUE;
}
}
if( !b_event_active )
- vlc_meta_Add( p_meta, VLC_META_NOW_PLAYING, "" );
+ vlc_meta_SetNowPlaying( p_meta, "" );
es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
p_eit->i_service_id, p_meta );
vlc_meta_Delete( p_meta );
{
dvbpsi_stream_identifier_dr_t *si;
si = dvbpsi_DecodeStreamIdentifierDr( p_dr );
-
+
msg_Dbg( p_demux, " * Stream Component Identifier: %d", si->i_component_tag );
}
#endif
if( p_decoded )
{
+#if DR_0A_API_VER >= 2
+ pid->es->fmt.psz_language = malloc( 4 );
+ memcpy( pid->es->fmt.psz_language,
+ p_decoded->code[0].iso_639_code, 3 );
+ pid->es->fmt.psz_language[3] = 0;
+ msg_Dbg( p_demux, "found language: %s", pid->es->fmt.psz_language);
+ switch( p_decoded->code[0].i_audio_type ) {
+ case 0:
+ pid->es->fmt.psz_description = NULL;
+ break;
+ case 1:
+ pid->es->fmt.psz_description =
+ strdup(_("clean effects"));
+ break;
+ case 2:
+ pid->es->fmt.psz_description =
+ strdup(_("hearing impaired"));
+ break;
+ case 3:
+ pid->es->fmt.psz_description =
+ strdup(_("visual impaired commentary"));
+ break;
+ default:
+ msg_Dbg( p_demux, "unknown audio type: %d",
+ p_decoded->code[0].i_audio_type);
+ pid->es->fmt.psz_description = NULL;
+ break;
+ }
+ pid->es->fmt.i_extra_languages = p_decoded->i_code_count-1;
+ pid->es->fmt.p_extra_languages =
+ malloc( sizeof(*pid->es->fmt.p_extra_languages) *
+ pid->es->fmt.i_extra_languages );
+ for( i = 0; i < pid->es->fmt.i_extra_languages; i++ ) {
+ msg_Dbg( p_demux, "bang" );
+ pid->es->fmt.p_extra_languages[i].psz_language =
+ malloc(4);
+ memcpy(pid->es->fmt.p_extra_languages[i].psz_language,
+ p_decoded->code[i+1].iso_639_code, 3 );
+ pid->es->fmt.p_extra_languages[i].psz_language[3] = '\0';
+ switch( p_decoded->code[i].i_audio_type ) {
+ case 0:
+ pid->es->fmt.p_extra_languages[i].psz_description =
+ NULL;
+ break;
+ case 1:
+ pid->es->fmt.p_extra_languages[i].psz_description =
+ strdup(_("clean effects"));
+ break;
+ case 2:
+ pid->es->fmt.p_extra_languages[i].psz_description =
+ strdup(_("hearing impaired"));
+ break;
+ case 3:
+ pid->es->fmt.p_extra_languages[i].psz_description =
+ strdup(_("visual impaired commentary"));
+ break;
+ default:
+ msg_Dbg( p_demux, "unknown audio type: %d",
+ p_decoded->code[i].i_audio_type);
+ pid->es->fmt.psz_description = NULL;
+ break;
+ }
+
+ }
+#else
pid->es->fmt.psz_language = malloc( 4 );
memcpy( pid->es->fmt.psz_language,
p_decoded->i_iso_639_code, 3 );
pid->es->fmt.psz_language[3] = 0;
+#endif
}
}
}