[vlc-commits] demux: ps: handle PSP PSMF

Francois Cartegnie git at videolan.org
Thu Mar 9 16:31:50 CET 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Mar  8 16:48:45 2017 +0100| [bdcc2d16641c7f5ee243ab3061aee9aca5aea29c] | committer: Francois Cartegnie

demux: ps: handle PSP PSMF

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=bdcc2d16641c7f5ee243ab3061aee9aca5aea29c
---

 modules/demux/mpeg/ps.c | 101 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 79 insertions(+), 22 deletions(-)

diff --git a/modules/demux/mpeg/ps.c b/modules/demux/mpeg/ps.c
index d60edfe..5da4422 100644
--- a/modules/demux/mpeg/ps.c
+++ b/modules/demux/mpeg/ps.c
@@ -47,6 +47,7 @@
     "be usable. Disable this option to calculate from the bitrate instead." )
 
 #define PS_PACKET_PROBE 3
+#define CDXA_HEADER_SIZE 44
 
 /*****************************************************************************
  * Module descriptor
@@ -90,6 +91,7 @@ struct demux_sys_t
     int64_t     i_length;
     int         i_time_track;
     int64_t     i_current_pts;
+    uint64_t    i_start_byte;
 
     int         i_aob_mlp_count;
 
@@ -97,13 +99,18 @@ struct demux_sys_t
     bool  b_have_pack;
     bool  b_bad_scr;
     bool  b_seekable;
-    bool  b_cdxa;
+    enum
+    {
+        MPEG_PS = 0,
+        CDXA_PS,
+        PSMF_PS,
+    } format;
 };
 
 static int Demux  ( demux_t *p_demux );
 static int Control( demux_t *p_demux, int i_query, va_list args );
 
-static int      ps_pkt_resynch( stream_t *, bool, bool );
+static int      ps_pkt_resynch( stream_t *, int, bool );
 static block_t *ps_pkt_read   ( stream_t * );
 
 /*****************************************************************************
@@ -117,7 +124,11 @@ static int OpenCommon( vlc_object_t *p_this, bool b_force )
     const uint8_t *p_peek;
     ssize_t i_peek = 0;
     ssize_t i_offset = 0;
-    bool b_cdxa = false;
+    ssize_t i_skip = 0;
+    unsigned i_max_packets = PS_PACKET_PROBE;
+    int format = MPEG_PS;
+    int i_mux_rate = 0;
+    int i_length = -1;
 
     i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 );
     if( i_peek < 16 )
@@ -126,17 +137,35 @@ static int OpenCommon( vlc_object_t *p_this, bool b_force )
         return VLC_EGENERIC;
     }
 
-    if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) )
+    if( !memcmp( p_peek, "PSMF", 4 ) &&
+        (GetDWBE( &p_peek[4] ) & 0x30303030) == 0x30303030 )
+    {
+        i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 100 );
+        if( i_peek < 100 )
+            return VLC_EGENERIC;
+        i_skip = i_offset = GetWBE( &p_peek[10] );
+        format = PSMF_PS;
+        msg_Info( p_demux, "Detected PSMF-PS header");
+        i_mux_rate = GetDWBE( &p_peek[96] );
+        if( GetDWBE( &p_peek[86] ) > 0 )
+            i_length = CLOCK_FREQ * GetDWBE( &p_peek[92] ) / GetDWBE( &p_peek[86] );
+    }
+    else if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) )
     {
-        b_cdxa = true;
+        format = CDXA_PS;
+        i_max_packets = 0; /* We can't probe here */
+        i_skip = CDXA_HEADER_SIZE;
         msg_Info( p_demux, "Detected CDXA-PS" );
+        /* FIXME: have a proper way to decap CD sectors or make an access stream filter */
     }
     else if( b_force )
     {
         msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
                   "continuing anyway" );
+        i_max_packets = 0;
     }
