[vlc-devel] [PATCH] Use encoding scope to correctly decode data

Denis Charmet typx at dinauz.org
Tue Nov 13 23:58:53 CET 2012


Fix #5196
---
 modules/demux/mkv/matroska_segment_parse.cpp |   13 +++++
 modules/demux/mkv/mkv.cpp                    |   10 +++-
 modules/demux/mkv/mkv.hpp                    |    8 +++
 modules/demux/mkv/util.cpp                   |   78 +++++++++++++++++++++++++-
 modules/demux/mkv/util.hpp                   |    3 +
 5 files changed, 107 insertions(+), 5 deletions(-)

diff --git a/modules/demux/mkv/matroska_segment_parse.cpp b/modules/demux/mkv/matroska_segment_parse.cpp
index 7f7bba0..cff09a2 100644
--- a/modules/demux/mkv/matroska_segment_parse.cpp
+++ b/modules/demux/mkv/matroska_segment_parse.cpp
@@ -30,6 +30,8 @@
 
 #include "Ebml_parser.hpp"
 
+#include "util.hpp"
+
 /*****************************************************************************
  * Some functions to manipulate memory
  *****************************************************************************/
@@ -199,6 +201,7 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
     tk->psz_codec_download_url = NULL;
 
     tk->i_compression_type     = MATROSKA_COMPRESSION_NONE;
+    tk->i_encoding_scope       = MATROSKA_ENCODING_SCOPE_ALL_FRAMES;
     tk->p_compression_data     = NULL;
 
     msg_Dbg( &sys.demuxer, "|   |   + Track Entry" );
@@ -392,6 +395,7 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
                         else if( MKV_IS_ID( l3, KaxContentEncodingScope ) )
                         {
                             KaxContentEncodingScope &encscope = *(KaxContentEncodingScope*)l3;
+                            tk->i_encoding_scope = uint32( encscope );
                             MkvTree( sys.demuxer, 5, "Scope: %i", uint32( encscope ) );
                         }
                         else if( MKV_IS_ID( l3, KaxContentEncodingType ) )
@@ -654,11 +658,20 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
 
     if ( bSupported )
     {
+#ifdef HAVE_ZLIB_H
+        if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
+            tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_PRIVATE &&
+            tk->i_extra_data && tk->p_extra_data &&
+            zlib_decompress_extra( &sys.demuxer, tk) )
+            return;
+#endif
+
         tracks.push_back( tk );
     }
     else
     {
         msg_Err( &sys.demuxer, "Track Entry %d not supported", tk->i_number );
+        free(tk->p_extra_data);
         delete tk;
     }
 }
diff --git a/modules/demux/mkv/mkv.cpp b/modules/demux/mkv/mkv.cpp
index 84a71a4..6834367 100644
--- a/modules/demux/mkv/mkv.cpp
+++ b/modules/demux/mkv/mkv.cpp
@@ -561,7 +561,9 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
             break;
         }
 
-        if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER && tk->p_compression_data != NULL )
+        if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER &&
+            tk->p_compression_data != NULL &&
+            tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
             p_block = MemToBlock( data->Buffer(), data->Size(), tk->p_compression_data->GetSize() );
         else
             p_block = MemToBlock( data->Buffer(), data->Size(), 0 );
@@ -572,7 +574,8 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
         }
 
 #if defined(HAVE_ZLIB_H)
-        if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB )
+        if( tk->i_compression_type == MATROSKA_COMPRESSION_ZLIB &&
+            tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
         {
             p_block = block_zlib_decompress( VLC_OBJECT(p_demux), p_block );
             if( p_block == NULL )
@@ -580,7 +583,8 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
         }
         else
 #endif
-        if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER )
+        if( tk->i_compression_type == MATROSKA_COMPRESSION_HEADER &&
+            tk->i_encoding_scope & MATROSKA_ENCODING_SCOPE_ALL_FRAMES )
         {
             memcpy( p_block->p_buffer, tk->p_compression_data->GetBuffer(), tk->p_compression_data->GetSize() );
         }
diff --git a/modules/demux/mkv/mkv.hpp b/modules/demux/mkv/mkv.hpp
index 7c7a942..6d6fbc8 100644
--- a/modules/demux/mkv/mkv.hpp
+++ b/modules/demux/mkv/mkv.hpp
@@ -113,6 +113,13 @@ extern "C" {
 #define MATROSKA_COMPRESSION_LZOX   2
 #define MATROSKA_COMPRESSION_HEADER 3
 
+enum
+{
+    MATROSKA_ENCODING_SCOPE_ALL_FRAMES = 1,
+    MATROSKA_ENCODING_SCOPE_PRIVATE = 2,
+    MATROSKA_ENCODING_SCOPE_NEXT = 4 /* unsupported */
+};
+
 #define MKVD_TIMECODESCALE 1000000
 
 #define MKV_IS_ID( el, C ) ( el != NULL && typeid( *el ) == typeid( C ) )
@@ -229,6 +236,7 @@ struct mkv_track_t
 
     /* encryption/compression */
     int                    i_compression_type;
+    uint32_t               i_encoding_scope;
     KaxContentCompSettings *p_compression_data;
 
 };
