]> git.sesse.net Git - vlc/blobdiff - modules/demux/mkv.cpp
mkv.cpp: more memory leaks fixed
[vlc] / modules / demux / mkv.cpp
index 152f682396bb74b2633cbbdae158df6f7834d9de..870b63db7b076d2640a0242053b89f25d266c1bc 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * mkv.cpp : matroska demuxer
  *****************************************************************************
- * Copyright (C) 2003-2004 VideoLAN
+ * Copyright (C) 2003-2004 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
@@ -381,7 +381,7 @@ static int  Open ( vlc_object_t * );
 static void Close( vlc_object_t * );
 
 vlc_module_begin();
-    set_shortname( _("Matroska") );
+    set_shortname( "Matroska" );
     set_description( _("Matroska stream demuxer" ) );
     set_capability( "demux2", 50 );
     set_callbacks( Open, Close );
@@ -390,19 +390,19 @@ vlc_module_begin();
 
     add_bool( "mkv-use-ordered-chapters", 1, NULL,
             N_("Ordered chapters"),
-            N_("Play ordered chapters as specified in the segment"), VLC_TRUE );
+            N_("Play ordered chapters as specified in the segment."), VLC_TRUE );
 
     add_bool( "mkv-use-chapter-codec", 1, NULL,
             N_("Chapter codecs"),
-            N_("Use chapter codecs found in the segment"), VLC_TRUE );
+            N_("Use chapter codecs found in the segment."), VLC_TRUE );
 
     add_bool( "mkv-seek-percent", 0, NULL,
             N_("Seek based on percent not time"),
-            N_("Seek based on percent not time"), VLC_TRUE );
+            N_("Seek based on percent not time."), VLC_TRUE );
 
     add_bool( "mkv-use-dummy", 0, NULL,
             N_("Dummy Elements"),
-            N_("Read and discard unknown EBML elements (not good for broken files)"), VLC_TRUE );
+            N_("Read and discard unknown EBML elements (not good for broken files)."), VLC_TRUE );
 
     add_shortcut( "mka" );
     add_shortcut( "mkv" );
@@ -492,9 +492,16 @@ class vlc_stream_io_callback: public IOCallback
   private:
     stream_t       *s;
     vlc_bool_t     mb_eof;
+    vlc_bool_t     b_owner;
 
   public:
-    vlc_stream_io_callback( stream_t * );
+    vlc_stream_io_callback( stream_t *, vlc_bool_t );
+
+    virtual ~vlc_stream_io_callback()
+    {
+        if( b_owner )
+            stream_Delete( s );
+    }
 
     virtual uint32   read            ( void *p_buffer, size_t i_size);
     virtual void     setFilePointer  ( int64_t i_offset, seek_mode mode = seek_beginning );
@@ -946,9 +953,9 @@ public:
     
     std::vector<chapter_codec_cmds_c*> codecs;
 
-    bool operator<( const chapter_item_c & item ) const
+    static bool CompareTimecode( const chapter_item_c * itemA, const chapter_item_c * itemB )
     {
-        return ( i_user_start_time < item.i_user_start_time || (i_user_start_time == item.i_user_start_time && i_user_end_time < item.i_user_end_time) );
+        return ( itemA->i_user_start_time < itemB->i_user_start_time || (itemA->i_user_start_time == itemB->i_user_start_time && itemA->i_user_end_time < itemB->i_user_end_time) );
     }
 
     bool Enter( bool b_do_subchapters );
@@ -1014,14 +1021,14 @@ public:
             {
                 free( tracks[i_track]->fmt.psz_description );
             }
-/*            if( tracks[i_track]->psz_codec )
+            if( tracks[i_track]->psz_codec )
             {
                 free( tracks[i_track]->psz_codec );
             }
             if( tracks[i_track]->fmt.psz_language )
             {
                 free( tracks[i_track]->fmt.psz_language );
-            }*/
+            }
             delete tracks[i_track];
         }
         
@@ -1049,6 +1056,7 @@ public:
             free( p_indexes );
 
         delete ep;
+        delete segment;
         delete p_segment_uid;
         delete p_prev_segment_uid;
         delete p_next_segment_uid;
@@ -1065,6 +1073,12 @@ public:
             delete (*indext);
             indext++;
         }
