/***********************************************************************
 * AUTHOR: Andrew Bachmann, Marcus Overhagen
 *   FILE: MediaDecoder.cpp
 *  DESCR: 
 ***********************************************************************/
#include <MediaDecoder.h>
#include <DecoderPlugin.h>
#include <new>
#include "PluginManager.h"
#include "MediaDebug.h"
 
/*************************************************************
 * public BMediaDecoder
 *************************************************************/
 
BMediaDecoder::BMediaDecoder()
 :	fDecoder(NULL),
 	fInitStatus(B_NO_INIT)
{
}
 
 
BMediaDecoder::BMediaDecoder(const media_format *in_format,
							 const void *info,
							 size_t info_size)
 :	fDecoder(NULL),
 	fInitStatus(B_NO_INIT)
{
	SetTo(in_format, info, info_size);
}
 
 
BMediaDecoder::BMediaDecoder(const media_codec_info *mci)
 :	fDecoder(NULL),
 	fInitStatus(B_NO_INIT)
{
	SetTo(mci);
}
 
 
/* virtual */
BMediaDecoder::~BMediaDecoder()
{
	gPluginManager.DestroyDecoder(fDecoder);
}
 
 
status_t 
BMediaDecoder::InitCheck() const
{
	return fInitStatus;
}
 
 
status_t 
BMediaDecoder::SetTo(const media_format *in_format,
					 const void *info,
					 size_t info_size)
{
	gPluginManager.DestroyDecoder(fDecoder);
	fDecoder = NULL;
 
	status_t err = gPluginManager.CreateDecoder(&fDecoder, *in_format);
	if (err < B_OK)
		goto fail;
 
	err = AttachToDecoder();
	if (err < B_OK)
		goto fail;
 
	err = SetInputFormat(in_format, info, info_size);
	if (err < B_OK)
		goto fail;
 
	fInitStatus = B_OK;
	return B_OK;
 
fail:
	gPluginManager.DestroyDecoder(fDecoder);
	fDecoder = NULL;
	fInitStatus = B_NO_INIT;
	return err;
}
 
 
status_t 
BMediaDecoder::SetTo(const media_codec_info *mci)
{
	gPluginManager.DestroyDecoder(fDecoder);
	fDecoder = NULL;
 
	status_t err = gPluginManager.CreateDecoder(&fDecoder, *mci);
	if (err < B_OK)
		goto fail;
 
	err = AttachToDecoder();
	if (err < B_OK)
		goto fail;
 
	fInitStatus = B_OK;
	return B_OK;
 
fail:
	gPluginManager.DestroyDecoder(fDecoder);
	fDecoder = NULL;
	fInitStatus = B_NO_INIT;
	return err;
}
 
 
/**	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 (!fDecoder)
		return B_NO_INIT;
 
	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 (!fDecoder)
		return B_NO_INIT;
 
	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 (!fDecoder)
		return B_NO_INIT;
 
	return fDecoder->Decode(out_buffer, out_frameCount, out_mh, info);
}
 
 
status_t 
BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const
{
	if (!fDecoder)
		return B_NO_INIT;
 
	return gPluginManager.GetDecoderInfo(fDecoder, out_info);
}
 
 
/*************************************************************
 * 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(const void **chunkBuffer, size_t *chunkSize,
		                              media_header *mediaHeader) {
			return fDecoder->GetNextChunk(chunkBuffer, chunkSize, mediaHeader);
		}
	} * provider = new(std::nothrow) MediaDecoderChunkProvider(this);
	
	if (!provider)
		return B_NO_MEMORY;
	
	fDecoder->SetChunkProvider(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()
 ,	fBufferSize(0)
{
}
 
 
BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format,
										 const void *info,
										 size_t info_size)
 :	BMediaDecoder(in_format, info, info_size)
 ,	fBufferSize(0)
{
}
 
 
BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci)
 :	BMediaDecoder(mci)
 ,	fBufferSize(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)
{
	fBuffer = input_buffer;
	fBufferSize = 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 (!fBufferSize)
		return B_LAST_BUFFER_ERROR;
 
	*chunkData = fBuffer;
	*chunkLen = fBufferSize;
	fBufferSize = 0;
	return B_OK;
}

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fBuffer.

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fBuffer.

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fBuffer.