diff --git a/src/kits/media/DecoderPlugin.cpp b/src/kits/media/DecoderPlugin.cpp index 2bd46bfc38..3c7f5795e2 100644 --- a/src/kits/media/DecoderPlugin.cpp +++ b/src/kits/media/DecoderPlugin.cpp @@ -6,24 +6,26 @@ Decoder::Decoder() { + fChunkProvider = 0; } Decoder::~Decoder() { + delete fChunkProvider; } status_t Decoder::GetNextChunk(void **chunkBuffer, int32 *chunkSize, media_header *mediaHeader) { - return fExtractor->GetNextChunk(fStream, chunkBuffer, chunkSize, mediaHeader); + return fChunkProvider->GetNextChunk(chunkBuffer, chunkSize, mediaHeader); } void -Decoder::Setup(MediaExtractor *extractor, int32 stream) +Decoder::Setup(ChunkProvider *provider) { - fExtractor = extractor; - fStream = stream; + delete fChunkProvider; + fChunkProvider = provider; } DecoderPlugin::DecoderPlugin() diff --git a/src/kits/media/MediaDecoder.cpp b/src/kits/media/MediaDecoder.cpp index 6ea344e97e..c38ffa1611 100644 --- a/src/kits/media/MediaDecoder.cpp +++ b/src/kits/media/MediaDecoder.cpp @@ -4,6 +4,7 @@ * DESCR: ***********************************************************************/ #include +#include #include "debug.h" /************************************************************* @@ -12,84 +13,160 @@ BMediaDecoder::BMediaDecoder() { - UNIMPLEMENTED(); + fDecoder = NULL; + fDecoderPlugin = NULL; + fInitStatus = B_NO_INIT; } BMediaDecoder::BMediaDecoder(const media_format *in_format, const void *info, size_t info_size) { - UNIMPLEMENTED(); + fDecoder = NULL; + fDecoderPlugin = NULL; + SetTo(in_format,info,info_size); } BMediaDecoder::BMediaDecoder(const media_codec_info *mci) { - UNIMPLEMENTED(); + fDecoder = NULL; + fDecoderPlugin = NULL; + SetTo(mci); } /* virtual */ BMediaDecoder::~BMediaDecoder() { - UNIMPLEMENTED(); + delete fDecoder; } status_t BMediaDecoder::InitCheck() const { - UNIMPLEMENTED(); - - return B_OK; + return fInitStatus; } +DecoderPlugin * GetDecoderPlugin(int32 id) +{ + UNIMPLEMENTED(); + // if our decoder plugin area id is not valid, + // ask the server for a new one. + // retrieve the id'th plugin here. + return NULL; +} +// ask the server for a good decoder for the arguments +// GETS THE CODEC for in_format->type + in_format->u.x.encoding status_t BMediaDecoder::SetTo(const media_format *in_format, const void *info, size_t info_size) { UNIMPLEMENTED(); - return B_OK; + return fInitStatus = B_NO_INIT; } +// ask the server for a good decoder for the arguments +// GETS THE CODEC for mci->id, mci->sub_id +// fails if the mci->id = 0 status_t BMediaDecoder::SetTo(const media_codec_info *mci) { - UNIMPLEMENTED(); - return B_OK; + class MediaDecoderChunkProvider : public ChunkProvider { + private: + BMediaDecoder * fDecoder; + public: + MediaDecoderChunkProvider(BMediaDecoder * decoder) { + fDecoder = decoder; + } + virtual status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader) { + const void ** buffer = const_cast(chunkBuffer); + size_t * size = reinterpret_cast(chunkSize); + return fDecoder->GetNextChunk(buffer,size,mediaHeader); + } + } * provider = new MediaDecoderChunkProvider(this); + if (provider == NULL) { + return fInitStatus = B_NO_MEMORY; + } + DecoderPlugin * plugin = GetDecoderPlugin(mci->id); + if (plugin == NULL) { + return fInitStatus = B_BAD_VALUE; + } + Decoder * decoder = plugin->NewDecoder(); + if (decoder == NULL) { + return fInitStatus = B_ERROR; + } + decoder->Setup(provider); + delete fDecoder; + fDecoderPluginID = mci->id; + fDecoderPlugin = plugin; + fDecoderID = mci->sub_id; + fDecoder = decoder; + return fInitStatus = B_OK; } +/* SetInputFormat() sets the input data format to in_format. + Unlike SetTo(), the SetInputFormat() function does not + select a codec, so the currently-selected codec will + continue to be used. You should only use SetInputFormat() + to refine the format settings if it will not require the + use of a different decoder. */ status_t BMediaDecoder::SetInputFormat(const media_format *in_format, const void *in_info, size_t in_size) { - UNIMPLEMENTED(); - return B_OK; + if (fInitStatus != B_OK) { + return fInitStatus; + } + media_format format = *in_format; + return fDecoder->Setup(&format,in_info,in_size); } +/* SetOutputFormat() sets the format the decoder should output. + On return, the output_format is changed to match the actual + format that will be output; this can be different if you + specified any wildcards. */ status_t BMediaDecoder::SetOutputFormat(media_format *output_format) { - UNIMPLEMENTED(); - return B_OK; + if (fInitStatus != B_OK) { + return fInitStatus; + } + return fDecoder->NegotiateOutputFormat(output_format); } -// Set output format to closest acceptable format, returns the -// format used. +/* Decodes a chunk of media data into the output buffer specified + by out_buffer. On return, out_frameCount is set to indicate how + many frames of data were decoded, and out_mh is the header for + the decoded buffer. The media_decode_info structure info is used + on input to specify decoding parameters. + + The amount of data decoded is part of the format determined by + SetTo() or SetInputFormat(). For audio, it's the buffer_size. + For video, it's one frame, which is height*row_bytes. The data + to be decoded will be fetched from the source by the decoder + add-on calling the derived class' GetNextChunk() function. */ status_t BMediaDecoder::Decode(void *out_buffer, int64 *out_frameCount, media_header *out_mh, media_decode_info *info) { - UNIMPLEMENTED(); - return B_OK; + if (fInitStatus != B_OK) { + return fInitStatus; + } + return fDecoder->Decode(out_buffer,out_frameCount,out_mh,info); } status_t BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const { + if (fInitStatus != B_OK) { + return fInitStatus; + } UNIMPLEMENTED(); return B_OK; } @@ -146,20 +223,23 @@ status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ER *************************************************************/ BMediaBufferDecoder::BMediaBufferDecoder() + : BMediaDecoder() { - UNIMPLEMENTED(); + buffer_size = 0; } BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format, const void *info, size_t info_size) + : BMediaDecoder(in_format,info,info_size) { - UNIMPLEMENTED(); + buffer_size = 0; } BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci) + : BMediaDecoder(mci) { - UNIMPLEMENTED(); + buffer_size = 0; } status_t @@ -170,8 +250,9 @@ BMediaBufferDecoder::DecodeBuffer(const void *input_buffer, media_header *out_mh, media_decode_info *info) { - UNIMPLEMENTED(); - return B_OK; + buffer = input_buffer; + buffer_size = input_size; + return Decode(out_buffer,out_frameCount,out_mh,info); } /************************************************************* @@ -183,7 +264,11 @@ status_t BMediaBufferDecoder::GetNextChunk(const void **chunkData, size_t *chunkLen, media_header *mh) { - UNIMPLEMENTED(); + if (!buffer_size) { + return B_LAST_BUFFER_ERROR; + } + *chunkData = buffer; + *chunkLen = buffer_size; + buffer_size = 0; return B_OK; } - diff --git a/src/kits/media/MediaExtractor.cpp b/src/kits/media/MediaExtractor.cpp index 31de2ef1b7..82440c4d5e 100644 --- a/src/kits/media/MediaExtractor.cpp +++ b/src/kits/media/MediaExtractor.cpp @@ -159,6 +159,21 @@ MediaExtractor::GetNextChunk(int32 stream, return fReader->GetNextChunk(fStreamInfo[stream].cookie, chunkBuffer, chunkSize, mediaHeader); } +class MediaExtractorChunkProvider : public ChunkProvider { +private: + MediaExtractor * fExtractor; + int32 fStream; +public: + MediaExtractorChunkProvider(MediaExtractor * extractor, int32 stream) { + fExtractor = extractor; + fStream = stream; + } + virtual status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize, + media_header *mediaHeader) { + return fExtractor->GetNextChunk(fStream,chunkBuffer,chunkSize,mediaHeader); + } +}; + status_t MediaExtractor::CreateDecoder(int32 stream, Decoder **decoder, media_codec_info *mci) { @@ -177,7 +192,7 @@ MediaExtractor::CreateDecoder(int32 stream, Decoder **decoder, media_codec_info return res; } - (*decoder)->Setup(this, stream); + (*decoder)->Setup(new MediaExtractorChunkProvider(this,stream)); res = (*decoder)->Setup(&fStreamInfo[stream].encodedFormat, fStreamInfo[stream].infoBuffer , fStreamInfo[stream].infoBufferSize); if (res != B_OK) {