diff --git a/headers/os/media/MediaRoster.h b/headers/os/media/MediaRoster.h index 0eb6a6e83b..536c1630b7 100644 --- a/headers/os/media/MediaRoster.h +++ b/headers/os/media/MediaRoster.h @@ -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. */ diff --git a/headers/private/media/DecoderPlugin.h b/headers/private/media/DecoderPlugin.h index 296d12723f..5e9a4c6ba1 100644 --- a/headers/private/media/DecoderPlugin.h +++ b/headers/private/media/DecoderPlugin.h @@ -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, diff --git a/headers/private/media/MediaExtractor.h b/headers/private/media/MediaExtractor.h index 5585ae86ac..f7ee5f42dd 100644 --- a/headers/private/media/MediaExtractor.h +++ b/headers/private/media/MediaExtractor.h @@ -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); diff --git a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp index fe7125a208..9eae7b6ec6 100644 --- a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp +++ b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #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(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 diff --git a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h index 130eebe3b4..36f56b0066 100644 --- a/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h +++ b/src/add-ons/media/plugins/mp3_decoder/mp3DecoderPlugin.h @@ -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; }; diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp index 5be2cd08e7..1d012dd985 100644 --- a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp @@ -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; } diff --git a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h index addc5b1304..b5b91524d5 100644 --- a/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h +++ b/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.h @@ -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; }; diff --git a/src/kits/media/MediaExtractor.cpp b/src/kits/media/MediaExtractor.cpp index 339df1e5cf..72506e5528 100644 --- a/src/kits/media/MediaExtractor.cpp +++ b/src/kits/media/MediaExtractor.cpp @@ -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; } diff --git a/src/kits/media/MediaTrack.cpp b/src/kits/media/MediaTrack.cpp index de911cc2b7..3d95ea938e 100644 --- a/src/kits/media/MediaTrack.cpp +++ b/src/kits/media/MediaTrack.cpp @@ -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); }