Commit 14106cb1 authored by Laurent Aimar's avatar Laurent Aimar

* vlc_meta.h: added a few const

 * es_out: added ES_OUT_SET_GROUP_META to add on the fly meta for a program
 (it's not yet really clean).
 * demux/ts: parse SI tables of DVB (channel names + events), it needs last
 libdvbpsi svn (set TS_USE_DVB_SI to 1 in modules/demux/ts.c to use it).
parent 652b8fc0
......@@ -78,6 +78,8 @@ enum es_out_query_e
/* Allow preroll of data (data with dts/pts < i_pts for one ES will be decoded but not displayed */
ES_OUT_SET_NEXT_DISPLAY_TIME, /* arg1=es_out_id_t* arg2=int64_t i_pts(microsecond) */
/* Set meta data for group (dynamic) */
ES_OUT_SET_GROUP_META, /* arg1=int i_group arg2=vlc_meta_t */
};
struct es_out_t
......
......@@ -108,7 +108,8 @@ static inline void vlc_meta_Delete( vlc_meta_t *m )
free( m );
}
static inline void vlc_meta_Add( vlc_meta_t *m, char *name, char *value )
static inline void vlc_meta_Add( vlc_meta_t *m,
const char *name, const char *value )
{
m->name = (char**)realloc( m->name, sizeof(char*) * ( m->i_meta + 1 ) );
m->name[m->i_meta] = strdup( name );
......@@ -156,7 +157,7 @@ static inline void vlc_meta_Merge( vlc_meta_t *dst, vlc_meta_t *src )
}
}
static inline char *vlc_meta_GetValue( vlc_meta_t *m, char *name )
static inline char *vlc_meta_GetValue( vlc_meta_t *m, const char *name )
{
int i;
......
......@@ -34,23 +34,35 @@
#include "../mux/mpeg/csa.h"
#define TS_USE_DVB_SI 0
/* Undef it to disable sdt/eit parsing */
#define TS_USE_DVB_SI 0
/* Include dvbpsi headers */
#ifdef HAVE_DVBPSI_DR_H
# include <dvbpsi/dvbpsi.h>
# include <dvbpsi/demux.h>
# include <dvbpsi/descriptor.h>
# include <dvbpsi/pat.h>
# include <dvbpsi/pmt.h>
# include <dvbpsi/sdt.h>
# include <dvbpsi/eit.h>
# include <dvbpsi/dr.h>
# include <dvbpsi/psi.h>
#else
# include "dvbpsi.h"
# include "demux.h"
# include "descriptor.h"
# include "tables/pat.h"
# include "tables/pmt.h"
# include "tables/sdt.h"
# include "tables/eit.h"
# include "descriptors/dr.h"
# include "psi.h"
#endif
/* TODO:
* - XXX: do not mark options message to be translated, they are too osbcure for now ...
* - test it
......@@ -206,14 +218,27 @@ typedef struct
typedef struct
{
/* for special PAT case */
dvbpsi_handle handle;
demux_t *p_demux; /* Hack */
int i_table_id;
int i_version;
int i_service_id;
} ts_eit_psi_t;
typedef struct
{
/* for special PAT/SDT case */
dvbpsi_handle handle; /* PAT/SDT/EIT */
int i_pat_version;
int i_sdt_version;
/* For PMT */
int i_prg;
ts_prg_psi_t **prg;
/* For EIT */
int i_eit;
ts_eit_psi_t **eit;
} ts_psi_t;
typedef struct
......@@ -280,6 +305,9 @@ struct demux_sys_t
vlc_bool_t b_dvb_control;
int i_dvb_program;
vlc_list_t *p_programs_list;
/* */
vlc_bool_t b_meta;
};
static int Demux ( demux_t *p_demux );
......@@ -292,6 +320,9 @@ static int PIDFillFormat( ts_pid_t *pid, int i_stream_type );
static void PATCallBack( demux_t *, dvbpsi_pat_t * );
static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt );
static void PSINewTableCallBack( demux_t *, dvbpsi_handle,
uint8_t i_table_id, uint16_t i_extension );
static inline int PIDGet( block_t *p )
{
......@@ -382,6 +413,11 @@ static int Open( vlc_object_t *p_this )
memset( p_sys, 0, sizeof( demux_sys_t ) );
/* Init p_sys field */
#if TS_USE_DVB_SI
p_sys->b_meta = VLC_TRUE;
#else
p_sys->b_meta = VLC_TRUE;
#endif
p_sys->b_dvb_control = VLC_TRUE;
p_sys->i_dvb_program = 0;
for( i = 0; i < 8192; i++ )
......@@ -402,6 +438,27 @@ static int Open( vlc_object_t *p_this )
PIDInit( pat, VLC_TRUE, NULL );
pat->psi->handle = dvbpsi_AttachPAT( (dvbpsi_pat_callback)PATCallBack,
p_demux );
#if TS_USE_DVB_SI
if( p_sys->b_meta )
{
ts_pid_t *sdt = &p_sys->pid[0x11];
ts_pid_t *eit = &p_sys->pid[0x12];
PIDInit( sdt, VLC_TRUE, NULL );
sdt->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,
p_demux );
PIDInit( eit, VLC_TRUE, NULL );
eit->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,
p_demux );
if( p_sys->b_dvb_control )
{
stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
ACCESS_SET_PRIVATE_ID_STATE, 0x11, VLC_TRUE );
stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
ACCESS_SET_PRIVATE_ID_STATE, 0x12, VLC_TRUE );
}
}
#endif
/* Init PMT array */
p_sys->i_pmt = 0;
......@@ -594,6 +651,7 @@ static void Close( vlc_object_t *p_this )
if( pid->b_valid && pid->psi )
{
int j;
switch( pid->i_pid )
{
case 0: /* PAT */
......@@ -603,6 +661,20 @@ static void Close( vlc_object_t *p_this )
case 1: /* CAT */
free( pid->psi );
break;
case 0x11: /* SDT */
dvbpsi_DetachDemux( pid->psi->handle );
free( pid->psi );
break;
case 0x12: /* EIT */
dvbpsi_DetachDemux( pid->psi->handle );
for( j = 0; j < pid->psi->i_eit; j++ )
{
free( pid->psi->eit[j] );
}
if( pid->psi->i_eit )
free( pid->psi->eit );
free( pid->psi );
break;
default:
PIDClean( p_demux->out, pid );
break;
......@@ -728,7 +800,7 @@ static int Demux( demux_t *p_demux )
{
if( p_pid->psi )
{
if( p_pid->i_pid == 0 )
if( p_pid->i_pid == 0 || p_pid->i_pid == 0x11 || p_pid->i_pid == 0x12 )
{
dvbpsi_PushPacket( p_pid->psi->handle, p_pkt->p_buffer );
}
......@@ -990,11 +1062,14 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner )
if( !b_old_valid )
{
pid->psi = malloc( sizeof( ts_psi_t ) );
pid->psi->handle= NULL;
pid->psi->i_prg = 0;
pid->psi->prg = NULL;
pid->psi->handle= NULL;
pid->psi->i_eit = 0;
pid->psi->eit = NULL;
}
pid->psi->i_pat_version = -1;
pid->psi->i_sdt_version = -1;
if( p_owner )
{
ts_prg_psi_t *prg = malloc( sizeof( ts_prg_psi_t ) );
......@@ -1949,6 +2024,285 @@ static vlc_bool_t DVBProgramIsSelected( demux_t *p_demux, uint16_t i_pgrm )
return VLC_FALSE;
}
#if TS_USE_DVB_SI
static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
{
demux_sys_t *p_sys = p_demux->p_sys;
ts_pid_t *sdt = &p_sys->pid[0x11];
dvbpsi_sdt_service_t *p_srv;
msg_Dbg( p_demux, "SDTCallBack called" );
if( sdt->psi->i_sdt_version != -1 &&
( !p_sdt->b_current_next ||
p_sdt->i_version == sdt->psi->i_sdt_version ) )
{
dvbpsi_DeleteSDT( p_sdt );
return;
}
msg_Dbg( p_demux, "new SDT ts_id=%d version=%d current_next=%d network_id=%d",
p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next, p_sdt->i_network_id );
for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
{
vlc_meta_t *p_meta = vlc_meta_New();
dvbpsi_descriptor_t *p_dr;
msg_Dbg( p_demux, " * service id=%d eit schedule=%d present=%d runing=%d free_ca=%d",
p_srv->i_service_id,
p_srv->b_eit_schedule, p_srv->b_eit_present, p_srv->i_running_status,
p_srv->b_free_ca );
for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
{
if( p_dr->i_tag == 0x48 )
{
static const char *psz_type[0x11] = {
"Reserved",
"Digital television service",
"Digital radio sound service",
"Teletext service",
"NVOD reference service",
"NVOD time-shifted service",
"Mosaic service",
"PAL coded signal",
"SECAM coded signal",
"D/D2-MAC",
"FM Radio",
"NTSC coded signal",
"Data broadcast service",
"Reserved for Common Interface Usage",
"RCS Map (see EN 301 790 [35])",
"RCS FLS (see EN 301 790 [35])",
"DVB MHP service"
};
dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
char str1[257];
char str2[257];
memcpy( str1, pD->i_service_provider_name, pD->i_service_provider_name_length );
str1[pD->i_service_provider_name_length] = '\0';
memcpy( str2, pD->i_service_name, pD->i_service_name_length );
str2[pD->i_service_name_length] = '\0';
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 );
if( pD->i_service_type >= 0x01 && pD->i_service_type <= 0x10 )
vlc_meta_Add( p_meta, "Type", psz_type[pD->i_service_type] );
}
}
if( p_srv->i_running_status == 0x01 )
vlc_meta_Add( p_meta, "Status", "Not running" );
else if( p_srv->i_running_status == 0x02 )
vlc_meta_Add( p_meta, "Status", "Starts in a few seconds" );
else if( p_srv->i_running_status == 0x03 )
vlc_meta_Add( p_meta, "Status", "Pausing" );
else if( p_srv->i_running_status == 0x04 )
vlc_meta_Add( p_meta, "Status", "Running" );
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 );
}
sdt->psi->i_sdt_version = p_sdt->i_version;
dvbpsi_DeleteSDT( p_sdt );
}
#if 0
static void DecodeMjd( int i_mjd, int *p_y, int *p_m, int *p_d )
{
int yp = (int)( ( (double)i_mjd - 15078.2)/365.25 );
int mp = (int)( ((double)i_mjd - 14956.1 - (int)(yp * 365.25)) / 30.6001 );
*p_d = i_mjd - 14956 - (int)(yp*365.25) - (int)(mp*30.6001);
if( mp == 14 || mp == 15 )
{
*p_y = yp + 1;
*p_m = mp - 1 + 12;
}
else
{
*p_y = yp;
*p_m = mp - 1;
}
}
#endif
static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
{
demux_t *p_demux = psi->p_demux;
dvbpsi_eit_event_t *p_evt;
msg_Dbg( p_demux, "EITCallBack called" );
if( psi->i_version != -1 &&
( !p_eit->b_current_next || psi->i_version == p_eit->i_version ) )
{
dvbpsi_DeleteEIT( p_eit );
return;
}
msg_Dbg( p_demux, "new EIT service_id=%d version=%d current_next=%d ts_id=%d network_id=%d"
"segment_last_section_number=%d last_table_id=%d",
p_eit->i_service_id, p_eit->i_version, p_eit->b_current_next, p_eit->i_ts_id,
p_eit->i_network_id, p_eit->i_segment_last_section_number, p_eit->i_last_table_id );
for( p_evt = p_eit->p_first_event; p_evt; p_evt = p_evt->p_next )
{
vlc_meta_t *p_meta = vlc_meta_New();
dvbpsi_descriptor_t *p_dr;
char *psz_cat = malloc( strlen("Event")+10 );
char psz_start[15];
char psz_duration[15];
char psz_name[256];
char psz_text[256];
char *psz_extra = strdup("");
char *psz_value;
sprintf( psz_cat, "Event %d", p_evt->i_event_id );
sprintf( psz_start, "%d%d:%d%d:%d%d",
(int)(p_evt->i_start_time >> 20)&0xf,
(int)(p_evt->i_start_time >> 16)&0xf,
(int)(p_evt->i_start_time >> 12)&0xf,
(int)(p_evt->i_start_time >> 8)&0xf,
(int)(p_evt->i_start_time >> 4)&0xf,
(int)(p_evt->i_start_time )&0xf );
sprintf( psz_duration, "%d%d:%d%d:%d%d",
(p_evt->i_duration >> 20)&0xf, (p_evt->i_duration >> 16)&0xf,
(p_evt->i_duration >> 12)&0xf, (p_evt->i_duration >> 8)&0xf,
(p_evt->i_duration >> 4)&0xf, (p_evt->i_duration )&0xf );
psz_name[0] = psz_text[0] = '\0';
msg_Dbg( p_demux, " * event id=%d start_time:mjd=%d %s duration=%s "
"running=%d free_ca=%d",
p_evt->i_event_id,
(int)(p_evt->i_start_time >> 24),
psz_start, psz_duration,
p_evt->i_running_status, p_evt->b_free_ca );
for( p_dr = p_evt->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
{
if( p_dr->i_tag == 0x4d )
{
dvbpsi_short_event_dr_t *pE = dvbpsi_DecodeShortEventDr( p_dr );
if( pE )
{
memcpy( psz_name, pE->i_event_name, pE->i_event_name_length);
psz_name[pE->i_event_name_length] = '\0';
memcpy( psz_text, pE->i_text, pE->i_text_length );
psz_text[pE->i_text_length] = '\0';
msg_Dbg( p_demux, " - short event lang=%3.3s '%s' : '%s'",
pE->i_iso_639_code, psz_name, psz_text );
}
}
else if( p_dr->i_tag == 0x4e )
{
dvbpsi_extended_event_dr_t *pE = dvbpsi_DecodeExtendedEventDr( p_dr );
char str1[257];
char str2[257];
if( pE )
{
int i;
msg_Dbg( p_demux, " - extended event lang=%3.3s",
pE->i_iso_639_code );
for( i = 0; i < pE->i_entry_count; i++ )
{
memcpy( str1, pE->i_item_description[i],
pE->i_item_description_length[i] );
str1[pE->i_item_description_length[i]] = '\0';
memcpy( str1, pE->i_item[i],
pE->i_item_length[i] );
str2[pE->i_item_length[i]] = '\0';
msg_Dbg( p_demux, " - desc='%s' item='%s'", str1, str2 );
psz_extra = realloc( psz_extra,
strlen(psz_extra) +
strlen(str1) +strlen(str2) + 1 + 3 );
strcat( psz_extra, str1 );
strcat( psz_extra, "(" );
strcat( psz_extra, str2 );
strcat( psz_extra, ") " );
}
memcpy( str1, pE->i_text, pE->i_text_length );
str1[pE->i_text_length] = '\0';
msg_Dbg( p_demux, " - text='%s'", str1 );
psz_extra = realloc( psz_extra,
strlen(psz_extra) + strlen(str1) + 2 );
strcat( psz_extra, str1 );
strcat( psz_extra, " " );
}
}
else
{
msg_Dbg( p_demux, " - tag=0x%x(%d)", p_dr->i_tag, p_dr->i_tag );
}
}
asprintf( &psz_value, "%s: %s (+%s) %s (%s)",
psz_start,
psz_name,
psz_duration,
psz_text, psz_extra );
vlc_meta_Add( p_meta, psz_cat, psz_value );
free( psz_value );
es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
p_eit->i_service_id, p_meta );
vlc_meta_Delete( p_meta );
free( psz_cat );
free( psz_extra );
}
psi->i_version = p_eit->i_version;
dvbpsi_DeleteEIT( p_eit );
}
static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h,
uint8_t i_table_id, uint16_t i_extension )
{
#if 0
msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension );
#endif
if( i_table_id == 0x42 )
{
msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension );
dvbpsi_AttachSDT( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_demux );
}
else if( i_table_id == 0x4e || /* Current/Following */
( i_table_id >= 0x50 && i_table_id <= 0x5f ) ) /* Schedule */
{
ts_eit_psi_t *psi = malloc( sizeof(ts_eit_psi_t) );
msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
i_table_id, i_table_id, i_extension, i_extension );
psi->p_demux = p_demux;
psi->i_table_id = i_table_id;
psi->i_version = -1;
psi->i_service_id = i_extension;
dvbpsi_AttachEIT( h, i_table_id, i_extension, (dvbpsi_eit_callback)EITCallBack, psi );
}
}
#endif
static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
{
demux_sys_t *p_sys = p_demux->p_sys;
......
......@@ -479,6 +479,28 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
return p_pgrm;
}
/* EsOutProgramMeta:
*/
static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta )
{
es_out_sys_t *p_sys = out->p_sys;
input_thread_t *p_input = p_sys->p_input;
char *psz_cat = malloc( strlen(_("Program")) + 10 );
int i;
msg_Dbg( p_input, "EsOutProgramMeta: number=%d", i_group );
sprintf( psz_cat, "%s %d", _("Program"), i_group );
for( i = 0; i < p_meta->i_meta; i++ )
{
msg_Dbg( p_input, " - %s = %s", p_meta->name[i], p_meta->value[i] );
input_Control( p_input, INPUT_ADD_INFO, psz_cat,
_(p_meta->name[i]), "%s", p_meta->value[i] );
}
free( psz_cat );
}
/* EsOutAdd:
* Add an es_out
*/
......@@ -1211,6 +1233,14 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
return VLC_SUCCESS;
}
case ES_OUT_SET_GROUP_META:
{
int i_group = (int)va_arg( args, int );
vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t * );
EsOutProgramMeta( out, i_group, p_meta );
return VLC_SUCCESS;
}
default:
msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
......
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