]> git.sesse.net Git - vlc/commitdiff
mkv.cpp: make editions children of chapters
authorSteve Lhomme <robux@videolan.org>
Sun, 3 Apr 2005 16:27:13 +0000 (16:27 +0000)
committerSteve Lhomme <robux@videolan.org>
Sun, 3 Apr 2005 16:27:13 +0000 (16:27 +0000)
modules/demux/mkv.cpp

index 51dc86b961bfd518b27f4afb344a14c9c5a1549c..3b2b549e6b9737b187d524158cce2955ff6bae6a 100644 (file)
@@ -123,11 +123,11 @@ vlc_module_begin();
 
     add_bool( "mkv-use-ordered-chapters", 1, NULL,
             N_("Ordered chapters"),
-            N_("Play chapters in the specified order as specified in the file"), 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 file"), 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"),
@@ -336,7 +336,8 @@ public:
     ,psz_parent(NULL)
     {}
     
-    int64_t RefreshChapters( bool b_ordered, int64_t i_prev_user_time, input_title_t & title );
+    int64_t RefreshChapters( bool b_ordered, int64_t i_prev_user_time );
+    void PublishChapters( input_title_t & title, int i_level );
     const chapter_item_t * FindTimecode( mtime_t i_timecode ) const;
     
     int64_t                     i_start_time, i_end_time;
@@ -358,20 +359,19 @@ protected:
     bool Leave();
 };
 
-class chapter_edition_t 
+class chapter_edition_t : public chapter_item_t
 {
 public:
     chapter_edition_t()
-    :i_uid(-1)
-    ,b_ordered(false)
+    :b_ordered(false)
     {}
     
-    void RefreshChapters( input_title_t & title );
-    double Duration() const;
-    const chapter_item_t * FindTimecode( mtime_t i_timecode ) const;
+    void RefreshChapters( );
+    mtime_t Duration() const;
+    void PublishChapters( input_title_t & title );
+    void Append( const chapter_edition_t & edition );
+    chapter_item_t * FindChapter( const chapter_item_t & chapter ) const;
     
-    std::vector<chapter_item_t> chapters;
-    int64_t                     i_uid;
     bool                        b_ordered;
 };
 
@@ -577,6 +577,7 @@ public:
 
 /* TODO handle/merge chapters here */
     void UpdateCurrentToChapter( demux_t & demux );
+    bool Select( input_title_t & title );
 
 protected:
     std::vector<matroska_segment_t*> linked_segments;
@@ -658,7 +659,7 @@ public:
     matroska_segment_t *FindSegment( const EbmlBinary & uid ) const;
     void PreloadFamily( );
     void PreloadLinked( matroska_segment_t *p_segment );
-    void PreparePlayback( );
+    bool PreparePlayback( );
     matroska_stream_t *AnalyseAllSegmentsFound( EbmlStream *p_estream );
 };
 
@@ -798,12 +799,7 @@ static int Open( vlc_object_t * p_this )
 
     p_sys->PreloadFamily( );
     p_sys->PreloadLinked( p_segment );
-    p_sys->PreparePlayback( );
-
-    /* add information */
-    p_segment->InformationCreate( );
-
-    if ( !p_segment->Select( 0 ) )
+    if ( !p_sys->PreparePlayback( ) )
     {
         msg_Err( p_demux, "cannot use the segment" );
         goto error;
@@ -1332,10 +1328,16 @@ bool matroska_segment_t::Select( mtime_t i_start_time )
         else if( !strcmp( tk->psz_codec, "V_QUICKTIME" ) )
         {
             MP4_Box_t *p_box = (MP4_Box_t*)malloc( sizeof( MP4_Box_t ) );
+#ifdef VSLHC
+            stream_t *p_mp4_stream = stream_MemoryNew( VLC_OBJECT(&sys.demuxer),
+                                                       tk->p_extra_data,
+                                                       tk->i_extra_data );
+#else
             stream_t *p_mp4_stream = stream_MemoryNew( VLC_OBJECT(&sys.demuxer),
                                                        tk->p_extra_data,
                                                        tk->i_extra_data,
                                                        VLC_FALSE );
+#endif
             MP4_ReadBoxCommon( p_mp4_stream, p_box );
             MP4_ReadBox_sample_vide( p_mp4_stream, p_box );
             tk->fmt.i_codec = p_box->i_type;
@@ -1345,7 +1347,11 @@ bool matroska_segment_t::Select( mtime_t i_start_time )
             tk->fmt.p_extra = malloc( tk->fmt.i_extra );
             memcpy( tk->fmt.p_extra, p_box->data.p_sample_vide->p_qt_image_description, tk->fmt.i_extra );
             MP4_FreeBox_sample_vide( p_box );
+#ifdef VSLHC
+            stream_MemoryDelete( p_mp4_stream, VLC_TRUE );
+#else
             stream_Delete( p_mp4_stream );
+#endif        
         }
         else if( !strcmp( tk->psz_codec, "A_MS/ACM" ) )
         {
@@ -1586,6 +1592,65 @@ void matroska_segment_t::UnSelect( )
     }
 }
 