+        std::vector<KaxSegmentFamily*>::iterator indexf = families.begin();
+        while ( indexf != families.end() )
+        {
+            delete (*indexf);
+            indexf++;
+        }
     }
 
     KaxSegment              *segment;
@@ -1112,7 +1126,7 @@ public:
     int                             i_default_edition;
 
     std::vector<chapter_translation_c*> translations;
-    std::vector<KaxSegmentFamily>  families;
+    std::vector<KaxSegmentFamily*>  families;
     
     demux_sys_t                    & sys;
     EbmlParser                     *ep;
@@ -1267,6 +1281,7 @@ public:
     demux_sys_t( demux_t & demux )
         :demuxer(demux)
         ,i_pts(0)
+        ,i_last_dts(0)
         ,i_start_pts(0)
         ,i_chapter_time(0)
         ,meta(NULL)
@@ -1299,6 +1314,7 @@ public:
     demux_t                 & demuxer;
 
     mtime_t                 i_pts;
+    mtime_t                 i_last_dts;
     mtime_t                 i_start_pts;
     mtime_t                 i_chapter_time;
 
@@ -1328,7 +1344,7 @@ public:
     void PreloadFamily( const matroska_segment_c & of_segment );
     void PreloadLinked( matroska_segment_c *p_segment );
     bool PreparePlayback( virtual_segment_c *p_new_segment );
-    matroska_stream_c *AnalyseAllSegmentsFound( EbmlStream *p_estream );
+    matroska_stream_c *AnalyseAllSegmentsFound( EbmlStream *p_estream, bool b_initial = false );
     void JumpTo( virtual_segment_c & p_segment, chapter_item_c * p_chapter );
 
     void StartUiThread();
@@ -1340,7 +1356,7 @@ public:
     input_thread_t *p_input;
     pci_t          pci_packet;
     bool           b_pci_packet_set;
-    uint8_t        alpha[4];
+    uint8_t        palette[4][4];
     vlc_mutex_t    lock_demuxer;
 
     /* event */
