pass a wave structure as meta data. avcodec needs it

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28077 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2008-10-14 12:53:20 +00:00
parent 57f8452b78
commit f4be1422f2
3 changed files with 79 additions and 57 deletions
@@ -31,19 +31,24 @@
#include "WavReaderPlugin.h"
#include "RawFormats.h"
//#define TRACE_WAVE_READER
#define TRACE_WAVE_READER
#ifdef TRACE_WAVE_READER
#define TRACE printf
#else
#define TRACE(a...)
#endif
#define ERROR(a...) fprintf(stderr, a)
#define BUFFER_SIZE 16384 // must be > 5200 for mp3 decoder to work
#define FOURCC(a,b,c,d) ((((uint32)(d)) << 24) | (((uint32)(c)) << 16) | (((uint32)(b)) << 8) | ((uint32)(a)))
#define UINT16(a) ((uint16)B_LENDIAN_TO_HOST_INT16((a)))
#define UINT32(a) ((uint32)B_LENDIAN_TO_HOST_INT32((a)))
// This Reader only deals with CBR audio
// My understanding is that no WAV file will have VBR audio anyway
struct wavdata
{
int64 position;
@@ -144,25 +149,25 @@ WavReader::Sniff(int32 *streamCount)
while (pos + sizeof(chunk_struct) <= fFileSize) {
chunk_struct chunk;
if (sizeof(chunk) != Source()->ReadAt(pos, &chunk, sizeof(chunk))) {
TRACE("WavReader::Sniff: chunk header reading failed\n");
ERROR("WavReader::Sniff: chunk header reading failed\n");
return B_ERROR;
}
pos += sizeof(chunk);
if (UINT32(chunk.len) == 0) {
TRACE("WavReader::Sniff: Error: chunk of size 0 found\n");
ERROR("WavReader::Sniff: Error: chunk of size 0 found\n");
return B_ERROR;
}
switch (UINT32(chunk.fourcc)) {
case FOURCC('f','m','t',' '):
if (UINT32(chunk.len) >= sizeof(format)) {
if (sizeof(format) != Source()->ReadAt(pos, &format, sizeof(format))) {
TRACE("WavReader::Sniff: format chunk reading failed\n");
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))) {
TRACE("WavReader::Sniff: format extensible chunk reading failed\n");
ERROR("WavReader::Sniff: format extensible chunk reading failed\n");
break;
}
foundFmtExt = true;
@@ -172,7 +177,7 @@ WavReader::Sniff(int32 *streamCount)
case FOURCC('f','a','c','t'):
if (UINT32(chunk.len) >= sizeof(fact)) {
if (sizeof(fact) != Source()->ReadAt(pos, &fact, sizeof(fact))) {
TRACE("WavReader::Sniff: fact chunk reading failed\n");
ERROR("WavReader::Sniff: fact chunk reading failed\n");
break;
}
foundFact = true;
@@ -201,11 +206,11 @@ WavReader::Sniff(int32 *streamCount)
}
if (!foundFmt) {
TRACE("WavReader::Sniff: couldn't find format chunk\n");
ERROR("WavReader::Sniff: couldn't find format chunk\n");
return B_ERROR;
}
if (!foundData) {
TRACE("WavReader::Sniff: couldn't find data chunk\n");
ERROR("WavReader::Sniff: couldn't find data chunk\n");
return B_ERROR;
}
@@ -227,38 +232,39 @@ WavReader::Sniff(int32 *streamCount)
TRACE(" sample_length %ld\n", UINT32(fact.sample_length));
}
fChannelCount = UINT16(format.channels);
fSampleRate = UINT32(format.samples_per_sec);
fBlockAlign = UINT16(format.block_align);
fBitsPerSample = UINT16(format.bits_per_sample);
if (fBitsPerSample == 0) {
printf("WavReader::Sniff: Error, bits_per_sample = 0 calculating\n");
fBitsPerSample = fBlockAlign * 8 / fChannelCount;
fMetaData.extra_size = 0;
fMetaData.channels = UINT16(format.channels);
fMetaData.samples_per_sec = UINT32(format.samples_per_sec);
fMetaData.block_align = UINT16(format.block_align);
fMetaData.bits_per_sample = UINT16(format.bits_per_sample);
if (fMetaData.bits_per_sample == 0) {
fMetaData.bits_per_sample = fMetaData.block_align * 8 / fMetaData.channels;
ERROR("WavReader::Sniff: Error, bits_per_sample = 0 calculating as %d\n",fMetaData.bits_per_sample);
}
fFrameRate = fSampleRate * fChannelCount;
fFrameRate = fMetaData.samples_per_sec * fMetaData.channels;
fAvgBytesPerSec = format.avg_bytes_per_sec;
fMetaData.avg_bytes_per_sec = format.avg_bytes_per_sec;
// fact.sample_length is really no of samples for all channels
fFrameCount = foundFact ? UINT32(fact.sample_length) / fChannelCount : 0;
fFormatCode = UINT16(format.format_tag);
if (fFormatCode == 0xfffe && foundFmtExt)
fFormatCode = (format_ext.guid[1] << 8) | format_ext.guid[0];
fFrameCount = foundFact ? UINT32(fact.sample_length) / fMetaData.channels : 0;
fMetaData.format_tag = UINT16(format.format_tag);
if (fMetaData.format_tag == 0xfffe && foundFmtExt)
fMetaData.format_tag = (format_ext.guid[1] << 8) | format_ext.guid[0];
int min_align = (fFormatCode == 0x0001) ? (fBitsPerSample * fChannelCount + 7) / 8 : 1;
if (fBlockAlign < min_align)
fBlockAlign = min_align;
int min_align = (fMetaData.format_tag == 0x0001) ? (fMetaData.bits_per_sample * fMetaData.channels + 7) / 8 : 1;
if (fMetaData.block_align < min_align)
fMetaData.block_align = min_align;
TRACE(" fDataStart %Ld\n", fDataStart);
TRACE(" fDataSize %Ld\n", fDataSize);
TRACE(" fChannelCount %ld\n", fChannelCount);
TRACE(" fSampleRate %ld\n", fSampleRate);
TRACE(" Channels %d\n", fMetaData.channels);
TRACE(" SampleRate %ld\n", fMetaData.samples_per_sec);
TRACE(" fFrameRate %ld\n", fFrameRate);
TRACE(" fFrameCount %Ld\n", fFrameCount);
TRACE(" fBitsPerSample %d\n", fBitsPerSample);
TRACE(" fBlockAlign %d\n", fBlockAlign);
TRACE(" BitsPerSample %d\n", fMetaData.bits_per_sample);
TRACE(" BlockAlign %d\n", fMetaData.block_align);
TRACE(" min_align %d\n", min_align);
TRACE(" fFormatCode 0x%04x\n", fFormatCode);
TRACE(" Format 0x%04x\n", fMetaData.format_tag);
// XXX fact.sample_length contains duration of encoded files?
@@ -291,18 +297,18 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie)
data->position = 0;
data->datasize = fDataSize;
data->fps = fSampleRate;
data->buffersize = (BUFFER_SIZE / fBlockAlign) * fBlockAlign;
data->fps = fMetaData.samples_per_sec;
data->buffersize = (BUFFER_SIZE / fMetaData.block_align) * fMetaData.block_align;
data->buffer = malloc(data->buffersize);
data->framecount = fFrameCount ? fFrameCount : (8 * fDataSize) / (fChannelCount * fBitsPerSample);
data->raw = fFormatCode == 0x0001;
data->framecount = fFrameCount ? fFrameCount : (8 * fDataSize) / (fMetaData.channels * fMetaData.bits_per_sample);
data->raw = fMetaData.format_tag == 0x0001;
if (!fAvgBytesPerSec) {
fAvgBytesPerSec = fSampleRate * fBlockAlign;
if (!fMetaData.avg_bytes_per_sec) {
fMetaData.avg_bytes_per_sec = fMetaData.samples_per_sec * fMetaData.block_align;
}
data->duration = (data->datasize * 1000000LL) / fAvgBytesPerSec;
data->bitrate = fAvgBytesPerSec * 8;
data->duration = (data->datasize * 1000000LL) / fMetaData.avg_bytes_per_sec;
data->bitrate = fMetaData.avg_bytes_per_sec * 8;
TRACE(" raw %s\n", data->raw ? "true" : "false");
TRACE(" framecount %Ld\n", data->framecount);
@@ -312,16 +318,16 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie)
TRACE(" buffersize %ld\n", data->buffersize);
BMediaFormats formats;
if (fFormatCode == 0x0001) {
if (fMetaData.format_tag == 0x0001) {
// a raw PCM format
media_format_description description;
description.family = B_BEOS_FORMAT_FAMILY;
description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO;
formats.GetFormatFor(description, &data->format);
// Really SampleRate
data->format.u.raw_audio.frame_rate = fSampleRate;
data->format.u.raw_audio.channel_count = fChannelCount;
switch (fBitsPerSample) {
data->format.u.raw_audio.frame_rate = fMetaData.samples_per_sec;
data->format.u.raw_audio.channel_count = fMetaData.channels;
switch (fMetaData.bits_per_sample) {
case 8:
data->format.u.raw_audio.format = B_AUDIO_FORMAT_UINT8;
break;
@@ -335,7 +341,8 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie)
data->format.u.raw_audio.format = B_AUDIO_FORMAT_INT32;
break;
default:
TRACE("WavReader::AllocateCookie: unhandled bits per sample %d\n", fBitsPerSample);
ERROR("WavReader::AllocateCookie: unhandled bits per sample %d\n", fMetaData.bits_per_sample);
delete data;
return B_ERROR;
}
data->format.u.raw_audio.format |= B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE;
@@ -345,13 +352,22 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie)
// some encoded format
media_format_description description;
description.family = B_WAV_FORMAT_FAMILY;
description.u.wav.codec = fFormatCode;
description.u.wav.codec = fMetaData.format_tag;
formats.GetFormatFor(description, &data->format);
// Really SampleRate
data->format.u.encoded_audio.output.frame_rate = fSampleRate;
data->format.u.encoded_audio.output.channel_count = fChannelCount;
data->format.u.encoded_audio.bit_rate = data->bitrate;
data->format.u.encoded_audio.output.frame_rate = fMetaData.samples_per_sec;
data->format.u.encoded_audio.output.channel_count = fMetaData.channels;
}
printf("SetMetaData called with size %ld\n",sizeof(wave_format_ex));
if (data->format.SetMetaData(&fMetaData, sizeof(wave_format_ex)) != B_OK) {
ERROR("WavReader::Failed to SetMetaData\n");
delete data;
return B_ERROR;
}
// store the cookie
*cookie = data;
return B_OK;
@@ -380,8 +396,8 @@ WavReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration,
*frameCount = data->framecount;
*duration = data->duration;
*format = data->format;
*infoBuffer = 0;
*infoSize = 0;
*infoBuffer = &fMetaData;
*infoSize = sizeof(wave_format_ex);
return B_OK;
}
@@ -404,7 +420,7 @@ WavReader::CalculateNewPosition(void *cookie,
return B_ERROR;
}
*position = (*position / fBlockAlign) * fBlockAlign; // round down to a block start
*position = (*position / fMetaData.block_align) * fMetaData.block_align; // round down to a block start
TRACE(", position %Ld ", *position);
@@ -415,7 +431,7 @@ WavReader::CalculateNewPosition(void *cookie,
TRACE("newframe %Ld\n", *frame);
if (*position < 0 || *position > data->datasize) {
printf("WavReader::CalculateNewPosition invalid position %Ld\n", *position);
ERROR("WavReader::CalculateNewPosition invalid position %Ld\n", *position);
return B_ERROR;
}
@@ -476,12 +492,12 @@ WavReader::GetNextChunk(void *cookie,
if (maxreadsize < readsize)
readsize = maxreadsize;
if (readsize == 0) {
printf("WavReader::GetNextChunk: LAST BUFFER ERROR at time %9Ld\n",mediaHeader->start_time);
ERROR("WavReader::GetNextChunk: LAST BUFFER ERROR at time %9Ld\n",mediaHeader->start_time);
return B_LAST_BUFFER_ERROR;
}
if (readsize != Source()->ReadAt(fDataStart + data->position, data->buffer, readsize)) {
printf("WavReader::GetNextChunk: unexpected read error at position %9Ld\n",fDataStart + data->position);
ERROR("WavReader::GetNextChunk: unexpected read error at position %9Ld\n",fDataStart + data->position);
return B_ERROR;
}
@@ -66,15 +66,11 @@ private:
int64 fFileSize;
int64 fDataStart;
int64 fDataSize;
wave_format_ex fMetaData;
int64 fFrameCount;
int32 fChannelCount;
int32 fFrameRate;
int32 fSampleRate;
uint16 fBitsPerSample;
uint16 fFormatCode;
uint16 fBlockAlign;
uint32 fAvgBytesPerSec;
};
@@ -48,6 +48,16 @@ struct format_struct
uint16 bits_per_sample;
};
struct wave_format_ex {
uint16 format_tag;
uint16 channels;
uint32 samples_per_sec;
uint32 avg_bytes_per_sec;
uint16 block_align;
uint16 bits_per_sample;
uint16 extra_size;
} _PACKED;
struct format_struct_extensible
{
uint16 format_tag; // 0xfffe for extensible format