]> git.sesse.net Git - vlc/commitdiff
* modules/demux/mkv.cpp: fix for chapters seeking + support for more chapter elements...
authorGildas Bazin <gbazin@videolan.org>
Mon, 14 Feb 2005 09:38:51 +0000 (09:38 +0000)
committerGildas Bazin <gbazin@videolan.org>
Mon, 14 Feb 2005 09:38:51 +0000 (09:38 +0000)
* include/vlc_input.h: added an i_level member to seekpoint_t for nested chapters (patch by Steve Lhomme).

include/vlc_input.h
modules/demux/mkv.cpp

index cae13922dc8cb79ba331ff5e90e0584f0ed31343..1ceab6efb529a4f2d9725678b8f9b89ff4975f04 100644 (file)
@@ -169,6 +169,7 @@ struct seekpoint_t
     int64_t i_byte_offset;
     int64_t i_time_offset;
     char    *psz_name;
+    int     i_level;
 };
 
 static inline seekpoint_t *vlc_seekpoint_New( void )
@@ -176,6 +177,7 @@ static inline seekpoint_t *vlc_seekpoint_New( void )
     seekpoint_t *point = (seekpoint_t*)malloc( sizeof( seekpoint_t ) );
     point->i_byte_offset =
     point->i_time_offset = 0;
+    point->i_level = 0;
     point->psz_name = NULL;
     return point;
 }
index bd2d6a74cacaa1be1c247fc22b6a95f7debb6d0b..24386dde47abd5100e9424b52fa3bcd93f353e84 100644 (file)
@@ -56,7 +56,6 @@
 #include "ebml/EbmlSubHead.h"
 #include "ebml/EbmlStream.h"
 #include "ebml/EbmlContexts.h"
-#include "ebml/EbmlVersion.h"
 #include "ebml/EbmlVoid.h"
 #include "ebml/StdIOCallback.h"
 
@@ -333,6 +332,7 @@ public:
         ,segment(NULL)
         ,cluster(NULL)
         ,i_pts(0)
+        ,i_start_pts(0)
         ,b_cues(false)
         ,i_index(0)
         ,i_index_max(0)
@@ -371,6 +371,7 @@ public:
     KaxSegmentUID           segment_uid;
 
     mtime_t                 i_pts;
+    mtime_t                 i_start_pts;
 
     vlc_bool_t              b_cues;
     int                     i_index;
@@ -390,6 +391,9 @@ public:
 
     std::vector<KaxSegmentFamily> families;
     std::vector<KaxSegment*> family_members;
+
+    int64_t                  edition_uid;
+    bool                     edition_ordered;
 };
 
 #define MKVD_TIMECODESCALE 1000000
