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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user