diff --git a/modules/demux/mkv/util.cpp b/modules/demux/mkv/util.cpp
index 414738b..758335a 100644
--- a/modules/demux/mkv/util.cpp
+++ b/modules/demux/mkv/util.cpp
@@ -21,6 +21,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
+#include "mkv.hpp"
 #include "util.hpp"
 #include "demux.hpp"
 
@@ -30,6 +31,77 @@
  *****************************************************************************/
 
 #ifdef HAVE_ZLIB_H
+int32_t zlib_decompress_extra( demux_t * p_demux, mkv_track_t * tk )
+{
+    int result;
+    z_stream d_stream;
+    size_t n = 0;
+    uint8_t * p_new_extra = NULL;
+
+    msg_Dbg(p_demux,"Inflating private data");
+
+    d_stream.zalloc = Z_NULL;
+    d_stream.zfree = Z_NULL;
+    d_stream.opaque = Z_NULL;
+    if( inflateInit( &d_stream ) != Z_OK )
+    {
+        msg_Err( p_demux, "Couldn't initiate inflation ignore track %d",
+                 tk->i_number );
+        free(tk->p_extra_data);
+        delete tk;
+        return 1;
+    }
+
+    d_stream.next_in = tk->p_extra_data;
+    d_stream.avail_in = tk->i_extra_data;
+    do
+    {
+        n++;
+        p_new_extra = (uint8_t *) realloc(p_new_extra, n*1024);
+        if( !p_new_extra )
+        {
+            msg_Err( p_demux, "Couldn't allocate buffer to inflate data, ignore track %d",
+                      tk->i_number );
+            inflateEnd( &d_stream );
+            free(tk->p_extra_data);
+            delete tk;
+            return 1;
+        }
+        d_stream.next_out = &p_new_extra[(n - 1) * 1024];
+        d_stream.avail_out = 1024;
+        result = inflate(&d_stream, Z_NO_FLUSH);
+        if( result != Z_OK && result != Z_STREAM_END )
+        {
+            msg_Err( p_demux, "Zlib decompression failed. Result: %d", result );
+            inflateEnd( &d_stream );
+            free(p_new_extra);
+            free(tk->p_extra_data);
+            delete tk;
+            return 1;
+        }
+    }
+    while ( d_stream.avail_out == 0 && d_stream.avail_in != 0  &&
+            result != Z_STREAM_END );
+
+    free( tk->p_extra_data );
+    tk->i_extra_data = d_stream.total_out;
+    p_new_extra = (uint8_t *) realloc(p_new_extra, tk->i_extra_data);
+    if( !p_new_extra )
+    {
+        msg_Err( p_demux, "Couldn't allocate buffer to inflate data, ignore track %d",
+                 tk->i_number );
+        inflateEnd( &d_stream );
+        free(p_new_extra);
+        delete tk;
+        return 1;
+    }
+
+    tk->p_extra_data = p_new_extra;
+    
+    inflateEnd( &d_stream );
+    return 0;
+}
+
 block_t *block_zlib_decompress( vlc_object_t *p_this, block_t *p_in_block ) {
     int result, dstsize, n;
     unsigned char *dst;
@@ -61,8 +133,10 @@ block_t *block_zlib_decompress( vlc_object_t *p_this, block_t *p_in_block ) {
         result = inflate(&d_stream, Z_NO_FLUSH);
         if( ( result != Z_OK ) && ( result != Z_STREAM_END ) )
         {
-            msg_Dbg( p_this, "Zlib decompression failed. Result: %d", result );
-            return NULL;
+            msg_Err( p_this, "Zlib decompression failed. Result: %d", result );
+            inflateEnd( &d_stream );
+            block_Release( p_block );
+            return p_in_block;
         }
     }
     while( ( d_stream.avail_out == 0 ) && ( d_stream.avail_in != 0 ) &&
diff --git a/modules/demux/mkv/util.hpp b/modules/demux/mkv/util.hpp
index cd661a8..3ec5a70 100644
--- a/modules/demux/mkv/util.hpp
+++ b/modules/demux/mkv/util.hpp
@@ -25,7 +25,10 @@
 
 #include "mkv.hpp"
 
+#ifdef HAVE_ZLIB_H
+int32_t zlib_decompress_extra( demux_t * p_demux, mkv_track_t * tk );
 block_t *block_zlib_decompress( vlc_object_t *p_this, block_t *p_in_block );
+#endif
 
 block_t *MemToBlock( uint8_t *p_mem, size_t i_mem, size_t offset);
 void handle_real_audio(demux_t * p_demux, mkv_track_t * p_tk, block_t * p_blk, mtime_t i_pts);
-- 
1.7.10.4




More information about the vlc-devel mailing list