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