vlc | branch: master | Denis Charmet <[email protected]> | Tue Nov 13 23:58:53 2012 +0100| [b42bf2478e7f43b827019b9e5fef5869ecc85c57] | committer: Jean-Baptiste Kempf
Use encoding scope to correctly decode data Fix #5196 Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b42bf2478e7f43b827019b9e5fef5869ecc85c57 --- 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 dd6bbca..6d9ab63 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); _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
