]> git.sesse.net Git - vlc/blobdiff - modules/demux/mkv.cpp
i18n fixes
[vlc] / modules / demux / mkv.cpp
index 3e556cfb9b25fa11e50f81ce79a125124afe3303..39497fa85c0f9c55e2019e45c6d564307dc29d17 100644 (file)
@@ -62,6 +62,7 @@
 #include "ebml/StdIOCallback.h"
 
 #include "matroska/KaxAttachments.h"
+#include "matroska/KaxAttached.h"
 #include "matroska/KaxBlock.h"
 #include "matroska/KaxBlockData.h"
 #include "matroska/KaxChapters.h"
@@ -1154,6 +1155,7 @@ public:
     bool Preload( );
     bool PreloadFamily( const matroska_segment_c & segment );
     void ParseInfo( KaxInfo *info );
+    void ParseAttachments( KaxAttachments *attachments );
     void ParseChapters( KaxChapters *chapters );
     void ParseSeekHead( KaxSeekHead *seekhead );
     void ParseTracks( KaxTracks *tracks );
@@ -1298,6 +1300,25 @@ typedef struct
 
 } event_thread_t;
 
+
+class attachment_c
+{
+public:
+    attachment_c()
+        :p_data(NULL)
+        ,i_size(0)
+    {}
+    virtual ~attachment_c()
+    {
+        if( p_data ) free( p_data );
+    }
+
+    std::string    psz_file_name;
+    std::string    psz_mime_type;
+    void          *p_data;
+    int            i_size;
+};
+
 class demux_sys_t
 {
 public:
@@ -1329,6 +1350,8 @@ public:
             delete opened_segments[i];
         for ( i=0; i<used_segments.size(); i++ )
             delete used_segments[i];
+        for ( i=0; i<stored_attachments.size(); i++ )
+            delete stored_attachments[i];
         if( meta ) vlc_meta_Delete( meta );
 
         while( titles.size() )
@@ -1350,6 +1373,7 @@ public:
     size_t                           i_current_title;
 
     std::vector<matroska_stream_c*>  streams;
+    std::vector<attachment_c*>       stored_attachments;
     std::vector<matroska_segment_c*> opened_segments;
     std::vector<virtual_segment_c*>  used_segments;
     virtual_segment_c                *p_current_segment;
@@ -1520,8 +1544,16 @@ static int Open( vlc_object_t * p_this )
 #endif
                         {
                             // test wether this file belongs to our family
+                            uint8_t *p_peek;
+                            bool file_ok = false;
                             stream_t *p_file_stream = stream_UrlNew( p_demux, s_filename.c_str());
-                            if ( p_file_stream != NULL )
+                            /* peek the begining */
+                            if( p_file_stream &&
+                                stream_Peek( p_file_stream, &p_peek, 4 ) >= 4
+                                && p_peek[0] == 0x1a && p_peek[1] == 0x45 &&
+                                p_peek[2] == 0xdf && p_peek[3] == 0xa3 ) file_ok = true;
+
+                            if ( file_ok )
                             {
                                 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);
@@ -1543,6 +1575,9 @@ static int Open( vlc_object_t * p_this )
                             }
                             else
                             {
+                                if( p_file_stream ) {
+                                    stream_Delete( p_file_stream );
+                                }
                                 msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() );
                             }
                         }
@@ -1596,9 +1631,32 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     size_t      i_idx;
 
     vlc_meta_t *p_meta;
+    input_attachment_t ***ppp_attach;
+    int *pi_int;
+    int i;
 
     switch( i_query )
     {
+        case DEMUX_GET_ATTACHMENTS:
+            ppp_attach = (input_attachment_t***)va_arg( args, input_attachment_t*** );
+            pi_int = (int*)va_arg( args, int * );
+
+            if( p_sys->stored_attachments.size() <= 0 )
+                return VLC_EGENERIC;
+
+            *pi_int = p_sys->stored_attachments.size();
+            *ppp_attach = (input_attachment_t**)malloc( sizeof(input_attachment_t**) *
+                                                        p_sys->stored_attachments.size() );
+            if( !(*ppp_attach) )
+                return VLC_ENOMEM;
+            for( i = 0; i < p_sys->stored_attachments.size(); i++ )
+            {
+                attachment_c *a = p_sys->stored_attachments[i];
+                (*ppp_attach)[i] = vlc_input_attachment_New( a->psz_file_name.c_str(), a->psz_mime_type.c_str(), NULL,
+                                                             a->p_data, a->i_size );
+            }
+            return VLC_SUCCESS;
+
         case DEMUX_GET_META:
             p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
             vlc_meta_Merge( p_meta, p_sys->meta );
@@ -2132,7 +2190,10 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlS
                 p_stream1->segments.push_back( p_segment1 );
             }
             else
