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