[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