codec output format negotiation has been moved into NegotiateOutputFormat,
Setup is now only called once git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5596 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -343,7 +343,7 @@ static BMediaRoster * CurrentRoster(); // won't create it if there isn't one
|
||||
int32 channel_count,
|
||||
uint32 sample_format,
|
||||
float frame_rate,
|
||||
bus_type bus_kind);
|
||||
bus_type bus_kind = B_UNKNOWN_BUS);
|
||||
|
||||
/* Use MediaFlags to inquire about specific features of the Media Kit. */
|
||||
/* Returns < 0 for "not present", positive size for output data size. */
|
||||
|
||||
@@ -15,8 +15,9 @@ public:
|
||||
virtual ~Decoder();
|
||||
|
||||
// Setup get's called with the info data from Reader::GetStreamInfo
|
||||
virtual status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
||||
const void *infoBuffer, int32 infoSize) = 0;
|
||||
virtual status_t Setup(media_format *ioEncodedFormat, const void *infoBuffer, int32 infoSize) = 0;
|
||||
|
||||
virtual status_t NegotiateOutputFormat(media_format *ioDecodedFormat) = 0;
|
||||
|
||||
virtual status_t Seek(uint32 seekTo,
|
||||
int64 seekFrame, int64 *frame,
|
||||
|
||||
@@ -28,11 +28,9 @@ public:
|
||||
|
||||
int32 StreamCount();
|
||||
|
||||
media_format * EncodedFormat(int32 stream);
|
||||
const media_format * EncodedFormat(int32 stream);
|
||||
int64 CountFrames(int32 stream) const;
|
||||
bigtime_t Duration(int32 stream) const;
|
||||
void * InfoBuffer(int32 stream) const;
|
||||
int32 InfoBufferSize(int32 stream) const;
|
||||
|
||||
status_t Seek(int32 stream, uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <DataIO.h>
|
||||
#include <Locker.h>
|
||||
#include <MediaFormats.h>
|
||||
#include <MediaRoster.h>
|
||||
#include "mp3DecoderPlugin.h"
|
||||
|
||||
#define TRACE_THIS 1
|
||||
@@ -11,7 +12,6 @@
|
||||
#define TRACE(a...)
|
||||
#endif
|
||||
|
||||
#define OUTPUT_BUFFER_SIZE (8 * 1024)
|
||||
#define DECODE_BUFFER_SIZE (32 * 1024)
|
||||
|
||||
mp3Decoder::mp3Decoder()
|
||||
@@ -20,7 +20,12 @@ mp3Decoder::mp3Decoder()
|
||||
fResidualBytes = 0;
|
||||
fResidualBuffer = 0;
|
||||
fDecodeBuffer = new uint8 [DECODE_BUFFER_SIZE];
|
||||
fStartTime = 0;
|
||||
fFrameSize = 0;
|
||||
fFrameRate = 0;
|
||||
fBitRate = 0;
|
||||
fChannelCount = 0;
|
||||
fOutputBufferSize = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,19 +37,56 @@ mp3Decoder::~mp3Decoder()
|
||||
|
||||
|
||||
status_t
|
||||
mp3Decoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
||||
mp3Decoder::Setup(media_format *ioEncodedFormat,
|
||||
const void *infoBuffer, int32 infoSize)
|
||||
{
|
||||
memset(ioDecodedFormat, 0, sizeof(*ioDecodedFormat));
|
||||
// decode first chunk to initialize mpeg library
|
||||
if (B_OK != DecodeNextChunk()) {
|
||||
printf("mp3Decoder::Setup failed, can't decode first chunk\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// initialize fBitRate, fFrameRate and fChannelCount from mpg decode library values of first header
|
||||
extern int tabsel_123[2][3][16];
|
||||
extern long freqs[9];
|
||||
fBitRate = tabsel_123[fMpgLibPrivate.fr.lsf][fMpgLibPrivate.fr.lay-1][fMpgLibPrivate.fr.bitrate_index] * 1000;
|
||||
fFrameRate = freqs[fMpgLibPrivate.fr.sampling_frequency];
|
||||
fChannelCount = fMpgLibPrivate.fr.stereo;
|
||||
|
||||
printf("mp3Decoder::Setup: channels %d, bitrate %d, framerate %d\n", fChannelCount, fBitRate, fFrameRate);
|
||||
|
||||
// put some more useful info into the media_format describing our input format
|
||||
ioEncodedFormat->u.encoded_audio.bit_rate = fBitRate;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
mp3Decoder::NegotiateOutputFormat(media_format *ioDecodedFormat)
|
||||
{
|
||||
// fFrameRate and fChannelCount are already valid here
|
||||
|
||||
// BeBook says: The codec will find and return in ioFormat its best matching format
|
||||
// => This means, we never return an error, and always change the format values
|
||||
// that we don't support to something more applicable
|
||||
|
||||
ioDecodedFormat->type = B_MEDIA_RAW_AUDIO;
|
||||
ioDecodedFormat->u.raw_audio.frame_rate = 44100;
|
||||
ioDecodedFormat->u.raw_audio.channel_count = 2;
|
||||
ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
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;
|
||||
fFps = 44100;
|
||||
ioDecodedFormat->u.raw_audio.frame_rate = fFrameRate;
|
||||
ioDecodedFormat->u.raw_audio.channel_count = fChannelCount;
|
||||
ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; // XXX should support other formats, too
|
||||
ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too
|
||||
if (ioDecodedFormat->u.raw_audio.buffer_size < 512 || ioDecodedFormat->u.raw_audio.buffer_size > 65536)
|
||||
ioDecodedFormat->u.raw_audio.buffer_size = BMediaRoster::Roster()->AudioBufferSizeFor(
|
||||
fChannelCount,
|
||||
ioDecodedFormat->u.raw_audio.format,
|
||||
fFrameRate);
|
||||
if (ioDecodedFormat->u.raw_audio.channel_mask == 0)
|
||||
ioDecodedFormat->u.raw_audio.channel_mask = (fChannelCount == 1) ? B_CHANNEL_LEFT : B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
|
||||
|
||||
// setup rest of the needed variables
|
||||
fFrameSize = (ioDecodedFormat->u.raw_audio.format & 0xf) * fChannelCount;
|
||||
fOutputBufferSize = ioDecodedFormat->u.raw_audio.buffer_size;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -66,7 +108,7 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
||||
media_header *mediaHeader, media_decode_info *info /* = 0 */)
|
||||
{
|
||||
uint8 * out_buffer = static_cast<uint8 *>(buffer);
|
||||
int32 out_bytes_needed = OUTPUT_BUFFER_SIZE;
|
||||
int32 out_bytes_needed = fOutputBufferSize;
|
||||
|
||||
mediaHeader->start_time = fStartTime;
|
||||
//TRACE("mp3Decoder: Decoding start time %.6f\n", fStartTime / 1000000.0);
|
||||
@@ -80,7 +122,7 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
||||
out_buffer += bytes;
|
||||
out_bytes_needed -= bytes;
|
||||
|
||||
fStartTime += (1000000LL * (bytes / fFrameSize)) / fFps;
|
||||
fStartTime += (1000000LL * (bytes / fFrameSize)) / fFrameRate;
|
||||
|
||||
//TRACE("mp3Decoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
||||
continue;
|
||||
@@ -90,10 +132,10 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
||||
break;
|
||||
}
|
||||
|
||||
*frameCount = (OUTPUT_BUFFER_SIZE - out_bytes_needed) / fFrameSize;
|
||||
*frameCount = (fOutputBufferSize - 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;
|
||||
return (out_bytes_needed == 0) ? B_OK : (out_bytes_needed == fOutputBufferSize) ? B_ERROR : B_LAST_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
status_t
|
||||
|
||||
@@ -8,9 +8,11 @@ public:
|
||||
mp3Decoder();
|
||||
~mp3Decoder();
|
||||
|
||||
status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
||||
status_t Setup(media_format *ioEncodedFormat,
|
||||
const void *infoBuffer, int32 infoSize);
|
||||
|
||||
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
|
||||
|
||||
status_t Seek(uint32 seekTo,
|
||||
int64 seekFrame, int64 *frame,
|
||||
bigtime_t seekTime, bigtime_t *time);
|
||||
@@ -26,9 +28,12 @@ private:
|
||||
int32 fResidualBytes;
|
||||
uint8 * fResidualBuffer;
|
||||
uint8 * fDecodeBuffer;
|
||||
int32 fFrameSize;
|
||||
int32 fFps;
|
||||
bigtime_t fStartTime;
|
||||
int fFrameSize;
|
||||
int fFrameRate;
|
||||
int fBitRate;
|
||||
int fChannelCount;
|
||||
int fOutputBufferSize;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,24 +7,36 @@
|
||||
#if TRACE_THIS
|
||||
#define TRACE printf
|
||||
#else
|
||||
#define TRACE ((void)0)
|
||||
#define TRACE TRACE(a...)
|
||||
#endif
|
||||
|
||||
|
||||
status_t
|
||||
RawDecoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
||||
RawDecoder::Setup(media_format *ioEncodedFormat,
|
||||
const void *infoBuffer, int32 infoSize)
|
||||
{
|
||||
if (ioEncodedFormat->type != B_MEDIA_RAW_AUDIO && ioEncodedFormat->type != B_MEDIA_RAW_VIDEO)
|
||||
return B_ERROR;
|
||||
|
||||
fInputFormat = *ioEncodedFormat;
|
||||
|
||||
if (ioEncodedFormat->type == B_MEDIA_RAW_VIDEO)
|
||||
fFrameSize = ioEncodedFormat->u.raw_video.display.line_count * ioEncodedFormat->u.raw_video.display.bytes_per_row;
|
||||
else
|
||||
fFrameSize = (ioEncodedFormat->u.raw_audio.format & 0xf) * ioEncodedFormat->u.raw_audio.channel_count;
|
||||
|
||||
*ioDecodedFormat = *ioEncodedFormat;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
RawDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat)
|
||||
{
|
||||
// BeBook says: The codec will find and return in ioFormat its best matching format
|
||||
// => This means, we never return an error, and always change the format values
|
||||
// that we don't support to something more applicable
|
||||
|
||||
*ioDecodedFormat = fInputFormat;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
class RawDecoder : public Decoder
|
||||
{
|
||||
public:
|
||||
status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
||||
status_t Setup(media_format *ioEncodedFormat,
|
||||
const void *infoBuffer, int32 infoSize);
|
||||
|
||||
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
|
||||
|
||||
status_t Seek(uint32 seekTo,
|
||||
int64 seekFrame, int64 *frame,
|
||||
@@ -13,7 +15,8 @@ public:
|
||||
status_t Decode(void *buffer, int64 *frameCount,
|
||||
media_header *mediaHeader, media_decode_info *info);
|
||||
private:
|
||||
int32 fFrameSize;
|
||||
int32 fFrameSize;
|
||||
media_format fInputFormat;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ MediaExtractor::StreamCount()
|
||||
return fStreamCount;
|
||||
}
|
||||
|
||||
media_format *
|
||||
const media_format *
|
||||
MediaExtractor::EncodedFormat(int32 stream)
|
||||
{
|
||||
return &fStreamInfo[stream].encodedFormat;
|
||||
@@ -126,18 +126,6 @@ MediaExtractor::Duration(int32 stream) const
|
||||
return duration;
|
||||
}
|
||||
|
||||
void *
|
||||
MediaExtractor::InfoBuffer(int32 stream) const
|
||||
{
|
||||
return fStreamInfo[stream].infoBuffer;
|
||||
}
|
||||
|
||||
int32
|
||||
MediaExtractor::InfoBufferSize(int32 stream) const
|
||||
{
|
||||
return fStreamInfo[stream].infoBufferSize;
|
||||
}
|
||||
|
||||
status_t
|
||||
MediaExtractor::Seek(int32 stream, uint32 seekTo,
|
||||
int64 *frame, bigtime_t *time)
|
||||
@@ -178,8 +166,13 @@ MediaExtractor::CreateDecoder(int32 stream, Decoder **decoder, media_codec_info
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
(*decoder)->Setup(this, stream);
|
||||
(*decoder)->Setup(this, stream);
|
||||
|
||||
return B_OK;
|
||||
status_t res;
|
||||
res = (*decoder)->Setup(&fStreamInfo[stream].encodedFormat, fStreamInfo[stream].infoBuffer , fStreamInfo[stream].infoBufferSize);
|
||||
if (res != B_OK) {
|
||||
printf("MediaExtractor::CreateDecoder Setup failed for stream %ld\n", stream);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,8 +69,7 @@ BMediaTrack::DecodedFormat(media_format *inout_format)
|
||||
if (!fExtractor || !fDecoder)
|
||||
return B_NO_INIT;
|
||||
|
||||
return fDecoder->Setup(fExtractor->EncodedFormat(fStream), inout_format,
|
||||
fExtractor->InfoBuffer(fStream), fExtractor->InfoBufferSize(fStream));
|
||||
return fDecoder->NegotiateOutputFormat(inout_format);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user