demux: asf: fix mmsh es id offset and PCR handling (fix #11470)
authorFrancois Cartegnie <fcvlcdev@free.fr>
Sat, 10 May 2014 14:44:26 +0000 (16:44 +0200)
committerFrancois Cartegnie <fcvlcdev@free.fr>
Wed, 14 May 2014 18:01:35 +0000 (20:01 +0200)
might fix 11458

modules/access/mms/mmsh.c
modules/demux/asf/asf.c

index 414dfd4..d1d3c2d 100644 (file)
@@ -42,6 +42,7 @@
 #include "mms.h"
 #include "mmsh.h"
 
+#include "assert.h"
 /* TODO:
  *  - authentication
  */
@@ -262,25 +263,42 @@ static int Control( access_t *p_access, int i_query, va_list args )
             break;
 
         case ACCESS_SET_PRIVATE_ID_STATE:
+        {
             i_int = (int)va_arg( args, int );
             b_bool = (bool)va_arg( args, int );
-            if( (i_int < 0) || (i_int > 127) )
+            int i_cat;
+            if( i_int > 127 )
                 return VLC_EGENERIC;
+            else if ( i_int < 0 )
+            {
+                /* Deselecting all ES in this category */
+                assert( !b_bool );
+                i_cat = -1 * i_int;
+                if ( i_cat > ES_CATEGORY_COUNT )
+                    return VLC_EGENERIC;
+            }
             else
             {
-                int i_cat = p_sys->asfh.stream[i_int].i_cat;
-                for ( int i=0; i< 128; i++ )
-                {
-                    /* First unselect all streams from the same cat */
-                    if ( i_cat == p_sys->asfh.stream[i].i_cat )
-                        p_sys->asfh.stream[i].i_selected = false;
-                }
-                p_sys->asfh.stream[i_int].i_selected = true;
-                Stop( p_access );
-                Seek( p_access, p_access->info.i_pos );
-                return VLC_SUCCESS;
+                /* Chose another ES */
+                assert( b_bool );
+                i_cat = p_sys->asfh.stream[i_int].i_cat;
             }
 
+            for ( int i=0; i< 128; i++ )
+            {
+                /* First unselect all streams from the same cat */
+                if ( i_cat == p_sys->asfh.stream[i].i_cat )
+                    p_sys->asfh.stream[i].i_selected = false;
+            }
+
+            if ( i_int > 0 )
+                p_sys->asfh.stream[i_int].i_selected = true;
+
+            Stop( p_access );
+            Seek( p_access, p_access->info.i_pos );
+            return VLC_SUCCESS;
+        }
+
         case ACCESS_SET_PAUSE_STATE:
             b_bool = (bool)va_arg( args, int );
             if( b_bool )
index 6b339f0..7c435ce 100644 (file)
@@ -42,6 +42,7 @@
 #include <limits.h>
 
 #include "libasf.h"
+#include "assert.h"
 
 /* TODO
  *  - add support for the newly added object: language, bitrate,
@@ -79,6 +80,7 @@ typedef struct
 
     es_out_id_t     *p_es;
     es_format_t     *p_fmt; /* format backup for video changes */
+    bool             b_selected;
 
     asf_object_stream_properties_t *p_sp;
     asf_object_extended_stream_properties_t *p_esp;
@@ -106,6 +108,7 @@ struct demux_sys_t
     bool                b_index;
     bool                b_canfastseek;
     uint8_t             i_seek_track;
+    uint8_t             i_access_selected_track[ES_CATEGORY_COUNT]; /* mms, depends on access algorithm */
     unsigned int        i_wait_keyframe;
 
     vlc_meta_t          *meta;
@@ -153,6 +156,27 @@ static int Demux( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
 
+    for( int i=0; i<ES_CATEGORY_COUNT; i++ )
+    {
+        if ( p_sys->i_access_selected_track[i] > 0 )
+        {
+            es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE,
+                            p_sys->track[p_sys->i_access_selected_track[i]]->p_es, true );
+            p_sys->i_access_selected_track[i] = 0;
+        }
+    }
+
+    /* Get selected tracks, especially for computing PCR */
+    for( int i=0; i<MAX_ASF_TRACKS; i++ )
+    {
+        asf_track_t *tk = p_sys->track[i];
+        if ( !tk ) continue;
+        if ( tk->p_es )
+            es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, & tk->b_selected );
+        else
+            tk->b_selected = false;
+    }
+
     for( ;; )
     {
         const uint8_t *p_peek;
@@ -247,16 +271,10 @@ static void WaitKeyframe( demux_t *p_demux )
         for ( int i=0; i<MAX_ASF_TRACKS; i++ )
         {
             asf_track_t *tk = p_sys->track[i];
-            if ( tk && tk->p_sp && tk->i_cat == VIDEO_ES )
+            if ( tk && tk->p_sp && tk->i_cat == VIDEO_ES && tk->b_selected )
             {
-                bool b_selected = false;
-                es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
-                                tk->p_es, &b_selected );
-                if ( b_selected )
-                {
-                    p_sys->i_seek_track = tk->p_sp->i_stream_number;
-                    break;
-                }
+                p_sys->i_seek_track = tk->p_sp->i_stream_number;
+                break;
             }
         }
     }
@@ -401,14 +419,26 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     case DEMUX_SET_ES:
     {
         i = (int)va_arg( args, int );
-        int i_ret = stream_Control( p_demux->s,
-                                    STREAM_SET_PRIVATE_ID_STATE, i, true );
+        int i_ret;
+        if ( i >= 0 )
+        {
+            i++; /* video/audio-es variable starts 0 */
+            msg_Dbg( p_demux, "Requesting access to enable stream %d", i );
+            i_ret = stream_Control( p_demux->s, STREAM_SET_PRIVATE_ID_STATE, i, true );
+        }
+        else
+        {  /* i contains -1 * es_category */
+            msg_Dbg( p_demux, "Requesting access to disable stream %d", i );
+            i_ret = stream_Control( p_demux->s, STREAM_SET_PRIVATE_ID_STATE, i, false );
+        }
+
         if ( i_ret == VLC_SUCCESS )
         {
             SeekPrepare( p_demux );
             p_sys->i_seek_track = 0;
             WaitKeyframe( p_demux );
         }
+        assert( i_ret == VLC_SUCCESS );
         return i_ret;
     }
 
@@ -478,12 +508,13 @@ static mtime_t GetMoviePTS( demux_sys_t *p_sys )
 {
     mtime_t i_time = -1;
     int     i;
-
+    /* As some tracks might have been deselected by access, the PCR might
+     * stop updating */
     for( i = 0; i < MAX_ASF_TRACKS ; i++ )
     {
-        asf_track_t *tk = p_sys->track[i];
+        const asf_track_t *tk = p_sys->track[i];
 
-        if( tk && tk->p_es && tk->i_time > 0)
+        if( tk && tk->p_es && tk->i_time > 0 && tk->b_selected )
         {
             if( i_time < 0 ) i_time = tk->i_time;
             else i_time = __MIN( i_time, tk->i_time );
@@ -1438,6 +1469,14 @@ static int DemuxInit( demux_t *p_demux )
             }
 
             tk->p_es = es_out_Add( p_demux->out, &fmt );
+
+            if( !stream_Control( p_demux->s, STREAM_GET_PRIVATE_ID_STATE,
+                                 (int) p_sp->i_stream_number, &b_access_selected ) &&
+                b_access_selected )
+            {
+                p_sys->i_access_selected_track[fmt.i_cat] = p_sp->i_stream_number;
+            }
+
         }
         else
         {