@@ -1364,7 +1380,10 @@ static void Seek   ( demux_t *, mtime_t i_date, double f_percent, chapter_item_c
 
 #define MKV_IS_ID( el, C ) ( EbmlId( (*el) ) == C::ClassInfos.GlobalId )
 
-static char *UTF8ToStr          ( const UTFstring &u );
+static inline char * ToUTF8( const UTFstring &u )
+{
+    return strdup( u.GetUTF8().c_str() );
+}
 
 /*****************************************************************************
  * Open: initializes matroska demux structures
@@ -1392,7 +1411,7 @@ static int Open( vlc_object_t * p_this )
     p_demux->pf_control = Control;
     p_demux->p_sys      = p_sys = new demux_sys_t( *p_demux );
 
-    p_io_callback = new vlc_stream_io_callback( p_demux->s );
+    p_io_callback = new vlc_stream_io_callback( p_demux->s, VLC_FALSE );
     p_io_stream = new EbmlStream( *p_io_callback );
 
     if( p_io_stream == NULL )
@@ -1403,7 +1422,7 @@ static int Open( vlc_object_t * p_this )
         return VLC_EGENERIC;
     }
 
-    p_stream = p_sys->AnalyseAllSegmentsFound( p_io_stream );
+    p_stream = p_sys->AnalyseAllSegmentsFound( p_io_stream, true );
     if( p_stream == NULL )
     {
         msg_Err( p_demux, "cannot find KaxSegment" );
@@ -1468,22 +1487,31 @@ static int Open( vlc_object_t * p_this )
                         !s_filename.compare(s_filename.length() - 3, 3, "mka"))
 #endif
                     {
-                        // test wether this file belongs to the our family
-                        StdIOCallback *p_file_io = new StdIOCallback(s_filename.c_str(), MODE_READ);
-                        EbmlStream *p_estream = new EbmlStream(*p_file_io);
-
-                        p_stream = p_sys->AnalyseAllSegmentsFound( p_estream );
-                        if ( p_stream == NULL )
+                        // test wether this file belongs to our family
+                        stream_t *p_file_stream = stream_UrlNew( p_demux, s_filename.c_str());
+                        if ( p_file_stream != NULL )
                         {
-                            msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() );
-                            delete p_estream;
-                            delete p_file_io;
+                            vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, VLC_TRUE );
+                            EbmlStream *p_estream = new EbmlStream(*p_file_io);
+
+                            p_stream = p_sys->AnalyseAllSegmentsFound( p_estream );
+
+                            if ( p_stream == NULL )
+                            {
+                                msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() );
+                                delete p_estream;
+                                delete p_file_io;
+                            }
+                            else
+                            {
+                                p_stream->p_in = p_file_io;
+                                p_stream->p_es = p_estream;
+                                p_sys->streams.push_back( p_stream );
+                            }
                         }
                         else
                         {
-                            p_stream->p_in = p_file_io;
-                            p_stream->p_es = p_estream;
-                            p_sys->streams.push_back( p_stream );
+                            msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() );
                         }
                     }
                 }
@@ -1616,8 +1644,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 int matroska_segment_c::BlockGet( KaxBlock * & pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration )
 {
     pp_block = NULL;
-    *pi_ref1  = -1;
-    *pi_ref2  = -1;
+    *pi_ref1  = 0;
+    *pi_ref2  = 0;
 
     for( ;; )
     {
@@ -1637,7 +1665,7 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, int64_t *pi_ref1, int64
             if( i_index > 0 && idx.i_time == -1 )
             {
                 idx.i_time        = (*pp_block).GlobalTimecode() / (mtime_t)1000;
-                idx.b_key         = *pi_ref1 == -1 ? VLC_TRUE : VLC_FALSE;
+                idx.b_key         = *pi_ref1 == 0 ? VLC_TRUE : VLC_FALSE;
             }
 #undef idx
             return VLC_SUCCESS;
@@ -1728,13 +1756,13 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, int64_t *pi_ref1, int64
                 KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
 
                 ref.ReadData( es.I_O() );
-                if( *pi_ref1 == -1 )
+                if( *pi_ref1 == 0 )
                 {
-                    *pi_ref1 = int64( ref );
+                    *pi_ref1 = int64( ref ) * cluster->GlobalTimecodeScale();
                 }
                 else
                 {
-                    *pi_ref2 = int64( ref );
+                    *pi_ref2 = int64( ref ) * cluster->GlobalTimecodeScale();
                 }
             }
             else if( MKV_IS_ID( el, KaxClusterSilentTrackNumber ) )
@@ -1797,7 +1825,7 @@ static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts,
         msg_Err( p_demux, "unknown track number=%d", block->TrackNum() );
         return;
     }
-    if( i_pts < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES )
+    if( i_pts + i_duration < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES )
     {
         return; /* discard audio packets that shouldn't be rendered */
     }
@@ -1859,17 +1887,27 @@ static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts,
             }
             return;
         }
-        // TODO implement correct timestamping when B frames are used
+        // correct timestamping when B frames are used
         if( tk->fmt.i_cat != VIDEO_ES )
         {
             p_block->i_dts = p_block->i_pts = i_pts;
         }
         else
         {
-            p_block->i_dts = i_pts;
-            p_block->i_pts = 0;
+            if( !strcmp( tk->psz_codec, "V_MS/VFW/FOURCC" ) )
+            {
+                p_block->i_pts = 0;
+            }
+            else
+            {
+                p_block->i_pts = i_pts;
+            }
+            p_block->i_dts = p_sys->i_pts;
         }
 
+#if 0
+msg_Dbg( p_demux, "block i_dts: "I64Fd" / i_pts: "I64Fd, p_block->i_dts, p_block->i_pts);
+#endif
         if( strcmp( tk->psz_codec, "S_VOBSUB" ) )
         {
             p_block->i_length = i_duration * 1000;
@@ -1884,7 +1922,7 @@ static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts,
 #undef tk
 }
 
-matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream )
+matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream, bool b_initial )
 {
     int i_upper_lvl = 0;
     size_t i;
@@ -1897,7 +1935,7 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream )
     {
         return NULL;
     }
-    p_l0->SkipData(*p_estream, EbmlHead_Context);
+    p_l0->SkipData(*p_estream, KaxMatroska_Context);
     delete p_l0;
 
     // find all segments in this file
