From 2cbce7bb7aa2954c568fdd38e36cf146d4476abb Mon Sep 17 00:00:00 2001 From: David McPaul Date: Thu, 30 Apr 2009 22:36:22 +0000 Subject: [PATCH] Add support for mpeg audio in wav format files git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30520 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../plugins/wav_reader/WavReaderPlugin.cpp | 64 ++++++++++++++++++- .../plugins/wav_reader/WavReaderPlugin.h | 1 + src/add-ons/media/plugins/wav_reader/wav.h | 35 +++++++++- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp index 1acbcc9e51..842f27b080 100644 --- a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp @@ -137,7 +137,11 @@ WavReader::Sniff(int32 *streamCount) } format_struct format; + wave_format_ex wav_format; format_struct_extensible format_ext; + mpeg1_wav_format mpeg1_format; + mpeg3_wav_format mpeg3_format; + fact_struct fact; // read all chunks and search for "fact", "fmt" (normal or extensible) and "data" @@ -146,6 +150,9 @@ WavReader::Sniff(int32 *streamCount) bool foundFmt = false; bool foundFmtExt = false; bool foundData = false; + bool foundMPEG1 = false; + bool foundMPEG3 = false; + while (pos + sizeof(chunk_struct) <= fFileSize) { chunk_struct chunk; if (sizeof(chunk) != Source()->ReadAt(pos, &chunk, sizeof(chunk))) { @@ -159,12 +166,43 @@ WavReader::Sniff(int32 *streamCount) } switch (UINT32(chunk.fourcc)) { case FOURCC('f','m','t',' '): - if (UINT32(chunk.len) >= sizeof(format)) { + // 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))) { + 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; + } + foundFmt = true; + + if (UINT16(wav_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; + } + foundMPEG1 = true; + } + + } else if (UINT32(chunk.len) >= sizeof(format)) { if (sizeof(format) != Source()->ReadAt(pos, &format, sizeof(format))) { ERROR("WavReader::Sniff: format chunk reading failed\n"); break; } 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"); @@ -231,6 +269,28 @@ WavReader::Sniff(int32 *streamCount) if (foundFact) { TRACE(" sample_length %ld\n", UINT32(fact.sample_length)); } + + if (foundMPEG1) { + TRACE(" layer %d\n", UINT16(mpeg1_format.head_layer)); + TRACE(" bitrate %ld\n", UINT32(mpeg1_format.head_bitrate)); + TRACE(" mode %d\n", UINT16(mpeg1_format.head_mode)); + TRACE(" mode ext %d\n", UINT16(mpeg1_format.head_mode_ext)); + TRACE(" emphisis %d\n", UINT16(mpeg1_format.head_emphasis)); + TRACE(" flags %d\n", UINT16(mpeg1_format.head_flags)); + TRACE(" pts low %ld\n", UINT32(mpeg1_format.pts_low)); + TRACE(" pts high %ld\n", UINT32(mpeg1_format.pts_high)); + } + + if (foundMPEG3) { + TRACE(" id %d\n", UINT16(mpeg3_format.id)); + TRACE(" flags %ld\n", UINT32(mpeg3_format.flags)); + TRACE(" block size %d\n", UINT16(mpeg3_format.block_size)); + TRACE(" frames per block %d\n", UINT16(mpeg3_format.frames_per_block)); + TRACE(" codec delay %d\n", UINT16(mpeg3_format.codec_delay)); + fBufferSize = mpeg3_format.block_size; + } else { + fBufferSize = BUFFER_SIZE; + } fMetaData.extra_size = 0; fMetaData.channels = UINT16(format.channels); @@ -298,7 +358,7 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie) data->position = 0; data->datasize = fDataSize; data->fps = fMetaData.samples_per_sec; - data->buffersize = (BUFFER_SIZE / fMetaData.block_align) * fMetaData.block_align; + data->buffersize = (fBufferSize / fMetaData.block_align) * fMetaData.block_align; data->buffer = malloc(data->buffersize); data->framecount = fFrameCount ? fFrameCount : (8 * fDataSize) / (fMetaData.channels * fMetaData.bits_per_sample); data->raw = fMetaData.format_tag == 0x0001; diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h index 6de7cd42b6..0152cf3793 100644 --- a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h @@ -71,6 +71,7 @@ private: int64 fFrameCount; int32 fFrameRate; + uint16 fBufferSize; }; diff --git a/src/add-ons/media/plugins/wav_reader/wav.h b/src/add-ons/media/plugins/wav_reader/wav.h index 28b75db802..a7dcdbac2a 100644 --- a/src/add-ons/media/plugins/wav_reader/wav.h +++ b/src/add-ons/media/plugins/wav_reader/wav.h @@ -56,7 +56,40 @@ struct wave_format_ex { uint16 block_align; uint16 bits_per_sample; uint16 extra_size; -} _PACKED; +}; + +struct mpeg3_wav_format { + uint16 format_tag; + uint16 channels; + uint32 samples_per_sec; + uint32 avg_bytes_per_sec; + uint16 block_align; + uint16 bits_per_sample; + uint16 extra_size; + uint16 id; + uint32 flags; + uint16 block_size; + uint16 frames_per_block; + uint16 codec_delay; +}; + +struct mpeg1_wav_format { + uint16 format_tag; + uint16 channels; + uint32 samples_per_sec; + uint32 avg_bytes_per_sec; + uint16 block_align; + uint16 bits_per_sample; + uint16 extra_size; + uint16 head_layer; + uint32 head_bitrate; + uint16 head_mode; + uint16 head_mode_ext; + uint16 head_emphasis; + uint16 head_flags; + uint32 pts_low; + uint32 pts_high; +}; struct format_struct_extensible {