xref: /haiku/src/kits/media/MediaTrack.cpp (revision 2030e24a4ebb6fb3118be072ba4adaeb2189680f)
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 	strlcpy(mci->pretty_name, fMCI.pretty_name, sizeof(mci->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 // BMediaTrack::ReadFrames(char *, long long *, media_header *)
274 // Compatibility for R5 and below. Required by Corum III and Civ:CTP.
275 #if __GNUC__ < 3
276 
277 extern "C" status_t
278 ReadFrames__11BMediaTrackPcPxP12media_header(BMediaTrack *self,
279 											 char *out_buffer,
280 											 int64 *out_frameCount,
281 											 media_header *mh)
282 {
283 	return self->ReadFrames(out_buffer, out_frameCount, mh, 0);
284 }
285 
286 #endif	// __GNUC__ < 3
287 
288 status_t
289 BMediaTrack::ReadFrames(void *out_buffer,
290 						int64 *out_frameCount,
291 						media_header *mh)
292 {
293 	return ReadFrames(out_buffer, out_frameCount, mh, 0);
294 }
295 
296 
297 status_t
298 BMediaTrack::ReadFrames(void *out_buffer,
299 						int64 *out_frameCount,
300 						media_header *mh /* = 0 */,
301 						media_decode_info *info /* = 0 */)
302 {
303 //	CALLED();
304 	if (!fDecoder)
305 		return B_NO_INIT;
306 	if (!out_buffer || !out_frameCount)
307 		return B_BAD_VALUE;
308 
309 	status_t result;
310 	media_header header;
311 
312 	memset(&header, 0, sizeof(header)); // always clear it first, as the decoder doesn't set all fields
313 
314 	if (fRawDecoder)
315 		result = fRawDecoder->Decode(out_buffer, out_frameCount, &header, info);
316 	else
317 		result = fDecoder->Decode(out_buffer, out_frameCount, &header, info);
318 	if (result == B_OK) {
319 		fCurFrame += *out_frameCount;
320 		fCurTime = header.start_time;
321 	} else {
322 		ERROR("BMediaTrack::ReadFrames: decoder returned error 0x%08lx (%s)\n", result, strerror(result));
323 		*out_frameCount = 0;
324 	}
325 	if (mh)
326 		*mh = header;
327 
328 //	PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, %Ld frames\n", fStream,  header.start_time / 1000000, header.start_time % 1000000, *out_frameCount);
329 
330 	return result;
331 }
332 
333 
334 status_t
335 BMediaTrack::ReplaceFrames(const void *in_buffer,
336 						   int64 *io_frameCount,
337 						   const media_header *mh)
338 {
339 	UNIMPLEMENTED();
340 
341 	return B_OK;
342 }
343 
344 
345 status_t
346 BMediaTrack::SeekToTime(bigtime_t *inout_time, int32 flags)
347 {
348 	CALLED();
349 	if (!fDecoder || !fExtractor)
350 		return B_NO_INIT;
351 	if (!inout_time)
352 		return B_BAD_VALUE;
353 
354 	uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
355 		| B_MEDIA_SEEK_TO_TIME;
356 	bigtime_t seekTime = *inout_time;
357 
358 	int64 frame = 0;
359 	bigtime_t time = seekTime;
360 	status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time);
361 	if (result != B_OK) {
362 		ERROR("BMediaTrack::SeekToTime: extractor seek failed\n");
363 		return result;
364 	}
365 
366 	// TODO: Codecs cannot actually "seek" in the stream, all they
367 	// can do is "reset" their decoder state, since they are made
368 	// aware of the fact that there will be a jump in the data. Maybe
369 	// rename the codec method?
370 	result = fDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
371 	if (result != B_OK) {
372 		ERROR("BMediaTrack::SeekToTime: decoder seek failed\n");
373 		return result;
374 	}
375 
376 	if (fRawDecoder) {
377 		result = fRawDecoder->Seek(seekTo, 0, &frame, seekTime, &time);
378 		if (result != B_OK) {
379 			ERROR("BMediaTrack::SeekToTime: raw decoder seek failed\n");
380 			return result;
381 		}
382 	}
383 
384 	*inout_time = time;
385 	fCurFrame = frame;
386 	fCurTime = time;
387 
388 	PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", seekTime / 1000000.0, *inout_time / 1000000.0);
389 
390 	return B_OK;
391 }
392 
393 
394 status_t
395 BMediaTrack::SeekToFrame(int64 *inout_frame, int32 flags)
396 {
397 	CALLED();
398 	if (!fDecoder || !fExtractor)
399 		return B_NO_INIT;
400 	if (!inout_frame)
401 		return B_BAD_VALUE;
402 
403 	uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
404 		| B_MEDIA_SEEK_TO_FRAME;
405 	int64 seekFrame = *inout_frame;
406 
407 	int64 frame = seekFrame;
408 	bigtime_t time = 0;
409 	status_t result = fExtractor->Seek(fStream, seekTo, &frame, &time);
410 	if (result != B_OK) {
411 		ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n");
412 		return result;
413 	}
414 
415 	// TODO: Codecs cannot actually "seek" in the stream, all they
416 	// can do is "reset" their decoder state, since they are made
417 	// aware of the fact that there will be a jump in the data. Maybe
418 	// rename the codec method?
419 	result = fDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
420 	if (result != B_OK) {
421 		ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n");
422 		return result;
423 	}
424 
425 	if (fRawDecoder) {
426 		result = fRawDecoder->Seek(seekTo, seekFrame, &frame, 0, &time);
427 		if (result != B_OK) {
428 			ERROR("BMediaTrack::SeekToFrame: raw decoder seek failed\n");
429 			return result;
430 		}
431 	}
432 
433 	*inout_frame = frame;
434 	fCurFrame = frame;
435 	fCurTime = time;
436 
437 	PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %Ld, result %Ld\n", seekFrame, *inout_frame);
438 
439 	return B_OK;
440 }
441 
442 
443 status_t
444 BMediaTrack::FindKeyFrameForTime(bigtime_t *inoutTime, int32 flags) const
445 {
446 	CALLED();
447 	if (!fExtractor)
448 		return B_NO_INIT;
449 	if (!inoutTime)
450 		return B_BAD_VALUE;
451 
452 	uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
453 		| B_MEDIA_SEEK_TO_TIME;
454 
455 	int64 frame = 0;
456 		// dummy frame, will be ignored because of flags
457 	status_t result = fExtractor->FindKeyFrame(fStream, seekTo, &frame,
458 		inoutTime);
459 	if (result != B_OK) {
460 		ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n",
461 			strerror(result));
462 		return result;
463 	}
464 
465 	return B_OK;
466 }
467 
468 
469 status_t
470 BMediaTrack::FindKeyFrameForFrame(int64 *inoutFrame,
471 								  int32 flags) const
472 {
473 	CALLED();
474 	if (!fExtractor)
475 		return B_NO_INIT;
476 	if (!inoutFrame)
477 		return B_BAD_VALUE;
478 
479 	uint32 seekTo = (flags & B_MEDIA_SEEK_DIRECTION_MASK)
480 		| B_MEDIA_SEEK_TO_FRAME;
481 
482 	bigtime_t time = 0;
483 		// dummy time, will be ignored because of flags
484 	status_t result = fExtractor->FindKeyFrame(fStream, seekTo, inoutFrame,
485 		&time);
486 	if (result != B_OK) {
487 		ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n",
488 			strerror(result));
489 		return result;
490 	}
491 
492 	return B_OK;
493 }
494 
495 
496 status_t
497 BMediaTrack::ReadChunk(char **out_buffer,
498 					   int32 *out_size,
499 					   media_header *mh /* = 0 */)
500 {
501 	CALLED();
502 	if (!fExtractor)
503 		return B_NO_INIT;
504 	if (!out_buffer || !out_size)
505 		return B_BAD_VALUE;
506 
507 	status_t result;
508 	media_header header;
509 	const void *buffer;
510 	size_t size;
511 
512 	memset(&header, 0, sizeof(header)); // always clear it first, as the reader doesn't set all fields
513 
514 	result = fExtractor->GetNextChunk(fStream, &buffer, &size, &header);
515 	if (result == B_OK) {
516 		*out_buffer = const_cast<char *>(static_cast<const char *>(buffer)); // yes this *is* ugly
517 		*out_size  = size;
518 		fCurTime = header.start_time;
519 		if (mh)
520 			*mh = header;
521 	}
522 
523 	return result;
524 }
525 
526 
527 status_t
528 BMediaTrack::AddCopyright(const char *data)
529 {
530 	UNIMPLEMENTED();
531 
532 	return B_OK;
533 }
534 
535 
536 status_t
537 BMediaTrack::AddTrackInfo(uint32 code,
538 						  const void *data,
539 						  size_t size,
540 						  uint32 flags)
541 {
542 	UNIMPLEMENTED();
543 
544 	return B_OK;
545 }
546 
547 
548 status_t
549 BMediaTrack::WriteFrames(const void *data,
550 						 int32 num_frames,
551 						 int32 flags)
552 {
553 	UNIMPLEMENTED();
554 
555 	return B_OK;
556 }
557 
558 
559 status_t
560 BMediaTrack::WriteFrames(const void *data,
561 						 int64 num_frames,
562 						 media_encode_info *info)
563 {
564 	UNIMPLEMENTED();
565 
566 	return B_OK;
567 }
568 
569 
570 status_t
571 BMediaTrack::WriteChunk(const void *data,
572 						size_t size,
573 						uint32 flags)
574 {
575 	UNIMPLEMENTED();
576 
577 	return B_OK;
578 }
579 
580 
581 status_t
582 BMediaTrack::WriteChunk(const void *data,
583 						size_t size,
584 						media_encode_info *info)
585 {
586 	UNIMPLEMENTED();
587 
588 	return B_OK;
589 }
590 
591 
592 status_t
593 BMediaTrack::Flush()
594 {
595 	UNIMPLEMENTED();
596 
597 	return B_OK;
598 }
599 
600 
601 // deprecated BeOS R5 API
602 BParameterWeb *
603 BMediaTrack::Web()
604 {
605 	UNIMPLEMENTED();
606 	return NULL;
607 }
608 
609 
610 // returns a copy of the parameter web
611 status_t
612 BMediaTrack::GetParameterWeb(BParameterWeb** outWeb)
613 {
614 	UNIMPLEMENTED();
615 
616 	return B_OK;
617 }
618 
619 
620 status_t
621 BMediaTrack::GetParameterValue(int32 id,
622 							   void *valu,
623 							   size_t *size)
624 {
625 	UNIMPLEMENTED();
626 
627 	return B_ERROR;
628 }
629 
630 
631 status_t
632 BMediaTrack::SetParameterValue(int32 id,
633 							   const void *valu,
634 							   size_t size)
635 {
636 	UNIMPLEMENTED();
637 
638 	return B_ERROR;
639 }
640 
641 
642 BView *
643 BMediaTrack::GetParameterView()
644 {
645 	UNIMPLEMENTED();
646 	return NULL;
647 }
648 
649 
650 status_t
651 BMediaTrack::GetQuality(float *quality)
652 {
653 	UNIMPLEMENTED();
654 
655 	return B_ERROR;
656 }
657 
658 
659 status_t
660 BMediaTrack::SetQuality(float quality)
661 {
662 	UNIMPLEMENTED();
663 
664 	return B_ERROR;
665 }
666 
667 
668 status_t
669 BMediaTrack::GetEncodeParameters(encode_parameters *parameters) const
670 {
671 	UNIMPLEMENTED();
672 
673 	return B_ERROR;
674 }
675 
676 
677 status_t
678 BMediaTrack::SetEncodeParameters(encode_parameters *parameters)
679 {
680 	UNIMPLEMENTED();
681 
682 	return B_ERROR;
683 }
684 
685 
686 status_t
687 BMediaTrack::Perform(int32 selector,
688 					 void *data)
689 {
690 	UNIMPLEMENTED();
691 
692 	return B_ERROR;
693 }
694 
695 /*************************************************************
696  * private BMediaTrack
697  *************************************************************/
698 
699 BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor *extractor,
700 						 int32 stream)
701 {
702 	CALLED();
703 	fWorkaroundFlags = 0;
704 	fDecoder = NULL;
705 	fRawDecoder = NULL;
706 	fExtractor = extractor;
707 	fStream = stream;
708 	fErr = B_OK;
709 
710 	SetupWorkaround();
711 
712 	status_t ret = fExtractor->CreateDecoder(fStream, &fDecoder, &fMCI);
713 	if (ret != B_OK) {
714 		TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: "
715 			"%s\n", strerror(ret));
716 		// we do not set fErr here, because ReadChunk should still work
717 		fDecoder = NULL;
718 		return;
719 	}
720 
721 	fCurFrame = 0;
722 	fCurTime = 0;
723 
724 	// not used:
725 	fEncoder = NULL;
726 	fEncoderID = 0;
727 	fWriter = NULL;
728 }
729 
730 
731 BMediaTrack::BMediaTrack(BPrivate::MediaWriter *writer,
732 						 int32 stream_num,
733 						 media_format *in_format,
734 						 BPrivate::media::Encoder *encoder,
735 						 media_codec_info *mci)
736 {
737 	UNIMPLEMENTED();
738 }
739 
740 
741 // Does nothing, returns B_ERROR, for Zeta compatiblity only
742 status_t
743 BMediaTrack::ControlCodec(int32 selector, void *io_data, size_t size)
744 {
745 	return B_ERROR;
746 }
747 
748 
749 void
750 BMediaTrack::SetupWorkaround()
751 {
752 	app_info	ainfo;
753 	thread_info	tinfo;
754 
755 	get_thread_info(find_thread(0), &tinfo);
756 	be_roster->GetRunningAppInfo(tinfo.team, &ainfo);
757 
758 	if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) {
759 		fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT | FORCE_RAW_AUDIO_HOST_ENDIAN;
760 		printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n");
761 	}
762 	if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) {
763 		fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO;
764 		printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n");
765 	}
766 
767 #if CONVERT_TO_INT32 // XXX test
768 	if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT))
769 		fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT;
770 #endif
771 }
772 
773 bool
774 BMediaTrack::SetupFormatTranslation(const media_format &from, media_format *to)
775 {
776 	_plugin_manager.DestroyDecoder(fRawDecoder);
777 	fRawDecoder = NULL;
778 
779 #ifdef TRACE_MEDIA_TRACK
780 	char s[200];
781 	string_for_format(from, s, sizeof(s));
782 	printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s);
783 #endif
784 
785 	status_t res = _plugin_manager.CreateDecoder(&fRawDecoder, from);
786 	if (res != B_OK) {
787 		ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n");
788 		return false;
789 	}
790 
791 	// XXX video?
792 	int buffer_size = from.u.raw_audio.buffer_size;
793 	int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count;
794 	media_format notconstFrom = from;
795 
796 	ChunkProvider *chunkProvider = new(std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, frame_size);
797 	if (!chunkProvider) {
798 		ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk provider\n");
799 		goto error;
800 	}
801 	fRawDecoder->SetChunkProvider(chunkProvider);
802 
803 	res = fRawDecoder->Setup(&notconstFrom, 0, 0);
804 	if (res != B_OK) {
805 		ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n");
806 		goto error;
807 	}
808 
809 #ifdef TRACE_MEDIA_TRACK
810 	string_for_format(*to, s, sizeof(s));
811 	printf("BMediaTrack::SetupFormatTranslation:   to: %s\n", s);
812 #endif
813 
814 	res = fRawDecoder->NegotiateOutputFormat(to);
815 	if (res != B_OK) {
816 		ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat failed\n");
817 		goto error;
818 	}
819 
820 #ifdef TRACE_MEDIA_TRACK
821 	string_for_format(*to, s, sizeof(s));
822 	printf("BMediaTrack::SetupFormatTranslation:  res: %s\n", s);
823 #endif
824 
825 	return true;
826 
827 error:
828 	_plugin_manager.DestroyDecoder(fRawDecoder);
829 	fRawDecoder = NULL;
830 	return false;
831 }
832 
833 /*
834 // unimplemented
835 BMediaTrack::BMediaTrack()
836 BMediaTrack::BMediaTrack(const BMediaTrack &)
837 BMediaTrack &BMediaTrack::operator=(const BMediaTrack &)
838 */
839 
840 status_t BMediaTrack::_Reserved_BMediaTrack_0(int32 arg, ...) { return B_ERROR; }
841 status_t BMediaTrack::_Reserved_BMediaTrack_1(int32 arg, ...) { return B_ERROR; }
842 status_t BMediaTrack::_Reserved_BMediaTrack_2(int32 arg, ...) { return B_ERROR; }
843 status_t BMediaTrack::_Reserved_BMediaTrack_3(int32 arg, ...) { return B_ERROR; }
844 status_t BMediaTrack::_Reserved_BMediaTrack_4(int32 arg, ...) { return B_ERROR; }
845 status_t BMediaTrack::_Reserved_BMediaTrack_5(int32 arg, ...) { return B_ERROR; }
846 status_t BMediaTrack::_Reserved_BMediaTrack_6(int32 arg, ...) { return B_ERROR; }
847 status_t BMediaTrack::_Reserved_BMediaTrack_7(int32 arg, ...) { return B_ERROR; }
848 status_t BMediaTrack::_Reserved_BMediaTrack_8(int32 arg, ...) { return B_ERROR; }
849 status_t BMediaTrack::_Reserved_BMediaTrack_9(int32 arg, ...) { return B_ERROR; }
850 status_t BMediaTrack::_Reserved_BMediaTrack_10(int32 arg, ...) { return B_ERROR; }
851 status_t BMediaTrack::_Reserved_BMediaTrack_11(int32 arg, ...) { return B_ERROR; }
852 status_t BMediaTrack::_Reserved_BMediaTrack_12(int32 arg, ...) { return B_ERROR; }
853 status_t BMediaTrack::_Reserved_BMediaTrack_13(int32 arg, ...) { return B_ERROR; }
854 status_t BMediaTrack::_Reserved_BMediaTrack_14(int32 arg, ...) { return B_ERROR; }
855 status_t BMediaTrack::_Reserved_BMediaTrack_15(int32 arg, ...) { return B_ERROR; }
856 status_t BMediaTrack::_Reserved_BMediaTrack_16(int32 arg, ...) { return B_ERROR; }
857 status_t BMediaTrack::_Reserved_BMediaTrack_17(int32 arg, ...) { return B_ERROR; }
858 status_t BMediaTrack::_Reserved_BMediaTrack_18(int32 arg, ...) { return B_ERROR; }
859 status_t BMediaTrack::_Reserved_BMediaTrack_19(int32 arg, ...) { return B_ERROR; }
860 status_t BMediaTrack::_Reserved_BMediaTrack_20(int32 arg, ...) { return B_ERROR; }
861 status_t BMediaTrack::_Reserved_BMediaTrack_21(int32 arg, ...) { return B_ERROR; }
862 status_t BMediaTrack::_Reserved_BMediaTrack_22(int32 arg, ...) { return B_ERROR; }
863 status_t BMediaTrack::_Reserved_BMediaTrack_23(int32 arg, ...) { return B_ERROR; }
864 status_t BMediaTrack::_Reserved_BMediaTrack_24(int32 arg, ...) { return B_ERROR; }
865 status_t BMediaTrack::_Reserved_BMediaTrack_25(int32 arg, ...) { return B_ERROR; }
866 status_t BMediaTrack::_Reserved_BMediaTrack_26(int32 arg, ...) { return B_ERROR; }
867 status_t BMediaTrack::_Reserved_BMediaTrack_27(int32 arg, ...) { return B_ERROR; }
868 status_t BMediaTrack::_Reserved_BMediaTrack_28(int32 arg, ...) { return B_ERROR; }
869 status_t BMediaTrack::_Reserved_BMediaTrack_29(int32 arg, ...) { return B_ERROR; }
870 status_t BMediaTrack::_Reserved_BMediaTrack_30(int32 arg, ...) { return B_ERROR; }
871 status_t BMediaTrack::_Reserved_BMediaTrack_31(int32 arg, ...) { return B_ERROR; }
872 status_t BMediaTrack::_Reserved_BMediaTrack_32(int32 arg, ...) { return B_ERROR; }
873 status_t BMediaTrack::_Reserved_BMediaTrack_33(int32 arg, ...) { return B_ERROR; }
874 status_t BMediaTrack::_Reserved_BMediaTrack_34(int32 arg, ...) { return B_ERROR; }
875 status_t BMediaTrack::_Reserved_BMediaTrack_35(int32 arg, ...) { return B_ERROR; }
876 status_t BMediaTrack::_Reserved_BMediaTrack_36(int32 arg, ...) { return B_ERROR; }
877 status_t BMediaTrack::_Reserved_BMediaTrack_37(int32 arg, ...) { return B_ERROR; }
878 status_t BMediaTrack::_Reserved_BMediaTrack_38(int32 arg, ...) { return B_ERROR; }
879 status_t BMediaTrack::_Reserved_BMediaTrack_39(int32 arg, ...) { return B_ERROR; }
880 status_t BMediaTrack::_Reserved_BMediaTrack_40(int32 arg, ...) { return B_ERROR; }
881 status_t BMediaTrack::_Reserved_BMediaTrack_41(int32 arg, ...) { return B_ERROR; }
882 status_t BMediaTrack::_Reserved_BMediaTrack_42(int32 arg, ...) { return B_ERROR; }
883 status_t BMediaTrack::_Reserved_BMediaTrack_43(int32 arg, ...) { return B_ERROR; }
884 status_t BMediaTrack::_Reserved_BMediaTrack_44(int32 arg, ...) { return B_ERROR; }
885 status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR; }
886 status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; }
887 status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; }
888 
889 
890 RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder *decoder, int buffer_size, int frame_size)
891 {
892 //	printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n", buffer_size, frame_size);
893 	fDecoder = decoder;
894 	fFrameSize = frame_size;
895 	fBufferSize = buffer_size;
896 	fBuffer = malloc(buffer_size);
897 }
898 
899 RawDecoderChunkProvider::~RawDecoderChunkProvider()
900 {
901 	free(fBuffer);
902 }
903 
904 status_t
905 RawDecoderChunkProvider::GetNextChunk(const void **chunkBuffer, size_t *chunkSize,
906                                       media_header *mediaHeader)
907 {
908 	int64 frames;
909 	media_decode_info info;
910 	status_t res = fDecoder->Decode(fBuffer, &frames, mediaHeader, &info);
911 	if (res == B_OK) {
912 		*chunkBuffer = fBuffer;
913 		*chunkSize = frames * fFrameSize;
914 //		printf("RawDecoderChunkProvider::GetNextChunk, %Ld frames, %ld bytes, start-time %Ld\n", frames, *chunkSize, mediaHeader->start_time);
915 	} else {
916 		ERROR("RawDecoderChunkProvider::GetNextChunk failed\n");
917 	}
918 	return res;
919 }
920