@@ -1915,7 +1953,7 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream )
         {
             EbmlParser  *ep;
             matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
-            b_keep_segment = false;
+            b_keep_segment = b_initial;
 
             ep = new EbmlParser(p_estream, p_l0, &demuxer );
             p_segment1->ep = ep;
@@ -1954,7 +1992,7 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream )
                         else if( MKV_IS_ID( l, KaxSegmentFamily ) )
                         {
                             KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) );
-                            p_segment1->families.push_back( *p_fam );
+                            p_segment1->families.push_back( p_fam );
                         }
                     }
                     break;
@@ -1968,9 +2006,13 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream )
             else
                 delete p_segment1;
         }
-
-        p_l0->SkipData(*p_estream, EbmlHead_Context);
-        p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
+        if (p_l0->IsFiniteSize() )
+        {
+            p_l0->SkipData(*p_estream, KaxMatroska_Context);
+            p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
+        }
+        else
+            p_l0 = p_l0->SkipData(*p_estream, KaxSegment_Context);
     }
 
     if ( !b_keep_stream )
@@ -1987,14 +2029,14 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
     size_t i_track;
 
     /* add all es */
-    msg_Dbg( &sys.demuxer, "found %d es", tracks.size() );
+    msg_Dbg( &sys.demuxer, "found %d es", (int)tracks.size() );
     sys.b_pci_packet_set = false;
 
     for( i_track = 0; i_track < tracks.size(); i_track++ )
     {
         if( tracks[i_track]->fmt.i_cat == UNKNOWN_ES )
         {
-            msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", i_track, tracks[i_track]->i_number );
+            msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
             tracks[i_track]->p_es = NULL;
             continue;
         }
@@ -2036,7 +2078,6 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             else if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/ISO/AVC" ) )
             {
                 tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', 'v', 'c', '1' );
-                tracks[i_track]->fmt.b_packetized = VLC_FALSE;
                 tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
                 tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
                 memcpy( tracks[i_track]->fmt.p_extra,tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
@@ -2211,13 +2252,13 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
         else if( !strcmp( tracks[i_track]->psz_codec, "A_TTA1" ) )
         {
             /* FIXME: support this codec */
-            msg_Err( &sys.demuxer, "TTA not supported yet[%d, n=%d]", i_track, tracks[i_track]->i_number );
+            msg_Err( &sys.demuxer, "TTA not supported yet[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
             tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
         }
         else if( !strcmp( tracks[i_track]->psz_codec, "A_WAVPACK4" ) )
         {
             /* FIXME: support this codec */
-            msg_Err( &sys.demuxer, "Wavpack not supported yet[%d, n=%d]", i_track, tracks[i_track]->i_number );
+            msg_Err( &sys.demuxer, "Wavpack not supported yet[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
             tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
         }
         else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/UTF8" ) )
@@ -2300,7 +2341,7 @@ void demux_sys_t::StartUiThread()
         var_Create( p_input, "x-end", VLC_VAR_INTEGER );
         var_Create( p_input, "y-end", VLC_VAR_INTEGER );
         var_Create( p_input, "color", VLC_VAR_ADDRESS );
-        var_Create( p_input, "menu-contrast", VLC_VAR_ADDRESS );
+        var_Create( p_input, "menu-palette", VLC_VAR_ADDRESS );
         var_Create( p_input, "highlight", VLC_VAR_BOOL );
         var_Create( p_input, "highlight-mutex", VLC_VAR_MUTEX );
 
@@ -2332,7 +2373,9 @@ void demux_sys_t::StopUiThread()
         var_Destroy( p_input, "y-start" );
         var_Destroy( p_input, "y-end" );
         var_Destroy( p_input, "color" );
-        var_Destroy( p_input, "menu-contrast" );
+        var_Destroy( p_input, "menu-palette" );
+
+        vlc_object_release( p_input );
 
         msg_Dbg( &demuxer, "Stopping the UI Hook" );
     }
@@ -2553,8 +2596,10 @@ int demux_sys_t::EventThread( vlc_object_t *p_this )
                 {
                     btni_t *button_ptr = &(pci->hli.btnit[button-1]);
 
-                    if((valx.i_int >= button_ptr->x_start) && (valx.i_int <= button_ptr->x_end) &&
-                       (valy.i_int >= button_ptr->y_start) && (valy.i_int <= button_ptr->y_end)) 
+                    if(((unsigned)valx.i_int >= button_ptr->x_start)
+                     && ((unsigned)valx.i_int <= button_ptr->x_end)
+                     && ((unsigned)valy.i_int >= button_ptr->y_start)
+                     && ((unsigned)valy.i_int <= button_ptr->y_end)) 
                     {
                         mx = (button_ptr->x_start + button_ptr->x_end)/2;
                         my = (button_ptr->y_start + button_ptr->y_end)/2;
@@ -2600,10 +2645,18 @@ int demux_sys_t::EventThread( vlc_object_t *p_this )
                             } else {
                                 i_palette = 0;
                             }
-                            p_sys->alpha[0] = i_palette      & 0x0f;
-                            p_sys->alpha[1] = (i_palette>>4) & 0x0f;
-                            p_sys->alpha[2] = (i_palette>>8) & 0x0f;
-                            p_sys->alpha[3] = (i_palette>>12)& 0x0f;
+
+                            for( int i = 0; i < 4; i++ )
+                            {
+                                uint32_t i_yuv = 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
+                                uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
+                                i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;
+
+                                p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
+                                p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
+                                p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
+                                p_sys->palette[i][3] = i_alpha;
+                            }
 
                             vlc_mutex_lock( p_mutex );
                             val.i_int = button_ptr.x_start; var_Set( p_sys->p_input, "x-start", val );
@@ -2611,8 +2664,8 @@ int demux_sys_t::EventThread( vlc_object_t *p_this )
                             val.i_int = button_ptr.y_start; var_Set( p_sys->p_input, "y-start", val );
                             val.i_int = button_ptr.y_end;   var_Set( p_sys->p_input, "y-end",   val );
 
-                            val.p_address = (void *)p_sys->alpha;
-                            var_Set( p_sys->p_input, "menu-contrast", val );
+                            val.p_address = (void *)p_sys->palette;
+                            var_Set( p_sys->p_input, "menu-palette", val );
 
                             val.b_bool = VLC_TRUE; var_Set( p_sys->p_input, "highlight", val );
                             vlc_mutex_unlock( p_mutex );
@@ -3138,7 +3191,7 @@ static int Demux( demux_t *p_demux)
                     if ( p_chap->i_user_start_time == p_chap->i_user_start_time )
                         p_vsegment->SelectNext();
                     */
-                    p_sys->i_pts = p_chap->i_user_end_time;
+                    p_sys->i_last_dts = p_sys->i_pts = p_chap->i_user_end_time;
                     p_sys->i_pts++; // trick to avoid staying on segments with no duration and no content
 
                     i_return = 1;
@@ -3168,17 +3221,34 @@ static int Demux( demux_t *p_demux)
             }
         }
 
-        p_sys->i_pts = p_sys->i_chapter_time + block->GlobalTimecode() / (mtime_t) 1000;
+        mtime_t i_pts, i_dts;
+
+        mtime_t i_time = block->GlobalTimecode();
+        if ( i_block_ref1 != 0 )
+            i_time += min( 0, i_block_ref1 );
+        if ( i_block_ref2 != 0 )
+            i_time += min( 0, i_block_ref2 );
+
+        i_pts = (p_sys->i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
+        i_dts = (p_sys->i_chapter_time + i_time) / (mtime_t) 1000;
+
+        if ( i_dts != i_pts && p_sys->i_last_dts >= i_dts )
+            p_sys->i_last_dts += 200;
+        else
+            p_sys->i_last_dts = i_dts;
+
+        p_sys->i_pts = i_pts;
 
         if( p_sys->i_pts >= p_sys->i_start_pts  )
         {
             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pts );
         }
 
-        if( p_sys->i_pts >= p_sys->i_start_pts  )
+        if( i_pts >= p_sys->i_start_pts  )
             if ( p_vsegment->UpdateCurrentToChapter( *p_demux ) )
             {
                 i_return = 1;
+                delete block;
                 break;
             }
         
@@ -3186,7 +3256,10 @@ static int Demux( demux_t *p_demux)
         {
             /* nothing left to read in this ordered edition */
             if ( !p_vsegment->SelectNext() )
+            {
+                delete block;
                 break;
+            }
             p_segment->UnSelect( );
             
             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
@@ -3196,12 +3269,14 @@ static int Demux( demux_t *p_demux)
             if ( !p_segment->Select( 0 ) )
             {
                 msg_Err( p_demux, "Failed to select new segment" );
+                delete block;
                 break;
             }
+            delete block;
             continue;
         }
 
-        BlockDecode( p_demux, block, p_sys->i_pts, i_block_duration );
+        BlockDecode( p_demux, block, i_pts, i_block_duration );
 
         delete block;
         i_block_count++;
@@ -3224,9 +3299,10 @@ static int Demux( demux_t *p_demux)
 /*****************************************************************************
  * Stream managment
  *****************************************************************************/
-vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_ )
+vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_, vlc_bool_t b_owner_ )
 {
     s = s_;
+    b_owner = b_owner_;
     mb_eof = VLC_FALSE;
 }
 
@@ -3275,6 +3351,8 @@ size_t vlc_stream_io_callback::write( const void *p_buffer, size_t i_size )
 }
 uint64 vlc_stream_io_callback::getFilePointer( void )
 {
+    if ( s == NULL )
+        return 0;
     return stream_Tell( s );
 }
 void vlc_stream_io_callback::close( void )
