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
43inline size_t
44AudioBufferSize(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
50void
51RawDecoder::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
62status_t
63RawDecoder::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
122status_t
123RawDecoder::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
137status_t
138RawDecoder::NegotiateVideoOutputFormat(media_format *ioDecodedFormat)
139{
140	return B_ERROR;
141}
142
143
144status_t
145RawDecoder::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
465status_t
466RawDecoder::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
478status_t
479RawDecoder::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
525Decoder *
526RawDecoderPlugin::NewDecoder(uint index)
527{
528	return new RawDecoder;
529}
530
531
532static media_format raw_formats[2];
533
534status_t
535RawDecoderPlugin::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
570MediaPlugin *instantiate_plugin()
571{
572	return new RawDecoderPlugin;
573}
574