xref: /haiku/src/kits/media/MediaTrack.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 /*
2  * Copyright (c) 2002-2004, Marcus Overhagen <marcus@overhagen.de>
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"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <MediaTrack.h>
27 #include <Roster.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include "MediaExtractor.h"
31 #include "PluginManager.h"
32 #include "ReaderPlugin.h"
33 #include "debug.h"
34 
35 #define CONVERT_TO_INT32 0 // XXX test! this triggers a few bugs!
36 
37 // flags used for workarounds
38 enum {
39 	FORCE_RAW_AUDIO 				= 0x0001,
40 	FORCE_RAW_VIDEO 				= 0x0002,
41 	FORCE_RAW_AUDIO_INT16_FORMAT 	= 0x0010,
42 	FORCE_RAW_AUDIO_INT32_FORMAT 	= 0x0020,
43 	FORCE_RAW_AUDIO_FLOAT_FORMAT 	= 0x0040,
44 	FORCE_RAW_AUDIO_HOST_ENDIAN 	= 0x0100,
45 	IGNORE_ENCODED_AUDIO 			= 0x1000,
46 	IGNORE_ENCODED_VIDEO 			= 0x2000,
47 };
48 
49 #define B_MEDIA_DISABLE_FORMAT_TRANSLATION 0x4000 // XXX move this (after name change?) to MediaDefs.h
50 
51 class RawDecoderChunkProvider : public ChunkProvider
52 {
53 public:
54 				RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size);
55 	virtual 	~RawDecoderChunkProvider();
56 
57 	status_t	GetNextChunk(const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader);
58 
59 private:
60 	Decoder *fDecoder;
61 	void *fBuffer;
62 	int	fBufferSize;
63 	int	fFrameSize;
64 };
65 
66 
67 /*************************************************************
68  * protected BMediaTrack
69  *************************************************************/
70 
71 BMediaTrack::~BMediaTrack()
72 {
73 	CALLED();
74 	if (fRawDecoder)
75 		_DestroyDecoder(fRawDecoder);
76 	if (fDecoder)
77 		_DestroyDecoder(fDecoder);
78 }
79 
80 /*************************************************************
81  * public BMediaTrack
82  *************************************************************/
83 
84 status_t
85 BMediaTrack::InitCheck() const
86 {
87 	CALLED();
88 	return fErr;
89 }
90 
91 
92 status_t
93 BMediaTrack::GetCodecInfo(media_codec_info *mci) const
94 {
95 	CALLED();
96 	if (!fDecoder)
97 		return B_NO_INIT;
98 
99 	*mci = fMCI;
100 	snprintf(mci->pretty_name, sizeof(mci->pretty_name), "Haiku Media Kit:\n%s", fMCI.pretty_name);
101 
102 	return B_OK;
103 }
104 
105 
106 status_t
107 BMediaTrack::EncodedFormat(media_format *out_format) const
108 {
109 	CALLED();
110 	if (!out_format)
111 		return B_BAD_VALUE;
112 	if (!fExtractor)
113 		return B_NO_INIT;
114 
115 	*out_format = *fExtractor->EncodedFormat(fStream);
116 
117 	char s[200];
118 	string_for_format(*out_format, s, sizeof(s));
119 	printf("BMediaTrack::EncodedFormat: %s\n", s);
120 
121 	return B_OK;
122 }
123 
124 
125 // for BeOS R5 compatibilitly
126 extern "C" status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self, media_format *inout_format);
127 status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack *self,
128 													 media_format *inout_format)
129 {
130 	return self->DecodedFormat(inout_format, 0);
131 }
132 
133 
134 status_t
135 BMediaTrack::DecodedFormat(media_format *inout_format, uint32 flags)
136 {
137 	CALLED();
138 	if (!inout_format)
139 		return B_BAD_VALUE;
140 	if (!fExtractor || !fDecoder)
141 		return B_NO_INIT;
142 
143 	if (fRawDecoder) {
144 		_DestroyDecoder(fRawDecoder);
145 		fRawDecoder = 0;
146 	}
147 
148 	char s[200];
149 
150 	string_for_format(*inout_format, s, sizeof(s));
151 	printf("BMediaTrack::DecodedFormat: req1: %s\n", s);
152 
153 	if ((fWorkaroundFlags & FORCE_RAW_AUDIO) || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO) && inout_format->type == B_MEDIA_ENCODED_AUDIO)) {
154 		inout_format->type = B_MEDIA_RAW_AUDIO;
155 		inout_format->u.raw_audio = media_multi_audio_format::wildcard;
156 	}
157 	if ((fWorkaroundFlags & FORCE_RAW_VIDEO) || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO) && inout_format->type == B_MEDIA_ENCODED_VIDEO)) {
158 		inout_format->type = B_MEDIA_RAW_VIDEO;
159 		inout_format->u.raw_video = media_raw_video_format::wildcard;
160 	}
161 	if (inout_format->type == B_MEDIA_RAW_AUDIO) {
162 		if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN)
163 			inout_format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
164 		if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)
165 			inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT;
166 		if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT)
167 			inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT;
168 		if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT)
169 			inout_format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
170 	}
171 
172 	string_for_format(*inout_format, s, sizeof(s));
173 	printf("BMediaTrack::DecodedFormat: req2: %s\n", s);
174 
175 	media_format requested_format = *inout_format;
176 
177 	status_t res;
178 
179 	res = fDecoder->NegotiateOutputFormat(inout_format);
180 
181 	string_for_format(*inout_format, s, sizeof(s));
182 	printf("BMediaTrack::DecodedFormat: nego: %s\n", s);
183 
184 	if (inout_format->type == 0)
185 		debugger("Decoder didn't set output format type");
186 	if (inout_format->type == B_MEDIA_RAW_AUDIO) {
187 		if (inout_format->u.raw_audio.byte_order == 0)
188 			debugger("Decoder didn't set raw audio output byte order");
189 		if (inout_format->u.raw_audio.format == 0)
190 			debugger("Decoder didn't set raw audio output sample format");
191 		if (inout_format->u.raw_audio.buffer_size <= 0)
192 			debugger("Decoder didn't set raw audio output buffer size");
193 	}
194 	if (inout_format->type == B_MEDIA_RAW_VIDEO) {
195 		if (inout_format->u.raw_video.display.format == 0)
196 			debugger("Decoder didn't set raw video output color space");
197 		if (inout_format->u.raw_video.display.line_width == 0)
198 			debugger("Decoder didn't set raw video output line_width");
199 		if (inout_format->u.raw_video.display.line_count == 0)
200 			debugger("Decoder didn't set raw video output line_count");
201 		if (inout_format->u.raw_video.display.bytes_per_row == 0)
202 			debugger("Decoder didn't set raw video output bytes_per_row");
203 	}
204 
205 	if (0 == (flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION)) {
206 		if (requested_format.type == B_MEDIA_RAW_AUDIO
207 			&& inout_format->type == B_MEDIA_RAW_AUDIO
208 			&& requested_format.u.raw_audio.format != 0
209 			&& requested_format.u.raw_audio.format != inout_format->u.raw_audio.format) {
210 				if (SetupFormatTranslation(*inout_format, &requested_format)) {
211 					*inout_format = requested_format;
212 				}
213 		}
214 	}
215 
216 //	string_for_format(*inout_format, s, sizeof(s));
217 //	printf("BMediaTrack::DecodedFormat: res: %s\n", s);
218 
219 	return res;
220 }
221 
222 
223 int64
224 BMediaTrack::CountFrames() const
225 {
226 	CALLED();
227 	int64 frames = fExtractor ? fExtractor->CountFrames(fStream) : 0;
228 //	printf("BMediaTrack::CountFrames: %Ld\n", frames);
229 	return frames;
230 }
231 
232 
233 bigtime_t
234 BMediaTrack::Duration() const
235 {
236 	CALLED();
237 	bigtime_t duration = fExtractor ? fExtractor->Duration(fStream) : 0;
238 //	printf("BMediaTrack::Duration: %Ld\n", duration);
239 	return duration;
240 }
241 
242 
243 int64
244 BMediaTrack::CurrentFrame() const
245 {
246 	return fCurFrame;
247 }
248 
249 
250 bigtime_t
251 BMediaTrack::CurrentTime() const
252 {
253 	return fCurTime;
254 }
255 
256 
257 status_t
258 BMediaTrack::ReadFrames(void *out_buffer,
259 						int64 *out_frameCount,
260 						media_header *mh)
261 {
262 	return ReadFrames(out_buffer, out_frameCount, mh, 0);
263 }
264 
265 
266 status_t
267 BMediaTrack::ReadFrames(void *out_buffer,
268 						int64 *out_frameCount,
269 						media_header *mh /* = 0 */,
270 						media_decode_info *info /* = 0 */)
271 {
272 //	CALLED();
273 	if (!fDecoder)
274 		return B_NO_INIT;
275 	if (!out_buffer || !out_frameCount)
276 		return B_BAD_VALUE;
277 
278 	status_t result;
279 	media_header header;
280 
281 	memset(&header, 0, sizeof(header)); // always clear it first, as the decoder doesn't set all fields
282 
283 	if (fRawDecoder)
284 		result = fRawDecoder->Decode(out_buffer, out_frameCount, &header, info);
285 	else
286 		result = fDecoder->Decode(out_buffer, out_frameCount, &header, info);
287 	if (result == B_OK) {
288 		fCurFrame += *out_frameCount;
289 		fCurTime = header.start_time;
290 	} else {
291 		printf("BMediaTrack::ReadFrames: decoder returned error 0x%08lx (%s)\n", result, strerror(result));
292 		*out_frameCount = 0;
293 	}
294 	if (mh)
295 		*mh = header;
296 
297 //	PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, %Ld frames\n", fStream,  header.start_time / 1000000, header.start_time % 1000000, *out_frameCount);
298 
299 	return result;
300 }
301 
302 
303 status_t
304 BMediaTrack::ReplaceFrames(const void *in_buffer,
305 						   int64 *io_frameCount,
306 						   const media_header *mh)
307 {
308 	UNIMPLEMENTED();
309 
310 	return B_OK;
311 }
312 
313 
314 status_t
315 BMediaTrack::SeekToTime(bigtime_t *inout_time,
316 						int32 flags)
317 {
318 	CALLED();
319 	if (!fDecoder || !fExtractor)
320 		return B_NO_INIT;
321 	if (!inout_time)
322 		return B_BAD_VALUE;
323 
324 	status_t result;
325 	uint32 seekTo;
326 	bigtime_t seekTime;
327 
328 	int64 frame;
329 	bigtime_t time;
330 
331 	seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME;
332 	seekTime = *inout_time;
333 
334 	time = seekTime;
335 	result = fExtractor->Seek(fStream, seekTo, &frame, &time);
336 	if (result != B_OK) {
337 		printf("BMediaTrack::SeekToTime: extractor seek failed\n");
338 		return result;
339 	}
340 
341 	result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
342 	if (result != B_OK) {
343 		printf("BMediaTrack::SeekToTime: decoder seek failed\n");
344 		return result;
345 	}
346 
347 	if (fRawDecoder) {
348 		result = fRawDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
349 		if (result != B_OK) {
350 			printf("BMediaTrack::SeekToTime: raw decoder seek failed\n");
351 			return result;
352 		}
353 	}
354 
355 	*inout_time = time;
356 	fCurFrame = frame;
357 	fCurTime = time;
358 
359 	PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", seekTime / 1000000.0, *inout_time / 1000000.0);
360 
361 	return B_OK;
362 }
363 
364 
365 status_t
366 BMediaTrack::SeekToFrame(int64 *inout_frame,
367 						 int32 flags)
368 {
369 	CALLED();
370 	if (!fDecoder || !fExtractor)
371 		return B_NO_INIT;
372 	if (!inout_frame)
373 		return B_BAD_VALUE;
374 
375 	status_t result;
376 	uint32 seekTo;
377 	int64 seekFrame;
378 
379 	int64 frame;
380 	bigtime_t time;
381 
382 	seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME;
383 	seekFrame = *inout_frame;
384 
385 	frame = seekFrame;
386 	result = fExtractor->Seek(fStream, seekTo, &frame, &time);
387 	if (result != B_OK) {
388 		printf("BMediaTrack::SeekToFrame: extractor seek failed\n");
389 		return result;
390 	}
391 
392 	result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
393 	if (result != B_OK) {
394 		return result;
395 		printf("BMediaTrack::SeekToFrame: decoder seek failed\n");
396 	}
397 
398 	if (fRawDecoder) {
399 		result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
400 		if (result != B_OK) {
401 			printf("BMediaTrack::SeekToFrame: raw decoder seek failed\n");
402 			return result;
403 		}
404 	}
405 
406 	*inout_frame = frame;
407 	fCurFrame = frame;
408 	fCurTime = time;
409 
410 	PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %Ld, result %Ld\n", seekFrame, *inout_frame);
411 
412 	return B_OK;
413 }
414 
415 
416 status_t
417 BMediaTrack::FindKeyFrameForTime(bigtime_t *inout_time,
418 								 int32 flags) const
419 {
420 	UNIMPLEMENTED();
421 
422 	return B_OK;
423 }
424 
425 
426 status_t
427 BMediaTrack::FindKeyFrameForFrame(int64 *inout_frame,
428 								  int32 flags) const
429 {
430 	UNIMPLEMENTED();
431 
432 	return B_OK;
433 }
434 
435 
436 status_t
437 BMediaTrack::ReadChunk(char **out_buffer,
438 					   int32 *out_size,
439 					   media_header *mh /* = 0 */)
440 {
441 	CALLED();
442 	if (!fExtractor)
443 		return B_NO_INIT;
444 	if (!out_buffer || !out_size)
445 		return B_BAD_VALUE;
446 
447 	status_t result;
448 	media_header header;
449 	const void *buffer;
450 	size_t size;
451 
452 	memset(&header, 0, sizeof(header)); // always clear it first, as the reader doesn't set all fields
453 
454 	result = fExtractor->GetNextChunk(fStream, &buffer, &size, &header);
455 	if (result == B_OK) {
456 		*out_buffer = const_cast<char *>(static_cast<const char *>(buffer)); // yes this *is* ugly
457 		*out_size  = size;
458 		fCurTime = header.start_time;
459 		if (mh)
460 			*mh = header;
461 	}
462 
463 	return result;
464 }
465 
466 
467 status_t
468 BMediaTrack::AddCopyright(const char *data)
469 {
470 	UNIMPLEMENTED();
471 
472 	return B_OK;
473 }
474 
475 
476 status_t
477 BMediaTrack::AddTrackInfo(uint32 code,
478 						  const void *data,
479 						  size_t size,
480 						  uint32 flags)
481 {
482 	UNIMPLEMENTED();
483 
484 	return B_OK;
485 }
486 
487 
488 status_t
489 BMediaTrack::WriteFrames(const void *data,
490 						 int32 num_frames,
491 						 int32 flags)
492 {
493 	UNIMPLEMENTED();
494 
495 	return B_OK;
496 }
497 
498 
499 status_t
500 BMediaTrack::WriteFrames(const void *data,
501 						 int64 num_frames,
502 						 media_encode_info *info)
503 {
504 	UNIMPLEMENTED();
505 
506 	return B_OK;
507 }
508 
509 
510 status_t
511 BMediaTrack::WriteChunk(const void *data,
512 						size_t size,
513 						uint32 flags)
514 {
515 	UNIMPLEMENTED();
516 
517 	return B_OK;
518 }
519 
520 
521 status_t
522 BMediaTrack::WriteChunk(const void *data,
523 						size_t size,
524 						media_encode_info *info)
525 {
526 	UNIMPLEMENTED();
527 
528 	return B_OK;
529 }
530 
531 
532 status_t
533 BMediaTrack::Flush()
534 {
535 	UNIMPLEMENTED();
536 
537 	return B_OK;
538 }
539 
540 
541 // deprecated BeOS R5 API
542 BParameterWeb *
543 BMediaTrack::Web()
544 {
545 	UNIMPLEMENTED();
546 	return NULL;
547 }
548 
549 
550 // returns a copy of the parameter web
551 status_t
552 BMediaTrack::GetParameterWeb(BParameterWeb** outWeb)
553 {
554 	UNIMPLEMENTED();
555 
556 	return B_OK;
557 }
558 
559 
560 status_t
561 BMediaTrack::GetParameterValue(int32 id,
562 							   void *valu,
563 							   size_t *size)
564 {
565 	UNIMPLEMENTED();
566 
567 	return B_ERROR;
568 }
569 
570 
571 status_t
572 BMediaTrack::SetParameterValue(int32 id,
573 							   const void *valu,
574 							   size_t size)
575 {
576 	UNIMPLEMENTED();
577 
578 	return B_ERROR;
579 }
580 
581 
582 BView *
583 BMediaTrack::GetParameterView()
584 {
585 	UNIMPLEMENTED();
586 	return NULL;
587 }
588 
589 
590 status_t
591 BMediaTrack::GetQuality(float *quality)
592 {
593 	UNIMPLEMENTED();
594 
595 	return B_ERROR;
596 }
597 
598 
599 status_t
600 BMediaTrack::SetQuality(float quality)
601 {
602 	UNIMPLEMENTED();
603 
604 	return B_ERROR;
605 }
606 
607 
608 status_t
609 BMediaTrack::GetEncodeParameters(encode_parameters *parameters) const
610 {
611 	UNIMPLEMENTED();
612 
613 	return B_ERROR;
614 }
615 
616 
617 status_t
618 BMediaTrack::SetEncodeParameters(encode_parameters *parameters)
619 {
620 	UNIMPLEMENTED();
621 
622 	return B_ERROR;
623 }
624 
625 
626 status_t
627 BMediaTrack::Perform(int32 selector,
628 					 void *data)
629 {
630 	UNIMPLEMENTED();
631 
632 	return B_ERROR;
633 }
634 
635 /*************************************************************
636  * private BMediaTrack
637  *************************************************************/
638 
639 BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor,
640 						 int32 stream)
641 {
642 	CALLED();
643 	fWorkaroundFlags = 0;
644 	fRawDecoder = 0;
645 	fExtractor = extractor;
646 	fStream = stream;
647 	fErr = B_OK;
648 
649 	SetupWorkaround();
650 
651 	if (fExtractor->CreateDecoder(fStream, &fDecoder, &fMCI) != B_OK) {
652 		ERROR("BMediaTrack::BMediaTrack: Error: creating decoder failed\n");
653 		// we do not set fErr here, because ReadChunk should still work
654 		fDecoder = 0;
655 		return;
656 	}
657 
658 	fCurFrame = 0;
659 	fCurTime = 0;
660 
661 	// not used:
662 	fEncoder = 0;
663 	fEncoderID = 0;
664 	fWriter = 0;
665 }
666 
667 
668 BMediaTrack::BMediaTrack(BPrivate::MediaWriter *writer,
669 						 int32 stream_num,
670 						 media_format *in_format,
671 						 BPrivate::media::Encoder *encoder,
672 						 media_codec_info *mci)
673 {
674 	UNIMPLEMENTED();
675 }
676 
677 
678 // Does nothing, returns B_ERROR, for Zeta compatiblity only
679 status_t
680 BMediaTrack::ControlCodec(int32 selector, void *io_data, size_t size)
681 {
682 	return B_ERROR;
683 }
684 
685 
686 void
687 BMediaTrack::SetupWorkaround()
688 {
689 	app_info	ainfo;
690 	thread_info	tinfo;
691 
692 	get_thread_info(find_thread(0), &tinfo);
693 	be_roster->GetRunningAppInfo(tinfo.team, &ainfo);
694 
695 	if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) {
696 		fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT | FORCE_RAW_AUDIO_HOST_ENDIAN;
697 		printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n");
698 	}
699 	if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) {
700 		fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO;
701 		printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n");
702 	}
703 
704 #if CONVERT_TO_INT32 // XXX test
705 	if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT))
706 		fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT;
707 #endif
708 }
709 
710 bool
711 BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to)
712 {
713 	char s[200];
714 	status_t res;
715 
716 	string_for_format(from, s, sizeof(s));
717 	printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s);
718 
719 	res = _CreateDecoder(&fRawDecoder, from);
720 	if (res != B_OK) {
721 		printf("BMediaTrack::SetupFormatTranslation: _CreateDecoder failed\n");
722 		return false;
723 	}
724 
725 	// XXX video?
726 	int buffer_size = from.u.raw_audio.buffer_size;
727 	int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count;
728 
729 	fRawDecoder->Setup(new RawDecoderChunkProvider(fDecoder, buffer_size, frame_size));
730 
731 	media_format from_temp = from;
732 	res = fRawDecoder->Setup(&from_temp, 0, 0);
733 	if (res != B_OK) {
734 		printf("BMediaTrack::SetupFormatTranslation: Setup failed\n");
735 		goto error;
736 	}
737 
738 	string_for_format(*to, s, sizeof(s));
739 	printf("BMediaTrack::SetupFormatTranslation:   to: %s\n", s);
740 
741 	res = fRawDecoder->NegotiateOutputFormat(to);
742 	if (res != B_OK) {
743 		printf("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat failed\n");
744 		goto error;
745 	}
746 
747 	string_for_format(*to, s, sizeof(s));
748 	printf("BMediaTrack::SetupFormatTranslation:  res: %s\n", s);
749 
750 	return true;
751 
752 error:
753 	_DestroyDecoder(fRawDecoder);
754 	fRawDecoder = 0;
755 	return false;
756 }
757 
758 /*
759 // unimplemented
760 BMediaTrack::BMediaTrack()
761 BMediaTrack::BMediaTrack(const BMediaTrack &)
762 BMediaTrack &BMediaTrack::operator=(const BMediaTrack &)
763 */
764 
765 status_t BMediaTrack::_Reserved_BMediaTrack_0(int32 arg, ...) { return B_ERROR; }
766 status_t BMediaTrack::_Reserved_BMediaTrack_1(int32 arg, ...) { return B_ERROR; }
767 status_t BMediaTrack::_Reserved_BMediaTrack_2(int32 arg, ...) { return B_ERROR; }
768 status_t BMediaTrack::_Reserved_BMediaTrack_3(int32 arg, ...) { return B_ERROR; }
769 status_t BMediaTrack::_Reserved_BMediaTrack_4(int32 arg, ...) { return B_ERROR; }
770 status_t BMediaTrack::_Reserved_BMediaTrack_5(int32 arg, ...) { return B_ERROR; }
771 status_t BMediaTrack::_Reserved_BMediaTrack_6(int32 arg, ...) { return B_ERROR; }
772 status_t BMediaTrack::_Reserved_BMediaTrack_7(int32 arg, ...) { return B_ERROR; }
773 status_t BMediaTrack::_Reserved_BMediaTrack_8(int32 arg, ...) { return B_ERROR; }
774 status_t BMediaTrack::_Reserved_BMediaTrack_9(int32 arg, ...) { return B_ERROR; }
775 status_t BMediaTrack::_Reserved_BMediaTrack_10(int32 arg, ...) { return B_ERROR; }
776 status_t BMediaTrack::_Reserved_BMediaTrack_11(int32 arg, ...) { return B_ERROR; }
777 status_t BMediaTrack::_Reserved_BMediaTrack_12(int32 arg, ...) { return B_ERROR; }
778 status_t BMediaTrack::_Reserved_BMediaTrack_13(int32 arg, ...) { return B_ERROR; }
779 status_t BMediaTrack::_Reserved_BMediaTrack_14(int32 arg, ...) { return B_ERROR; }
780 status_t BMediaTrack::_Reserved_BMediaTrack_15(int32 arg, ...) { return B_ERROR; }
781 status_t BMediaTrack::_Reserved_BMediaTrack_16(int32 arg, ...) { return B_ERROR; }
782 status_t BMediaTrack::_Reserved_BMediaTrack_17(int32 arg, ...) { return B_ERROR; }
783 status_t BMediaTrack::_Reserved_BMediaTrack_18(int32 arg, ...) { return B_ERROR; }
784 status_t BMediaTrack::_Reserved_BMediaTrack_19(int32 arg, ...) { return B_ERROR; }
785 status_t BMediaTrack::_Reserved_BMediaTrack_20(int32 arg, ...) { return B_ERROR; }
786 status_t BMediaTrack::_Reserved_BMediaTrack_21(int32 arg, ...) { return B_ERROR; }
787 status_t BMediaTrack::_Reserved_BMediaTrack_22(int32 arg, ...) { return B_ERROR; }
788 status_t BMediaTrack::_Reserved_BMediaTrack_23(int32 arg, ...) { return B_ERROR; }
789 status_t BMediaTrack::_Reserved_BMediaTrack_24(int32 arg, ...) { return B_ERROR; }
790 status_t BMediaTrack::_Reserved_BMediaTrack_25(int32 arg, ...) { return B_ERROR; }
791 status_t BMediaTrack::_Reserved_BMediaTrack_26(int32 arg, ...) { return B_ERROR; }
792 status_t BMediaTrack::_Reserved_BMediaTrack_27(int32 arg, ...) { return B_ERROR; }
793 status_t BMediaTrack::_Reserved_BMediaTrack_28(int32 arg, ...) { return B_ERROR; }
794 status_t BMediaTrack::_Reserved_BMediaTrack_29(int32 arg, ...) { return B_ERROR; }
795 status_t BMediaTrack::_Reserved_BMediaTrack_30(int32 arg, ...) { return B_ERROR; }
796 status_t BMediaTrack::_Reserved_BMediaTrack_31(int32 arg, ...) { return B_ERROR; }
797 status_t BMediaTrack::_Reserved_BMediaTrack_32(int32 arg, ...) { return B_ERROR; }
798 status_t BMediaTrack::_Reserved_BMediaTrack_33(int32 arg, ...) { return B_ERROR; }
799 status_t BMediaTrack::_Reserved_BMediaTrack_34(int32 arg, ...) { return B_ERROR; }
800 status_t BMediaTrack::_Reserved_BMediaTrack_35(int32 arg, ...) { return B_ERROR; }
801 status_t BMediaTrack::_Reserved_BMediaTrack_36(int32 arg, ...) { return B_ERROR; }
802 status_t BMediaTrack::_Reserved_BMediaTrack_37(int32 arg, ...) { return B_ERROR; }
803 status_t BMediaTrack::_Reserved_BMediaTrack_38(int32 arg, ...) { return B_ERROR; }
804 status_t BMediaTrack::_Reserved_BMediaTrack_39(int32 arg, ...) { return B_ERROR; }
805 status_t BMediaTrack::_Reserved_BMediaTrack_40(int32 arg, ...) { return B_ERROR; }
806 status_t BMediaTrack::_Reserved_BMediaTrack_41(int32 arg, ...) { return B_ERROR; }
807 status_t BMediaTrack::_Reserved_BMediaTrack_42(int32 arg, ...) { return B_ERROR; }
808 status_t BMediaTrack::_Reserved_BMediaTrack_43(int32 arg, ...) { return B_ERROR; }
809 status_t BMediaTrack::_Reserved_BMediaTrack_44(int32 arg, ...) { return B_ERROR; }
810 status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR; }
811 status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; }
812 status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; }
813 
814 
815 RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size)
816 {
817 //	printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n", buffer_size, frame_size);
818 	fDecoder = decoder;
819 	fFrameSize = frame_size;
820 	fBufferSize = buffer_size;
821 	fBuffer = malloc(buffer_size);
822 }
823 
824 RawDecoderChunkProvider::~RawDecoderChunkProvider()
825 {
826 	free(fBuffer);
827 }
828 
829 status_t
830 RawDecoderChunkProvider::GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
831                                       media_header *mediaHeader)
832 {
833 	int64 frames;
834 	media_decode_info info;
835 	status_t res = fDecoder->Decode(fBuffer, &frames, mediaHeader, &info);
836 	if (res == B_OK) {
837 		*chunkBuffer = fBuffer;
838 		*chunkSize = frames * fFrameSize;
839 //		printf("RawDecoderChunkProvider::GetNextChunk, %Ld frames, %ld bytes, start-time %Ld\n", frames, *chunkSize, mediaHeader->start_time);
840 	} else {
841 		printf("RawDecoderChunkProvider::GetNextChunk failed\n");
842 	}
843 	return res;
844 }
845