+bool virtual_segment_t::Select( input_title_t & title )
+{
+    if ( linked_segments.size() == 0 )
+        return false;
+
+    // !!! should be called only once !!!
+    matroska_segment_t *p_segment;
+    size_t i, j;
+
+    // copy editions from the first segment
+    p_segment = linked_segments[0];
+    editions = p_segment->stored_editions;
+    i_current_edition = p_segment->i_default_edition;
+
+    for ( i=1 ; i<linked_segments.size(); i++ )
+    {
+        p_segment = linked_segments[i];
+        // FIXME assume we have the same editions in all segments
+        for (j=0; j<p_segment->stored_editions.size(); j++)
+            editions[j].Append( p_segment->stored_editions[j] );
+    }
+
+    Edition()->PublishChapters( title );
+
+    return true;
+}
+
+void chapter_edition_t::PublishChapters( input_title_t & title )
+{
+    title.i_seekpoint = 0;
+    if ( title.seekpoint != NULL )
+        free( title.seekpoint );
+    chapter_item_t::PublishChapters( title, 0 );
+}
+
+void chapter_item_t::PublishChapters( input_title_t & title, int i_level )
+{
+    if (b_display_seekpoint)
+    {
+        seekpoint_t *sk = vlc_seekpoint_New();
+
+        sk->i_level = i_level;
+        sk->i_time_offset = i_start_time;
+        sk->psz_name = strdup( psz_name.c_str() );
+
+        // A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value.
+        title.i_seekpoint++;
+        title.seekpoint = (seekpoint_t**)realloc( title.seekpoint, title.i_seekpoint * sizeof( seekpoint_t* ) );
+        title.seekpoint[title.i_seekpoint-1] = sk;
+    }
+
+    i_seekpoint_num = title.i_seekpoint;
+
+    for ( size_t i=0; i<sub_chapters.size() ; i++)
+    {
+        sub_chapters[i].PublishChapters( title, i_level+1 );
+    }
+}
+
 void virtual_segment_t::UpdateCurrentToChapter( demux_t & demux )
 {
     demux_sys_t & sys = *demux.p_sys;
@@ -1598,7 +1663,7 @@ void virtual_segment_t::UpdateCurrentToChapter( demux_t & demux )
         psz_curr_chapter = editions[i_current_edition].FindTimecode( sys.i_pts );
 
         /* we have moved to a new chapter */
-        if (psz_curr_chapter != NULL && psz_current_chapter != psz_curr_chapter)
+        if (psz_curr_chapter != NULL && psz_current_chapter != NULL && psz_current_chapter != psz_curr_chapter)
         {
             if (psz_current_chapter->i_seekpoint_num != psz_curr_chapter->i_seekpoint_num && psz_curr_chapter->i_seekpoint_num > 0)
             {
@@ -1622,6 +1687,28 @@ void virtual_segment_t::UpdateCurrentToChapter( demux_t & demux )
     }
 }
 
+void chapter_edition_t::Append( const chapter_edition_t & edition )
+{
+    size_t i;
+    chapter_item_t *p_chapter;
+
+    for ( i=0; i<edition.sub_chapters.size(); i++ )
+    {
+        p_chapter = FindChapter( edition.sub_chapters[i] );
+        if ( p_chapter != NULL )
+        {
+        }
+        else
+        {
+        }
+    }
+}
+
+chapter_item_t * chapter_edition_t::FindChapter( const chapter_item_t & chapter ) const
+{
+    return NULL;
+}
+
 static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, const chapter_item_t *psz_chapter )
 {
     demux_sys_t        *p_sys = p_demux->p_sys;
@@ -2986,7 +3073,7 @@ void matroska_segment_t::ParseChapters( EbmlElement *chapters )
     EbmlMaster  *m;
     unsigned int i;
     int i_upper_level = 0;
-    float f_dur;
+    mtime_t i_dur;
 
     /* Master elements */
     m = static_cast<EbmlMaster *>(chapters);
@@ -3011,7 +3098,7 @@ void matroska_segment_t::ParseChapters( EbmlElement *chapters )
                 {
                     chapter_item_t new_sub_chapter;
                     ParseChapterAtom( 0, static_cast<EbmlMaster *>(l), new_sub_chapter );
-                    edition.chapters.push_back( new_sub_chapter );
+                    edition.sub_chapters.push_back( new_sub_chapter );
                 }
                 else if( MKV_IS_ID( l, KaxEditionUID ) )
                 {
@@ -3041,15 +3128,15 @@ void matroska_segment_t::ParseChapters( EbmlElement *chapters )
 
     for( i = 0; i < stored_editions.size(); i++ )
     {
-        stored_editions[i].RefreshChapters( *sys.title );
+        stored_editions[i].RefreshChapters( );
     }
     
     if ( stored_editions[i_default_edition].b_ordered )
     {
         /* update the duration of the segment according to the sum of all sub chapters */
-        f_dur = stored_editions[i_default_edition].Duration() / I64C(1000);
-        if (f_dur > 0.0)
-            i_duration = f_dur;
+        i_dur = stored_editions[i_default_edition].Duration() / I64C(1000);
+        if (i_dur > 0)
+            i_duration = i_dur;
     }
 }
 
@@ -3204,19 +3291,13 @@ static char * UTF8ToStr( const UTFstring &u )
     return dst;
 }
 
