fixed timing information returned in media_header
added GetFileFormatInfo to reader api git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5595 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -21,6 +21,8 @@ public:
|
||||
|
||||
virtual status_t Sniff(int32 *streamCount) = 0;
|
||||
|
||||
virtual void GetFileFormatInfo(media_file_format *mff) = 0;
|
||||
|
||||
virtual status_t AllocateCookie(int32 streamNumber, void **cookie) = 0;
|
||||
virtual status_t FreeCookie(void *cookie) = 0;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ mp3Decoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
||||
ioDecodedFormat->u.raw_audio.buffer_size = OUTPUT_BUFFER_SIZE;
|
||||
ioDecodedFormat->u.raw_audio.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
|
||||
fFrameSize = 4;
|
||||
fFps = 44100;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -67,6 +68,9 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
||||
uint8 * out_buffer = static_cast<uint8 *>(buffer);
|
||||
int32 out_bytes_needed = OUTPUT_BUFFER_SIZE;
|
||||
|
||||
mediaHeader->start_time = fStartTime;
|
||||
//TRACE("mp3Decoder: Decoding start time %.6f\n", fStartTime / 1000000.0);
|
||||
|
||||
while (out_bytes_needed > 0) {
|
||||
if (fResidualBytes) {
|
||||
int32 bytes = min_c(fResidualBytes, out_bytes_needed);
|
||||
@@ -75,32 +79,51 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
||||
fResidualBytes -= bytes;
|
||||
out_buffer += bytes;
|
||||
out_bytes_needed -= bytes;
|
||||
|
||||
fStartTime += (1000000LL * (bytes / fFrameSize)) / fFps;
|
||||
|
||||
//TRACE("mp3Decoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
if (B_OK != DecodeNextChunk())
|
||||
break;
|
||||
}
|
||||
|
||||
*frameCount = OUTPUT_BUFFER_SIZE / fFrameSize;
|
||||
*frameCount = (OUTPUT_BUFFER_SIZE - out_bytes_needed) / fFrameSize;
|
||||
|
||||
// XXX this doesn't guarantee that we always return B_LAST_BUFFER_ERROR bofore returning B_ERROR
|
||||
return (out_bytes_needed == 0) ? B_OK : (out_bytes_needed == OUTPUT_BUFFER_SIZE) ? B_ERROR : B_LAST_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
status_t
|
||||
mp3Decoder::DecodeNextChunk()
|
||||
{
|
||||
void *chunkBuffer;
|
||||
int32 chunkSize;
|
||||
media_header mh;
|
||||
if (B_OK != GetNextChunk(&chunkBuffer, &chunkSize, &mh)) {
|
||||
TRACE("mp3Decoder::Decode: GetNextChunk failed\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fStartTime = mh.start_time;
|
||||
|
||||
//TRACE("mp3Decoder: fStartTime reset to %.6f\n", fStartTime / 1000000.0);
|
||||
|
||||
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;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,17 @@ public:
|
||||
|
||||
status_t Decode(void *buffer, int64 *frameCount,
|
||||
media_header *mediaHeader, media_decode_info *info);
|
||||
|
||||
status_t DecodeNextChunk();
|
||||
|
||||
private:
|
||||
struct mpstr fMpgLibPrivate;
|
||||
int32 fResidualBytes;
|
||||
uint8 * fResidualBuffer;
|
||||
uint8 * fDecodeBuffer;
|
||||
int32 fFrameSize;
|
||||
int32 fFrameSize;
|
||||
int32 fFps;
|
||||
bigtime_t fStartTime;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -69,6 +69,15 @@ static const int frame_rate_table[4][4] =
|
||||
{ 44100, 48000, 32000, 0} // mpeg version 1
|
||||
};
|
||||
|
||||
// name_table[mpeg_version_index][layer_index]
|
||||
static const char * name_table[4][4] =
|
||||
{
|
||||
{ 0, "MPEG 2.5 Audio Layer 3", "MPEG 2.5 Audio Layer 2", "MPEG 2.5 Audio Layer 1" },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, "MPEG 2 Audio Layer 3", "MPEG 2 Audio Layer 2", "MPEG 2 Audio Layer 1" },
|
||||
{ 0, "MPEG 1 Audio Layer 3", "MPEG 1 Audio Layer 2", "MPEG 1 Audio Layer 1" },
|
||||
};
|
||||
|
||||
// frame_sample_count_table[layer_index]
|
||||
static const int frame_sample_count_table[4] = { 0, 1152, 1152, 384 };
|
||||
|
||||
@@ -106,6 +115,7 @@ struct mp3Reader::fhg_vbr_info
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
mp3Reader::mp3Reader()
|
||||
: fXingVbrInfo(0),
|
||||
fFhgVbrInfo(0)
|
||||
@@ -113,11 +123,13 @@ mp3Reader::mp3Reader()
|
||||
TRACE("mp3Reader::mp3Reader\n");
|
||||
}
|
||||
|
||||
|
||||
mp3Reader::~mp3Reader()
|
||||
{
|
||||
delete fXingVbrInfo;
|
||||
delete fFhgVbrInfo;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
mp3Reader::Copyright()
|
||||
@@ -125,7 +137,7 @@ mp3Reader::Copyright()
|
||||
return "mp3 reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen";
|
||||
}
|
||||
|
||||
|
||||
|
||||
status_t
|
||||
mp3Reader::Sniff(int32 *streamCount)
|
||||
{
|
||||
@@ -158,6 +170,26 @@ mp3Reader::Sniff(int32 *streamCount)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mp3Reader::GetFileFormatInfo(media_file_format *mff)
|
||||
{
|
||||
mff->capabilities = media_file_format::B_READABLE
|
||||
| media_file_format::B_KNOWS_ENCODED_AUDIO
|
||||
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
||||
mff->family = B_MPEG_FORMAT_FAMILY;
|
||||
mff->version = 100;
|
||||
strcpy(mff->mime_type, "audio/mpeg");
|
||||
strcpy(mff->file_extension, "mp3");
|
||||
|
||||
uint8 header[4];
|
||||
Source()->ReadAt(fDataStart, header, sizeof(header));
|
||||
int mpeg_version_index = (header[1] >> 3) & 0x03;
|
||||
int layer_index = (header[1] >> 1) & 0x03;
|
||||
strcpy(mff->short_name, name_table[mpeg_version_index][layer_index]);
|
||||
strcpy(mff->pretty_name, name_table[mpeg_version_index][layer_index]);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
mp3Reader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||
{
|
||||
@@ -306,6 +338,8 @@ mp3Reader::Seek(void *cookie,
|
||||
}
|
||||
data->position = pos + ofs;
|
||||
|
||||
data->framePosition = *frame; // this is not exact
|
||||
|
||||
TRACE("mp3Reader::Seek: synchronized at position %Ld\n", data->position);
|
||||
return B_OK;
|
||||
}
|
||||
@@ -322,7 +356,7 @@ mp3Reader::GetNextChunk(void *cookie,
|
||||
if (maxbytes < 4)
|
||||
return B_ERROR;
|
||||
|
||||
mediaHeader->start_time = (data->framePosition * 1000000) / data->frameCount;
|
||||
mediaHeader->start_time = (data->framePosition * 1000000) / data->frameRate;
|
||||
mediaHeader->file_pos = data->position;
|
||||
|
||||
if (4 != Source()->ReadAt(fDataStart + data->position, data->chunkBuffer, 4)) {
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
|
||||
status_t Sniff(int32 *streamCount);
|
||||
|
||||
void GetFileFormatInfo(media_file_format *mff);
|
||||
|
||||
status_t AllocateCookie(int32 streamNumber, void **cookie);
|
||||
status_t FreeCookie(void *cookie);
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ WavReader::Sniff(int32 *streamCount)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WavReader::GetFileFormatInfo(media_file_format *mff)
|
||||
{
|
||||
mff->capabilities = media_file_format::B_READABLE
|
||||
| media_file_format::B_KNOWS_ENCODED_AUDIO
|
||||
| media_file_format::B_IMPERFECTLY_SEEKABLE;
|
||||
mff->family = B_WAV_FORMAT_FAMILY;
|
||||
mff->version = 100;
|
||||
strcpy(mff->mime_type, "audio/x-wav");
|
||||
strcpy(mff->file_extension, "wav");
|
||||
strcpy(mff->short_name, "RIFF WAV audio");
|
||||
strcpy(mff->pretty_name, "RIFF WAV audio");
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
WavReader::AllocateCookie(int32 streamNumber, void **cookie)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@ public:
|
||||
|
||||
status_t Sniff(int32 *streamCount);
|
||||
|
||||
void GetFileFormatInfo(media_file_format *mff);
|
||||
|
||||
status_t AllocateCookie(int32 streamNumber, void **cookie);
|
||||
status_t FreeCookie(void *cookie);
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ const char *
|
||||
BMediaFile::Copyright(void) const
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return "BMediaFile::Copyright";
|
||||
return "";
|
||||
}
|
||||
|
||||
int32
|
||||
|
||||
@@ -40,6 +40,8 @@ _CreateReader(Reader **reader, int32 *streamCount, media_file_format *mff, BData
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
(*reader)->GetFileFormatInfo(mff);
|
||||
|
||||
printf("_CreateReader leave\n");
|
||||
|
||||
return B_OK;
|
||||
@@ -71,6 +73,9 @@ _CreateDecoder(Decoder **decoder, media_codec_info *mci, const media_format *for
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
strcpy(mci->short_name, " mci short_name");
|
||||
strcpy(mci->pretty_name, " mci pretty_name");
|
||||
|
||||
printf("_CreateDecoder leave\n");
|
||||
|
||||
return B_OK;
|
||||
|
||||
Reference in New Issue
Block a user