]> git.sesse.net Git - vlc/commitdiff
demux: ts: fully probe TopField VDR headers and set service id (fix #11034)
authorFrancois Cartegnie <fcvlcdev@free.fr>
Mon, 19 Jan 2015 20:11:47 +0000 (21:11 +0100)
committerFrancois Cartegnie <fcvlcdev@free.fr>
Mon, 19 Jan 2015 20:39:02 +0000 (21:39 +0100)
NEWS
modules/demux/ts.c

diff --git a/NEWS b/NEWS
index 4d0d64dcf31ea249fb5dd8404feea5b775c7f7ec..13fb7ebdf767ed8e46878b3455f2bbbd4efaee2e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,7 @@ Demuxers:
  * Support WMV and WMAV in MP4/mov, aka Flip4Mac files
  * Support bitmap audio channel reordering in MP4/mov
  * Support AlbumArtist and DiscNumber metadata
+ * Fixed selecting recorded program from TopField TS files
 
 Stream filter:
  * Added ARIB STD-B25 TS streams decoder
index a49f9b1d73497e007ce89ee9ad05a9f8af2374a3..f0789f0369f0e6089f5438767c937fef0c291c49 100644 (file)
@@ -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_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;
+
     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;
 
-    *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++ )
     {
-        if( p_peek[i_sync] != 0x47 )
+        if( p_peek[i_offset + i_sync] != 0x47 )
             continue;
 
         /* 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 )
         {
             msg_Err( p_demux, "cannot peek" );
             return -1;
         }
-        if( p_peek[i_sync + 1 * TS_PACKET_SIZE_188] == 0x47 &&
-            p_peek[i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 &&
-            p_peek[i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 )
+        if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_188] == 0x47 &&
+            p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 &&
+            p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 )
         {
             return TS_PACKET_SIZE_188;
         }
-        else if( p_peek[i_sync + 1 * TS_PACKET_SIZE_192] == 0x47 &&
-                 p_peek[i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 &&
-                 p_peek[i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 )
+        else if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_192] == 0x47 &&
+                 p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 &&
+                 p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 )
         {
             if( i_sync == 4 )
             {
@@ -542,9 +472,9 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size )
             }
             return TS_PACKET_SIZE_192;
         }
-        else if( p_peek[i_sync + 1 * TS_PACKET_SIZE_204] == 0x47 &&
-                 p_peek[i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 &&
-                 p_peek[i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 )
+        else if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_204] == 0x47 &&
+                 p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 &&
+                 p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 )
         {
             return TS_PACKET_SIZE_204;
         }
@@ -559,6 +489,99 @@ static int DetectPacketSize( demux_t *p_demux, int *pi_header_size )
     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))
 static void vlc_dvbpsi_reset( demux_t *p_demux )
 {
@@ -617,7 +640,7 @@ static int Open( vlc_object_t *p_this )
     vdr_info_t   vdr = {0};
 
     /* 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 )
         return VLC_EGENERIC;