-void chapter_edition_t::RefreshChapters( input_title_t & title )
+void chapter_edition_t::RefreshChapters( )
 {
-    int64_t i_prev_user_time = 0;
-    std::vector<chapter_item_t>::iterator index = chapters.begin();
-
-    while ( index != chapters.end() )
-    {
-        i_prev_user_time = (*index).RefreshChapters( b_ordered, i_prev_user_time, title );
-        index++;
-    }
+    chapter_item_t::RefreshChapters( b_ordered, -1 );
+    b_display_seekpoint = false;
 }
 
-int64_t chapter_item_t::RefreshChapters( bool b_ordered, int64_t i_prev_user_time, input_title_t & title )
+int64_t chapter_item_t::RefreshChapters( bool b_ordered, int64_t i_prev_user_time )
 {
     int64_t i_user_time = i_prev_user_time;
     
@@ -3224,7 +3305,7 @@ int64_t chapter_item_t::RefreshChapters( bool b_ordered, int64_t i_prev_user_tim
     std::vector<chapter_item_t>::iterator index = sub_chapters.begin();
     while ( index != sub_chapters.end() )
     {
-        i_user_time = (*index).RefreshChapters( b_ordered, i_user_time, title );
+        i_user_time = (*index).RefreshChapters( b_ordered, i_user_time );
         index++;
     }
 
@@ -3244,40 +3325,29 @@ int64_t chapter_item_t::RefreshChapters( bool b_ordered, int64_t i_prev_user_tim
     {
         std::sort( sub_chapters.begin(), sub_chapters.end() );
         i_user_start_time = i_start_time;
-        i_user_end_time = i_end_time;
-    }
-
-    if (b_display_seekpoint)
-    {
-        seekpoint_t *sk = vlc_seekpoint_New();
-
-//        sk->i_level = i_level;
-        sk->i_time_offset = i_start_time;
-        sk->psz_name = strdup( psz_name.c_str() );
-
-        // A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value.
-        title.i_seekpoint++;
-        title.seekpoint = (seekpoint_t**)realloc( title.seekpoint, title.i_seekpoint * sizeof( seekpoint_t* ) );
-        title.seekpoint[title.i_seekpoint-1] = sk;
+        if ( i_end_time != -1 )
+            i_user_end_time = i_end_time;
+        else if ( i_user_time != -1 )
+            i_user_end_time = i_user_time;
+        else
+            i_user_end_time = i_user_start_time;
     }
 
-    i_seekpoint_num = title.i_seekpoint;
-
     return i_user_end_time;
 }
 
-double chapter_edition_t::Duration() const
+mtime_t chapter_edition_t::Duration() const
 {
-    double f_result = 0.0;
+    mtime_t i_result = 0.0;
     
-    if ( chapters.size() )
+    if ( sub_chapters.size() )
     {
-        std::vector<chapter_item_t>::const_iterator index = chapters.end();
+        std::vector<chapter_item_t>::const_iterator index = sub_chapters.end();
         index--;
-        f_result = (*index).i_user_end_time;
+        i_result = (*index).i_user_end_time;
     }
     
-    return f_result;
+    return i_result;
 }
 
 const chapter_item_t *chapter_item_t::FindTimecode( mtime_t i_user_timecode ) const
@@ -3300,20 +3370,6 @@ const chapter_item_t *chapter_item_t::FindTimecode( mtime_t i_user_timecode ) co
     return psz_result;
 }
 
-const chapter_item_t *chapter_edition_t::FindTimecode( mtime_t i_user_timecode ) const
-{
-    const chapter_item_t *psz_result = NULL;
-
-    std::vector<chapter_item_t>::const_iterator index = chapters.begin();
-    while ( index != chapters.end() && psz_result == NULL )
-    {
-        psz_result = (*index).FindTimecode( i_user_timecode );
-        index++;
-    }
-
-    return psz_result;
-}
-
 void demux_sys_t::PreloadFamily( )
 {
 /* TODO enable family handling again
@@ -3379,10 +3435,15 @@ void demux_sys_t::PreloadLinked( matroska_segment_t *p_segment )
     p_current_segment->PreloadLinked( );
 }
 
-void demux_sys_t::PreparePlayback( )
+bool demux_sys_t::PreparePlayback( )
 {
     p_current_segment->LoadCues();
     f_duration = p_current_segment->Duration();
+
+    /* add information */
+    p_current_segment->Segment()->InformationCreate( );
+
+    return p_current_segment->Select( *title );
 }
 
 bool matroska_segment_t::CompareSegmentUIDs( const matroska_segment_t * p_item_a, const matroska_segment_t * p_item_b )