xref: /haiku/src/kits/media/MediaDecoder.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /***********************************************************************
2  * AUTHOR: Andrew Bachmann, Marcus Overhagen
3  *   FILE: MediaDecoder.cpp
4  *  DESCR:
5  ***********************************************************************/
6 #include <MediaDecoder.h>
7 #include <DecoderPlugin.h>
8 #include "PluginManager.h"
9 #include "DataExchange.h"
10 #include "debug.h"
11 
12 extern PluginManager _plugin_manager;
13 
14 /*************************************************************
15  * public BMediaDecoder
16  *************************************************************/
17 
18 BMediaDecoder::BMediaDecoder()
19  :	fDecoder(NULL),
20  	fDecoderID(0),
21  	fDecoderPlugin(NULL),
22  	fDecoderPluginID(0),
23  	fInitStatus(B_NO_INIT),
24  	fNeedsInit(false),
25  	fInitFormat(NULL),
26  	fInitInfo(NULL),
27  	fInitInfoSize(0)
28 {
29 }
30 
31 
32 BMediaDecoder::BMediaDecoder(const media_format *in_format,
33 							 const void *info,
34 							 size_t info_size)
35  :	fDecoder(NULL),
36  	fDecoderID(0),
37  	fDecoderPlugin(NULL),
38  	fDecoderPluginID(0),
39  	fInitStatus(B_NO_INIT),
40  	fNeedsInit(true),
41  	fInitFormat(new media_format(*in_format)),
42  	fInitInfo(NULL),
43  	fInitInfoSize(0)
44 {
45 	if (info_size) {
46 		fInitInfoSize = info_size;
47 		fInitInfo = new char[info_size];
48 		memcpy(fInitInfo, info, info_size);
49 	}
50 }
51 
52 
53 BMediaDecoder::BMediaDecoder(const media_codec_info *mci)
54  :	fDecoder(NULL),
55  	fDecoderID(0),
56  	fDecoderPlugin(NULL),
57  	fDecoderPluginID(0),
58  	fInitStatus(B_NO_INIT),
59  	fNeedsInit(false),
60  	fInitFormat(NULL),
61  	fInitInfo(NULL),
62  	fInitInfoSize(0)
63 {
64 	SetTo(mci);
65 }
66 
67 
68 /* virtual */
69 BMediaDecoder::~BMediaDecoder()
70 {
71 	delete fDecoder;
72 	delete fInitFormat;
73 	delete fInitInfo;
74 }
75 
76 
77 status_t
78 BMediaDecoder::InitCheck() const
79 {
80 	if (fNeedsInit) {
81 		// casting away const: yes this solution does suck
82 		// it is necessary while decoders need to call GetNextChunk in Setup
83 		const_cast<BMediaDecoder*>(this)->SetTo(fInitFormat, fInitInfo, fInitInfoSize);
84 	}
85 	return fInitStatus;
86 }
87 
88 
89 static DecoderPlugin *
90 GetDecoderPlugin(const media_format * format)
91 {
92 	server_get_decoder_for_format_request request;
93 	server_get_decoder_for_format_reply reply;
94 	request.format = *format;
95 	status_t result = QueryServer(SERVER_GET_DECODER_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply));
96 	if (result != B_OK) {
97 		printf("BMediaDecoder::SetTo: can't get decoder for format\n");
98 		return NULL;
99 	}
100 	MediaPlugin * media_plugin = _plugin_manager.GetPlugin(reply.ref);
101 	if (!media_plugin) {
102 		printf("BMediaDecoder::SetTo: GetPlugin failed\n");
103 		return NULL;
104 	}
105 	DecoderPlugin * plugin = dynamic_cast<DecoderPlugin *>(media_plugin);
106 	if (!plugin) {
107 		printf("BMediaDecoder::SetTo: dynamic_cast failed\n");
108 		return NULL;
109 	}
110 	return plugin;
111 }
112 
113 // ask the server for a good decoder for the arguments
114 // GETS THE CODEC for in_format->type + in_format->u.x.encoding
115 status_t
116 BMediaDecoder::SetTo(const media_format *in_format,
117 					 const void *info,
118 					 size_t info_size)
119 {
120 	fNeedsInit = false;
121 	fInitStatus = B_NO_INIT;
122 	delete fDecoder;
123 	DecoderPlugin * plugin = GetDecoderPlugin(in_format);
124 	if (plugin == NULL) {
125 		return fInitStatus = B_ERROR;
126 	}
127 	Decoder * decoder = plugin->NewDecoder(0);
128 	if (decoder == NULL) {
129 		return fInitStatus = B_ERROR;
130 	}
131 	fDecoder = decoder;
132 //	fDecoderID = mci->sub_id;
133 	if ((fInitStatus = AttachToDecoder()) != B_OK) {
134 		return fInitStatus;
135 	}
136 	fInitStatus = SetInputFormat(in_format,info,info_size);
137 	return fInitStatus;
138 }
139 
140 // ask the server for the id'th plugin
141 static DecoderPlugin *
142 GetDecoderPlugin(int32 id)
143 {
144 	if (id == 0) {
145 		return NULL;
146 	}
147 	UNIMPLEMENTED();
148 	return NULL;
149 }
150 
151 // ask the server for a good decoder for the arguments
152 // GETS THE CODEC for mci->id, mci->sub_id
153 // fails if the mci->id = 0
154 status_t
155 BMediaDecoder::SetTo(const media_codec_info *mci)
156 {
157 	fInitStatus = B_NO_INIT;
158 	delete fDecoder;
159 	DecoderPlugin * plugin = GetDecoderPlugin(mci->id);
160 	if (plugin == NULL) {
161 		return fInitStatus = B_ERROR;
162 	}
163 	Decoder * decoder = plugin->NewDecoder(0);
164 	if (decoder == NULL) {
165 		return fInitStatus = B_ERROR;
166 	}
167 	fDecoder = decoder;
168 	fDecoderID = mci->sub_id;
169 	if ((fInitStatus = AttachToDecoder()) != B_OK) {
170 		return fInitStatus;
171 	}
172 	return fInitStatus;
173 }
174 
175 
176 /**	SetInputFormat() sets the input data format to in_format.
177  *	Unlike SetTo(), the SetInputFormat() function does not
178  *	select a codec, so the currently-selected codec will
179  *	continue to be used.  You should only use SetInputFormat()
180  *	to refine the format settings if it will not require the
181  *	use of a different decoder.
182  */
183 
184 status_t
185 BMediaDecoder::SetInputFormat(const media_format *in_format,
186 							  const void *in_info,
187 							  size_t in_size)
188 {
189 	if (InitCheck() != B_OK) {
190 		return fInitStatus;
191 	}
192 	printf("DISCARDING FORMAT %s\n",__PRETTY_FUNCTION__);
193 	media_format format = *in_format;
194 	return fDecoder->Setup(&format,in_info,in_size);
195 }
196 
197 
198 /**	SetOutputFormat() sets the format the decoder should output.
199  *	On return, the output_format is changed to match the actual
200  *	format that will be output; this can be different if you
201  *	specified any wildcards.
202  */
203 
204 status_t
205 BMediaDecoder::SetOutputFormat(media_format *output_format)
206 {
207 	if (InitCheck() != B_OK) {
208 		return fInitStatus;
209 	}
210 	return fDecoder->NegotiateOutputFormat(output_format);
211 }
212 
213 
214 /**	Decodes a chunk of media data into the output buffer specified
215  *	by out_buffer.  On return, out_frameCount is set to indicate how
216  *	many frames of data were decoded, and out_mh is the header for
217  *	the decoded buffer.  The media_decode_info structure info is used
218  *	on input to specify decoding parameters.
219  *
220  *	The amount of data decoded is part of the format determined by
221  *	SetTo() or SetInputFormat().  For audio, it's the buffer_size.
222  *	For video, it's one frame, which is height*row_bytes.  The data
223  *	to be decoded will be fetched from the source by the decoder
224  *	add-on calling the derived class' GetNextChunk() function.
225  */
226 
227 status_t
228 BMediaDecoder::Decode(void *out_buffer,
229 					  int64 *out_frameCount,
230 					  media_header *out_mh,
231 					  media_decode_info *info)
232 {
233 	if (InitCheck() != B_OK) {
234 		return fInitStatus;
235 	}
236 	return fDecoder->Decode(out_buffer,out_frameCount,out_mh,info);
237 }
238 
239 
240 status_t
241 BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const
242 {
243 	if (InitCheck() != B_OK) {
244 		return fInitStatus;
245 	}
246 	fDecoder->GetCodecInfo(out_info);
247 	out_info->id = fDecoderPluginID;
248 	out_info->sub_id = fDecoderID;
249 	return B_OK;
250 }
251 
252 
253 /*************************************************************
254  * protected BMediaDecoder
255  *************************************************************/
256 
257 
258 /*************************************************************
259  * private BMediaDecoder
260  *************************************************************/
261 
262 /*
263 // unimplemented
264 BMediaDecoder::BMediaDecoder(const BMediaDecoder &);
265 BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &);
266 */
267 
268 status_t
269 BMediaDecoder::AttachToDecoder()
270 {
271 	class MediaDecoderChunkProvider : public ChunkProvider {
272 	private:
273 		BMediaDecoder * fDecoder;
274 	public:
275 		MediaDecoderChunkProvider(BMediaDecoder * decoder) {
276 			fDecoder = decoder;
277 		}
278 		virtual status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize,
279 		                              media_header *mediaHeader) {
280 			const void ** buffer = const_cast<const void**>(chunkBuffer);
281 			size_t * size = reinterpret_cast<size_t*>(chunkSize);
282 			return fDecoder->GetNextChunk(buffer,size,mediaHeader);
283 		}
284 	} * provider = new MediaDecoderChunkProvider(this);
285 	if (provider == NULL) {
286 		return B_NO_MEMORY;
287 	}
288 	fDecoder->Setup(provider);
289 	return B_OK;
290 }
291 
292 
293 status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; }
294 status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; }
295 status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; }
296 status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; }
297 status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; }
298 status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; }
299 status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; }
300 status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; }
301 status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; }
302 status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; }
303 status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; }
304 status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; }
305 status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; }
306 status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; }
307 status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; }
308 status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; }
309 
310 /*************************************************************
311  * public BMediaBufferDecoder
312  *************************************************************/
313 
314 BMediaBufferDecoder::BMediaBufferDecoder()
315  : BMediaDecoder()
316 {
317 	buffer_size = 0;
318 }
319 
320 
321 BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format,
322 										 const void *info,
323 										 size_t info_size)
324  : BMediaDecoder(in_format,info,info_size)
325 {
326 	buffer_size = 0;
327 }
328 
329 
330 BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci)
331  : BMediaDecoder(mci)
332 {
333 	buffer_size = 0;
334 }
335 
336 
337 status_t
338 BMediaBufferDecoder::DecodeBuffer(const void *input_buffer,
339 								  size_t input_size,
340 								  void *out_buffer,
341 								  int64 *out_frameCount,
342 								  media_header *out_mh,
343 								  media_decode_info *info)
344 {
345 	buffer = input_buffer;
346 	buffer_size = input_size;
347 	return Decode(out_buffer,out_frameCount,out_mh,info);
348 }
349 
350 
351 /*************************************************************
352  * protected BMediaBufferDecoder
353  *************************************************************/
354 
355 /* virtual */
356 status_t
357 BMediaBufferDecoder::GetNextChunk(const void **chunkData, size_t *chunkLen,
358                                   media_header *mh)
359 {
360 	if (!buffer_size) {
361 		return B_LAST_BUFFER_ERROR;
362 	}
363 	*chunkData = buffer;
364 	*chunkLen = buffer_size;
365 	buffer_size = 0;
366 	return B_OK;
367 }
368