Commit 2226f517 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: ts: fully probe TopField VDR headers and set service id (fix #11034)

parent 665b85ad
...@@ -38,6 +38,7 @@ Demuxers: ...@@ -38,6 +38,7 @@ Demuxers:
* Support WMV and WMAV in MP4/mov, aka Flip4Mac files * Support WMV and WMAV in MP4/mov, aka Flip4Mac files
* Support bitmap audio channel reordering in MP4/mov * Support bitmap audio channel reordering in MP4/mov
* Support AlbumArtist and DiscNumber metadata * Support AlbumArtist and DiscNumber metadata
* Fixed selecting recorded program from TopField TS files
Stream filter: Stream filter:
* Added ARIB STD-B25 TS streams decoder * Added ARIB STD-B25 TS streams decoder
......
...@@ -436,105 +436,35 @@ static void SetPrgFilter( demux_t *, int i_prg, bool b_selected ); ...@@ -436,105 +436,35 @@ static void SetPrgFilter( demux_t *, int i_prg, bool b_selected );
#define TS_PACKET_SIZE_204 204 #define TS_PACKET_SIZE_204 204
#define TS_PACKET_SIZE_MAX 204 #define TS_PACKET_SIZE_MAX 204
static int DetectPacketSize( demux_t *p_demux, int *pi_header_size ) static int DetectPacketSize( demux_t *p_demux, int *pi_header_size, int i_offset )
{ {
const uint8_t *p_peek; const uint8_t *p_peek;
if( stream_Peek( p_demux->s, if( stream_Peek( p_demux->s,
&p_peek, TS_PACKET_SIZE_MAX ) < TS_PACKET_SIZE_MAX ) &p_peek, i_offset + TS_PACKET_SIZE_MAX ) < i_offset + TS_PACKET_SIZE_MAX )
return -1; return -1;
*pi_header_size = 0;
if( memcmp( p_peek, "TFrc", 4 ) == 0 )
{
#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 = xmalloc(25);
char *psz_event_name;
char *psz_event_text = xmalloc(130);
char *psz_ext_text = xmalloc(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 = xmalloc( 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
msg_Dbg( p_demux, "this is a topfield file" );
return TS_PACKET_SIZE_188;
}
for( int i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ ) for( int i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ )
{ {
if( p_peek[i_sync] != 0x47 ) if( p_peek[i_offset + i_sync] != 0x47 )
continue; continue;
/* Check next 3 sync bytes */ /* Check next 3 sync bytes */
int i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1; int i_peek = i_offset + TS_PACKET_SIZE_MAX * 3 + i_sync + 1;
if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek ) if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek )
{ {
msg_Err( p_demux, "cannot peek" ); msg_Err( p_demux, "cannot peek" );
return -1; return -1;
} }
if( p_peek[i_sync + 1 * TS_PACKET_SIZE_188] == 0x47 && if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_188] == 0x47 &&
p_peek[i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 && p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 &&
p_peek[i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 ) p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 )
{ {
return TS_PACKET_SIZE_188; return TS_PACKET_SIZE_188;
} }
else if( p_peek[i_sync + 1 * TS_PACKET_SIZE_192] == 0x47 && else if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_192] == 0x47 &&
p_peek[i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 && p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 &&
p_peek[i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 ) p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 )
{ {
if( i_sync == 4 ) if( i_sync == 4 )
{ {
...@@ -542,9 +472,9 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size ) ...@@ -542,9 +472,9 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size )
} }
return TS_PACKET_SIZE_192; return TS_PACKET_SIZE_192;
} }
else if( p_peek[i_sync + 1 * TS_PACKET_SIZE_204] == 0x47 && else if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_204] == 0x47 &&
p_peek[i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 && p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 &&
p_peek[i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 ) p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 )
{ {
return TS_PACKET_SIZE_204; return TS_PACKET_SIZE_204;
} }
...@@ -559,6 +489,99 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size ) ...@@ -559,6 +489,99 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size )
return -1; return -1;
} }
#define TOPFIELD_HEADER_SIZE 3712
static int DetectPVRHeadersAndHeaderSize( demux_t *p_demux, int *pi_header_size, vdr_info_t *p_vdr )
{
const uint8_t *p_peek;
*pi_header_size = 0;
int i_packet_size = -1;
if( stream_Peek( p_demux->s,
&p_peek, TS_PACKET_SIZE_MAX ) < TS_PACKET_SIZE_MAX )
return -1;
if( memcmp( p_peek, "TFrc", 4 ) == 0 &&
stream_Peek( p_demux->s, &p_peek, TOPFIELD_HEADER_SIZE + TS_PACKET_SIZE_MAX )
== TOPFIELD_HEADER_SIZE + TS_PACKET_SIZE_MAX )
{
i_packet_size = DetectPacketSize( p_demux, pi_header_size, TOPFIELD_HEADER_SIZE );
if( i_packet_size != -1 )
{
msg_Dbg( p_demux, "this is a topfield file" );
#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 = xmalloc(25);
char *psz_event_name;
char *psz_event_text = xmalloc(130);
char *psz_ext_text = xmalloc(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 = xmalloc( 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
p_vdr->i_service = GetWBE(&p_peek[18]);
return i_packet_size;
//return TS_PACKET_SIZE_188;
}
}
return DetectPacketSize( p_demux, pi_header_size, 0 );
}
#if (DVBPSI_VERSION_INT >= DVBPSI_VERSION_WANTED(1,0,0)) #if (DVBPSI_VERSION_INT >= DVBPSI_VERSION_WANTED(1,0,0))
static void vlc_dvbpsi_reset( demux_t *p_demux ) static void vlc_dvbpsi_reset( demux_t *p_demux )
{ {
...@@ -617,7 +640,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -617,7 +640,7 @@ static int Open( vlc_object_t *p_this )
vdr_info_t vdr = {0}; vdr_info_t vdr = {0};
/* Search first sync byte */ /* Search first sync byte */
i_packet_size = DetectPacketSize( p_demux, &i_packet_header_size ); i_packet_size = DetectPVRHeadersAndHeaderSize( p_demux, &i_packet_header_size, &vdr );
if( i_packet_size < 0 ) if( i_packet_size < 0 )
return VLC_EGENERIC; return VLC_EGENERIC;
......
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