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