mp3 decoding and seeking works now

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5581 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2003-12-05 22:11:52 +00:00
parent b65a0ac50e
commit d0b86c0f31
7 changed files with 99 additions and 46 deletions
@@ -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;
}
uint8 * out_buffer = static_cast<uint8 *>(buffer);
int32 out_bytes_needed = OUTPUT_BUFFER_SIZE;
int availsize;
int outsize;
int result;
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()
{
@@ -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;
};
@@ -225,7 +225,7 @@ mp3Reader::FreeCookie(void *cookie)
{
TRACE("mp3Reader::FreeCookie\n");
mp3data *data = reinterpret_cast<mp3data *>(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);
@@ -353,6 +353,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;
}
+4 -3
View File
@@ -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
+6 -1
View File
@@ -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;
}
+23 -7
View File
@@ -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,17 +175,23 @@ 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;
}
+5
View File
@@ -3,6 +3,7 @@
#include <string.h>
#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<plugin_info>;
}
@@ -110,6 +114,7 @@ PluginManager::PluginManager()
PluginManager::~PluginManager()
{
CALLED();
while (!fPluginList->IsEmpty()) {
plugin_info *info;
fPluginList->Get(fPluginList->CountItems() - 1, &info);