]> git.sesse.net Git - vlc/blobdiff - modules/demux/mkv/matroska_segment.cpp
MKV : Add MJPEG codec ID.
[vlc] / modules / demux / mkv / matroska_segment.cpp
index 6fe1d1b77235cbb920e52850a4913d9b3f7e48f5..29b55b1ec56ff95dd7a959f25b65387ad65ce71f 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * mkv.cpp : matroska demuxer
  *****************************************************************************
- * Copyright (C) 2003-2004 the VideoLAN team
+ * Copyright (C) 2003-2010 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
@@ -205,6 +205,67 @@ void matroska_segment_c::LoadCues( KaxCues *cues )
     }                                      \
     ep->Up(); } while( 0 )
 
+static const struct {
+    vlc_meta_type_t type;
+    const char *key;
+} metadata_map[] = { {vlc_meta_Title,       "TITLE"},
+                     {vlc_meta_Artist,      "ARTIST"},
+                     {vlc_meta_Genre,       "GENRE"},
+                     {vlc_meta_Copyright,   "COPYRIGHT"},
+                     {vlc_meta_Description, "DESCRIPTION"},
+                     {vlc_meta_Publisher,   "PUBLISHER"},
+                     {vlc_meta_URL,         "URL"},
+                     {vlc_meta_Title,       NULL},
+};
+
+void matroska_segment_c::ParseSimpleTags( KaxTagSimple *tag )
+{
+    EbmlElement *el;
+    EbmlParser *ep = new EbmlParser( &es, tag, &sys.demuxer );
+    char *k = NULL, *v = NULL;
+
+    if( !sys.meta )
+        sys.meta = vlc_meta_New();
+
+    msg_Dbg( &sys.demuxer, "|   + Simple Tag ");
+    while( ( el = ep->Get() ) != NULL )
+    {
+        if( MKV_IS_ID( el, KaxTagName ) )
+        {
+            KaxTagName &key = *(KaxTagName*)el;
+            key.ReadData( es.I_O(), SCOPE_ALL_DATA );
+            k = strdup( UTFstring( key ).GetUTF8().c_str() );
+        }
+        if( MKV_IS_ID( el, KaxTagString ) )
+        {
+            KaxTagString &value = *(KaxTagString*)el;
+            value.ReadData( es.I_O(), SCOPE_ALL_DATA );
+            v = strdup( UTFstring( value ).GetUTF8().c_str() );
+        }
+    }
+    delete ep;
+
+    if( !k || !v )
+    {
+        msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found.");
+        return;
+    }
+
+    for( int i = 0; metadata_map[i].key; i++ )
+    {
+        if( !strcmp( k, metadata_map[i].key ) )
+        {
+            vlc_meta_Set( sys.meta, metadata_map[i].type, v );
+            goto done;
+        }
+    }
+    vlc_meta_AddExtra( sys.meta, k, v );
+done:
+    free( k );
+    free( v );
+    return;
+}
+
 void matroska_segment_c::LoadTags( KaxTags *tags )
 {
     /* Master elements */
@@ -257,6 +318,8 @@ void matroska_segment_c::LoadTags( KaxTags *tags )
                 {
                     msg_Dbg( &sys.demuxer, "|   + Multi Title" );
                 }
+                else if( MKV_IS_ID( el, KaxTagSimple ) )
+                    ParseSimpleTags( static_cast<KaxTagSimple*>( el ) );
                 else
                 {
                     msg_Dbg( &sys.demuxer, "|   + LoadTag Unknown (%s)", typeid( *el ).name() );
@@ -280,6 +343,7 @@ void matroska_segment_c::LoadTags( KaxTags *tags )
  *****************************************************************************/
 void matroska_segment_c::InformationCreate( )
 {
+#if 0
     sys.meta = vlc_meta_New();
 
     if( psz_title )
@@ -290,7 +354,7 @@ void matroska_segment_c::InformationCreate( )
     {
         vlc_meta_SetDate( sys.meta, psz_date_utc );
     }
-#if 0
+
     if( psz_segment_filename )
     {
         fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
@@ -349,7 +413,6 @@ void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
 #undef idx
 }
 
-
 bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
 {
     if ( b_preloaded )
@@ -478,6 +541,8 @@ bool matroska_segment_c::Preload( )
                 ;//LoadTags( static_cast<KaxTags*>( el ) );
             i_tags_position = (int64_t) es.I_O().getFilePointer();
         }
+        else if( MKV_IS_ID( el, EbmlVoid ) )
+            msg_Dbg( &sys.demuxer, "|   + Void" );
         else
             msg_Dbg( &sys.demuxer, "|   + Preload Unknown (%s)", typeid(*el).name() );
     }
@@ -557,11 +622,11 @@ bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int
             ParseChapters( static_cast<KaxChapters*>( el ) );
         i_chapters_position = i_element_position;
     }
-    else if( MKV_IS_ID( el, KaxTag ) ) // FIXME
+    else if( MKV_IS_ID( el, KaxTags ) )
     {
         msg_Dbg( &sys.demuxer, "|   + Tags" );
         if( i_tags_position < 0 )
-            ;//LoadTags( static_cast<KaxTags*>( el ) );
+            LoadTags( static_cast<KaxTags*>( el ) );
         i_tags_position = i_element_position;
     }
     else
@@ -719,12 +784,10 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
     }
 }
 
