Ensure extra data is passed to decoder

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31003 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul 2009-06-10 02:49:45 +00:00
parent 3db68fb0bb
commit cbec1ef4af
2 changed files with 46 additions and 34 deletions

View File

@ -31,7 +31,7 @@
#include "WavReaderPlugin.h"
#include "RawFormats.h"
//#define TRACE_WAVE_READER
#define TRACE_WAVE_READER
#ifdef TRACE_WAVE_READER
#define TRACE printf
#else
@ -136,12 +136,13 @@ WavReader::Sniff(int32 *streamCount)
return B_ERROR;
}
format_struct format;
wave_format_ex wav_format;
wave_format_ex format;
format_struct_extensible format_ext;
mpeg1_wav_format mpeg1_format;
mpeg3_wav_format mpeg3_format;
uint32 wavFmtSize = sizeof(format_struct) + 2;
fact_struct fact;
// read all chunks and search for "fact", "fmt" (normal or extensible) and "data"
@ -167,49 +168,56 @@ WavReader::Sniff(int32 *streamCount)
switch (UINT32(chunk.fourcc)) {
case FOURCC('f','m','t',' '):
// So what do we have a std format structure, a wav_format structure or a extended structure
if (UINT32(chunk.len) >= sizeof(wav_format)) {
// Read both format and wav format
if (sizeof(format) != Source()->ReadAt(pos, &format, sizeof(format))) {
if (UINT32(chunk.len) >= wavFmtSize) {
// Must be some sort of extended format structure
// First Read common data + extra size
if (wavFmtSize != Source()->ReadAt(pos, &format, wavFmtSize)) {
ERROR("WavReader::Sniff: format chunk reading failed\n");
break;
}
if (sizeof(wav_format) != Source()->ReadAt(pos, &wav_format, sizeof(wav_format))) {
ERROR("WavReader::Sniff: format chunk reading failed\n");
break;
// If extra size seems valid then re-read with the extra data included
if (UINT16(format.extra_size) > 0 && UINT16(format.extra_size) < 64) {
// Read the extra data we need to pass across to the decoder
if ((wavFmtSize + format.extra_size) != Source()->ReadAt(pos, &format, wavFmtSize + format.extra_size)) {
ERROR("WavReader::Sniff: format extensible chunk reading failed\n");
break;
}
}
foundFmt = true;
if (UINT16(wav_format.extra_size) == 12) {
// Check for structure we recognise and might need values from.
if (UINT16(format.extra_size) == 12) {
// MPEG3 WAV FORMAT Structure
if (sizeof(mpeg3_format) != Source()->ReadAt(pos, &mpeg3_format, sizeof(mpeg3_format))) {
ERROR("WavReader::Sniff: format chunk reading failed\n");
break;
}
foundMPEG3 = true;
}
if (UINT16(wav_format.extra_size) == 22) {
// MPEG1 WAV FORMAT Structure
if (sizeof(mpeg1_format) != Source()->ReadAt(pos, &mpeg1_format, sizeof(mpeg1_format))) {
ERROR("WavReader::Sniff: format chunk reading failed\n");
break;
} else if (UINT16(format.extra_size) == 22) {
if (UINT16(format.format_tag) == 0xfffe) {
// GUID structure
if (sizeof(format_ext) != Source()->ReadAt(pos, &format_ext, sizeof(format_ext))) {
ERROR("WavReader::Sniff: format extensible chunk reading failed\n");
break;
}
foundFmtExt = true;
} else {
// MPEG1 WAV FORMAT Structure
if (sizeof(mpeg1_format) != Source()->ReadAt(pos, &mpeg1_format, sizeof(mpeg1_format))) {
ERROR("WavReader::Sniff: format chunk reading failed\n");
break;
}
foundMPEG1 = true;
}
foundMPEG1 = true;
}
} else if (UINT32(chunk.len) >= sizeof(format)) {
if (sizeof(format) != Source()->ReadAt(pos, &format, sizeof(format))) {
} else if (UINT32(chunk.len) >= wavFmtSize - 2) {
if ((wavFmtSize - 2) != Source()->ReadAt(pos, &format, wavFmtSize - 2)) {
ERROR("WavReader::Sniff: format chunk reading failed\n");
break;
}
format.extra_size = 0;
foundFmt = true;
if (UINT32(chunk.len) >= sizeof(format_ext) && UINT16(format.format_tag) == 0xfffe) {
if (sizeof(format_ext) != Source()->ReadAt(pos, &format_ext, sizeof(format_ext))) {
ERROR("WavReader::Sniff: format extensible chunk reading failed\n");
break;
}
foundFmtExt = true;
}
}
break;
case FOURCC('f','a','c','t'):
@ -260,8 +268,8 @@ WavReader::Sniff(int32 *streamCount)
TRACE(" avg_bytes_per_sec %ld\n", UINT32(format.avg_bytes_per_sec));
TRACE(" block_align %d\n", UINT16(format.block_align));
TRACE(" bits_per_sample %d\n", UINT16(format.bits_per_sample));
TRACE(" ext_size %d\n", UINT16(format.extra_size));
if (foundFmtExt) {
TRACE(" ext_size %d\n", UINT16(format_ext.ext_size));
TRACE(" valid_bits_per_sample %d\n", UINT16(format_ext.valid_bits_per_sample));
TRACE(" channel_mask %ld\n", UINT32(format_ext.channel_mask));
TRACE(" guid[0-1] format 0x%04x\n", (format_ext.guid[1] << 8) | format_ext.guid[0]);
@ -292,7 +300,10 @@ WavReader::Sniff(int32 *streamCount)
fBufferSize = BUFFER_SIZE;
}
fMetaData.extra_size = 0;
fMetaData.extra_size = format.extra_size;
if (fMetaData.extra_size > 0) {
fMetaData.extra_data = format.extra_data;
}
fMetaData.channels = UINT16(format.channels);
fMetaData.samples_per_sec = UINT32(format.samples_per_sec);
fMetaData.block_align = UINT16(format.block_align);
@ -420,9 +431,9 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie)
data->format.u.encoded_audio.output.channel_count = fMetaData.channels;
}
printf("SetMetaData called with size %ld\n",sizeof(wave_format_ex));
printf("SetMetaData called with size %ld\n",sizeof(format_struct) + fMetaData.extra_size + 2);
if (data->format.SetMetaData(&fMetaData, sizeof(wave_format_ex)) != B_OK) {
if (data->format.SetMetaData(&fMetaData, (sizeof(format_struct) + fMetaData.extra_size + 2)) != B_OK) {
ERROR("WavReader::Failed to SetMetaData\n");
delete data;
return B_ERROR;
@ -457,7 +468,7 @@ WavReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
*duration = data->duration;
*format = data->format;
*infoBuffer = &fMetaData;
*infoSize = sizeof(wave_format_ex);
*infoSize = (sizeof(format_struct) + fMetaData.extra_size + 2);
return B_OK;
}

View File

@ -56,6 +56,7 @@ struct wave_format_ex {
uint16 block_align;
uint16 bits_per_sample;
uint16 extra_size;
uint8 extra_data[64]; // allow for 64 bytes of extra data
};
struct mpeg3_wav_format {