+            {
+                p_segment1->segment = NULL;
                 delete p_segment1;
+            }
         }
         if (p_l0->IsFiniteSize() )
         {
@@ -2489,6 +2550,17 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             tracks[i_track]->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
             tracks[i_track]->fmt.subs.psz_encoding = strdup( "UTF-8" );
         }
+        else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/USF" ) )
+        {
+            tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 's', 'f', ' ' );
+            tracks[i_track]->fmt.subs.psz_encoding = strdup( "UTF-8" );
+            if( tracks[i_track]->i_extra_data )
+            {
+                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 );
+            }
+        }
         else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/SSA" ) ||
                  !strcmp( tracks[i_track]->psz_codec, "S_TEXT/ASS" ) ||
                  !strcmp( tracks[i_track]->psz_codec, "S_SSA" ) ||
@@ -2588,8 +2660,7 @@ void demux_sys_t::StopUiThread()
 {
     if ( b_ui_hooked )
     {
-        p_ev->b_die = VLC_TRUE;
-
+        vlc_object_kill( p_ev );
         vlc_thread_join( p_ev );
         vlc_object_destroy( p_ev );
 
@@ -4889,6 +4960,48 @@ void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chap
     }
 }
 
+/*****************************************************************************
+ * ParseAttachments:
+ *****************************************************************************/
+void matroska_segment_c::ParseAttachments( KaxAttachments *attachments )
+{
+    EbmlElement *el;
+    int i_upper_level = 0;
+
+    attachments->Read( es, attachments->Generic().Context, i_upper_level, el, true );
+
+    KaxAttached *attachedFile = FindChild<KaxAttached>( *attachments );
+
+    while( attachedFile && ( attachedFile->GetSize() > 0 ) )
+    {
+        std::string psz_mime_type  = GetChild<KaxMimeType>( *attachedFile );
+        KaxFileName  &file_name    = GetChild<KaxFileName>( *attachedFile );
+        KaxFileData  &img_data     = GetChild<KaxFileData>( *attachedFile );
+
+        attachment_c *new_attachment = new attachment_c();
+
+        if( new_attachment )
+        {
+            new_attachment->psz_file_name  = ToUTF8( UTFstring( file_name ) );
+            new_attachment->psz_mime_type  = psz_mime_type;
+            new_attachment->i_size         = img_data.GetSize();
+            new_attachment->p_data         = malloc( img_data.GetSize() );
+
+            if( new_attachment->p_data )
+            {
+                memcpy( new_attachment->p_data, img_data.GetBuffer(), img_data.GetSize() );
+                sys.stored_attachments.push_back( new_attachment );
+            }
+            else
+            {
+                delete new_attachment;
+            }
+        }
+
+        attachedFile = &GetNextChild<KaxAttached>( *attachments, *attachedFile );
+    }
+}
+
 /*****************************************************************************
  * ParseChapters:
  *****************************************************************************/
@@ -5359,6 +5472,9 @@ bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a
         return true;
 
     p_tmp = (EbmlBinary *)p_item_a->p_next_segment_uid;
+    if ( !p_tmp )
+        return false;
+    
     if ( p_item_b->p_segment_uid != NULL
           && *p_tmp == *p_item_b->p_segment_uid )
         return true;
@@ -5417,7 +5533,8 @@ bool matroska_segment_c::Preload( )
         }
         else if( MKV_IS_ID( el, KaxAttachments ) )
         {
-            msg_Dbg( &sys.demuxer, "|   + Attachments FIXME (but probably never supported)" );
+            msg_Dbg( &sys.demuxer, "|   + Attachments" );
+            ParseAttachments( static_cast<KaxAttachments*>( el ) );
         }
         else if( MKV_IS_ID( el, KaxChapters ) )
         {
@@ -5648,13 +5765,23 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
 
         for( i_track = 0; i_track < tracks.size(); i_track++ )
         {
+#if LIBMATROSKA_VERSION >= 0x000800
+            if( (simpleblock && tracks[i_track]->i_number == simpleblock->TrackNum()) ||
+                (block && tracks[i_track]->i_number == block->TrackNum()) )
+#else
             if( tracks[i_track]->i_number == block->TrackNum() )
+#endif
             {
                 break;
             }
         }
 
-        sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
+#if LIBMATROSKA_VERSION >= 0x000800
+        if( simpleblock )
+            sys.i_pts = (sys.i_chapter_time + simpleblock->GlobalTimecode()) / (mtime_t) 1000;
+        else
+#endif
+            sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
 
         if( i_track < tracks.size() )
         {