-
 int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,
                                              const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock )
 {
     size_t i_track;
-
     for( i_track = 0; i_track < tracks.size(); i_track++ )
     {
         const mkv_track_t *tk = tracks[i_track];
@@ -744,6 +807,13 @@ int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,
     return VLC_SUCCESS;
 }
 
+static inline void fill_extra_data( mkv_track_t *p_tk )
+{
+      p_tk->fmt.i_extra = p_tk->i_extra_data;
+      p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
+      memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+}
+
 bool matroska_segment_c::Select( mtime_t i_start_time )
 {
     /* add all es */
@@ -790,13 +860,13 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
                  !strcmp( p_tk->psz_codec, "V_MPEG2" ) )
         {
             p_tk->fmt.i_codec = VLC_CODEC_MPGV;
+            if( p_tk->i_extra_data )
+                fill_extra_data( p_tk );
         }
         else if( !strncmp( p_tk->psz_codec, "V_THEORA", 8 ) )
         {
             p_tk->fmt.i_codec = VLC_CODEC_THEORA;
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
             p_tk->b_pts_only = true;
         }
         else if( !strncmp( p_tk->psz_codec, "V_REAL/RV", 9 ) )
@@ -843,9 +913,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
                     p_tk->fmt.i_codec = VLC_FOURCC( 'a', 'v', 'c', '1' );
                 else
                     p_tk->fmt.i_codec = VLC_CODEC_MP4V;
-                p_tk->fmt.i_extra = p_tk->i_extra_data;
-                p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-                memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+                fill_extra_data( p_tk );
             }
         }
         else if( !strcmp( p_tk->psz_codec, "V_QUICKTIME" ) )
@@ -872,6 +940,10 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             }
             stream_Delete( p_mp4_stream );
         }
+        else if( !strcmp( p_tk->psz_codec, "V_MJPEG" ) )
+        {
+            p_tk->fmt.i_codec = VLC_CODEC_MJPG;
+        }
         else if( !strcmp( p_tk->psz_codec, "A_MS/ACM" ) )
         {
             if( p_tk->i_extra_data < (int)sizeof( WAVEFORMATEX ) )
@@ -930,16 +1002,12 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
         else if( !strcmp( p_tk->psz_codec, "A_FLAC" ) )
         {
             p_tk->fmt.i_codec = VLC_CODEC_FLAC;
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
         }
         else if( !strcmp( p_tk->psz_codec, "A_VORBIS" ) )
         {
             p_tk->fmt.i_codec = VLC_CODEC_VORBIS;
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
         }
         else if( !strncmp( p_tk->psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
                  !strncmp( p_tk->psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
@@ -1004,25 +1072,19 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
         else if( !strcmp( p_tk->psz_codec, "A_AAC" ) )
         {
             p_tk->fmt.i_codec = VLC_CODEC_MP4A;
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
         }
         else if( !strcmp( p_tk->psz_codec, "A_WAVPACK4" ) )
         {
             p_tk->fmt.i_codec = VLC_CODEC_WAVPACK;
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
         }
         else if( !strcmp( p_tk->psz_codec, "A_TTA1" ) )
         {
             p_fmt->i_codec = VLC_CODEC_TTA;
-            p_fmt->i_extra = p_tk->i_extra_data;
-            if( p_fmt->i_extra > 0 )
+            if( p_tk->i_extra_data > 0 )
             {
-                p_fmt->p_extra = xmalloc( p_tk->i_extra_data );
-                memcpy( p_fmt->p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+                fill_extra_data( p_tk );
             }
             else
             {
@@ -1061,9 +1123,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             else if( !strcmp( p_tk->psz_codec, "A_REAL/28_8" ) )
                 p_tk->fmt.i_codec = VLC_CODEC_RA_288;
             /* FIXME 14_4, RALF and SIPR */
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
         }
         else if( !strcmp( p_tk->psz_codec, "A_REAL/14_4" ) )
         {
@@ -1081,9 +1141,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             p_tk->fmt.i_codec = VLC_CODEC_KATE;
             p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
 
-            p_tk->fmt.i_extra = p_tk->i_extra_data;
-            p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-            memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+            fill_extra_data( p_tk );
         }
         else if( !strcmp( p_tk->psz_codec, "S_TEXT/ASCII" ) )
         {
@@ -1101,9 +1159,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
             if( p_tk->i_extra_data )
             {
-                p_tk->fmt.i_extra = p_tk->i_extra_data;
-                p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-                memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+                fill_extra_data( p_tk );
             }
         }
         else if( !strcmp( p_tk->psz_codec, "S_TEXT/SSA" ) ||
@@ -1115,9 +1171,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
             if( p_tk->i_extra_data )
             {
-                p_tk->fmt.i_extra = p_tk->i_extra_data;
-                p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
-                memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+                fill_extra_data( p_tk );
             }
         }
         else if( !strcmp( p_tk->psz_codec, "S_VOBSUB" ) )
@@ -1196,7 +1250,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
         }
     }
     es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_start_time );
+
     sys.i_start_pts = i_start_time;
     // reset the stream reading to the first cluster of the segment used
     es.I_O().setFilePointer( i_start_pos );
@@ -1209,9 +1263,7 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
 
 void matroska_segment_c::UnSelect( )
 {
-    size_t i_track;
-
-    for( i_track = 0; i_track < tracks.size(); i_track++ )
+    for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
     {
         if ( tracks[i_track]->p_es != NULL )
         {