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