xref: /haiku/src/add-ons/media/plugins/raw_decoder/RawDecoderPlugin.cpp (revision bb83316a5811a550c4f850d07fa8e328e7ac0a94)
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  
486  	status_t status = B_OK;
487  	while (*frameCount < fOutputBufferFrameCount) {
488  		if (fChunkSize == 0) {
489  			media_header mh;
490  			status = GetNextChunk(&fChunkBuffer, &fChunkSize, &mh);
491  			if (status != B_OK || fChunkSize < (size_t)fInputFrameSize) {
492  				fChunkSize = 0;
493  				break;
494  			}
495  			if (fSwapInput)
496  				fSwapInput(const_cast<void *>(fChunkBuffer), fChunkSize / fInputSampleSize); // XXX TODO! FIX THIS, we write to a const buffer!!!
497  			fStartTime = mh.start_time;
498  			continue;
499  		}
500  		int32 frames = min_c(fOutputBufferFrameCount - *frameCount,
501  			(int64)(fChunkSize / fInputFrameSize));
502  		if (frames == 0)
503  			break;
504  
505  		int32 samples = frames * fInputFormat.u.raw_audio.channel_count;
506  		fConvert(output_buffer, fChunkBuffer, samples);
507  		fChunkBuffer = (const char *)fChunkBuffer + frames * fInputFrameSize;
508  		fChunkSize -= frames * fInputFrameSize;
509  		output_buffer += frames * fOutputFrameSize;
510  		*frameCount += frames;
511  		fStartTime += (1000000LL * frames) / fFrameRate;
512  	}
513  	// XXX should change channel order here for
514  	// B_AUDIO_FORMAT_CHANNEL_ORDER_WAVE and B_AUDIO_FORMAT_CHANNEL_ORDER_AIFF
515  
516  	if (fSwapOutput)
517  		fSwapOutput(buffer, *frameCount * fInputFormat.u.raw_audio.channel_count);
518  
519  	TRACE("framecount %lld, time %lld\n",*frameCount, mediaHeader->start_time);
520  
521  	return *frameCount ? B_OK : (status != B_OK ? status : B_ERROR);
522  }
523  
524  
525  Decoder *
526  RawDecoderPlugin::NewDecoder(uint index)
527  {
528  	return new RawDecoder;
529  }
530  
531  
532  static media_format raw_formats[2];
533  
534  status_t
535  RawDecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
536  {
537  	BMediaFormats mediaFormats;
538  	media_format_description description;
539  	media_format format;
540  
541  	// audio decoder
542  
543  	description.family = B_BEOS_FORMAT_FAMILY;
544  	description.u.beos.format = B_BEOS_FORMAT_RAW_AUDIO;
545  	format.type = B_MEDIA_RAW_AUDIO;
546  	format.u.raw_audio = media_multi_audio_format::wildcard;
547  
548  	status_t status = mediaFormats.MakeFormatFor(&description, 1, &format);
549  	if (status < B_OK)
550  		return status;
551  	raw_formats[0] = format;
552  
553  	// video decoder
554  
555  	description.u.beos.format = B_BEOS_FORMAT_RAW_VIDEO;
556  	format.type = B_MEDIA_RAW_VIDEO;
557  	format.u.raw_video = media_raw_video_format::wildcard;
558  
559  	status = mediaFormats.MakeFormatFor(&description, 1, &format);
560  	if (status < B_OK)
561  		return status;
562  	raw_formats[1] = format;
563  
564  	*formats = raw_formats;
565  	*count = 2;
566  
567  	return B_OK;
568  }
569  
570  MediaPlugin *instantiate_plugin()
571  {
572  	return new RawDecoderPlugin;
573  }
574