1/***********************************************************************
2 * AUTHOR: Andrew Bachmann, Marcus Overhagen
3 *   FILE: MediaDecoder.cpp
4 *  DESCR:
5 ***********************************************************************/
6#include <MediaDecoder.h>
7#include <DecoderPlugin.h>
8#include <new>
9#include "PluginManager.h"
10#include "MediaDebug.h"
11
12/*************************************************************
13 * public BMediaDecoder
14 *************************************************************/
15
16BMediaDecoder::BMediaDecoder()
17 :	fDecoder(NULL),
18 	fInitStatus(B_NO_INIT)
19{
20}
21
22
23BMediaDecoder::BMediaDecoder(const media_format *in_format,
24							 const void *info,
25							 size_t info_size)
26 :	fDecoder(NULL),
27 	fInitStatus(B_NO_INIT)
28{
29	SetTo(in_format, info, info_size);
30}
31
32
33BMediaDecoder::BMediaDecoder(const media_codec_info *mci)
34 :	fDecoder(NULL),
35 	fInitStatus(B_NO_INIT)
36{
37	SetTo(mci);
38}
39
40
41/* virtual */
42BMediaDecoder::~BMediaDecoder()
43{
44	gPluginManager.DestroyDecoder(fDecoder);
45}
46
47
48status_t
49BMediaDecoder::InitCheck() const
50{
51	return fInitStatus;
52}
53
54
55status_t
56BMediaDecoder::SetTo(const media_format *in_format,
57					 const void *info,
58					 size_t info_size)
59{
60	gPluginManager.DestroyDecoder(fDecoder);
61	fDecoder = NULL;
62
63	status_t err = gPluginManager.CreateDecoder(&fDecoder, *in_format);
64	if (err < B_OK)
65		goto fail;
66
67	err = AttachToDecoder();
68	if (err < B_OK)
69		goto fail;
70
71	err = SetInputFormat(in_format, info, info_size);
72	if (err < B_OK)
73		goto fail;
74
75	fInitStatus = B_OK;
76	return B_OK;
77
78fail:
79	gPluginManager.DestroyDecoder(fDecoder);
80	fDecoder = NULL;
81	fInitStatus = B_NO_INIT;
82	return err;
83}
84
85
86status_t
87BMediaDecoder::SetTo(const media_codec_info *mci)
88{
89	gPluginManager.DestroyDecoder(fDecoder);
90	fDecoder = NULL;
91
92	status_t err = gPluginManager.CreateDecoder(&fDecoder, *mci);
93	if (err < B_OK)
94		goto fail;
95
96	err = AttachToDecoder();
97	if (err < B_OK)
98		goto fail;
99
100	fInitStatus = B_OK;
101	return B_OK;
102
103fail:
104	gPluginManager.DestroyDecoder(fDecoder);
105	fDecoder = NULL;
106	fInitStatus = B_NO_INIT;
107	return err;
108}
109
110
111/**	SetInputFormat() sets the input data format to in_format.
112 *	Unlike SetTo(), the SetInputFormat() function does not
113 *	select a codec, so the currently-selected codec will
114 *	continue to be used.  You should only use SetInputFormat()
115 *	to refine the format settings if it will not require the
116 *	use of a different decoder.
117 */
118
119status_t
120BMediaDecoder::SetInputFormat(const media_format *in_format,
121							  const void *in_info,
122							  size_t in_size)
123{
124	if (!fDecoder)
125		return B_NO_INIT;
126
127	media_format format = *in_format;
128	return fDecoder->Setup(&format, in_info, in_size);
129}
130
131
132/**	SetOutputFormat() sets the format the decoder should output.
133 *	On return, the output_format is changed to match the actual
134 *	format that will be output; this can be different if you
135 *	specified any wildcards.
136 */
137
138status_t
139BMediaDecoder::SetOutputFormat(media_format *output_format)
140{
141	if (!fDecoder)
142		return B_NO_INIT;
143
144	return fDecoder->NegotiateOutputFormat(output_format);
145}
146
147
148/**	Decodes a chunk of media data into the output buffer specified
149 *	by out_buffer.  On return, out_frameCount is set to indicate how
150 *	many frames of data were decoded, and out_mh is the header for
151 *	the decoded buffer.  The media_decode_info structure info is used
152 *	on input to specify decoding parameters.
153 *
154 *	The amount of data decoded is part of the format determined by
155 *	SetTo() or SetInputFormat().  For audio, it's the buffer_size.
156 *	For video, it's one frame, which is height*row_bytes.  The data
157 *	to be decoded will be fetched from the source by the decoder
158 *	add-on calling the derived class' GetNextChunk() function.
159 */
160
161status_t
162BMediaDecoder::Decode(void *out_buffer,
163					  int64 *out_frameCount,
164					  media_header *out_mh,
165					  media_decode_info *info)
166{
167	if (!fDecoder)
168		return B_NO_INIT;
169
170	return fDecoder->Decode(out_buffer, out_frameCount, out_mh, info);
171}
172
173
174status_t
175BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const
176{
177	if (!fDecoder)
178		return B_NO_INIT;
179
180	return gPluginManager.GetDecoderInfo(fDecoder, out_info);
181}
182
183
184/*************************************************************
185 * protected BMediaDecoder
186 *************************************************************/
187
188
189/*************************************************************
190 * private BMediaDecoder
191 *************************************************************/
192
193/*
194// unimplemented
195BMediaDecoder::BMediaDecoder(const BMediaDecoder &);
196BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &);
197*/
198
199status_t
200BMediaDecoder::AttachToDecoder()
201{
202	class MediaDecoderChunkProvider : public ChunkProvider {
203	private:
204		BMediaDecoder * fDecoder;
205	public:
206		MediaDecoderChunkProvider(BMediaDecoder * decoder) {
207			fDecoder = decoder;
208		}
209		virtual status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
210		                              media_header *mediaHeader) {
211			return fDecoder->GetNextChunk(chunkBuffer, chunkSize, mediaHeader);
212		}
213	} * provider = new(std::nothrow) MediaDecoderChunkProvider(this);
214
215	if (!provider)
216		return B_NO_MEMORY;
217
218	fDecoder->SetChunkProvider(provider);
219	return B_OK;
220}
221
222
223status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; }
224status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; }
225status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; }
226status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; }
227status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; }
228status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; }
229status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; }
230status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; }
231status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; }
232status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; }
233status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; }
234status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; }
235status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; }
236status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; }
237status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; }
238status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; }
239
240/*************************************************************
241 * public BMediaBufferDecoder
242 *************************************************************/
243
244BMediaBufferDecoder::BMediaBufferDecoder()
245 :	BMediaDecoder()
246 ,	fBufferSize(0)
247{
248}
249
250
251BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format,
252										 const void *info,
253										 size_t info_size)
254 :	BMediaDecoder(in_format, info, info_size)
255 ,	fBufferSize(0)
256{
257}
258
259
260BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci)
261 :	BMediaDecoder(mci)
262 ,	fBufferSize(0)
263{
264}
265
266
267status_t
268BMediaBufferDecoder::DecodeBuffer(const void *input_buffer,
269								  size_t input_size,
270								  void *out_buffer,
271								  int64 *out_frameCount,
272								  media_header *out_mh,
273								  media_decode_info *info)
274{
275	fBuffer = input_buffer;
276	fBufferSize = input_size;
277	return Decode(out_buffer, out_frameCount, out_mh,info);
278}
279
280
281/*************************************************************
282 * protected BMediaBufferDecoder
283 *************************************************************/
284
285/* virtual */
286status_t
287BMediaBufferDecoder::GetNextChunk(const void **chunkData,
288								  size_t *chunkLen,
289                                  media_header *mh)
290{
291	if (!fBufferSize)
292		return B_LAST_BUFFER_ERROR;
293
294	*chunkData = fBuffer;
295	*chunkLen = fBufferSize;
296	fBufferSize = 0;
297	return B_OK;
298}
299