@@ -757,6 +761,10 @@ static int Open( vlc_object_t * p_this )
             else if( !strcmp( tk.psz_codec, "V_MPEG4/ISO/AVC" ) )
             {
                 tk.fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
+                tk.fmt.b_packetized = VLC_FALSE;
+                tk.fmt.i_extra = tk.i_extra_data;
+                tk.fmt.p_extra = malloc( tk.i_extra_data );
+                memcpy( tk.fmt.p_extra,tk.p_extra_data, tk.i_extra_data );
             }
             else
             {
@@ -1057,6 +1065,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     demux_sys_t *p_sys = p_demux->p_sys;
     int64_t     *pi64;
     double      *pf, f;
+    int         i_skp;
 
     vlc_meta_t **pp_meta;
 
@@ -1125,11 +1134,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 
         case DEMUX_SET_SEEKPOINT:
             /* FIXME do a better implementation */
-            if( p_sys->title && p_sys->title->i_seekpoint > 0 )
-            {
-                int i_skp = (int)va_arg( args, int );
+            i_skp = (int)va_arg( args, int );
 
+            if( p_sys->title && i_skp < p_sys->title->i_seekpoint)
+            {
                 Seek( p_demux, (int64_t)p_sys->title->seekpoint[i_skp]->i_time_offset, -1);
+                p_demux->info.i_seekpoint |= INPUT_UPDATE_SEEKPOINT;
+                p_demux->info.i_seekpoint = i_skp;
                 return VLC_SUCCESS;
             }
             return VLC_EGENERIC;
@@ -1344,8 +1355,16 @@ static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts,
         }
 #endif
 
-        if( tk.fmt.i_cat != VIDEO_ES )
+        if (i_pts < p_sys->i_start_pts)
+        {
+            p_block->i_pts = -1;
+            p_block->i_dts = -1;
+/*            p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;*/
+        }
+        else if( tk.fmt.i_cat != VIDEO_ES )
+        {
             p_block->i_dts = p_block->i_pts = i_pts;
+        }
         else
         {
             p_block->i_dts = i_pts;
@@ -1390,7 +1409,7 @@ static void Seek( demux_t *p_demux, mtime_t i_date, int i_percent)
     p_sys->cluster = NULL;
 
     /* seek without index or without date */
-    if( config_GetInt( p_demux, "mkv-seek-percent" ) || !p_sys->b_cues || i_date < 0 )
+    if( i_percent >= 0 && (config_GetInt( p_demux, "mkv-seek-percent" ) || !p_sys->b_cues || i_date < 0 ))
     {
         int64_t i_pos = i_percent * stream_Size( p_demux->s ) / 100;
 
@@ -1472,6 +1491,8 @@ static void Seek( demux_t *p_demux, mtime_t i_date, int i_percent)
         }
     }
 
+    p_sys->i_start_pts = i_date;
+
     while( i_track_skipping > 0 )
     {
         if( BlockGet( p_demux, &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
@@ -1481,7 +1502,7 @@ static void Seek( demux_t *p_demux, mtime_t i_date, int i_percent)
             return;
         }
 
-        p_sys->i_pts = block->GlobalTimecode() / (mtime_t) 1000 + 1;
+        p_sys->i_pts = block->GlobalTimecode() / (mtime_t) 1000;
 
         for( i_track = 0; i_track < p_sys->i_track; i_track++ )
         {
@@ -1536,7 +1557,7 @@ static int Demux( demux_t *p_demux)
             return 0;
         }
 
-        p_sys->i_pts = block->GlobalTimecode() / (mtime_t) 1000 + 1;
+        p_sys->i_pts = block->GlobalTimecode() / (mtime_t) 1000;
 
         if( p_sys->i_pts > 0 )
         {
@@ -2616,6 +2637,7 @@ static void ParseChapterAtom( demux_t *p_demux, int i_level, EbmlMaster *ca )
     demux_sys_t *p_sys = p_demux->p_sys;
     unsigned int i;
     seekpoint_t *sk;
+    bool b_display_seekpoint = true;
 
     if( p_sys->title == NULL )
     {
@@ -2623,6 +2645,8 @@ static void ParseChapterAtom( demux_t *p_demux, int i_level, EbmlMaster *ca )
     }
     sk = vlc_seekpoint_New();
 
+    sk->i_level = i_level;
+
     msg_Dbg( p_demux, "|   |   |   + ChapterAtom (level=%d)", i_level );
     for( i = 0; i < ca->ListSize(); i++ )
     {
@@ -2634,6 +2658,13 @@ static void ParseChapterAtom( demux_t *p_demux, int i_level, EbmlMaster *ca )
             uint32_t i_uid = uint32( uid );
             msg_Dbg( p_demux, "|   |   |   |   + ChapterUID: 0x%x", i_uid );
         }
+        else if( MKV_IS_ID( l, KaxChapterFlagHidden ) )
+        {
+            KaxChapterFlagHidden &flag =*(KaxChapterFlagHidden*)l;
+            b_display_seekpoint = uint8( flag ) == 0;
+
+            msg_Dbg( p_demux, "|   |   |   |   + ChapterFlagHidden: %s", b_display_seekpoint ? "no":"yes" );
+        }
         else if( MKV_IS_ID( l, KaxChapterTimeStart ) )
         {
             KaxChapterTimeStart &start =*(KaxChapterTimeStart*)l;
@@ -2660,10 +2691,16 @@ static void ParseChapterAtom( demux_t *p_demux, int i_level, EbmlMaster *ca )
 
                 if( MKV_IS_ID( l, KaxChapterString ) )
                 {
+                    std::string psz;
+                    int k;
+
                     KaxChapterString &name =*(KaxChapterString*)l;
-                    char *psz = UTF8ToStr( UTFstring( name ) );
-                    sk->psz_name = strdup( psz );
-                    msg_Dbg( p_demux, "|   |   |   |   |    + ChapterString '%s'", psz );
+                    for (k = 0; k < i_level; k++)
+                        psz += '+';
+                    psz += ' ';
+                    psz += UTF8ToStr( UTFstring( name ) );
+                    sk->psz_name = strdup( psz.c_str() );
+                    msg_Dbg( p_demux, "|   |   |   |   |    + ChapterString '%s'", UTF8ToStr(UTFstring(name)) );
                 }
                 else if( MKV_IS_ID( l, KaxChapterLanguage ) )
                 {
@@ -2686,10 +2723,18 @@ static void ParseChapterAtom( demux_t *p_demux, int i_level, EbmlMaster *ca )
             ParseChapterAtom( p_demux, i_level+1, static_cast<EbmlMaster *>(l) );
         }
     }
-    // A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value.
-    p_sys->title->i_seekpoint++;
-    p_sys->title->seekpoint = (seekpoint_t**)realloc( p_sys->title->seekpoint, p_sys->title->i_seekpoint * sizeof( seekpoint_t* ) );
-    p_sys->title->seekpoint[p_sys->title->i_seekpoint-1] = sk;
+
+    if (b_display_seekpoint)
+    {
+        // A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value.
+        p_sys->title->i_seekpoint++;
+        p_sys->title->seekpoint = (seekpoint_t**)realloc( p_sys->title->seekpoint, p_sys->title->i_seekpoint * sizeof( seekpoint_t* ) );
+        p_sys->title->seekpoint[p_sys->title->i_seekpoint-1] = sk;
+    }
+    else
+    {
+        vlc_seekpoint_Delete(sk);
+    }
 }
 
 /*****************************************************************************
@@ -2717,6 +2762,7 @@ static void ParseChapters( demux_t *p_demux, EbmlElement *chapters )
             EbmlMaster *E = static_cast<EbmlMaster *>(l );
             unsigned int j;
             msg_Dbg( p_demux, "|   |   + EditionEntry" );
+            p_sys->edition_ordered = false;
             for( j = 0; j < E->ListSize(); j++ )
             {
                 EbmlElement *l = (*E)[j];
@@ -2725,6 +2771,14 @@ static void ParseChapters( demux_t *p_demux, EbmlElement *chapters )
                 {
                     ParseChapterAtom( p_demux, 0, static_cast<EbmlMaster *>(l) );
                 }
+                else if( MKV_IS_ID( l, KaxEditionUID ) )
+                {
+                    p_sys->edition_uid = uint64(*static_cast<KaxEditionUID *>(l));
+                }
+                else if( MKV_IS_ID( l, KaxEditionFlagOrdered ) )
+                {
+                    p_sys->edition_ordered = uint8(*static_cast<KaxEditionFlagOrdered *>(l)) != 0;
+                }
                 else
                 {
                     msg_Dbg( p_demux, "|   |   |   + Unknown (%s)", typeid(*l).name() );