-    else for( unsigned i=0; i<PS_PACKET_PROBE; i++ )
+
+    for( unsigned i=0; i<i_max_packets; i++ )
     {
         if( i_peek < i_offset + 16 )
         {
@@ -159,6 +188,10 @@ static int OpenCommon( vlc_object_t *p_this, bool b_force )
         i_offset += i_pessize;
     }
 
+    if( i_skip > 0 && !p_demux->b_preparsing &&
+        vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
+        return VLC_EGENERIC;
+
     /* Fill p_demux field */
     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
     if( !p_sys ) return VLC_ENOMEM;
@@ -167,19 +200,20 @@ static int OpenCommon( vlc_object_t *p_this, bool b_force )
     p_demux->pf_control = Control;
 
     /* Init p_sys */
-    p_sys->i_mux_rate = 0;
+    p_sys->i_mux_rate = i_mux_rate;
     p_sys->i_scr      = -1;
     p_sys->i_last_scr = -1;
-    p_sys->i_length   = -1;
+    p_sys->i_length   = i_length;
     p_sys->i_current_pts = (mtime_t) 0;
     p_sys->i_time_track = -1;
     p_sys->i_aob_mlp_count = 0;
+    p_sys->i_start_byte = i_skip;
 
     p_sys->b_lost_sync = false;
     p_sys->b_have_pack = false;
     p_sys->b_bad_scr   = false;
     p_sys->b_seekable  = false;
-    p_sys->b_cdxa      = b_cdxa;
+    p_sys->format      = format;
 
     vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
 
@@ -231,7 +265,7 @@ static int Probe( demux_t *p_demux, bool b_end )
     int i_ret, i_id;
     block_t *p_pkt;
 
-    i_ret = ps_pkt_resynch( p_demux->s, p_sys->b_cdxa, p_sys->b_have_pack );
+    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
     if( i_ret < 0 )
     {
         return VLC_DEMUXER_EOF;
@@ -351,7 +385,7 @@ static int Demux( demux_t *p_demux )
     int i_ret, i_mux_rate;
     block_t *p_pkt;
 
-    i_ret = ps_pkt_resynch( p_demux->s, p_sys->b_cdxa, p_sys->b_have_pack );
+    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
     if( i_ret < 0 )
     {
         return VLC_DEMUXER_EOF;
@@ -464,6 +498,23 @@ static int Demux( demux_t *p_demux )
             {
                 if( !ps_track_fill( tk, &p_sys->psm, i_id, p_pkt ) )
                 {
+                    /* No PSM and no probing yet */
+                    if( p_sys->format == PSMF_PS )
+                    {
+                        if( tk->fmt.i_cat == VIDEO_ES )
+                            tk->fmt.i_codec = VLC_CODEC_H264;
+#if 0
+                        if( i_stream_id == PS_STREAM_ID_PRIVATE_STREAM1 )
+                        {
+                            tk->fmt.i_codec = VLC_CODEC_ATRAC3P;
+                            tk->fmt.i_cat = AUDIO_ES;
+                            tk->fmt.audio.i_blockalign = 376;
+                            tk->fmt.audio.i_channels = 2;
+                            tk->fmt.audio.i_rate = 44100;
+                        }
+#endif
+                    }
+
                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
                     b_new = true;
                 }
@@ -535,7 +586,13 @@ static int Demux( demux_t *p_demux )
                     p_pkt->i_flags = tk->i_next_block_flags;
                     tk->i_next_block_flags = 0;
                 }
-
+#if 0
+                if( tk->fmt.i_codec == VLC_CODEC_ATRAC3P )
+                {
+                    p_pkt->p_buffer += 14;
+                    p_pkt->i_buffer -= 14;
+                }
+#endif
                 es_out_Send( p_demux->out, tk->es, p_pkt );
             }
             else
@@ -570,10 +627,10 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 
         case DEMUX_GET_POSITION:
             pf = (double*) va_arg( args, double* );
-            i64 = stream_Size( p_demux->s );
+            i64 = stream_Size( p_demux->s ) - p_sys->i_start_byte;
             if( i64 > 0 )
             {
-                double current = vlc_stream_Tell( p_demux->s );
+                double current = vlc_stream_Tell( p_demux->s ) - p_sys->i_start_byte;
                 *pf = current / (double)i64;
             }
             else
@@ -584,11 +641,11 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 
         case DEMUX_SET_POSITION:
             f = (double) va_arg( args, double );
-            i64 = stream_Size( p_demux->s );
+            i64 = stream_Size( p_demux->s ) - p_sys->i_start_byte;
             p_sys->i_current_pts = 0;
             p_sys->i_last_scr = -1;
 
-            i_ret = vlc_stream_Seek( p_demux->s, (int64_t)(i64 * f) );
+            i_ret = vlc_stream_Seek( p_demux->s, p_sys->i_start_byte + (int64_t)(i64 * f) );
             if( i_ret == VLC_SUCCESS )
             {
                 NotifyDiscontinuity( p_sys->tk, p_demux->out );
@@ -605,7 +662,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
             if( p_sys->i_mux_rate > 0 )
             {
-                *pi64 = (int64_t)1000000 * ( vlc_stream_Tell( p_demux->s ) / 50 ) /
+                *pi64 = CLOCK_FREQ * ( vlc_stream_Tell( p_demux->s ) - p_sys->i_start_byte / 50 ) /
                     p_sys->i_mux_rate;
                 return VLC_SUCCESS;
             }
@@ -621,7 +678,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
             else if( p_sys->i_mux_rate > 0 )
             {
-                *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) /
+                *pi64 = CLOCK_FREQ * ( stream_Size( p_demux->s ) - p_sys->i_start_byte / 50 ) /
                     p_sys->i_mux_rate;
                 return VLC_SUCCESS;
             }
@@ -633,7 +690,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 )
             {
                 int64_t i_now = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts;
-                int64_t i_pos = vlc_stream_Tell( p_demux->s );
+                int64_t i_pos = vlc_stream_Tell( p_demux->s ) - p_sys->i_start_byte;
 
                 if( !i_now )
                     return i64 ? VLC_EGENERIC : VLC_SUCCESS;
@@ -642,7 +699,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
                 p_sys->i_last_scr = -1;
                 i_pos *= (float)i64 / (float)i_now;
 
-                i_ret = vlc_stream_Seek( p_demux->s, i_pos );
+                i_ret = vlc_stream_Seek( p_demux->s, p_sys->i_start_byte + i_pos );
                 if( i_ret == VLC_SUCCESS )
                 {
                     NotifyDiscontinuity( p_sys->tk, p_demux->out );
@@ -687,7 +744,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
  *  It doesn't skip more than 512 bytes
  *  -1 -> error, 0 -> not synch, 1 -> ok
  */
-static int ps_pkt_resynch( stream_t *s, bool b_cdxa, bool b_pack )
+static int ps_pkt_resynch( stream_t *s, int format, bool b_pack )
 {
     const uint8_t *p_peek;
     int     i_peek;
@@ -717,7 +774,7 @@ static int ps_pkt_resynch( stream_t *s, bool b_cdxa, bool b_pack )
         }
         /* Handle mid stream 24 bytes padding+CRC creating emulated sync codes with incorrect
            PES sizes and frelling up to UINT16_MAX bytes followed by 24 bytes CDXA Header */
-        if( b_cdxa && i_skip == 0 && i_peek >= 48 )
+        if( format == CDXA_PS && i_skip == 0 && i_peek >= 48 )
         {
             size_t i = 0;
             while( i<24 && p_peek[i] == 0 )



More information about the vlc-commits mailing list