Skip to content

Commit

Permalink
Correctly repacketize wavpack frames from Matroska
Browse files Browse the repository at this point in the history
Since libavcodec decoder doesn't expect matroska formatted wavpack anymore.
  • Loading branch information
TypX committed Sep 2, 2013
1 parent be64714 commit 8d0ea8a
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
2 changes: 2 additions & 0 deletions modules/demux/mkv/mkv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
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 if( unlikely( tk->fmt.i_codec == VLC_CODEC_WAVPACK ) )
p_block = packetize_wavpack(tk, data->Buffer(), data->Size());
else
p_block = MemToBlock( data->Buffer(), data->Size(), 0 );

Expand Down
91 changes: 91 additions & 0 deletions modules/demux/mkv/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,94 @@ Cook_PrivateTrackData::~Cook_PrivateTrackData()

free( p_subpackets );
}

static inline void fill_wvpk_block(uint16_t version, uint32_t block_samples, uint32_t flags,
uint32_t crc, uint8_t * src, size_t srclen, uint8_t * dst)
{
const uint8_t wvpk_header[] = {'w','v','p','k', /* ckId */
0x0, 0x0, 0x0, 0x0, /* ckSize */
0x0, 0x0, /* version */
0x0, /* track_no */
0x0, /* index_no */
0xFF, 0xFF, 0xFF, 0xFF, /* total_samples */
0x0, 0x0, 0x0, 0x0 }; /* block_index */
memcpy( dst, wvpk_header, sizeof( wvpk_header ) );
SetDWLE( dst + 4, srclen + 24 );
SetWLE( dst + 8, version );
SetDWLE( dst + 20, block_samples );
SetDWLE( dst + 24, flags );
SetDWLE( dst + 28, crc );
memcpy( dst + 32, src, srclen );
}

block_t * packetize_wavpack( mkv_track_t * p_tk, uint8_t * buffer, size_t size)
{
uint16_t version = 0x403;
uint32_t block_samples;
uint32_t flags;
uint32_t crc;
block_t * p_block = NULL;

if( p_tk->i_extra_data >= 2 )
version = GetWLE( p_tk->p_extra_data );

if( size < 12 )
return NULL;

block_samples = GetDWLE(buffer);
buffer += 4;
flags = GetDWLE(buffer);
size -= 4;

/* Check if WV_INITIAL_BLOCK and WV_FINAL_BLOCK are present */
if( ( flags & 0x1800 ) == 0x1800 )
{
crc = GetDWLE(buffer+4);
buffer += 8;
size -= 8;

p_block = block_Alloc( size + 32 );
if( !p_block )
return NULL;

fill_wvpk_block(version, block_samples, flags, crc, buffer, size, p_block->p_buffer);
}
else
{
/* Multiblock */
size_t total_size = 0;

p_block = block_Alloc( 0 );
if( !p_block )
return NULL;

while(size >= 12)
{
flags = GetDWLE(buffer);
buffer += 4;
crc = GetDWLE(buffer);
buffer += 4;
uint32_t bsz = GetDWLE(buffer);
buffer+= 4;
size -= 12;

bsz = (bsz < size)?bsz:size;

total_size += bsz + 32;

assert(total_size >= p_block->i_buffer);

p_block = block_Realloc( p_block, 0, total_size );

if( !p_block )
return NULL;

fill_wvpk_block(version, block_samples, flags, crc, buffer, bsz,
p_block->p_buffer + total_size - bsz - 32 );
buffer += bsz;
size -= bsz;
}
}

return p_block;
}
2 changes: 2 additions & 0 deletions modules/demux/mkv/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,5 @@ class Cook_PrivateTrackData : public PrivateTrackData
size_t i_subpackets;
size_t i_subpacket;
};

block_t * packetize_wavpack( mkv_track_t *, uint8_t *, size_t);

0 comments on commit 8d0ea8a

Please sign in to comment.