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,
|
int32 channel_count,
|
||||||
uint32 sample_format,
|
uint32 sample_format,
|
||||||
float frame_rate,
|
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. */
|
/* Use MediaFlags to inquire about specific features of the Media Kit. */
|
||||||
/* Returns < 0 for "not present", positive size for output data size. */
|
/* Returns < 0 for "not present", positive size for output data size. */
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ public:
|
|||||||
virtual ~Decoder();
|
virtual ~Decoder();
|
||||||
|
|
||||||
// Setup get's called with the info data from Reader::GetStreamInfo
|
// Setup get's called with the info data from Reader::GetStreamInfo
|
||||||
virtual status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
virtual status_t Setup(media_format *ioEncodedFormat, const void *infoBuffer, int32 infoSize) = 0;
|
||||||
const void *infoBuffer, int32 infoSize) = 0;
|
|
||||||
|
virtual status_t NegotiateOutputFormat(media_format *ioDecodedFormat) = 0;
|
||||||
|
|
||||||
virtual status_t Seek(uint32 seekTo,
|
virtual status_t Seek(uint32 seekTo,
|
||||||
int64 seekFrame, int64 *frame,
|
int64 seekFrame, int64 *frame,
|
||||||
|
|||||||
@@ -28,11 +28,9 @@ public:
|
|||||||
|
|
||||||
int32 StreamCount();
|
int32 StreamCount();
|
||||||
|
|
||||||
media_format * EncodedFormat(int32 stream);
|
const media_format * EncodedFormat(int32 stream);
|
||||||
int64 CountFrames(int32 stream) const;
|
int64 CountFrames(int32 stream) const;
|
||||||
bigtime_t Duration(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,
|
status_t Seek(int32 stream, uint32 seekTo,
|
||||||
int64 *frame, bigtime_t *time);
|
int64 *frame, bigtime_t *time);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <DataIO.h>
|
#include <DataIO.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
#include <MediaFormats.h>
|
#include <MediaFormats.h>
|
||||||
|
#include <MediaRoster.h>
|
||||||
#include "mp3DecoderPlugin.h"
|
#include "mp3DecoderPlugin.h"
|
||||||
|
|
||||||
#define TRACE_THIS 1
|
#define TRACE_THIS 1
|
||||||
@@ -11,7 +12,6 @@
|
|||||||
#define TRACE(a...)
|
#define TRACE(a...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define OUTPUT_BUFFER_SIZE (8 * 1024)
|
|
||||||
#define DECODE_BUFFER_SIZE (32 * 1024)
|
#define DECODE_BUFFER_SIZE (32 * 1024)
|
||||||
|
|
||||||
mp3Decoder::mp3Decoder()
|
mp3Decoder::mp3Decoder()
|
||||||
@@ -20,7 +20,12 @@ mp3Decoder::mp3Decoder()
|
|||||||
fResidualBytes = 0;
|
fResidualBytes = 0;
|
||||||
fResidualBuffer = 0;
|
fResidualBuffer = 0;
|
||||||
fDecodeBuffer = new uint8 [DECODE_BUFFER_SIZE];
|
fDecodeBuffer = new uint8 [DECODE_BUFFER_SIZE];
|
||||||
|
fStartTime = 0;
|
||||||
fFrameSize = 0;
|
fFrameSize = 0;
|
||||||
|
fFrameRate = 0;
|
||||||
|
fBitRate = 0;
|
||||||
|
fChannelCount = 0;
|
||||||
|
fOutputBufferSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -32,19 +37,56 @@ mp3Decoder::~mp3Decoder()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
mp3Decoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
mp3Decoder::Setup(media_format *ioEncodedFormat,
|
||||||
const void *infoBuffer, int32 infoSize)
|
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->type = B_MEDIA_RAW_AUDIO;
|
||||||
ioDecodedFormat->u.raw_audio.frame_rate = 44100;
|
ioDecodedFormat->u.raw_audio.frame_rate = fFrameRate;
|
||||||
ioDecodedFormat->u.raw_audio.channel_count = 2;
|
ioDecodedFormat->u.raw_audio.channel_count = fChannelCount;
|
||||||
ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
|
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_LITTLE_ENDIAN;
|
ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; // XXX should support other endain, too
|
||||||
ioDecodedFormat->u.raw_audio.buffer_size = OUTPUT_BUFFER_SIZE;
|
if (ioDecodedFormat->u.raw_audio.buffer_size < 512 || ioDecodedFormat->u.raw_audio.buffer_size > 65536)
|
||||||
ioDecodedFormat->u.raw_audio.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT;
|
ioDecodedFormat->u.raw_audio.buffer_size = BMediaRoster::Roster()->AudioBufferSizeFor(
|
||||||
fFrameSize = 4;
|
fChannelCount,
|
||||||
fFps = 44100;
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +108,7 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
media_header *mediaHeader, media_decode_info *info /* = 0 */)
|
media_header *mediaHeader, media_decode_info *info /* = 0 */)
|
||||||
{
|
{
|
||||||
uint8 * out_buffer = static_cast<uint8 *>(buffer);
|
uint8 * out_buffer = static_cast<uint8 *>(buffer);
|
||||||
int32 out_bytes_needed = OUTPUT_BUFFER_SIZE;
|
int32 out_bytes_needed = fOutputBufferSize;
|
||||||
|
|
||||||
mediaHeader->start_time = fStartTime;
|
mediaHeader->start_time = fStartTime;
|
||||||
//TRACE("mp3Decoder: Decoding start time %.6f\n", fStartTime / 1000000.0);
|
//TRACE("mp3Decoder: Decoding start time %.6f\n", fStartTime / 1000000.0);
|
||||||
@@ -80,7 +122,7 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
out_buffer += bytes;
|
out_buffer += bytes;
|
||||||
out_bytes_needed -= 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);
|
//TRACE("mp3Decoder: fStartTime inc'd to %.6f\n", fStartTime / 1000000.0);
|
||||||
continue;
|
continue;
|
||||||
@@ -90,10 +132,10 @@ mp3Decoder::Decode(void *buffer, int64 *frameCount,
|
|||||||
break;
|
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
|
// 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
|
status_t
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ public:
|
|||||||
mp3Decoder();
|
mp3Decoder();
|
||||||
~mp3Decoder();
|
~mp3Decoder();
|
||||||
|
|
||||||
status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
status_t Setup(media_format *ioEncodedFormat,
|
||||||
const void *infoBuffer, int32 infoSize);
|
const void *infoBuffer, int32 infoSize);
|
||||||
|
|
||||||
|
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
|
||||||
|
|
||||||
status_t Seek(uint32 seekTo,
|
status_t Seek(uint32 seekTo,
|
||||||
int64 seekFrame, int64 *frame,
|
int64 seekFrame, int64 *frame,
|
||||||
bigtime_t seekTime, bigtime_t *time);
|
bigtime_t seekTime, bigtime_t *time);
|
||||||
@@ -26,9 +28,12 @@ private:
|
|||||||
int32 fResidualBytes;
|
int32 fResidualBytes;
|
||||||
uint8 * fResidualBuffer;
|
uint8 * fResidualBuffer;
|
||||||
uint8 * fDecodeBuffer;
|
uint8 * fDecodeBuffer;
|
||||||
int32 fFrameSize;
|
|
||||||
int32 fFps;
|
|
||||||
bigtime_t fStartTime;
|
bigtime_t fStartTime;
|
||||||
|
int fFrameSize;
|
||||||
|
int fFrameRate;
|
||||||
|
int fBitRate;
|
||||||
|
int fChannelCount;
|
||||||
|
int fOutputBufferSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,24 +7,36 @@
|
|||||||
#if TRACE_THIS
|
#if TRACE_THIS
|
||||||
#define TRACE printf
|
#define TRACE printf
|
||||||
#else
|
#else
|
||||||
#define TRACE ((void)0)
|
#define TRACE TRACE(a...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
RawDecoder::Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
RawDecoder::Setup(media_format *ioEncodedFormat,
|
||||||
const void *infoBuffer, int32 infoSize)
|
const void *infoBuffer, int32 infoSize)
|
||||||
{
|
{
|
||||||
if (ioEncodedFormat->type != B_MEDIA_RAW_AUDIO && ioEncodedFormat->type != B_MEDIA_RAW_VIDEO)
|
if (ioEncodedFormat->type != B_MEDIA_RAW_AUDIO && ioEncodedFormat->type != B_MEDIA_RAW_VIDEO)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
|
fInputFormat = *ioEncodedFormat;
|
||||||
|
|
||||||
if (ioEncodedFormat->type == B_MEDIA_RAW_VIDEO)
|
if (ioEncodedFormat->type == B_MEDIA_RAW_VIDEO)
|
||||||
fFrameSize = ioEncodedFormat->u.raw_video.display.line_count * ioEncodedFormat->u.raw_video.display.bytes_per_row;
|
fFrameSize = ioEncodedFormat->u.raw_video.display.line_count * ioEncodedFormat->u.raw_video.display.bytes_per_row;
|
||||||
else
|
else
|
||||||
fFrameSize = (ioEncodedFormat->u.raw_audio.format & 0xf) * ioEncodedFormat->u.raw_audio.channel_count;
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
class RawDecoder : public Decoder
|
class RawDecoder : public Decoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
status_t Setup(media_format *ioEncodedFormat, media_format *ioDecodedFormat,
|
status_t Setup(media_format *ioEncodedFormat,
|
||||||
const void *infoBuffer, int32 infoSize);
|
const void *infoBuffer, int32 infoSize);
|
||||||
|
|
||||||
|
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
|
||||||
|
|
||||||
status_t Seek(uint32 seekTo,
|
status_t Seek(uint32 seekTo,
|
||||||
int64 seekFrame, int64 *frame,
|
int64 seekFrame, int64 *frame,
|
||||||
bigtime_t seekTime, bigtime_t *time);
|
bigtime_t seekTime, bigtime_t *time);
|
||||||
@@ -13,7 +15,8 @@ public:
|
|||||||
status_t Decode(void *buffer, int64 *frameCount,
|
status_t Decode(void *buffer, int64 *frameCount,
|
||||||
media_header *mediaHeader, media_decode_info *info);
|
media_header *mediaHeader, media_decode_info *info);
|
||||||
private:
|
private:
|
||||||
int32 fFrameSize;
|
int32 fFrameSize;
|
||||||
|
media_format fInputFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ MediaExtractor::StreamCount()
|
|||||||
return fStreamCount;
|
return fStreamCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
media_format *
|
const media_format *
|
||||||
MediaExtractor::EncodedFormat(int32 stream)
|
MediaExtractor::EncodedFormat(int32 stream)
|
||||||
{
|
{
|
||||||
return &fStreamInfo[stream].encodedFormat;
|
return &fStreamInfo[stream].encodedFormat;
|
||||||
@@ -126,18 +126,6 @@ MediaExtractor::Duration(int32 stream) const
|
|||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
|
||||||
MediaExtractor::InfoBuffer(int32 stream) const
|
|
||||||
{
|
|
||||||
return fStreamInfo[stream].infoBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32
|
|
||||||
MediaExtractor::InfoBufferSize(int32 stream) const
|
|
||||||
{
|
|
||||||
return fStreamInfo[stream].infoBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
MediaExtractor::Seek(int32 stream, uint32 seekTo,
|
MediaExtractor::Seek(int32 stream, uint32 seekTo,
|
||||||
int64 *frame, bigtime_t *time)
|
int64 *frame, bigtime_t *time)
|
||||||
@@ -180,6 +168,11 @@ MediaExtractor::CreateDecoder(int32 stream, Decoder **decoder, media_codec_info
|
|||||||
|
|
||||||
(*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)
|
if (!fExtractor || !fDecoder)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
return fDecoder->Setup(fExtractor->EncodedFormat(fStream), inout_format,
|
return fDecoder->NegotiateOutputFormat(inout_format);
|
||||||
fExtractor->InfoBuffer(fStream), fExtractor->InfoBufferSize(fStream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user