@@ -3916,13 +3994,15 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
         {
             KaxTrackName &tname = *(KaxTrackName*)l;
 
-            tk->fmt.psz_description = UTF8ToStr( UTFstring( tname ) );
+            tk->fmt.psz_description = ToUTF8( UTFstring( tname ) );
             msg_Dbg( &sys.demuxer, "|   |   |   + Track Name=%s", tk->fmt.psz_description );
         }
         else  if( MKV_IS_ID( l, KaxTrackLanguage ) )
         {
             KaxTrackLanguage &lang = *(KaxTrackLanguage*)l;
 
+            if ( tk->fmt.psz_language != NULL )
+                free( tk->fmt.psz_language );
             tk->fmt.psz_language = strdup( string( lang ).c_str() );
             msg_Dbg( &sys.demuxer,
                      "|   |   |   + Track Language=`%s'", tk->fmt.psz_language );
@@ -3950,7 +4030,7 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
         {
             KaxCodecName &cname = *(KaxCodecName*)l;
 
-            tk->psz_codec_name = UTF8ToStr( UTFstring( cname ) );
+            tk->psz_codec_name = ToUTF8( UTFstring( cname ) );
             msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Name=%s", tk->psz_codec_name );
         }
         else if( MKV_IS_ID( l, KaxContentEncodings ) )
@@ -4023,7 +4103,7 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
 //        {
 //            KaxCodecSettings &cset = *(KaxCodecSettings*)l;
 
-//            tk->psz_codec_settings = UTF8ToStr( UTFstring( cset ) );
+//            tk->psz_codec_settings = ToUTF8( UTFstring( cset ) );
 //            msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Settings=%s", tk->psz_codec_settings );
 //        }
 //        else if( EbmlId( *l ) == KaxCodecInfoURL::ClassInfos.GlobalId )
@@ -4060,6 +4140,9 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
             msg_Dbg( &sys.demuxer, "|   |   |   + Track Video" );
             tk->f_fps = 0.0;
 
+            tk->fmt.video.i_frame_rate_base = (unsigned int)(tk->i_default_duration / 1000);
+            tk->fmt.video.i_frame_rate = 1000000;     
+            
             for( j = 0; j < tkv->ListSize(); j++ )
             {
                 EbmlElement *l = (*tkv)[j];
@@ -4137,11 +4220,6 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
             }
             if ( tk->fmt.video.i_visible_height && tk->fmt.video.i_visible_width )
                 tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * tk->fmt.video.i_visible_width / tk->fmt.video.i_visible_height;
-            if( tk->f_fps )
-            {
-                tk->fmt.video.i_frame_rate = (unsigned int)(tk->f_fps * 1001);
-                tk->fmt.video.i_frame_rate_base = 1001;
-            }
         }
         else  if( MKV_IS_ID( l, KaxTrackAudio ) )
         {
@@ -4240,19 +4318,22 @@ void matroska_segment_c::ParseInfo( KaxInfo *info )
 
         if( MKV_IS_ID( l, KaxSegmentUID ) )
         {
-            p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
+            if ( p_segment_uid == NULL )
+                p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
 
             msg_Dbg( &sys.demuxer, "|   |   + UID=%d", *(uint32*)p_segment_uid->GetBuffer() );
         }
         else if( MKV_IS_ID( l, KaxPrevUID ) )
         {
-            p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
+            if ( p_prev_segment_uid == NULL )
+                p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
 
             msg_Dbg( &sys.demuxer, "|   |   + PrevUID=%d", *(uint32*)p_prev_segment_uid->GetBuffer() );
         }
         else if( MKV_IS_ID( l, KaxNextUID ) )
         {
-            p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
+            if ( p_next_segment_uid == NULL )
+                p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
 
             msg_Dbg( &sys.demuxer, "|   |   + NextUID=%d", *(uint32*)p_next_segment_uid->GetBuffer() );
         }
@@ -4278,7 +4359,7 @@ void matroska_segment_c::ParseInfo( KaxInfo *info )
         {
             KaxMuxingApp &mapp = *(KaxMuxingApp*)l;
 
-            psz_muxing_application = UTF8ToStr( UTFstring( mapp ) );
+            psz_muxing_application = ToUTF8( UTFstring( mapp ) );
 
             msg_Dbg( &sys.demuxer, "|   |   + Muxing Application=%s",
                      psz_muxing_application );
@@ -4287,7 +4368,7 @@ void matroska_segment_c::ParseInfo( KaxInfo *info )
         {
             KaxWritingApp &wapp = *(KaxWritingApp*)l;
 
-            psz_writing_application = UTF8ToStr( UTFstring( wapp ) );
+            psz_writing_application = ToUTF8( UTFstring( wapp ) );
 
             msg_Dbg( &sys.demuxer, "|   |   + Writing Application=%s",
                      psz_writing_application );
@@ -4296,7 +4377,7 @@ void matroska_segment_c::ParseInfo( KaxInfo *info )
         {
             KaxSegmentFilename &sfn = *(KaxSegmentFilename*)l;
 
-            psz_segment_filename = UTF8ToStr( UTFstring( sfn ) );
+            psz_segment_filename = ToUTF8( UTFstring( sfn ) );
 
             msg_Dbg( &sys.demuxer, "|   |   + Segment Filename=%s",
                      psz_segment_filename );
@@ -4305,7 +4386,7 @@ void matroska_segment_c::ParseInfo( KaxInfo *info )
         {
             KaxTitle &title = *(KaxTitle*)l;
 
-            psz_title = UTF8ToStr( UTFstring( title ) );
+            psz_title = ToUTF8( UTFstring( title ) );
 
             msg_Dbg( &sys.demuxer, "|   |   + Title=%s", psz_title );
         }
@@ -4313,7 +4394,7 @@ void matroska_segment_c::ParseInfo( KaxInfo *info )
         {
             KaxSegmentFamily *uid = static_cast<KaxSegmentFamily*>(l);
 
-            families.push_back(*uid);
+            families.push_back( new KaxSegmentFamily(*uid) );
 
             msg_Dbg( &sys.demuxer, "|   |   + family=%d", *(uint32*)uid->GetBuffer() );
         }
@@ -4430,10 +4511,12 @@ void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chap
                     for (k = 0; k < i_level; k++)
                         chapters.psz_name += '+';
                     chapters.psz_name += ' ';
-                    chapters.psz_name += UTF8ToStr( UTFstring( name ) );
+                    char *psz_tmp_utf8 = ToUTF8( UTFstring( name ) );
+                    chapters.psz_name += psz_tmp_utf8;
                     chapters.b_user_display = true;
 
-                    msg_Dbg( &sys.demuxer, "|   |   |   |   |    + ChapterString '%s'", UTF8ToStr(UTFstring(name)) );
+                    msg_Dbg( &sys.demuxer, "|   |   |   |   |    + ChapterString '%s'", psz_tmp_utf8 );
+                    free( psz_tmp_utf8 );
                 }
                 else if( MKV_IS_ID( l, KaxChapterLanguage ) )
                 {
@@ -4699,34 +4782,6 @@ void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
 #undef idx
 }
 
-static char * UTF8ToStr( const UTFstring &u )
-{
-    int     i_src;
-    const wchar_t *src;
-    char *dst, *p;
-
-    i_src = u.length();
-    src   = u.c_str();
-
-    p = dst = (char*)malloc( i_src + 1);
-    while( i_src > 0 )
-    {
-        if( *src < 255 )
-        {
-            *p++ = (char)*src;
-        }
-        else
-        {
-            *p++ = '?';
-        }
-        src++;
-        i_src--;
-    }
-    *p++= '\0';
-
-    return dst;
-}
-
 void chapter_edition_c::RefreshChapters( )
 {
     chapter_item_c::RefreshChapters( b_ordered, -1 );
@@ -4767,7 +4822,8 @@ int64_t chapter_item_c::RefreshChapters( bool b_ordered, int64_t i_prev_user_tim
     }
     else
     {
-        std::sort( sub_chapters.begin(), sub_chapters.end() );
+        if ( sub_chapters.begin() != sub_chapters.end() )
+            std::sort( sub_chapters.begin(), sub_chapters.end(), chapter_item_c::CompareTimecode );
         i_user_start_time = i_start_time;
         if ( i_end_time != -1 )
             i_user_end_time = i_end_time;
@@ -4859,7 +4915,7 @@ bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
     {
         for (size_t j=0; j<of_segment.families.size(); j++)
         {
-            if ( families[i] == of_segment.families[j] )
+            if ( *(families[i]) == *(of_segment.families[j]) )
                 return Preload( );
         }
     }
@@ -4923,7 +4979,7 @@ void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
             {
                 sz_name = N_("Segment ");
                 char psz_str[6];
-                sprintf( psz_str, "%d", i );
+                sprintf( psz_str, "%d", (int)i );
                 sz_name += psz_str;
                 p_title->psz_name = strdup( sz_name.c_str() );
             }
@@ -5012,15 +5068,18 @@ void demux_sys_t::JumpTo( virtual_segment_c & vsegment, chapter_item_c * p_chapt
 
 bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
 {
+    if ( p_item_a == NULL || p_item_b == NULL )
+        return false;
+
     EbmlBinary * p_itema = (EbmlBinary *)(p_item_a->p_segment_uid);
-    if ( *p_itema == *p_item_b->p_prev_segment_uid )
+    if ( p_item_b->p_prev_segment_uid != NULL && *p_itema == *p_item_b->p_prev_segment_uid )
         return true;
 
     p_itema = (EbmlBinary *)(&p_item_a->p_next_segment_uid);
-    if ( *p_itema == *p_item_b->p_segment_uid )
+    if ( p_item_b->p_segment_uid != NULL && *p_itema == *p_item_b->p_segment_uid )
         return true;
 
-    if ( *p_itema == *p_item_b->p_prev_segment_uid )
+    if ( p_item_b->p_prev_segment_uid != NULL && *p_itema == *p_item_b->p_prev_segment_uid )
         return true;
 
     return false;
@@ -5296,7 +5355,7 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
             }
         }
 
-        sys.i_pts = sys.i_chapter_time + block->GlobalTimecode() / (mtime_t) 1000;
+        sys.i_last_dts = sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
 
         if( i_track < tracks.size() )
         {
@@ -5307,7 +5366,7 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
             }
             else if( tracks[i_track]->fmt.i_cat == VIDEO_ES )
             {
-                if( i_block_ref1 == -1 && tracks[i_track]->b_search_keyframe )
+                if( i_block_ref1 == 0 && tracks[i_track]->b_search_keyframe )
                 {
                     tracks[i_track]->b_search_keyframe = VLC_FALSE;
                     i_track_skipping--;
@@ -5552,8 +5611,8 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
     if ( i_size != 8 )
         return false;
 
-    virtual_segment_c *p_segment;
-    chapter_item_c *p_chapter;
+    virtual_segment_c *p_segment = NULL;
+    chapter_item_c *p_chapter = NULL;
     bool f_result = false;
     uint16 i_command = ( p_command[0] << 8 ) + p_command[1];