diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp index cdd7e69cf0..1fe0f894b6 100644 --- a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.cpp @@ -46,16 +46,16 @@ struct wavdata { - uint64 position; - uint64 datasize; + int64 position; + int64 datasize; - int32 bitsperframe; - int32 fps; + uint32 bitrate; + uint32 fps; void *buffer; - int32 buffersize; + uint32 buffersize; - int64 framecount; + uint64 framecount; bigtime_t duration; bool raw; @@ -63,6 +63,30 @@ struct wavdata media_format format; }; +static bigtime_t FrameToTime(uint64 frame, uint32 fps) { + return frame * 1000000LL / fps; +} + +static uint64 TimeToFrame(bigtime_t time, uint32 fps) { + return (time * fps) / 1000000LL; +} + +static int64 TimeToPosition(bigtime_t time, uint32 bitrate) { + return (time * bitrate) / 8000000LL; +} + +static bigtime_t PositionToTime(int64 position, uint32 bitrate) { + return (position * 8000000LL) / bitrate; +} + +static int64 FrameToPosition(uint64 frame, uint32 bitrate, uint32 fps) { + return TimeToPosition(FrameToTime(frame,fps),bitrate); +} + +static uint64 PositionToFrame(int64 position, uint32 bitrate, uint32 fps) { + return TimeToFrame(PositionToTime(position,bitrate),fps); +} + WavReader::WavReader() { TRACE("WavReader::WavReader\n"); @@ -204,19 +228,23 @@ WavReader::Sniff(int32 *streamCount) } fChannelCount = UINT16(format.channels); - fFrameRate = UINT32(format.samples_per_sec); + 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 assuming 8\n"); - fBitsPerSample = 8; + printf("WavReader::Sniff: Error, bits_per_sample = 0 calculating\n"); + fBitsPerSample = fBlockAlign * 8 / fChannelCount; } + fFrameRate = fSampleRate * fChannelCount; + fAvgBytesPerSec = format.avg_bytes_per_sec; - fFrameCount = foundFact ? UINT32(fact.sample_length) : 0; + + // 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]; - fBlockAlign = UINT16(format.block_align); int min_align = (fFormatCode == 0x0001) ? (fBitsPerSample * fChannelCount + 7) / 8 : 1; if (fBlockAlign < min_align) fBlockAlign = min_align; @@ -224,6 +252,7 @@ WavReader::Sniff(int32 *streamCount) TRACE(" fDataStart %Ld\n", fDataStart); TRACE(" fDataSize %Ld\n", fDataSize); TRACE(" fChannelCount %ld\n", fChannelCount); + TRACE(" fSampleRate %ld\n", fSampleRate); TRACE(" fFrameRate %ld\n", fFrameRate); TRACE(" fFrameCount %Ld\n", fFrameCount); TRACE(" fBitsPerSample %d\n", fBitsPerSample); @@ -231,7 +260,7 @@ WavReader::Sniff(int32 *streamCount) TRACE(" min_align %d\n", min_align); TRACE(" fFormatCode 0x%04x\n", fFormatCode); - // XXX fact.sample_length contains duration of encodec files? + // XXX fact.sample_length contains duration of encoded files? *streamCount = 1; return B_OK; @@ -262,29 +291,25 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie) data->position = 0; data->datasize = fDataSize; - data->bitsperframe = fChannelCount * fBitsPerSample; - data->fps = fFrameRate; + data->fps = fSampleRate; data->buffersize = (BUFFER_SIZE / fBlockAlign) * fBlockAlign; data->buffer = malloc(data->buffersize); - data->framecount = fFrameCount ? fFrameCount : (8 * fDataSize) / data->bitsperframe; - if (fFormatCode == 0x0055) { - // mp3 in wav file - if (fAvgBytesPerSec) { - data->duration = (data->datasize * 1000000LL) / fAvgBytesPerSec; - } else { - data->duration = (data->framecount * 1000000LL) / data->fps / fBitsPerSample * fChannelCount; - } - } else { - data->duration = (data->framecount * 1000000LL) / data->fps; - } + data->framecount = fFrameCount ? fFrameCount : (8 * fDataSize) / (fChannelCount * fBitsPerSample); data->raw = fFormatCode == 0x0001; - TRACE(" bitsperframe %ld\n", data->bitsperframe); - TRACE(" fps %ld\n", data->fps); - TRACE(" buffersize %ld\n", data->buffersize); + if (!fAvgBytesPerSec) { + fAvgBytesPerSec = fSampleRate * fBlockAlign; + } + + data->duration = (data->datasize * 1000000LL) / fAvgBytesPerSec; + data->bitrate = fAvgBytesPerSec * 8; + + TRACE(" raw %s\n", data->raw ? "true" : "false"); TRACE(" framecount %Ld\n", data->framecount); - TRACE(" duration %Ld\n", data->duration); - TRACE(" raw %d\n", data->raw); + TRACE(" duration %Ld\n", data->duration); + TRACE(" bitrate %ld\n", data->bitrate); + TRACE(" fps %ld\n", data->fps); + TRACE(" buffersize %ld\n", data->buffersize); BMediaFormats formats; if (fFormatCode == 0x0001) { @@ -293,7 +318,8 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie) description.family = B_BEOS_FORMAT_FAMILY; description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO; formats.GetFormatFor(description, &data->format); - data->format.u.raw_audio.frame_rate = fFrameRate; + // Really SampleRate + data->format.u.raw_audio.frame_rate = fSampleRate; data->format.u.raw_audio.channel_count = fChannelCount; switch (fBitsPerSample) { case 8: @@ -321,7 +347,8 @@ WavReader::AllocateCookie(int32 streamNumber, void **cookie) description.family = B_WAV_FORMAT_FAMILY; description.u.wav.codec = fFormatCode; formats.GetFormatFor(description, &data->format); - data->format.u.encoded_audio.output.frame_rate = fFrameRate; + // Really SampleRate + data->format.u.encoded_audio.output.frame_rate = fSampleRate; data->format.u.encoded_audio.output.channel_count = fChannelCount; } @@ -358,6 +385,42 @@ WavReader::GetStreamInfo(void *cookie, int64 *frameCount, bigtime_t *duration, return B_OK; } +status_t +WavReader::CalculateNewPosition(void *cookie, + uint32 flags, + int64 *frame, bigtime_t *time, int64 *position) +{ + wavdata *data = reinterpret_cast(cookie); + + if (flags & B_MEDIA_SEEK_TO_FRAME) { + TRACE(" to frame %Ld",*frame); + *position = FrameToPosition(*frame, data->bitrate, data->fps); + + } else if (flags & B_MEDIA_SEEK_TO_TIME) { + TRACE(" to time %Ld", *time); + *position = TimeToPosition(*time, data->bitrate); + } else { + printf("WavReader::CalculateNewPosition invalid flag passed %ld\n", flags); + return B_ERROR; + } + + *position = (*position / fBlockAlign) * fBlockAlign; // round down to a block start + + TRACE(", position %Ld ", *position); + + *frame = PositionToFrame(*position, data->bitrate, data->fps); + *time = FrameToTime(*frame,data->fps); + + TRACE("newtime %Ld ", *time); + TRACE("newframe %Ld\n", *frame); + + if (*position < 0 || *position > data->datasize) { + printf("WavReader::CalculateNewPosition invalid position %Ld\n", *position); + return B_ERROR; + } + + return B_OK; +} status_t WavReader::Seek(void *cookie, @@ -366,42 +429,18 @@ WavReader::Seek(void *cookie, { // Seek to the given position wavdata *data = reinterpret_cast(cookie); - uint64 pos; - - if (flags & B_MEDIA_SEEK_TO_FRAME) { - if (data->raw) - pos = (*frame * data->bitsperframe) / 8; - else - pos = (*frame * fDataSize) / data->framecount; - pos = (pos / fBlockAlign) * fBlockAlign; // round down to a block start - TRACE("WavReader::Seek to frame %Ld, pos %Ld\n", *frame, pos); - } else if (flags & B_MEDIA_SEEK_TO_TIME) { - if (data->raw) - pos = (*time * data->fps * data->bitsperframe) / (1000000LL * 8); - else - pos = (*time * fDataSize) / data->duration; - pos = (pos / fBlockAlign) * fBlockAlign; // round down to a block start - TRACE("WavReader::Seek to time %Ld, pos %Ld\n", *time, pos); - } else { - return B_ERROR; - } - - if (data->raw) - *frame = (8 * pos) / data->bitsperframe; - else - *frame = (pos * data->framecount) / fDataSize; - *time = (*frame * 1000000LL) / data->fps; - - TRACE("WavReader::Seek newtime %Ld\n", *time); - TRACE("WavReader::Seek newframe %Ld\n", *frame); + status_t status; + int64 pos; - if (pos < 0 || pos > data->datasize) { - TRACE("WavReader::Seek invalid position %Ld\n", pos); - return B_ERROR; + TRACE("WavReader::Seek"); + status = CalculateNewPosition(cookie, flags, frame, time, &pos); + + if (status == B_OK) { + // set the new position so next GetNextChunk will read from new seek pos + data->position = pos; } - data->position = pos; - return B_OK; + return status; } status_t @@ -409,42 +448,10 @@ WavReader::FindKeyFrame(void* cookie, uint32 flags, int64* frame, bigtime_t* time) { // Find a seek position without actually seeking - wavdata *data = reinterpret_cast(cookie); - uint64 pos; - - if (flags & B_MEDIA_SEEK_TO_FRAME) { - if (data->raw) - pos = (*frame * data->bitsperframe) / 8; - else - pos = (*frame * fDataSize) / data->framecount; - pos = (pos / fBlockAlign) * fBlockAlign; // round down to a block start - TRACE("WavReader::Seek to frame %Ld, pos %Ld\n", *frame, pos); - } else if (flags & B_MEDIA_SEEK_TO_TIME) { - if (data->raw) - pos = (*time * data->fps * data->bitsperframe) / (1000000LL * 8); - else - pos = (*time * fDataSize) / data->duration; - pos = (pos / fBlockAlign) * fBlockAlign; // round down to a block start - TRACE("WavReader::Seek to time %Ld, pos %Ld\n", *time, pos); - } else { - return B_ERROR; - } - - if (data->raw) - *frame = (8 * pos) / data->bitsperframe; - else - *frame = (pos * data->framecount) / fDataSize; - *time = (*frame * 1000000LL) / data->fps; - - TRACE("WavReader::Seek newtime %Ld\n", *time); - TRACE("WavReader::Seek newframe %Ld\n", *frame); + int64 pos; + TRACE("WavReader::FindKeyFrame"); - if (pos < 0 || pos > data->datasize) { - TRACE("WavReader::Seek invalid position %Ld\n", pos); - return B_ERROR; - } - - return B_OK; + return CalculateNewPosition(cookie, flags, frame, time, &pos); } status_t @@ -456,28 +463,25 @@ WavReader::GetNextChunk(void *cookie, // XXX it might be much better to not return any start_time information for encoded formats here, // XXX and instead use the last time returned from seek and count forward after decoding. - if (data->raw) - mediaHeader->start_time = (((8 * data->position) / data->bitsperframe) * 1000000LL) / data->fps; - else - mediaHeader->start_time = (data->position * data->duration) / fDataSize; + mediaHeader->start_time = PositionToTime(data->position,data->bitrate); mediaHeader->file_pos = fDataStart + data->position; -/* - printf("position = %9Ld\n", data->position); - printf("fDataSize = %9Ld\n", fDataSize); - printf("duration = %9Ld\n", data->duration); - printf("start_time = %9Ld\n", mediaHeader->start_time); -*/ + TRACE("(%s) position = %9Ld ", data->raw ? "raw" : "encoded", data->position); + TRACE("frame = %9Ld ", PositionToFrame(data->position,data->bitrate,data->fps)); + TRACE("fDataSize = %9Ld ", fDataSize); + TRACE("start_time = %9Ld\n", mediaHeader->start_time); int64 maxreadsize = data->datasize - data->position; int32 readsize = data->buffersize; if (maxreadsize < readsize) readsize = maxreadsize; - if (readsize == 0) + if (readsize == 0) { + printf("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)) { - TRACE("WavReader::GetNextChunk: unexpected read error\n"); + printf("WavReader::GetNextChunk: unexpected read error at position %9Ld\n",fDataStart + data->position); return B_ERROR; } diff --git a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h index 077b3736e3..cc49200b79 100644 --- a/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h +++ b/src/add-ons/media/plugins/wav_reader/WavReaderPlugin.h @@ -55,7 +55,10 @@ public: status_t GetNextChunk(void *cookie, const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader); - + + status_t CalculateNewPosition(void* cookie, uint32 flags, + int64 *frame, bigtime_t *time, int64 *position); + BPositionIO *Source() { return fSource; } private: @@ -67,10 +70,11 @@ private: int64 fFrameCount; int32 fChannelCount; int32 fFrameRate; - int fBitsPerSample; + int32 fSampleRate; + uint16 fBitsPerSample; uint16 fFormatCode; uint16 fBlockAlign; - uint16 fAvgBytesPerSec; + uint32 fAvgBytesPerSec; };