Files
haiku-beta6/src/kits/media/MediaDecoder.cpp
T
shatty faca9355a7 fixed GetNextChunk not connected bug
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6671 a95241bf-73f2-0310-859d-f6bbb57e9c96
2004-02-22 06:12:45 +00:00

368 lines
10 KiB
C++

/***********************************************************************
* AUTHOR: Andrew Bachmann, Marcus Overhagen
* FILE: MediaDecoder.cpp
* DESCR:
***********************************************************************/
#include <MediaDecoder.h>
#include <DecoderPlugin.h>
#include "PluginManager.h"
#include "DataExchange.h"
#include "debug.h"
extern PluginManager _plugin_manager;
/*************************************************************
* public BMediaDecoder
*************************************************************/
BMediaDecoder::BMediaDecoder()
: fDecoder(NULL),
fDecoderID(0),
fDecoderPlugin(NULL),
fDecoderPluginID(0),
fInitStatus(B_NO_INIT),
fNeedsInit(false),
fInitFormat(NULL),
fInitInfo(NULL),
fInitInfoSize(0)
{
}
BMediaDecoder::BMediaDecoder(const media_format *in_format,
const void *info,
size_t info_size)
: fDecoder(NULL),
fDecoderID(0),
fDecoderPlugin(NULL),
fDecoderPluginID(0),
fInitStatus(B_NO_INIT),
fNeedsInit(true),
fInitFormat(new media_format(*in_format)),
fInitInfo(NULL),
fInitInfoSize(0)
{
if (info_size) {
fInitInfoSize = info_size;
fInitInfo = new char[info_size];
memcpy(fInitInfo, info, info_size);
}
}
BMediaDecoder::BMediaDecoder(const media_codec_info *mci)
: fDecoder(NULL),
fDecoderID(0),
fDecoderPlugin(NULL),
fDecoderPluginID(0),
fInitStatus(B_NO_INIT),
fNeedsInit(false),
fInitFormat(NULL),
fInitInfo(NULL),
fInitInfoSize(0)
{
SetTo(mci);
}
/* virtual */
BMediaDecoder::~BMediaDecoder()
{
delete fDecoder;
delete fInitFormat;
delete fInitInfo;
}
status_t
BMediaDecoder::InitCheck() const
{
if (fNeedsInit) {
// casting away const: yes this solution does suck
// it is necessary while decoders need to call GetNextChunk in Setup
const_cast<BMediaDecoder*>(this)->SetTo(fInitFormat, fInitInfo, fInitInfoSize);
}
return fInitStatus;
}
static DecoderPlugin *
GetDecoderPlugin(const media_format * format)
{
server_get_decoder_for_format_request request;
server_get_decoder_for_format_reply reply;
request.format = *format;
status_t result = QueryServer(SERVER_GET_DECODER_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
if (result != B_OK) {
printf("BMediaDecoder::SetTo: can't get decoder for format\n");
return NULL;
}
MediaPlugin * media_plugin = _plugin_manager.GetPlugin(reply.ref);
if (!media_plugin) {
printf("BMediaDecoder::SetTo: GetPlugin failed\n");
return NULL;
}
DecoderPlugin * plugin = dynamic_cast<DecoderPlugin *>(media_plugin);
if (!plugin) {
printf("BMediaDecoder::SetTo: dynamic_cast failed\n");
return NULL;
}
return plugin;
}
// 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)
{
fNeedsInit = false;
fInitStatus = B_NO_INIT;
delete fDecoder;
DecoderPlugin * plugin = GetDecoderPlugin(in_format);
if (plugin == NULL) {
return fInitStatus = B_ERROR;
}
Decoder * decoder = plugin->NewDecoder(0);
if (decoder == NULL) {
return fInitStatus = B_ERROR;
}
fDecoder = decoder;
// fDecoderID = mci->sub_id;
if ((fInitStatus = AttachToDecoder()) != B_OK) {
return fInitStatus;
}
fInitStatus = SetInputFormat(in_format,info,info_size);
return fInitStatus;
}
// ask the server for the id'th plugin
static DecoderPlugin *
GetDecoderPlugin(int32 id)
{
if (id == 0) {
return NULL;
}
UNIMPLEMENTED();
return NULL;
}
// 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)
{
fInitStatus = B_NO_INIT;
delete fDecoder;
DecoderPlugin * plugin = GetDecoderPlugin(mci->id);
if (plugin == NULL) {
return fInitStatus = B_ERROR;
}
Decoder * decoder = plugin->NewDecoder(0);
if (decoder == NULL) {
return fInitStatus = B_ERROR;
}
fDecoder = decoder;
fDecoderID = mci->sub_id;
if ((fInitStatus = AttachToDecoder()) != B_OK) {
return fInitStatus;
}
return fInitStatus;
}
/** 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)
{
if (InitCheck() != B_OK) {
return fInitStatus;
}
printf("DISCARDING FORMAT %s\n",__PRETTY_FUNCTION__);
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)
{
if (InitCheck() != B_OK) {
return fInitStatus;
}
return fDecoder->NegotiateOutputFormat(output_format);
}
/** 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)
{
if (InitCheck() != 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 (InitCheck() != B_OK) {
return fInitStatus;
}
fDecoder->GetCodecInfo(out_info);
out_info->id = fDecoderPluginID;
out_info->sub_id = fDecoderID;
return B_OK;
}
/*************************************************************
* protected BMediaDecoder
*************************************************************/
/*************************************************************
* private BMediaDecoder
*************************************************************/
/*
// unimplemented
BMediaDecoder::BMediaDecoder(const BMediaDecoder &);
BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &);
*/
status_t
BMediaDecoder::AttachToDecoder()
{
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<const void**>(chunkBuffer);
size_t * size = reinterpret_cast<size_t*>(chunkSize);
return fDecoder->GetNextChunk(buffer,size,mediaHeader);
}
} * provider = new MediaDecoderChunkProvider(this);
if (provider == NULL) {
return B_NO_MEMORY;
}
fDecoder->Setup(provider);
return B_OK;
}
status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; }
status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; }
/*************************************************************
* public BMediaBufferDecoder
*************************************************************/
BMediaBufferDecoder::BMediaBufferDecoder()
: BMediaDecoder()
{
buffer_size = 0;
}
BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format,
const void *info,
size_t info_size)
: BMediaDecoder(in_format,info,info_size)
{
buffer_size = 0;
}
BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci)
: BMediaDecoder(mci)
{
buffer_size = 0;
}
status_t
BMediaBufferDecoder::DecodeBuffer(const void *input_buffer,
size_t input_size,
void *out_buffer,
int64 *out_frameCount,
media_header *out_mh,
media_decode_info *info)
{
buffer = input_buffer;
buffer_size = input_size;
return Decode(out_buffer,out_frameCount,out_mh,info);
}
/*************************************************************
* protected BMediaBufferDecoder
*************************************************************/
/* virtual */
status_t
BMediaBufferDecoder::GetNextChunk(const void **chunkData, size_t *chunkLen,
media_header *mh)
{
if (!buffer_size) {
return B_LAST_BUFFER_ERROR;
}
*chunkData = buffer;
*chunkLen = buffer_size;
buffer_size = 0;
return B_OK;
}