xref: /haiku/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp (revision a127b88ecbfab58f64944c98aa47722a18e363b2)
1 /*
2  * Copyright (c) 2003-2004, Marcus Overhagen
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  *  * Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
23  * OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include <stdio.h>
26 #include <string.h>
27 #include <DataIO.h>
28 #include <OS.h>
29 #include <MediaRoster.h>
30 #include <ReaderPlugin.h>
31 
32 #include "RawFormats.h"
33 #include "RawDecoderPlugin.h"
34 #include "AudioConversion.h"
35 
36 //#define TRACE_RAW_DECODER
37 #ifdef TRACE_RAW_DECODER
38   #define TRACE printf
39 #else
40   #define TRACE(a...)
41 #endif
42 
43 inline size_t
44 AudioBufferSize(int32 channel_count, uint32 sample_format, float frame_rate, bigtime_t buffer_duration = 50000 /* 50 ms */)
45 {
46 	return (sample_format & 0xf) * channel_count * (size_t)((frame_rate * buffer_duration) / 1000000.0);
47 }
48 
49 
50 void
51 RawDecoder::GetCodecInfo(media_codec_info *info)
52 {
53 	strlcpy(info->short_name, "raw", sizeof(info->short_name));
54 
55 	if (fInputFormat.IsAudio())
56 		strlcpy(info->pretty_name, "Raw audio decoder", sizeof(info->pretty_name));
57 	else
58 		strlcpy(info->pretty_name, "Raw video decoder", sizeof(info->pretty_name));
59 }
60 
61 
62 status_t
63 RawDecoder::Setup(media_format *ioEncodedFormat,
64 				  const void *infoBuffer, size_t infoSize)
65 {
66 	char s[200];
67 	string_for_format(*ioEncodedFormat, s, sizeof(s));
68 	TRACE("RawDecoder::Setup: %s\n", s);
69 
70 	if (ioEncodedFormat->type != B_MEDIA_RAW_AUDIO && ioEncodedFormat->type != B_MEDIA_RAW_VIDEO)
71 		return B_ERROR;
72 
73 	fInputFormat = *ioEncodedFormat;
74 
75 	if (ioEncodedFormat->type == B_MEDIA_RAW_VIDEO) {
76 		fInputSampleSize = ioEncodedFormat->u.raw_video.display.line_count * ioEncodedFormat->u.raw_video.display.bytes_per_row;
77 		fInputFrameSize = fInputSampleSize;
78 	} else {
79 		fInputSampleSize = (ioEncodedFormat->u.raw_audio.format & B_AUDIO_FORMAT_SIZE_MASK);
80 		fInputFrameSize = fInputSampleSize * ioEncodedFormat->u.raw_audio.channel_count;
81 	}
82 
83 	// since ioEncodedFormat is later passed to the application by BMediaTrack::EncodedFormat()
84 	// we need to remove non public format specifications
85 
86 	// remove non format bits, like channel order
87 	ioEncodedFormat->u.raw_audio.format &= B_AUDIO_FORMAT_MASK;
88 
89 	switch (ioEncodedFormat->u.raw_audio.format) {
90 		case B_AUDIO_FORMAT_UINT8:
91 		case B_AUDIO_FORMAT_INT8:
92 		case B_AUDIO_FORMAT_INT16:
93 		case B_AUDIO_FORMAT_INT32:
94 		case B_AUDIO_FORMAT_FLOAT32:
95 			break; // ok to pass through
96 
97 		case B_AUDIO_FORMAT_INT24:
98 			ioEncodedFormat->u.raw_audio.format = B_AUDIO_FORMAT_INT32;
99 			break;
100 
101 		case B_AUDIO_FORMAT_FLOAT64:
102 			ioEncodedFormat->u.raw_audio.format = B_AUDIO_FORMAT_FLOAT32;
103 			break;
104 
105 		default:
106 			TRACE("RawDecoder::Setup: unknown input format\n");
107 			return B_ERROR;
108 	}
109 
110 	// since we can translate to a different buffer size,
111 	// suggest something nicer than delivered by the
112 	// file reader (perhaps we should even report wildcard?)
113 	// I don't believe we can negotiate the buffer size with the reader
114 //	ioEncodedFormat->u.raw_audio.buffer_size = AudioBufferSize(
115 //														ioEncodedFormat->u.raw_audio.channel_count,
116 //														ioEncodedFormat->u.raw_audio.format,
117 //														ioEncodedFormat->u.raw_audio.frame_rate);
118 	return B_OK;
119 }
120 
121 
122 status_t
123 RawDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat)
124 {
125 	// BeBook says: The codec will find and return in ioFormat its best matching format
126 	// => This means, we never return an error, and always change the format values
127 	//    that we don't support to something more applicable
128 	if (fInputFormat.type == B_MEDIA_RAW_VIDEO)
129 		return NegotiateVideoOutputFormat(ioDecodedFormat);
130 	if (fInputFormat.type == B_MEDIA_RAW_AUDIO)
131 		return NegotiateAudioOutputFormat(ioDecodedFormat);
132 	debugger("RawDecoder::NegotiateOutputFormat: wrong encoded format type");
133 	return B_ERROR;
134 }
135 
136 
137 status_t
138 RawDecoder::NegotiateVideoOutputFormat(media_format *ioDecodedFormat)
139 {
140 	return B_ERROR;
141 }
142 
143 
144 status_t
145 RawDecoder::NegotiateAudioOutputFormat(media_format *ioDecodedFormat)
146 {
147 	char s[1024];
148 
149 	TRACE("RawDecoder::NegotiateAudioOutputFormat enter:\n");
150 
151 	ioDecodedFormat->type = B_MEDIA_RAW_AUDIO;
152 	switch (ioDecodedFormat->u.raw_audio.format) {
153 		case media_raw_audio_format::B_AUDIO_FLOAT:
154 		case media_raw_audio_format::B_AUDIO_SHORT:
155 		case media_raw_audio_format::B_AUDIO_UCHAR:
156 		case media_raw_audio_format::B_AUDIO_CHAR:
157 			ioDecodedFormat->u.raw_audio.valid_bits = 0;
158 			break; // we can produce this on request
159 
160 		case media_raw_audio_format::B_AUDIO_INT:
161 			ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits;
162 			break; // we can produce this on request
163 
164 		default:
165 			switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) {
166 				case media_raw_audio_format::B_AUDIO_SHORT:
167 				case media_raw_audio_format::B_AUDIO_UCHAR:
168 				case media_raw_audio_format::B_AUDIO_CHAR:
169 					ioDecodedFormat->u.raw_audio.format = fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK;
170 					ioDecodedFormat->u.raw_audio.valid_bits = 0;
171 					break;
172 
173 				case media_raw_audio_format::B_AUDIO_INT:
174 				case B_AUDIO_FORMAT_INT24:
175 					ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
176 					ioDecodedFormat->u.raw_audio.valid_bits = fInputFormat.u.raw_audio.valid_bits;
177 					break;
178 
179 				case media_raw_audio_format::B_AUDIO_FLOAT:
180 				case B_AUDIO_FORMAT_FLOAT64:
181 				default:
182 					ioDecodedFormat->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
183 					ioDecodedFormat->u.raw_audio.valid_bits = 0;
184 					break;
185 			}
186 			break;
187 	}
188 
189 	ioDecodedFormat->u.raw_audio.frame_rate = fInputFormat.u.raw_audio.frame_rate;
190 	ioDecodedFormat->u.raw_audio.channel_count = fInputFormat.u.raw_audio.channel_count;
191 
192 	fFrameRate = (int32) ioDecodedFormat->u.raw_audio.frame_rate;
193 
194 	fOutputSampleSize = (ioDecodedFormat->u.raw_audio.format & B_AUDIO_FORMAT_SIZE_MASK);
195 	fOutputFrameSize = fOutputSampleSize * ioDecodedFormat->u.raw_audio.channel_count;
196 
197 	if (ioDecodedFormat->u.raw_audio.byte_order == 0)
198 		ioDecodedFormat->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
199 
200 	ioDecodedFormat->u.raw_audio.channel_mask = 0;
201 	ioDecodedFormat->u.raw_audio.matrix_mask = 0;
202 
203 	ioDecodedFormat->u.raw_audio.buffer_size = fInputFormat.u.raw_audio.buffer_size;
204 
205 // I don't believe we can negotiate the buffer size with the reader
206 // the decoder might use a different buffer for output but it must read all bytes given.
207 //	if (ioDecodedFormat->u.raw_audio.buffer_size < 128 || ioDecodedFormat->u.raw_audio.buffer_size > 65536) {
208 //		ioDecodedFormat->u.raw_audio.buffer_size = AudioBufferSize(
209 //														ioDecodedFormat->u.raw_audio.channel_count,
210 //														ioDecodedFormat->u.raw_audio.format,
211 //														ioDecodedFormat->u.raw_audio.frame_rate);
212 //	} else {
213 		// round down to exact multiple of output frame size
214 //		ioDecodedFormat->u.raw_audio.buffer_size = (ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize) * fOutputFrameSize;
215 //	}
216 
217 	fOutputBufferFrameCount = ioDecodedFormat->u.raw_audio.buffer_size / fOutputFrameSize;
218 
219 	// setup input swapping function
220 	if (fInputFormat.u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) {
221 		fSwapInput = 0;
222 	} else {
223 		switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) {
224 			case B_AUDIO_FORMAT_INT16:
225 				fSwapInput = &swap_int16;
226 				break;
227 			case B_AUDIO_FORMAT_INT24:
228 				fSwapInput = &swap_int24;
229 				break;
230 			case B_AUDIO_FORMAT_INT32:
231 				fSwapInput = &swap_int32;
232 				break;
233 			case B_AUDIO_FORMAT_FLOAT32:
234 				fSwapInput = &swap_float32;
235 				break;
236 			case B_AUDIO_FORMAT_FLOAT64:
237 				fSwapInput = &swap_float64;
238 				break;
239 			case B_AUDIO_FORMAT_UINT8:
240 			case B_AUDIO_FORMAT_INT8:
241 				fSwapInput = 0;
242 				break;
243 			default:
244 				debugger("RawDecoder::NegotiateAudioOutputFormat unknown input format\n");
245 				break;
246 		}
247 	}
248 
249 	// setup output swapping function
250 	if (ioDecodedFormat->u.raw_audio.byte_order == B_MEDIA_HOST_ENDIAN) {
251 		fSwapOutput = 0;
252 	} else {
253 		switch (ioDecodedFormat->u.raw_audio.format) {
254 			case B_AUDIO_FORMAT_INT16:
255 				fSwapOutput = &swap_int16;
256 				break;
257 			case B_AUDIO_FORMAT_INT32:
258 				fSwapOutput = &swap_int32;
259 				break;
260 			case B_AUDIO_FORMAT_FLOAT32:
261 				fSwapOutput = &swap_float32;
262 				break;
263 			case B_AUDIO_FORMAT_UINT8:
264 			case B_AUDIO_FORMAT_INT8:
265 				fSwapOutput = 0;
266 				break;
267 			default:
268 				debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
269 				break;
270 		}
271 	}
272 
273 	// setup sample conversation function
274 	switch (fInputFormat.u.raw_audio.format & B_AUDIO_FORMAT_MASK) {
275 		case B_AUDIO_FORMAT_UINT8:
276 			switch (ioDecodedFormat->u.raw_audio.format) {
277 				case B_AUDIO_FORMAT_UINT8:
278 					fConvert = &uint8_to_uint8;
279 					break;
280 				case B_AUDIO_FORMAT_INT8:
281 					fConvert = &uint8_to_int8;
282 					break;
283 				case B_AUDIO_FORMAT_INT16:
284 					fConvert = &uint8_to_int16;
285 					break;
286 				case B_AUDIO_FORMAT_INT32:
287 					fConvert = &uint8_to_int32;
288 					break;
289 				case B_AUDIO_FORMAT_FLOAT32:
290 					fConvert = &uint8_to_float32;
291 					break;
292 				default:
293 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
294 					break;
295 			}
296 			break;
297 
298 		case B_AUDIO_FORMAT_INT8:
299 			switch (ioDecodedFormat->u.raw_audio.format) {
300 				case B_AUDIO_FORMAT_UINT8:
301 					fConvert = &int8_to_uint8;
302 					break;
303 				case B_AUDIO_FORMAT_INT8:
304 					fConvert = &int8_to_int8;
305 					break;
306 				case B_AUDIO_FORMAT_INT16:
307 					fConvert = &int8_to_int16;
308 					break;
309 				case B_AUDIO_FORMAT_INT32:
310 					fConvert = &int8_to_int32;
311 					break;
312 				case B_AUDIO_FORMAT_FLOAT32:
313 					fConvert = &int8_to_float32;
314 					break;
315 				default:
316 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
317 					break;
318 			}
319 			break;
320 
321 		case B_AUDIO_FORMAT_INT16:
322 			switch (ioDecodedFormat->u.raw_audio.format) {
323 				case B_AUDIO_FORMAT_UINT8:
324 					fConvert = &int16_to_uint8;
325 					break;
326 				case B_AUDIO_FORMAT_INT8:
327 					fConvert = &int16_to_int8;
328 					break;
329 				case B_AUDIO_FORMAT_INT16:
330 					fConvert = &int16_to_int16;
331 					break;
332 				case B_AUDIO_FORMAT_INT32:
333 					fConvert = &int16_to_int32;
334 					break;
335 				case B_AUDIO_FORMAT_FLOAT32:
336 					fConvert = &int16_to_float32;
337 					break;
338 				default:
339 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
340 					break;
341 			}
342 			break;
343 
344 		case B_AUDIO_FORMAT_INT24:
345 			switch (ioDecodedFormat->u.raw_audio.format) {
346 				case B_AUDIO_FORMAT_UINT8:
347 					fConvert = &int24_to_uint8;
348 					break;
349 				case B_AUDIO_FORMAT_INT8:
350 					fConvert = &int24_to_int8;
351 					break;
352 				case B_AUDIO_FORMAT_INT16:
353 					fConvert = &int24_to_int16;
354 					break;
355 				case B_AUDIO_FORMAT_INT32:
356 					fConvert = &int24_to_int32;
357 					break;
358 				case B_AUDIO_FORMAT_FLOAT32:
359 					fConvert = &int24_to_float32;
360 					break;
361 				default:
362 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
363 					break;
364 			}
365 			break;
366 
367 		case B_AUDIO_FORMAT_INT32:
368 			switch (ioDecodedFormat->u.raw_audio.format) {
369 				case B_AUDIO_FORMAT_UINT8:
370 					fConvert = &int32_to_uint8;
371 					break;
372 				case B_AUDIO_FORMAT_INT8:
373 					fConvert = &int32_to_int8;
374 					break;
375 				case B_AUDIO_FORMAT_INT16:
376 					fConvert = &int32_to_int16;
377 					break;
378 				case B_AUDIO_FORMAT_INT32:
379 					fConvert = &int32_to_int32;
380 					break;
381 				case B_AUDIO_FORMAT_FLOAT32:
382 					fConvert = &int32_to_float32;
383 					break;
384 				default:
385 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
386 					break;
387 			}
388 			break;
389 
390 		case B_AUDIO_FORMAT_FLOAT32:
391 			switch (ioDecodedFormat->u.raw_audio.format) {
392 				case B_AUDIO_FORMAT_UINT8:
393 					fConvert = &float32_to_uint8;
394 					break;
395 				case B_AUDIO_FORMAT_INT8:
396 					fConvert = &float32_to_int8;
397 					break;
398 				case B_AUDIO_FORMAT_INT16:
399 					fConvert = &float32_to_int16;
400 					break;
401 				case B_AUDIO_FORMAT_INT32:
402 					fConvert = &float32_to_int32;
403 					break;
404 				case B_AUDIO_FORMAT_FLOAT32:
405 					fConvert = &float32_to_float32;
406 					break;
407 				default:
408 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
409 					break;
410 			}
411 			break;
412 
413 		case B_AUDIO_FORMAT_FLOAT64:
414 			switch (ioDecodedFormat->u.raw_audio.format) {
415 				case B_AUDIO_FORMAT_UINT8:
416 					fConvert = &float64_to_uint8;
417 					break;
418 				case B_AUDIO_FORMAT_INT8:
419 					fConvert = &float64_to_int8;
420 					break;
421 				case B_AUDIO_FORMAT_INT16:
422 					fConvert = &float64_to_int16;
423 					break;
424 				case B_AUDIO_FORMAT_INT32:
425 					fConvert = &float64_to_int32;
426 					break;
427 				case B_AUDIO_FORMAT_FLOAT32:
428 					fConvert = &float64_to_float32;
429 					break;
430 				default:
431 					debugger("RawDecoder::NegotiateAudioOutputFormat unknown output format\n");
432 					break;
433 			}
434 			break;
435 
436 		default:
437 			debugger("RawDecoder::NegotiateAudioOutputFormat unknown input format\n");
438 			break;
439 	}
440 
441 	fChunkBuffer = 0;
442 	fChunkSize = 0;
443 	fStartTime = 0;
444 
445 	string_for_format(*ioDecodedFormat, s, sizeof(s));
446 	TRACE("RawDecoder::NegotiateAudioOutputFormat leave: %s\n", s);
447 
448 	if (ioDecodedFormat->type == 0)
449 		debugger("RawDecoder::NegotiateAudioOutputFormat ioDecodedFormat->type == 0");
450 /*
451 	TRACE("fFrameRate              %ld\n", fFrameRate);
452 	TRACE("fInputFrameSize         %ld\n", fInputFrameSize);
453 	TRACE("fOutputFrameSize        %ld\n", fOutputFrameSize);
454 	TRACE("fInputSampleSize        %ld\n", fInputSampleSize);
455 	TRACE("fOutputSampleSize       %ld\n", fOutputSampleSize);
456 	TRACE("fOutputBufferFrameCount %ld\n", fOutputBufferFrameCount);
457 	TRACE("fSwapInput              %p\n", fSwapInput);
458 	TRACE("fConvert                %p\n", fConvert);
459 	TRACE("fSwapOutput             %p\n", fSwapOutput);
460 */
461 	return B_OK;
462 }
463 
464 
465 status_t
466 RawDecoder::SeekedTo(int64 frame, bigtime_t time)
467 {
468 	fChunkSize = 0;
469 
470 	TRACE("RawDecoder::SeekedTo called\n");
471 
472 	fStartTime = time;
473 
474 	return B_OK;
475 }
476 
477 
478 status_t
479 RawDecoder::Decode(void *buffer, int64 *frameCount,
480 				   media_header *mediaHeader, media_decode_info *info /* = 0 */)
481 {
482 	char *output_buffer = (char *)buffer;
483 	mediaHeader->start_time = fStartTime;
484 	*frameCount = 0;
485 	while (*frameCount < fOutputBufferFrameCount) {
486 		if (fChunkSize == 0) {
487 			media_header mh;
488 			status_t err;
489 			err = GetNextChunk(&fChunkBuffer, &fChunkSize, &mh);
490 			if (err != B_OK || fChunkSize < (size_t)fInputFrameSize) {
491 				fChunkSize = 0;
492 				break;
493 			}
494 			if (fSwapInput)
495 				fSwapInput(const_cast<void *>(fChunkBuffer), fChunkSize / fInputSampleSize); // XXX TODO! FIX THIS, we write to a const buffer!!!
496 			fStartTime = mh.start_time;
497 			continue;
498 		}
499 		int32 frames = min_c(fOutputBufferFrameCount - *frameCount,
500 			(int64)(fChunkSize / fInputFrameSize));
501 		if (frames == 0)
502 			break;
503 
504 		int32 samples = frames * fInputFormat.u.raw_audio.channel_count;
505 		fConvert(output_buffer, fChunkBuffer, samples);
506 		fChunkBuffer = (const char *)fChunkBuffer + frames * fInputFrameSize;
507 		fChunkSize -= frames * fInputFrameSize;
508 		output_buffer += frames * fOutputFrameSize;
509 		*frameCount += frames;
510 		fStartTime += (1000000LL * frames) / fFrameRate;
511 	}
512 	// XXX should change channel order here for
513 	// B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE and B_AUDIO_FORMAT_CHANNEL_ORDER_AIFF
514 
515 	if (fSwapOutput)
516 		fSwapOutput(buffer, *frameCount * fInputFormat.u.raw_audio.channel_count);
517 
518 	TRACE("framecount %Ld, time %Ld\n",*frameCount, mediaHeader->start_time);
519 
520 	return *frameCount ? B_OK : B_ERROR;
521 }
522 
523 
524 Decoder *
525 RawDecoderPlugin::NewDecoder(uint index)
526 {
527 	return new RawDecoder;
528 }
529 
530 
531 static media_format raw_formats[2];
532 
533 status_t
534 RawDecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
535 {
536 	BMediaFormats mediaFormats;
537 	media_format_description description;
538 	media_format format;
539 
540 	// audio decoder
541 
542 	description.family = B_BEOS_FORMAT_FAMILY;
543 	description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO;
544 	format.type = B_MEDIA_RAW_AUDIO;
545 	format.u.raw_audio = media_multi_audio_format::wildcard;
546 
547 	status_t status = mediaFormats.MakeFormatFor(&description, 1, &format);
548 	if (status < B_OK)
549 		return status;
550 	raw_formats[0] = format;
551 
552 	// video decoder
553 
554 	description.u.beos.format = B_BEOS_FORMAT_RAW_VIDEO;
555 	format.type = B_MEDIA_RAW_VIDEO;
556 	format.u.raw_video = media_raw_video_format::wildcard;
557 
558 	status = mediaFormats.MakeFormatFor(&description, 1, &format);
559 	if (status < B_OK)
560 		return status;
561 	raw_formats[1] = format;
562 
563 	*formats = raw_formats;
564 	*count = 2;
565 
566 	return B_OK;
567 }
568 
569 MediaPlugin *instantiate_plugin()
570 {
571 	return new RawDecoderPlugin;
572 }
573