diff --git a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp index 597e8072bf..c68d25c031 100644 --- a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp +++ b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp @@ -8,19 +8,26 @@ #if TRACE_THIS #define TRACE printf #else - #define TRACE ((void)0) + #define TRACE(a...) #endif -#define OUTPUT_BUFFER_SIZE 32768 +#define OUTPUT_BUFFER_SIZE (8 * 1024) +#define DECODE_BUFFER_SIZE (32 * 1024) mp3Decoder::mp3Decoder() { InitMP3(&fMpgLibPrivate); + fResidualBytes = 0; + fResidualBuffer = 0; + fDecodeBuffer = new uint8 [DECODE_BUFFER_SIZE]; + fFrameSize = 0; } + mp3Decoder::~mp3Decoder() { ExitMP3(&fMpgLibPrivate); + delete [] fDecodeBuffer; } @@ -36,9 +43,11 @@ mp3Decoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat, ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_LITTLE_ENDIAN; ioDecodedFormat->u.raw_audio.buffer_size = OUTPUT_BUFFER_SIZE; ioDecodedFormat->u.raw_audio.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; + fFrameSize = 4; return B_OK; } + status_t mp3Decoder::Seek(uint32 seekTo, int64 seekFrame, int64 *frame, @@ -54,40 +63,47 @@ status_t mp3Decoder::Decode(void *buffer, int64 *frameCount, media_header *mediaHeader, media_decode_info *info /* = 0 */) { - void *chunkBuffer; - int32 chunkSize; - if (B_OK != GetNextChunk(&chunkBuffer, &chunkSize, mediaHeader)) { - TRACE("mp3Decoder::Decode: GetNextChunk failed\n"); - return B_ERROR; - } - - int availsize; - int outsize; - int result; + uint8 * out_buffer = static_cast(buffer); + int32 out_bytes_needed = OUTPUT_BUFFER_SIZE; - availsize = OUTPUT_BUFFER_SIZE; - result = decodeMP3(&fMpgLibPrivate, (char *)chunkBuffer, chunkSize, (char *)buffer, availsize, &outsize); - if (result == MP3_ERR) { - TRACE("mp3Decoder::Decode: decodeMP3 returned MP3_ERR\n"); - return B_ERROR; - } - buffer = (char *)buffer + outsize; - availsize -= outsize; - - do { - result = decodeMP3(&fMpgLibPrivate, 0, 0, (char *)buffer, availsize, &outsize); - buffer = (char *)buffer + outsize; - availsize -= outsize; - if (availsize < 0) { - TRACE("mp3Decoder::Decode: decoded to much\n"); - exit(1); + while (out_bytes_needed > 0) { + if (fResidualBytes) { + int32 bytes = min_c(fResidualBytes, out_bytes_needed); + memcpy(out_buffer, fResidualBuffer, bytes); + fResidualBuffer += bytes; + fResidualBytes -= bytes; + out_buffer += bytes; + out_bytes_needed -= bytes; + continue; } - } while (result == MP3_OK); - - *frameCount = (OUTPUT_BUFFER_SIZE - availsize) / 4; + + void *chunkBuffer; + int32 chunkSize; + if (B_OK != GetNextChunk(&chunkBuffer, &chunkSize, mediaHeader)) { + TRACE("mp3Decoder::Decode: GetNextChunk failed\n"); + return B_ERROR; + } + + int outsize; + int result; + result = decodeMP3(&fMpgLibPrivate, (char *)chunkBuffer, chunkSize, (char *)fDecodeBuffer, DECODE_BUFFER_SIZE, &outsize); + if (result == MP3_ERR) { + TRACE("mp3Decoder::Decode: decodeMP3 returned MP3_ERR\n"); + return B_ERROR; + } + + //printf("mp3Decoder::Decode: decoded %d bytes into %d bytes\n",chunkSize, outsize); + + fResidualBuffer = fDecodeBuffer; + fResidualBytes = outsize; + } + + *frameCount = OUTPUT_BUFFER_SIZE / fFrameSize; + return B_OK; } + Decoder * mp3DecoderPlugin::NewDecoder() { @@ -102,6 +118,7 @@ mp3DecoderPlugin::NewDecoder() return new mp3Decoder; } + status_t mp3DecoderPlugin::RegisterPlugin() { diff --git a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h index e6114e0d27..ad443ad47e 100644 --- a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h +++ b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h @@ -19,7 +19,11 @@ public: status_t Decode(void *buffer, int64 *frameCount, media_header *mediaHeader, media_decode_info *info); private: - struct mpstr fMpgLibPrivate; + struct mpstr fMpgLibPrivate; + int32 fResidualBytes; + uint8 * fResidualBuffer; + uint8 * fDecodeBuffer; + int32 fFrameSize; }; diff --git a/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp b/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp index 2875b7051f..02c8a073b7 100644 --- a/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp +++ b/src/add-ons/media/plugins/mp3_reader/MP3ReaderPlugin.cpp @@ -225,7 +225,7 @@ mp3Reader::FreeCookie(void *cookie) { TRACE("mp3Reader::FreeCookie\n"); mp3data *data = reinterpret_cast(cookie); - delete data->chunkBuffer; + delete [] data->chunkBuffer; delete data; return B_OK; @@ -261,14 +261,14 @@ mp3Reader::Seek(void *cookie, // this isn't very accurate if (seekTo & B_MEDIA_SEEK_TO_FRAME) { - pos = fXingVbrInfo ? XingSeekPoint(*frame / (float)data->frameCount) : -1; + pos = fXingVbrInfo ? XingSeekPoint(100.0 * *frame / (float)data->frameCount) : -1; if (pos < 0) pos = (*frame * fDataSize) / data->frameCount; TRACE("mp3Reader::Seek to frame %Ld, pos %Ld\n", *frame, pos); *time = (*frame * data->duration) / data->frameCount; TRACE("mp3Reader::Seek newtime %Ld\n", *time); } else if (seekTo & B_MEDIA_SEEK_TO_TIME) { - pos = fXingVbrInfo ? XingSeekPoint(*time / (float)data->duration) : -1; + pos = fXingVbrInfo ? XingSeekPoint(100.0 * *time / (float)data->duration) : -1; if (pos < 0) pos = (*time * fDataSize) / data->duration; TRACE("mp3Reader::Seek to time %Ld, pos %Ld\n", *time, pos); @@ -352,6 +352,11 @@ mp3Reader::GetNextChunk(void *cookie, *chunkBuffer = data->chunkBuffer; *chunkSize = size + 4; + + if (*chunkSize > MAX_CHUNK_SIZE) { + printf("mp3Reader: chunk buffer overrun, read %ld bytes into %d bytes buffer\n", *chunkSize, MAX_CHUNK_SIZE); + exit(1); + } return B_OK; } diff --git a/src/kits/media/MediaExtractor.cpp b/src/kits/media/MediaExtractor.cpp index 424480add8..65d4b73165 100644 --- a/src/kits/media/MediaExtractor.cpp +++ b/src/kits/media/MediaExtractor.cpp @@ -61,7 +61,7 @@ MediaExtractor::MediaExtractor(BDataIO * source, int32 flags) fStreamInfo[i].encodedFormat.u.encoded_audio.output.channel_count = 2; fStreamInfo[i].encodedFormat.u.encoded_audio.output.format = 2; fStreamInfo[i].encodedFormat.u.encoded_audio.output.byte_order = B_MEDIA_LITTLE_ENDIAN; - fStreamInfo[i].encodedFormat.u.encoded_audio.output.buffer_size = 8 * 1024; + fStreamInfo[i].encodedFormat.u.encoded_audio.output.buffer_size = 4 * 1024; string_for_format(fStreamInfo[i].encodedFormat, sz, sizeof(sz)); printf("MediaExtractor::MediaExtractor: stream %d has new format %s\n", i, sz); } @@ -70,6 +70,7 @@ MediaExtractor::MediaExtractor(BDataIO * source, int32 flags) MediaExtractor::~MediaExtractor() { CALLED(); + // free all stream cookies for (int32 i = 0; i < fStreamCount; i++) { if (fStreamInfo[i].cookie) @@ -79,7 +80,7 @@ MediaExtractor::~MediaExtractor() if (fReader) _DestroyReader(fReader); - delete fStreamInfo; + delete [] fStreamInfo; delete fSource; } @@ -171,7 +172,7 @@ MediaExtractor::GetNextChunk(int32 stream, void **chunkBuffer, int32 *chunkSize, media_header *mediaHeader) { - CALLED(); + //CALLED(); // get buffered chunk // XXX this should be done in a different thread, and double buffered for each stream diff --git a/src/kits/media/MediaFile.cpp b/src/kits/media/MediaFile.cpp index 87e4c00ca3..a6daffc6ce 100644 --- a/src/kits/media/MediaFile.cpp +++ b/src/kits/media/MediaFile.cpp @@ -114,8 +114,11 @@ BMediaFile::TrackAt(int32 index) CALLED(); if (!fTrackList || !fExtractor || index < 0 || index >= fTrackNum) return 0; - if (!fTrackList[index]) + if (!fTrackList[index]) { + TRACE("BMediaFile::TrackAt, creating new track for index %ld\n", index); fTrackList[index] = new BMediaTrack(fExtractor, index); + TRACE("BMediaFile::TrackAt, new track is %p\n", fTrackList[index]); + } return fTrackList[index]; } @@ -132,6 +135,7 @@ BMediaFile::ReleaseTrack(BMediaTrack *track) return B_ERROR; for (int32 i = 0; i < fTrackNum; i++) { if (fTrackList[i] == track) { + TRACE("BMediaFile::ReleaseTrack, releasing track %p with index %ld\n", track, i); delete track; fTrackList[i] = 0; return B_OK; @@ -149,6 +153,7 @@ BMediaFile::ReleaseAllTracks(void) return B_ERROR; for (int32 i = 0; i < fTrackNum; i++) { if (fTrackList[i]) { + TRACE("BMediaFile::ReleaseAllTracks, releasing track %p with index %ld\n", fTrackList[i], i); delete fTrackList[i]; fTrackList[i] = 0; } diff --git a/src/kits/media/MediaTrack.cpp b/src/kits/media/MediaTrack.cpp index 608005aba5..ca0aaf5050 100644 --- a/src/kits/media/MediaTrack.cpp +++ b/src/kits/media/MediaTrack.cpp @@ -118,7 +118,7 @@ BMediaTrack::ReadFrames(void *out_buffer, media_header *mh /* = 0 */, media_decode_info *info /* = 0 */) { - CALLED(); +// CALLED(); if (!fDecoder) return B_NO_INIT; if (!out_buffer || !out_frameCount) @@ -158,9 +158,11 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, CALLED(); if (!fDecoder || !fExtractor) return B_NO_INIT; - if (!inout_time || !(flags & B_MEDIA_SEEK_DIRECTION_MASK)) + if (!inout_time) return B_BAD_VALUE; + bigtime_t request = *inout_time; + status_t result; uint32 seekTo; bigtime_t seekTime; @@ -173,16 +175,22 @@ BMediaTrack::SeekToTime(bigtime_t *inout_time, time = seekTime; result = fExtractor->Seek(fStream, seekTo, &frame, &time); - if (result != B_OK) + if (result != B_OK) { + TRACE("BMediaTrack::SeekToTime: extractor seek failed\n"); return result; + } result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time); - if (result != B_OK) + if (result != B_OK) { + TRACE("BMediaTrack::SeekToTime: decoder seek failed\n"); return result; + } *inout_time = time; fCurFrame = frame; fCurTime = time; + + printf("BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", request / 1000000.0, *inout_time / 1000000.0); return B_OK; } @@ -195,9 +203,11 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, CALLED(); if (!fDecoder || !fExtractor) return B_NO_INIT; - if (!inout_frame || !(flags & B_MEDIA_SEEK_DIRECTION_MASK)) + if (!inout_frame) return B_BAD_VALUE; + int64 request = *inout_frame; + status_t result; uint32 seekTo; int64 seekFrame; @@ -210,17 +220,23 @@ BMediaTrack::SeekToFrame(int64 *inout_frame, frame = seekFrame; result = fExtractor->Seek(fStream, seekTo, &frame, &time); - if (result != B_OK) + if (result != B_OK) { + TRACE("BMediaTrack::SeekToFrame: extractor seek failed\n"); return result; + } result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time); - if (result != B_OK) + if (result != B_OK) { return result; + TRACE("BMediaTrack::SeekToFrame: decoder seek failed\n"); + } *inout_frame = frame; fCurFrame = frame; fCurTime = time; + printf("BMediaTrack::SeekToTime SeekToFrame, requested %Ld, result %Ld\n", request, *inout_frame); + return B_OK; } diff --git a/src/kits/media/PluginManager.cpp b/src/kits/media/PluginManager.cpp index f27b70233e..f745a22257 100644 --- a/src/kits/media/PluginManager.cpp +++ b/src/kits/media/PluginManager.cpp @@ -3,6 +3,7 @@ #include #include "PluginManager.h" +#include "debug.h" PluginManager _plugin_manager; @@ -79,11 +80,13 @@ _CreateDecoder(Decoder **decoder, media_codec_info *mci, const media_format *for void _DestroyReader(Reader *reader) { + delete reader; } void _DestroyDecoder(Decoder *decoder) { + delete decoder; } status_t @@ -103,6 +106,7 @@ _PublishDecoder(DecoderPlugin *decoderplugin, PluginManager::PluginManager() { + CALLED(); fLocker = new BLocker; fPluginList = new List; } @@ -110,6 +114,7 @@ PluginManager::PluginManager() PluginManager::~PluginManager() { + CALLED(); while (!fPluginList->IsEmpty()) { plugin_info *info; fPluginList->Get(fPluginList->CountItems() - 1, &info);