* Preamble
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
#include <vlc_demux.h>
-#include "vlc_codec.h"
+#include <vlc_codec.h>
+#include <vlc_meta.h>
+#include <vlc_input.h>
#include "../codec/cc.h"
+#include <assert.h>
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close( vlc_object_t * );
-vlc_module_begin();
- set_shortname( _("TY") );
- set_description(_("TY Stream audio/video demux"));
- set_category( CAT_INPUT );
- set_subcategory( SUBCAT_INPUT_DEMUX );
- set_capability("demux2", 6);
+vlc_module_begin ()
+ set_shortname( N_("TY") )
+ set_description(N_("TY Stream audio/video demux"))
+ set_category( CAT_INPUT )
+ set_subcategory( SUBCAT_INPUT_DEMUX )
+ set_capability("demux", 6)
/* FIXME: there seems to be a segfault when using PVR access
* and TY demux has a bigger priority than PS
* Something must be wrong.
*/
- set_callbacks( Open, Close );
- add_shortcut("ty");
- add_shortcut("tivo");
-vlc_module_end();
+ set_callbacks( Open, Close )
+ add_shortcut("ty", "tivo")
+vlc_module_end ()
/*****************************************************************************
* Local prototypes
b/e0: video B-frame header start
c/e0: video GOP header start
e/01: closed-caption data
- e/02: Extended data services data
+ e/02: Extended data services data
e/03: ipreview data ("thumbs up to record" signal)
e/05: UK Teletext
*/
typedef struct
{
long l_rec_size;
- uint8_t ex1, ex2;
+ uint8_t ex[2];
uint8_t rec_type;
uint8_t subrec_type;
- vlc_bool_t b_ext;
+ bool b_ext;
uint64_t l_ty_pts; /* TY PTS in the record header */
} ty_rec_hdr_t;
TIVO_AUDIO_MPEG
} tivo_audio_t;
+#define XDS_MAX_DATA_SIZE (32)
+typedef enum
+{
+ XDS_CLASS_CURRENT = 0,
+ XDS_CLASS_FUTURE = 1,
+ XDS_CLASS_CHANNEL = 2,
+ XDS_CLASS_MISCELLANEOUS = 3,
+ XDS_CLASS_PUBLIC_SERVICE = 4,
+ XDS_CLASS_RESERVED = 5,
+ XDS_CLASS_UNDEFINED = 6,
+ XDS_CLASS_OTHER = 7,
+
+ XDS_MAX_CLASS_COUNT
+} xds_class_t;
+typedef struct
+{
+ bool b_started;
+ int i_data;
+ uint8_t p_data[XDS_MAX_DATA_SIZE];
+ int i_sum;
+} xds_packet_t;
+typedef enum
+{
+ XDS_META_PROGRAM_RATING_NONE,
+ XDS_META_PROGRAM_RATING_MPAA,
+ XDS_META_PROGRAM_RATING_TPG,
+ /* TODO add CA/CE rating */
+} xds_meta_program_rating_t;
+typedef struct
+{
+ char *psz_name;
+ xds_meta_program_rating_t rating;
+ char *psz_rating;
+ /* Add the other fields once I have the samples */
+} xds_meta_program_t;
+typedef struct
+{
+ char *psz_channel_name;
+ char *psz_channel_call_letter;
+ char *psz_channel_number;
+
+ xds_meta_program_t current;
+ xds_meta_program_t future;
+} xds_meta_t;
+typedef struct
+{
+ /* Are we in XDS mode */
+ bool b_xds;
+
+ /* Current class type */
+ xds_class_t i_class;
+ int i_type;
+ bool b_future;
+
+ /* */
+ xds_packet_t pkt[XDS_MAX_CLASS_COUNT][128]; /* XXX it is way too much, but simpler */
+
+ /* */
+ bool b_meta_changed;
+ xds_meta_t meta;
+
+} xds_t;
+
struct demux_sys_t
{
es_out_id_t *p_video; /* ptr to video codec */
cc_data_t cc;
es_out_id_t *p_cc[4];
+ xds_t xds;
+
int i_cur_chunk;
int i_stuff_cnt;
size_t i_stream_size; /* size of input stream (if known) */
//uint64_t l_program_len; /* length of this stream in msec */
- vlc_bool_t b_seekable; /* is this stream seekable? */
- vlc_bool_t b_have_master; /* are master chunks present? */
+ bool b_seekable; /* is this stream seekable? */
+ bool b_have_master; /* are master chunks present? */
tivo_type_t tivo_type; /* tivo type (SA / DTiVo) */
tivo_series_t tivo_series; /* Series1 or Series2 */
tivo_audio_t audio_type; /* AC3 or MPEG */
//mtime_t l_last_ty_pts_sync; /* audio PTS at time of last TY PTS */
uint64_t l_first_ty_pts; /* first TY PTS in this master chunk */
uint64_t l_final_ty_pts; /* final TY PTS in this master chunk */
- int i_seq_table_size; /* number of entries in SEQ table */
- int i_bits_per_seq_entry; /* # of bits in SEQ table bitmask */
+ unsigned i_seq_table_size; /* number of entries in SEQ table */
+ unsigned i_bits_per_seq_entry; /* # of bits in SEQ table bitmask */
mtime_t firstAudioPTS;
mtime_t lastAudioPTS;
int i_num_recs; /* number of recs in this chunk */
int i_seq_rec; /* record number where seq start is */
ty_seq_table_t *seq_table; /* table of SEQ entries from mstr chk */
- vlc_bool_t eof;
- vlc_bool_t b_first_chunk;
+ bool eof;
+ bool b_first_chunk;
};
static int get_chunk_header(demux_t *);
static int ty_stream_seek_pct(demux_t *p_demux, double seek_pct);
static int ty_stream_seek_time(demux_t *, uint64_t);
-static ty_rec_hdr_t *parse_chunk_headers( demux_t *p_demux, const uint8_t *p_buf,
+static ty_rec_hdr_t *parse_chunk_headers( const uint8_t *p_buf,
int i_num_recs, int *pi_payload_size);
static int probe_stream(demux_t *p_demux);
static void analyze_chunk(demux_t *p_demux, const uint8_t *p_chunk);
static void DemuxDecodeXds( demux_t *p_demux, uint8_t d1, uint8_t d2 );
+static void XdsInit( xds_t * );
+static void XdsExit( xds_t * );
+
+#define TY_ES_GROUP (1)
+
/*
* Open: check file and initialize demux structures
*
U32_AT(&p_peek[8]) != CHUNK_SIZE )
{
if( !p_demux->b_force &&
- !demux2_IsPathExtension( p_demux, ".ty" ) &&
- !demux2_IsPathExtension( p_demux, ".ty+" ) )
+ !demux_IsPathExtension( p_demux, ".ty" ) &&
+ !demux_IsPathExtension( p_demux, ".ty+" ) )
return VLC_EGENERIC;
msg_Warn( p_demux, "this does not look like a TY file, "
"continuing anyway..." );
}
- /* at this point, we assume we have a valid TY stream */
+ /* at this point, we assume we have a valid TY stream */
msg_Dbg( p_demux, "valid TY stream detected" );
/* Set exported functions */
memset(p_sys, 0, sizeof(demux_sys_t));
/* set up our struct (most were zero'd out with the memset above) */
- p_sys->b_first_chunk = VLC_TRUE;
+ p_sys->b_first_chunk = true;
p_sys->b_have_master = (U32_AT(p_peek) == TIVO_PES_FILEID);
p_sys->firstAudioPTS = -1;
+ p_sys->lastAudioPTS = VLC_TS_INVALID;
+ p_sys->lastVideoPTS = VLC_TS_INVALID;
p_sys->i_stream_size = stream_Size(p_demux->s);
p_sys->tivo_type = TIVO_TYPE_UNKNOWN;
p_sys->audio_type = TIVO_AUDIO_UNKNOWN;
p_sys->i_Pes_Length = 0;
p_sys->i_Pts_Offset = 0;
p_sys->l_ac3_pkt_size = 0;
-
+
/* see if this stream is seekable */
stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
/* register the proper audio codec */
if (p_sys->audio_type == TIVO_AUDIO_MPEG) {
- es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) );
+ es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_MPGA );
} else {
- es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) );
+ es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_A52 );
}
+ fmt.i_group = TY_ES_GROUP;
p_sys->p_audio = es_out_Add( p_demux->out, &fmt );
/* register the video stream */
- es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );
+ es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_MPGV );
+ fmt.i_group = TY_ES_GROUP;
p_sys->p_video = es_out_Add( p_demux->out, &fmt );
/* */
p_sys->p_cc[i] = NULL;
cc_Init( &p_sys->cc );
+ XdsInit( &p_sys->xds );
+
return VLC_SUCCESS;
}
block_t *p_block_in = NULL;
/*msg_Dbg(p_demux, "ty demux processing" );*/
-
+
/* did we hit EOF earlier? */
if( p_sys->eof )
return 0;
* - set PTS for data packets
* - pass the data on to the proper codec via es_out_Send()
- * if this is the first time or
+ * if this is the first time or
* if we're at the end of this chunk, start a new one
*/
/* parse the next chunk's record headers */
const long l_rec_size = p_rec->l_rec_size;
/*msg_Dbg(p_demux, "Record Type 0x%x/%02x %ld bytes",
subrec_type, p_rec->rec_type, l_rec_size );*/
-
+
/* some normal records are 0 length, so check for that... */
if( l_rec_size <= 0 )
{
/* set these as 'unknown' for now */
p_block_in->i_pts =
- p_block_in->i_dts = 0;
+ p_block_in->i_dts = VLC_TS_INVALID;
}
/*else
{
if( ( i64 = p_sys->i_stream_size ) > 0 )
{
pf = (double*) va_arg( args, double* );
- *pf = (double)stream_Tell( p_demux->s ) / (double) i64;
+ *pf = ((double)1.0) * stream_Tell( p_demux->s ) / (double) i64;
return VLC_SUCCESS;
}
return VLC_EGENERIC;
demux_t *p_demux = (demux_t*)p_this;
demux_sys_t *p_sys = p_demux->p_sys;
+ XdsExit( &p_sys->xds );
cc_Exit( &p_sys->cc );
free( p_sys->rec_hdrs );
- if( p_sys->seq_table )
- free( p_sys->seq_table );
+ free( p_sys->seq_table );
free(p_sys);
}
if( offset < 0 )
{
/* no header found, fake some 00's (this works, believe me) */
- memset( p_sys->pes_buffer, 4, 0 );
+ memset( p_sys->pes_buffer, 0, 4 );
p_sys->i_pes_buf_cnt = 4;
if( rec_len > 4 )
msg_Err( p_demux, "PES header not found in record of %d bytes!",
return -1; /* partial PES, no audio data */
}
/* full PES header present, extract PTS */
- p_sys->lastAudioPTS = get_pts( &p_block->p_buffer[ offset +
- p_sys->i_Pts_Offset ] );
+ p_sys->lastAudioPTS = VLC_TS_0 + get_pts( &p_block->p_buffer[ offset +
+ p_sys->i_Pts_Offset ] );
if (p_sys->firstAudioPTS < 0)
p_sys->firstAudioPTS = p_sys->lastAudioPTS;
p_block->i_pts = p_sys->lastAudioPTS;
- /*msg_Dbg(p_demux, "Audio PTS %lld", p_sys->lastAudioPTS );*/
+ /*msg_Dbg(p_demux, "Audio PTS %"PRId64, p_sys->lastAudioPTS );*/
/* adjust audio record to remove PES header */
memmove(p_block->p_buffer + offset, p_block->p_buffer + offset +
p_sys->i_Pes_Length, rec_len - p_sys->i_Pes_Length);
{
//msg_Dbg(p_demux, "Video PES hdr in pkt type 0x%02x at offset %d",
//subrec_type, esOffset1);
- p_sys->lastVideoPTS = get_pts(
+ p_sys->lastVideoPTS = VLC_TS_0 + get_pts(
&p_block_in->p_buffer[ esOffset1 + VIDEO_PTS_OFFSET ] );
- /*msg_Dbg(p_demux, "Video rec %d PTS "I64Fd, p_sys->i_cur_rec,
+ /*msg_Dbg(p_demux, "Video rec %d PTS %"PRId64, p_sys->i_cur_rec,
p_sys->lastVideoPTS );*/
if (subrec_type != 0x06) {
/* if we found a PES, and it's not type 6, then we're S2 */
//p_sys->l_last_ty_pts += 33366667;
}
/* set PTS for this block before we send */
- if (p_sys->lastVideoPTS > 0)
+ if (p_sys->lastVideoPTS > VLC_TS_INVALID)
{
p_block_in->i_pts = p_sys->lastVideoPTS;
- /* PTS gets used ONCE.
+ /* PTS gets used ONCE.
* Any subsequent frames we get BEFORE next PES
* header will have their PTS computed in the codec */
- p_sys->lastVideoPTS = 0;
+ p_sys->lastVideoPTS = VLC_TS_INVALID;
}
}
continue;
es_format_Init( &fmt, SPU_ES, fcc[i] );
- fmt.psz_description = strdup( _(ppsz_description[i]) );
+ fmt.psz_description = strdup( vlc_gettext(ppsz_description[i]) );
+ fmt.i_group = TY_ES_GROUP;
p_sys->p_cc[i] = es_out_Add( p_demux->out, &fmt );
es_format_Clean( &fmt );
}
/* Send the CC data */
- if( p_block_in->i_pts > 0 && p_sys->cc.i_data > 0 )
+ if( p_block_in->i_pts > VLC_TS_INVALID && p_sys->cc.i_data > 0 )
{
- int i_cc_count;
-
- block_t *p_cc = block_New( p_demux, p_sys->cc.i_data );
- p_cc->i_flags |= BLOCK_FLAG_TYPE_I;
- p_cc->i_pts = p_block_in->i_pts;
- memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data );
-
- for( i = 0, i_cc_count = 0; i < 4; i++ )
- i_cc_count += p_sys->p_cc[i] ? 1 : 0;
-
for( i = 0; i < 4; i++ )
{
- if( !p_sys->p_cc[i] )
- continue;
- if( i_cc_count > 1 )
- es_out_Send( p_demux->out, p_sys->p_cc[i], block_Duplicate( p_cc ) );
- else
+ if( p_sys->p_cc[i] )
+ {
+ block_t *p_cc = block_New( p_demux, p_sys->cc.i_data );
+ p_cc->i_flags |= BLOCK_FLAG_TYPE_I;
+ p_cc->i_pts = p_block_in->i_pts;
+ memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data );
+
es_out_Send( p_demux->out, p_sys->p_cc[i], p_cc );
+ }
}
cc_Flush( &p_sys->cc );
}
return -1;
#if 0
int i;
- printf( "Audio Packet Header " );
+ fprintf( stderr, "Audio Packet Header " );
for( i = 0 ; i < 24 ; i++ )
- printf( "%2.2x ", p_block_in->p_buffer[i] );
- printf( "\n" );
+ fprintf( stderr, "%2.2x ", p_block_in->p_buffer[i] );
+ fprintf( stderr, "\n" );
#endif
if( subrec_type == 2 )
}
else
{
- p_sys->lastAudioPTS = get_pts(
+ p_sys->lastAudioPTS = VLC_TS_0 + get_pts(
&p_sys->pes_buffer[ esOffset1 + p_sys->i_Pts_Offset ] );
p_block_in->i_pts = p_sys->lastAudioPTS;
}
/* ================================================ */
if ( ( esOffset1 == 0 ) && ( l_rec_size == 16 ) )
{
- p_sys->lastAudioPTS = get_pts( &p_block_in->p_buffer[
+ p_sys->lastAudioPTS = VLC_TS_0 + get_pts( &p_block_in->p_buffer[
SA_PTS_OFFSET ] );
if (p_sys->firstAudioPTS < 0)
p_sys->firstAudioPTS = p_sys->lastAudioPTS;
block_Release(p_block_in);
return 0;
- /*msg_Dbg(p_demux, "SA Audio PTS %lld",
- p_sys->lastAudioPTS );*/
+ /*msg_Dbg(p_demux, "SA Audio PTS %"PRId64, p_sys->lastAudioPTS );*/
}
/* DTiVo Audio with PES Header */
/* ================================================ */
if (check_sync_pes(p_demux, p_block_in, esOffset1,
l_rec_size) == -1)
{
- /* partial PES header found, nothing else.
+ /* partial PES header found, nothing else.
* we're done. */
block_Release(p_block_in);
return 0;
/*msg_Dbg(p_demux,
"Adding SA Audio Packet Size %ld", l_rec_size ); */
- if (p_sys->lastAudioPTS > 0)
+ if (p_sys->lastAudioPTS > VLC_TS_INVALID )
p_block_in->i_pts = p_sys->lastAudioPTS;
}
else if( subrec_type == 0x09 )
}
/* set PCR before we send (if PTS found) */
- if( p_block_in->i_pts > 0 )
+ if( p_block_in->i_pts > VLC_TS_INVALID )
es_out_Control( p_demux->out, ES_OUT_SET_PCR,
p_block_in->i_pts );
/* Send data */
{
demux_sys_t *p_sys = p_demux->p_sys;
int i_field;
- int i_channel;
if( p_block_in )
block_Release(p_block_in);
/* XDS data (extract programs infos) transmitted on field 2 only */
if( i_field == 1 )
- DemuxDecodeXds( p_demux, rec_hdr->ex1, rec_hdr->ex2 );
+ DemuxDecodeXds( p_demux, rec_hdr->ex[0], rec_hdr->ex[1] );
if( p_sys->cc.i_data + 3 > CC_MAX_DATA_SIZE )
return 0;
- p_sys->cc.p_data[p_sys->cc.i_data+0] = i_field;
- p_sys->cc.p_data[p_sys->cc.i_data+1] = rec_hdr->ex1;
- p_sys->cc.p_data[p_sys->cc.i_data+2] = rec_hdr->ex2;
- p_sys->cc.i_data += 3;
-
- i_channel = cc_Channel( i_field, &p_sys->cc.p_data[p_sys->cc.i_data+1] );
- if( i_channel >= 0 && i_channel < 4 )
- p_sys->cc.pb_present[i_channel] = VLC_TRUE;
+ cc_AppendData( &p_sys->cc, i_field, rec_hdr->ex );
return 0;
}
{
demux_sys_t *p_sys = p_demux->p_sys;
int64_t seek_pos = p_sys->i_stream_size * seek_pct;
- int i, i_cur_part;
- long l_skip_amt;
+ uint64_t l_skip_amt;
+ unsigned i_cur_part;
/* if we're not seekable, there's nothing to do */
if (!p_sys->b_seekable)
/* figure out which part & chunk we want & go there */
i_cur_part = seek_pos / TIVO_PART_LENGTH;
p_sys->i_cur_chunk = seek_pos / CHUNK_SIZE;
-
+
/* try to read the part header (master chunk) if it's there */
if ( stream_Seek( p_demux->s, i_cur_part * TIVO_PART_LENGTH ))
{
/* load the chunk */
p_sys->i_stuff_cnt = 0;
get_chunk_header(p_demux);
-
+
/* seek within the chunk to get roughly to where we want */
p_sys->i_cur_rec = (int)
((double) ((seek_pos % CHUNK_SIZE) / (double) (CHUNK_SIZE)) * p_sys->i_num_recs);
- msg_Dbg(p_demux, "Seeked to file pos " I64Fd, seek_pos);
+ msg_Dbg(p_demux, "Seeked to file pos %"PRId64, seek_pos);
msg_Dbg(p_demux, " (chunk %d, record %d)",
p_sys->i_cur_chunk - 1, p_sys->i_cur_rec);
/* seek to the start of this record's data.
* to do that, we have to skip past all prior records */
l_skip_amt = 0;
- for (i=0; i<p_sys->i_cur_rec; i++)
+ for ( int i=0; i<p_sys->i_cur_rec; i++)
l_skip_amt += p_sys->rec_hdrs[i].l_rec_size;
stream_Seek(p_demux->s, ((p_sys->i_cur_chunk-1) * CHUNK_SIZE) +
(p_sys->i_num_recs * 16) + l_skip_amt + 4);
/* to hell with syncing any audio or video, just start reading records... :) */
- /*p_sys->lastAudioPTS = p_sys->lastVideoPTS = 0;*/
- es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
+ /*p_sys->lastAudioPTS = p_sys->lastVideoPTS = VLC_TS_INVALID;*/
return VLC_SUCCESS;
}
+/* XDS decoder */
+//#define TY_XDS_DEBUG
+static void XdsInit( xds_t *h )
+{
+ h->b_xds = false;
+ h->i_class = XDS_MAX_CLASS_COUNT;
+ h->i_type = 0;
+ h->b_future = false;
+ for( int i = 0; i < XDS_MAX_CLASS_COUNT; i++ )
+ {
+ for( int j = 0; j < 128; j++ )
+ h->pkt[i][j].b_started = false;
+ }
+ h->b_meta_changed = false;
+ memset( &h->meta, 0, sizeof(h->meta) );
+}
+static void XdsExit( xds_t *h )
+{
+ /* */
+ free( h->meta.psz_channel_name );
+ free( h->meta.psz_channel_call_letter );
+ free( h->meta.psz_channel_number );
+
+ /* */
+ free( h->meta.current.psz_name );
+ free( h->meta.current.psz_rating );
+ /* */
+ free( h->meta.future.psz_name );
+ free( h->meta.future.psz_rating );
+}
+static void XdsStringUtf8( char dst[2*32+1], const uint8_t *p_src, int i_src )
+{
+ int i_dst = 0;
+ for( int i = 0; i < i_src; i++ )
+ {
+ switch( p_src[i] )
+ {
+#define E2( c, u1, u2 ) case c: dst[i_dst++] = u1; dst[i_dst++] = u2; break
+ E2( 0x2a, 0xc3,0xa1); // lowercase a, acute accent
+ E2( 0x5c, 0xc3,0xa9); // lowercase e, acute accent
+ E2( 0x5e, 0xc3,0xad); // lowercase i, acute accent
+ E2( 0x5f, 0xc3,0xb3); // lowercase o, acute accent
+ E2( 0x60, 0xc3,0xba); // lowercase u, acute accent
+ E2( 0x7b, 0xc3,0xa7); // lowercase c with cedilla
+ E2( 0x7c, 0xc3,0xb7); // division symbol
+ E2( 0x7d, 0xc3,0x91); // uppercase N tilde
+ E2( 0x7e, 0xc3,0xb1); // lowercase n tilde
+#undef E2
+ default:
+ dst[i_dst++] = p_src[i];
+ break;
+ }
+ }
+ dst[i_dst++] = '\0';
+}
+static bool XdsChangeString( xds_t *h, char **ppsz_dst, const char *psz_new )
+{
+ if( *ppsz_dst && psz_new && !strcmp( *ppsz_dst, psz_new ) )
+ return false;
+ if( *ppsz_dst == NULL && psz_new == NULL )
+ return false;
+
+ free( *ppsz_dst );
+ if( psz_new )
+ *ppsz_dst = strdup( psz_new );
+ else
+ *ppsz_dst = NULL;
+
+ h->b_meta_changed = true;
+ return true;
+}
+
+static void XdsDecodeCurrentFuture( xds_t *h, xds_packet_t *pk )
+{
+ xds_meta_program_t *p_prg = h->b_future ? &h->meta.future : &h->meta.current;
+ char name[2*32+1];
+ int i_rating;
+
+ switch( h->i_type )
+ {
+ case 0x03:
+ XdsStringUtf8( name, pk->p_data, pk->i_data );
+ if( XdsChangeString( h, &p_prg->psz_name, name ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Program Name) %d'\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> program name %s\n", name );
+ }
+ break;
+ case 0x05:
+ i_rating = (pk->p_data[0] & 0x18);
+ if( i_rating == 0x08 )
+ {
+ /* TPG */
+ static const char *pppsz_ratings[8][2] = {
+ { "None", "No rating (no content advisory)" },
+ { "TV-Y", "All Children (no content advisory)" },
+ { "TV-Y7", "Directed to Older Children (V = Fantasy Violence)" },
+ { "TV-G", "General Audience (no content advisory)" },
+ { "TV-PG", "Parental Guidance Suggested" },
+ { "TV-14", "Parents Strongly Cautioned" },
+ { "TV-MA", "Mature Audience Only" },
+ { "None", "No rating (no content advisory)" }
+ };
+ p_prg->rating = XDS_META_PROGRAM_RATING_TPG;
+ if( XdsChangeString( h, &p_prg->psz_rating, pppsz_ratings[pk->p_data[1]&0x07][0] ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> TPG Rating %s (%s)\n",
+ // pppsz_ratings[pk->p_data[1]&0x07][0], pppsz_ratings[pk->p_data[1]&0x07][1] );
+ }
+ }
+ else if( i_rating == 0x00 || i_rating == 0x10 )
+ {
+ /* MPAA */
+ static const char *pppsz_ratings[8][2] = {
+ { "N/A", "N/A" },
+ { "G", "General Audiences" },
+ { "PG", "Parental Guidance Suggested" },
+ { "PG-13", "Parents Strongly Cautioned" },
+ { "R", "Restricted" },
+ { "NC-17", "No one 17 and under admitted" },
+ { "X", "No one under 17 admitted" },
+ { "NR", "Not Rated" },
+ };
+ p_prg->rating = XDS_META_PROGRAM_RATING_MPAA;
+ if( XdsChangeString( h, &p_prg->psz_rating, pppsz_ratings[pk->p_data[0]&0x07][0] ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> TPG Rating %s (%s)\n",
+ // pppsz_ratings[pk->p_data[0]&0x07][0], pppsz_ratings[pk->p_data[0]&0x07][1] );
+ }
+ }
+ else
+ {
+ /* Non US Rating TODO */
+ assert( i_rating == 0x18 ); // only left value possible */
+ p_prg->rating = XDS_META_PROGRAM_RATING_NONE;
+ if( XdsChangeString( h, &p_prg->psz_rating, NULL ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> 0x%2.2x 0x%2.2x\n", pk->p_data[0], pk->p_data[1] );
+ }
+ }
+ break;
+
+ default:
+#ifdef TY_XDS_DEBUG
+ fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Unknown 0x%x)'\n", h->i_type );
+#endif
+ break;
+ }
+}
+
+static void XdsDecodeChannel( xds_t *h, xds_packet_t *pk )
+{
+ char name[2*32+1];
+ char chan[2*32+1];
+
+ switch( h->i_type )
+ {
+ case 0x01:
+ if( pk->i_data < 2 )
+ return;
+ XdsStringUtf8( name, pk->p_data, pk->i_data );
+ if( XdsChangeString( h, &h->meta.psz_channel_name, name ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Name) %d'\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> %s\n", name );
+ }
+ break;
+
+ case 0x02:
+ if( pk->i_data < 4 )
+ return;
+
+ XdsStringUtf8( name, pk->p_data, 4 );
+ if( XdsChangeString( h, &h->meta.psz_channel_call_letter, name ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %d\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> call letter %s\n", name );
+ }
+ if( pk->i_data >= 6 )
+ {
+ XdsStringUtf8( chan, &pk->p_data[4], 2 );
+ if( XdsChangeString( h, &h->meta.psz_channel_number, chan ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %d\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> channel number %s\n", chan );
+ }
+ }
+ else
+ {
+ if( XdsChangeString( h, &h->meta.psz_channel_number, NULL ) )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %d\n", pk->i_data );
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> no channel number letter anymore\n" );
+ }
+ }
+ break;
+ case 0x03:
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Channel Tape Delay)'\n" );
+ break;
+ case 0x04:
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Transmission Signal Identifier)'\n" );
+ break;
+ default:
+#ifdef TY_XDS_DEBUG
+ fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Unknown 0x%x)'\n", h->i_type );
+#endif
+ break;
+ }
+}
+
+static void XdsDecode( xds_t *h, xds_packet_t *pk )
+{
+ switch( h->i_class )
+ {
+ case XDS_CLASS_CURRENT:
+ case XDS_CLASS_FUTURE:
+ XdsDecodeCurrentFuture( h, pk );
+ break;
+ case XDS_CLASS_CHANNEL:
+ XdsDecodeChannel( h, pk );
+ break;
+ case XDS_CLASS_MISCELLANEOUS:
+#ifdef TY_XDS_DEBUG
+ fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Miscellaneous'\n" );
+#endif
+ break;
+ case XDS_CLASS_PUBLIC_SERVICE:
+#ifdef TY_XDS_DEBUG
+ fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Public Service'\n" );
+#endif
+ break;
+ default:
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: unknown class\n" );
+ break;
+ }
+}
+
+static void XdsParse( xds_t *h, uint8_t d1, uint8_t d2 )
+{
+ /* TODO check parity */
+ d1 &= 0x7f;
+ d2 &= 0x7f;
+
+ /* */
+ if( d1 >= 0x01 && d1 <= 0x0e )
+ {
+ const xds_class_t i_class = ( d1 - 1 ) >> 1;
+ const int i_type = d2;
+ const bool b_start = d1 & 0x01;
+ xds_packet_t *pk = &h->pkt[i_class][i_type];
+
+ if( !b_start && !pk->b_started )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS Continuying a non started packet, ignoring\n" );
+ h->b_xds = false;
+ return;
+ }
+
+ h->b_xds = true;
+ h->i_class = i_class;
+ h->i_type = i_type;
+ h->b_future = !b_start;
+ pk->b_started = true;
+ if( b_start )
+ {
+ pk->i_data = 0;
+ pk->i_sum = d1 + d2;
+ }
+ }
+ else if( d1 == 0x0f && h->b_xds )
+ {
+ xds_packet_t *pk = &h->pkt[h->i_class][h->i_type];
+
+ /* TODO checksum and decode */
+ pk->i_sum += d1 + d2;
+ if( pk->i_sum & 0x7f )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS invalid checksum, ignoring ---------------------------------\n" );
+ pk->b_started = false;
+ return;
+ }
+ if( pk->i_data <= 0 )
+ {
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS empty packet, ignoring ---------------------------------\n" );
+ pk->b_started = false;
+ return;
+ }
+
+ //if( pk->p_data[pk->i_data-1] == 0x40 ) /* Padding byte */
+ // pk->i_data--;
+ XdsDecode( h, pk );
+
+ /* Reset it */
+ pk->b_started = false;
+ }
+ else if( d1 >= 0x20 && h->b_xds )
+ {
+ xds_packet_t *pk = &h->pkt[h->i_class][h->i_type];
+
+ if( pk->i_data+2 > XDS_MAX_DATA_SIZE )
+ {
+ /* Broken -> reinit */
+ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS broken, reset\n" );
+ h->b_xds = false;
+ pk->b_started = false;
+ return;
+ }
+ /* TODO check parity bit */
+ pk->p_data[pk->i_data++] = d1 & 0x7f;
+ pk->p_data[pk->i_data++] = d2 & 0x7f;
+ pk->i_sum += d1+d2;
+ }
+ else
+ {
+ h->b_xds = false;
+ }
+}
+
static void DemuxDecodeXds( demux_t *p_demux, uint8_t d1, uint8_t d2 )
{
- /* TODO */
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ XdsParse( &p_demux->p_sys->xds, d1, d2 );
+ if( p_demux->p_sys->xds.b_meta_changed )
+ {
+ xds_meta_t *m = &p_sys->xds.meta;
+ vlc_meta_t *p_meta;
+ vlc_epg_t *p_epg;
+
+ /* Channel meta data */
+ p_meta = vlc_meta_New();
+ if( m->psz_channel_name )
+ vlc_meta_SetPublisher( p_meta, m->psz_channel_name );
+ if( m->psz_channel_call_letter )
+ vlc_meta_SetTitle( p_meta, m->psz_channel_call_letter );
+ if( m->psz_channel_number )
+ vlc_meta_AddExtra( p_meta, "Channel number", m->psz_channel_number );
+ es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META, TY_ES_GROUP, p_meta );
+ vlc_meta_Delete( p_meta );
+
+ /* Event meta data (current/future) */
+ p_epg = vlc_epg_New( NULL );
+ if( m->current.psz_name )
+ {
+ vlc_epg_AddEvent( p_epg, 0, 0, m->current.psz_name, NULL, NULL );
+ //if( m->current.psz_rating )
+ // TODO but VLC cannot yet handle rating per epg event
+ vlc_epg_SetCurrent( p_epg, 0 );
+ }
+ if( m->future.psz_name )
+ {
+ }
+ if( p_epg->i_event > 0 )
+ es_out_Control( p_demux->out, ES_OUT_SET_GROUP_EPG, TY_ES_GROUP, p_epg );
+ vlc_epg_Delete( p_epg );
+ }
+ p_demux->p_sys->xds.b_meta_changed = false;
}
/* seek to an exact time position within the stream, if possible.
static int ty_stream_seek_time(demux_t *p_demux, uint64_t l_seek_time)
{
demux_sys_t *p_sys = p_demux->p_sys;
- int i, i_seq_entry = 0;
+ unsigned i_seq_entry = 0;
+ unsigned i;
int i_skip_cnt;
- long l_cur_pos = stream_Tell(p_demux->s);
- int i_cur_part = l_cur_pos / TIVO_PART_LENGTH;
- long l_seek_secs = l_seek_time / 1000000000;
+ int64_t l_cur_pos = stream_Tell(p_demux->s);
+ unsigned i_cur_part = l_cur_pos / TIVO_PART_LENGTH;
+ uint64_t l_seek_secs = l_seek_time / 1000000000;
uint64_t l_fwd_stamp = 1;
/* if we're not seekable, there's nothing to do */
if (!p_sys->b_seekable || !p_sys->b_have_master)
return VLC_EGENERIC;
- msg_Dbg(p_demux, "Skipping to time %02ld:%02ld:%02ld",
+ msg_Dbg(p_demux, "Skipping to time %02"PRIu64":%02"PRIu64":%02"PRIu64,
l_seek_secs / 3600, (l_seek_secs / 60) % 60, l_seek_secs % 60);
/* seek to the proper segment if necessary */
break;
}
}
-
+
/* if we went through the entire last loop and didn't find our target,
then we skip to the next part. What has happened is that the actual
time we're seeking is within this part, but there isn't a SEQ hdr
i_cur_part++;
parse_master(p_demux);
i_seq_entry = 0;
- }
-
+ }
+
/* determine which chunk has our seek_time */
- for (i=0; i<p_sys->i_bits_per_seq_entry; i++) {
- long l_chunk_nr = i_seq_entry * p_sys->i_bits_per_seq_entry + i;
- long l_chunk_offset = (l_chunk_nr + 1) * CHUNK_SIZE;
- msg_Dbg(p_demux, "testing part %d chunk %ld mask 0x%02X bit %d",
+ for (unsigned i=0; i<p_sys->i_bits_per_seq_entry; i++) {
+ uint64_t l_chunk_nr = i_seq_entry * p_sys->i_bits_per_seq_entry + i;
+ uint64_t l_chunk_offset = (l_chunk_nr + 1) * CHUNK_SIZE;
+ msg_Dbg(p_demux, "testing part %d chunk %"PRIu64" mask 0x%02X bit %d",
i_cur_part, l_chunk_nr,
p_sys->seq_table[i_seq_entry].chunk_bitmask[i/8], i%8);
if (p_sys->seq_table[i_seq_entry].chunk_bitmask[i/8] & (1 << (i%8))) {
/* check this chunk's SEQ header timestamp */
- msg_Dbg(p_demux, "has SEQ. seeking to chunk at 0x%lX",
+ msg_Dbg(p_demux, "has SEQ. seeking to chunk at 0x%"PRIu64,
(i_cur_part * TIVO_PART_LENGTH) + l_chunk_offset);
stream_Seek(p_demux->s, (i_cur_part * TIVO_PART_LENGTH) +
l_chunk_offset);
}
l_seek_secs = p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts /
1000000000;
- msg_Dbg(p_demux, "found SEQ hdr for timestamp %02ld:%02ld:%02ld",
+ msg_Dbg(p_demux, "found SEQ hdr for timestamp %02"PRIu64":%02"PRIu64":%02"PRIu64,
l_seek_secs / 3600,
(l_seek_secs / 60) % 60, l_seek_secs % 60);
if (p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts >= l_seek_time) {
so we need to skip past any stream data prior to the seq_rec
in this chunk */
i_skip_cnt = 0;
- for (i=0; i<p_sys->i_seq_rec; i++)
- i_skip_cnt += p_sys->rec_hdrs[i].l_rec_size;
+ for (int j=0; j<p_sys->i_seq_rec; j++)
+ i_skip_cnt += p_sys->rec_hdrs[j].l_rec_size;
stream_Read(p_demux->s, NULL, i_skip_cnt);
p_sys->i_cur_rec = p_sys->i_seq_rec;
//p_sys->l_last_ty_pts = p_sys->rec_hdrs[p_sys->i_seq_rec].l_ty_pts;
{
demux_sys_t *p_sys = p_demux->p_sys;
uint8_t mst_buf[32];
- int i, i_map_size;
+ uint32_t i, i_map_size;
int64_t i_save_pos = stream_Tell(p_demux->s);
int64_t i_pts_secs;
entire table directly from the stream into memory in place. */
/* clear the SEQ table */
- if (p_sys->seq_table != NULL)
- free(p_sys->seq_table);
-
+ free(p_sys->seq_table);
+
/* parse header info */
stream_Read(p_demux->s, mst_buf, 32);
i_map_size = U32_AT(&mst_buf[20]); /* size of bitmask, in bytes */
p_sys->i_seq_table_size = i / (8 + i_map_size);
/* parse all the entries */
- p_sys->seq_table = malloc(p_sys->i_seq_table_size * sizeof(ty_seq_table_t));
- for (i=0; i<p_sys->i_seq_table_size; i++) {
- stream_Read(p_demux->s, mst_buf, 8 + i_map_size);
+ p_sys->seq_table = calloc(p_sys->i_seq_table_size, sizeof(ty_seq_table_t));
+ if (p_sys->seq_table == NULL)
+ {
+ p_sys->i_seq_table_size = 0;
+ return;
+ }
+ for (unsigned i=0; i<p_sys->i_seq_table_size; i++) {
+ stream_Read(p_demux->s, mst_buf, 8);
p_sys->seq_table[i].l_timestamp = U64_AT(&mst_buf[0]);
if (i_map_size > 8) {
msg_Err(p_demux, "Unsupported SEQ bitmap size in master chunk");
- memset(p_sys->seq_table[i].chunk_bitmask, i_map_size, 0);
+ stream_Read(p_demux->s, NULL, i_map_size);
} else {
+ stream_Read(p_demux->s, mst_buf + 8, i_map_size);
memcpy(p_sys->seq_table[i].chunk_bitmask, &mst_buf[8], i_map_size);
}
}
p_sys->l_first_ty_pts = p_sys->seq_table[0].l_timestamp;
p_sys->l_final_ty_pts =
p_sys->seq_table[p_sys->i_seq_table_size - 1].l_timestamp;
- p_sys->b_have_master = VLC_TRUE;
+ p_sys->b_have_master = true;
i_pts_secs = p_sys->l_first_ty_pts / 1000000000;
- msg_Dbg( p_demux, "first TY pts in master is %02d:%02d:%02d",
- (int)(i_pts_secs / 3600), (int)((i_pts_secs / 60) % 60), (int)(i_pts_secs % 60) );
+ msg_Dbg( p_demux,
+ "first TY pts in master is %02"PRId64":%02"PRId64":%02"PRId64,
+ i_pts_secs / 3600, (i_pts_secs / 60) % 60, i_pts_secs % 60 );
i_pts_secs = p_sys->l_final_ty_pts / 1000000000;
- msg_Dbg( p_demux, "final TY pts in master is %02d:%02d:%02d",
- (int)(i_pts_secs / 3600), (int)((i_pts_secs / 60) % 60), (int)(i_pts_secs % 60) );
+ msg_Dbg( p_demux,
+ "final TY pts in master is %02"PRId64":%02"PRId64":%02"PRId64,
+ i_pts_secs / 3600, (i_pts_secs / 60) % 60, i_pts_secs % 60 );
/* seek past this chunk */
stream_Seek(p_demux->s, i_save_pos + CHUNK_SIZE);
demux_sys_t *p_sys = p_demux->p_sys;
const uint8_t *p_buf;
int i;
- vlc_bool_t b_probe_error = VLC_FALSE;
+ bool b_probe_error = false;
/* we need CHUNK_PEEK_COUNT chunks of data, first one might be a Part header, so ... */
if (stream_Peek( p_demux->s, &p_buf, CHUNK_PEEK_COUNT * CHUNK_SIZE ) <
/* TODO: if seekable, then loop reading chunks into a temp buffer */
return VLC_EGENERIC;
}
-
+
/* the real work: analyze this chunk */
for (i = 0; i < CHUNK_PEEK_COUNT; i++) {
analyze_chunk(p_demux, p_buf);
break;
p_buf += CHUNK_SIZE;
}
-
+
/* the final tally */
if (p_sys->tivo_series == TIVO_SERIES_UNKNOWN) {
msg_Err(p_demux, "Can't determine Tivo Series.");
- b_probe_error = VLC_TRUE;
+ b_probe_error = true;
}
if (p_sys->audio_type == TIVO_AUDIO_UNKNOWN) {
msg_Err(p_demux, "Can't determine Tivo Audio Type.");
- b_probe_error = VLC_TRUE;
+ b_probe_error = true;
}
if (p_sys->tivo_type == TIVO_TYPE_UNKNOWN) {
msg_Err(p_demux, "Can't determine Tivo Type (SA/DTivo).");
- b_probe_error = VLC_TRUE;
+ b_probe_error = true;
}
return b_probe_error?VLC_EGENERIC:VLC_SUCCESS;
}
int i_num_recs, i;
ty_rec_hdr_t *p_hdrs;
int i_num_6e0, i_num_be0, i_num_9c0, i_num_3c0;
- uint32_t i_payload_size;
+ int i_payload_size;
/* skip if it's a Part header */
if( U32_AT( &p_chunk[ 0 ] ) == TIVO_PES_FILEID )
/* try again with the next chunk. Sometimes there are dead ones */
return;
}
-
+
p_chunk += 4; /* skip past rec count & SEQ bytes */
//msg_Dbg(p_demux, "probe: chunk has %d recs", i_num_recs);
- p_hdrs = parse_chunk_headers(p_demux, p_chunk, i_num_recs, &i_payload_size);
+ p_hdrs = parse_chunk_headers(p_chunk, i_num_recs, &i_payload_size);
/* scan headers.
* 1. check video packets. Presence of 0x6e0 means S1.
* No 6e0 but have be0 means S2.
/* read the TY packet header */
i_readSize = stream_Peek( p_demux->s, &p_peek, 4 );
p_sys->i_cur_chunk++;
-
+
if ( (i_readSize < 4) || ( U32_AT(&p_peek[ 0 ] ) == 0 ))
{
/* EOF */
p_sys->eof = 1;
return 0;
}
-
+
/* check if it's a PART Header */
if( U32_AT( &p_peek[ 0 ] ) == TIVO_PES_FILEID )
{
parse_master(p_demux);
return get_chunk_header(p_demux);
}
-
+
/* number of records in chunk (8- or 16-bit number) */
if (p_peek[3] & 0x80)
{
p_sys->i_seq_rec = p_peek[1];
}
p_sys->i_cur_rec = 0;
- p_sys->b_first_chunk = VLC_FALSE;
-
+ p_sys->b_first_chunk = false;
+
/*msg_Dbg( p_demux, "chunk has %d records", i_num_recs );*/
- if (p_sys->rec_hdrs)
- free(p_sys->rec_hdrs);
+ free(p_sys->rec_hdrs);
/* skip past the 4 bytes we "peeked" earlier */
stream_Read( p_demux->s, NULL, 4 );
p_hdr_buf = malloc(i_num_recs * 16);
if (stream_Read(p_demux->s, p_hdr_buf, i_num_recs * 16) < i_num_recs * 16) {
free( p_hdr_buf );
- p_sys->eof = VLC_TRUE;
+ p_sys->eof = true;
return 0;
}
/* parse them */
- p_sys->rec_hdrs = parse_chunk_headers(p_demux, p_hdr_buf, i_num_recs,
+ p_sys->rec_hdrs = parse_chunk_headers(p_hdr_buf, i_num_recs,
&i_payload_size);
free(p_hdr_buf);
}
-static ty_rec_hdr_t *parse_chunk_headers( demux_t *p_demux, const uint8_t *p_buf,
+static ty_rec_hdr_t *parse_chunk_headers( const uint8_t *p_buf,
int i_num_recs, int *pi_payload_size)
{
int i;
{
uint8_t b1, b2;
/* marker bit 2 set, so read extended data */
- b1 = ( ( ( record_header[ 0 ] & 0x0f ) << 4 ) |
+ b1 = ( ( ( record_header[ 0 ] & 0x0f ) << 4 ) |
( ( record_header[ 1 ] & 0xf0 ) >> 4 ) );
- b1 &= 0x7f;
- b2 = ( ( ( record_header[ 1 ] & 0x0f ) << 4 ) |
+ b2 = ( ( ( record_header[ 1 ] & 0x0f ) << 4 ) |
( ( record_header[ 2 ] & 0xf0 ) >> 4 ) );
- b2 &= 0x7f;
- p_rec_hdr->ex1 = b1;
- p_rec_hdr->ex2 = b2;
+ p_rec_hdr->ex[0] = b1;
+ p_rec_hdr->ex[1] = b2;
p_rec_hdr->l_rec_size = 0;
p_rec_hdr->l_ty_pts = 0;
- p_rec_hdr->b_ext = VLC_TRUE;
+ p_rec_hdr->b_ext = true;
}
else
{
p_rec_hdr->l_rec_size = ( record_header[ 0 ] << 8 |
record_header[ 1 ] ) << 4 | ( record_header[ 2 ] >> 4 );
*pi_payload_size += p_rec_hdr->l_rec_size;
- p_rec_hdr->b_ext = VLC_FALSE;
+ p_rec_hdr->b_ext = false;
p_rec_hdr->l_ty_pts = U64_AT( &record_header[ 8 ] );
}
//fprintf( stderr, "parse_chunk_headers[%d] t=0x%x s=%d\n", i, p_rec_hdr->rec_type, p_rec_hdr->subrec_type );