tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / media / MediaTrack.cpp
bloba654608be616141f1c2184a188f87624fa6cf841
1 /*
2 * Copyright 2002-2007, Marcus Overhagen <marcus@overhagen.de>
3 * Copyright 2009-2010, Stephan Aßmus <superstippi@gmx.de>
4 * Copyright 2013, Haiku, Inc. All Rights Reserved.
5 * All rights reserved. Distributed under the terms of the MIT license.
7 * Authors:
8 * Stephan Aßmus, superstippi@gmx.de
9 * Marcus Overhagen, marcus@overhagen.de
13 #include <MediaTrack.h>
15 #include <new>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
21 #include <Roster.h>
23 #include "MediaExtractor.h"
24 #include "MediaWriter.h"
25 #include "PluginManager.h"
28 //#define TRACE_MEDIA_TRACK
29 #ifdef TRACE_MEDIA_TRACK
30 # ifndef TRACE
31 # define TRACE printf
32 # endif
33 #else
34 # ifndef TRACE
35 # define TRACE(a...)
36 # endif
37 #endif
39 #define ERROR(a...) fprintf(stderr, a)
42 #define CONVERT_TO_INT32 0
43 // TODO: Test! This triggers a few bugs!
45 // flags used for workarounds
46 enum {
47 FORCE_RAW_AUDIO = 0x0001,
48 FORCE_RAW_VIDEO = 0x0002,
49 FORCE_RAW_AUDIO_INT16_FORMAT = 0x0010,
50 FORCE_RAW_AUDIO_INT32_FORMAT = 0x0020,
51 FORCE_RAW_AUDIO_FLOAT_FORMAT = 0x0040,
52 FORCE_RAW_AUDIO_HOST_ENDIAN = 0x0100,
53 IGNORE_ENCODED_AUDIO = 0x1000,
54 IGNORE_ENCODED_VIDEO = 0x2000,
57 #define B_MEDIA_DISABLE_FORMAT_TRANSLATION 0x4000
58 // TODO: move this (after name change?) to MediaDefs.h
61 class RawDecoderChunkProvider : public ChunkProvider {
62 public:
63 RawDecoderChunkProvider(Decoder* decoder,
64 int buffer_size, int frame_size);
65 virtual ~RawDecoderChunkProvider();
67 status_t GetNextChunk(const void** chunkBuffer,
68 size_t* chunkSize,
69 media_header* mediaHeader);
71 private:
72 Decoder* fDecoder;
73 void* fBuffer;
74 int fBufferSize;
75 int fFrameSize;
79 /*************************************************************
80 * protected BMediaTrack
81 *************************************************************/
83 BMediaTrack::~BMediaTrack()
85 CALLED();
87 gPluginManager.DestroyDecoder(fRawDecoder);
88 gPluginManager.DestroyDecoder(fDecoder);
89 gPluginManager.DestroyEncoder(fEncoder);
92 /*************************************************************
93 * public BMediaTrack
94 *************************************************************/
96 status_t
97 BMediaTrack::InitCheck() const
99 CALLED();
101 return fInitStatus;
105 status_t
106 BMediaTrack::GetCodecInfo(media_codec_info* _codecInfo) const
108 CALLED();
110 if (fDecoder == NULL)
111 return B_NO_INIT;
113 *_codecInfo = fCodecInfo;
114 strlcpy(_codecInfo->pretty_name, fCodecInfo.pretty_name,
115 sizeof(_codecInfo->pretty_name));
117 return B_OK;
121 status_t
122 BMediaTrack::EncodedFormat(media_format* _format) const
124 CALLED();
126 if (_format == NULL)
127 return B_BAD_VALUE;
129 if (fExtractor == NULL)
130 return B_NO_INIT;
132 *_format = *fExtractor->EncodedFormat(fStream);
134 #ifdef TRACE_MEDIA_TRACK
135 char s[200];
136 string_for_format(*_format, s, sizeof(s));
137 printf("BMediaTrack::EncodedFormat: %s\n", s);
138 #endif
140 return B_OK;
144 // for BeOS R5 compatibility
145 extern "C" status_t DecodedFormat__11BMediaTrackP12media_format(
146 BMediaTrack* self, media_format* _format);
148 status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack* self,
149 media_format* _format)
151 return self->DecodedFormat(_format, 0);
155 status_t
156 BMediaTrack::DecodedFormat(media_format* _format, uint32 flags)
158 CALLED();
160 if (_format == NULL)
161 return B_BAD_VALUE;
163 if (fExtractor == NULL || fDecoder == NULL)
164 return B_NO_INIT;
166 gPluginManager.DestroyDecoder(fRawDecoder);
167 fRawDecoder = NULL;
169 #ifdef TRACE_MEDIA_TRACK
170 char s[200];
171 string_for_format(*_format, s, sizeof(s));
172 printf("BMediaTrack::DecodedFormat: req1: %s\n", s);
173 #endif
175 if ((fWorkaroundFlags & FORCE_RAW_AUDIO)
176 || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO)
177 && _format->type == B_MEDIA_ENCODED_AUDIO)) {
178 _format->type = B_MEDIA_RAW_AUDIO;
179 _format->u.raw_audio = media_multi_audio_format::wildcard;
181 if ((fWorkaroundFlags & FORCE_RAW_VIDEO)
182 || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO)
183 && _format->type == B_MEDIA_ENCODED_VIDEO)) {
184 _format->type = B_MEDIA_RAW_VIDEO;
185 _format->u.raw_video = media_raw_video_format::wildcard;
187 if (_format->type == B_MEDIA_RAW_AUDIO) {
188 if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN)
189 _format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN;
191 if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT) {
192 _format->u.raw_audio.format
193 = media_raw_audio_format::B_AUDIO_SHORT;
195 if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT) {
196 _format->u.raw_audio.format
197 = media_raw_audio_format::B_AUDIO_INT;
199 if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT) {
200 _format->u.raw_audio.format
201 = media_raw_audio_format::B_AUDIO_FLOAT;
205 #ifdef TRACE_MEDIA_TRACK
206 string_for_format(*_format, s, sizeof(s));
207 printf("BMediaTrack::DecodedFormat: req2: %s\n", s);
208 #endif
210 fFormat = *_format;
211 status_t result = fDecoder->NegotiateOutputFormat(_format);
213 #ifdef TRACE_MEDIA_TRACK
214 string_for_format(*_format, s, sizeof(s));
215 printf("BMediaTrack::DecodedFormat: nego: %s\n", s);
216 #endif
218 if (_format->type == 0) {
219 #ifdef TRACE_MEDIA_TRACK
220 printf("BMediaTrack::DecodedFormat: Decoder didn't set output format "
221 "type.\n");
222 #endif
225 if (_format->type == B_MEDIA_RAW_AUDIO) {
226 if (_format->u.raw_audio.byte_order == 0) {
227 #ifdef TRACE_MEDIA_TRACK
228 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw audio "
229 "output byte order.\n");
230 #endif
232 if (_format->u.raw_audio.format == 0) {
233 #ifdef TRACE_MEDIA_TRACK
234 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw audio "
235 "output sample format.\n");
236 #endif
238 if (_format->u.raw_audio.buffer_size <= 0) {
239 #ifdef TRACE_MEDIA_TRACK
240 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw audio "
241 "output buffer size.\n");
242 #endif
246 if (_format->type == B_MEDIA_RAW_VIDEO) {
247 if (_format->u.raw_video.display.format == 0) {
248 #ifdef TRACE_MEDIA_TRACK
249 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video "
250 "output color space.\n");
251 #endif
253 if (_format->u.raw_video.display.line_width == 0) {
254 #ifdef TRACE_MEDIA_TRACK
255 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video "
256 "output line_width.\n");
257 #endif
259 if (_format->u.raw_video.display.line_count == 0) {
260 #ifdef TRACE_MEDIA_TRACK
261 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video "
262 "output line_count.\n");
263 #endif
265 if (_format->u.raw_video.display.bytes_per_row == 0) {
266 #ifdef TRACE_MEDIA_TRACK
267 printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video "
268 "output bytes_per_row.\n");
269 #endif
273 if ((flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION) == 0) {
274 if (fFormat.type == B_MEDIA_RAW_AUDIO
275 && _format->type == B_MEDIA_RAW_AUDIO
276 && fFormat.u.raw_audio.format != 0
277 && fFormat.u.raw_audio.format != _format->u.raw_audio.format) {
278 if (SetupFormatTranslation(*_format, &fFormat))
279 *_format = fFormat;
283 fFormat = *_format;
285 // string_for_format(*_format, s, sizeof(s));
286 // printf("BMediaTrack::DecodedFormat: status: %s\n", s);
287 return result;
291 status_t
292 BMediaTrack::GetMetaData(BMessage* _data) const
294 CALLED();
296 if (fExtractor == NULL)
297 return B_NO_INIT;
299 if (_data == NULL)
300 return B_BAD_VALUE;
302 _data->MakeEmpty();
304 return fExtractor->GetStreamMetaData(fStream, _data);
308 int64
309 BMediaTrack::CountFrames() const
311 CALLED();
313 int64 frames = fExtractor ? fExtractor->CountFrames(fStream) : 0;
314 // printf("BMediaTrack::CountFrames: %lld\n", frames);
315 return frames;
319 bigtime_t
320 BMediaTrack::Duration() const
322 CALLED();
324 bigtime_t duration = fExtractor ? fExtractor->Duration(fStream) : 0;
325 // printf("BMediaTrack::Duration: %lld\n", duration);
326 return duration;
330 int64
331 BMediaTrack::CurrentFrame() const
333 return fCurrentFrame;
337 bigtime_t
338 BMediaTrack::CurrentTime() const
340 return fCurrentTime;
343 // BMediaTrack::ReadFrames(char*, long long*, media_header*)
344 // Compatibility for R5 and below. Required by Corum III and Civ:CTP.
345 #if __GNUC__ < 3
347 extern "C" status_t
348 ReadFrames__11BMediaTrackPcPxP12media_header(BMediaTrack* self,
349 char* _buffer, int64* _frameCount, media_header* header)
351 return self->ReadFrames(_buffer, _frameCount, header, 0);
354 #endif // __GNUC__ < 3
356 status_t
357 BMediaTrack::ReadFrames(void* buffer, int64* _frameCount, media_header* header)
359 return ReadFrames(buffer, _frameCount, header, NULL);
363 status_t
364 BMediaTrack::ReadFrames(void* buffer, int64* _frameCount,
365 media_header* _header, media_decode_info* info)
367 // CALLED();
369 if (fDecoder == NULL)
370 return B_NO_INIT;
372 if (buffer == NULL || _frameCount == NULL)
373 return B_BAD_VALUE;
375 media_header header;
376 if (_header == NULL)
377 _header = &header;
379 // Always clear the header first, as the decoder may not set all fields.
380 memset(_header, 0, sizeof(media_header));
382 status_t result = fRawDecoder != NULL
383 ? fRawDecoder->Decode(buffer, _frameCount, _header, info)
384 : fDecoder->Decode(buffer, _frameCount, _header, info);
386 if (result == B_OK) {
387 fCurrentFrame += *_frameCount;
388 bigtime_t framesDuration = (bigtime_t)(*_frameCount * 1000000
389 / _FrameRate());
390 fCurrentTime = _header->start_time + framesDuration;
391 #if 0
392 // This debug output shows drift between calculated fCurrentFrame and
393 // time-based current frame, if there is any.
394 if (fFormat.type == B_MEDIA_RAW_AUDIO) {
395 printf("current frame: %lld / calculated: %lld (%.2f/%.2f)\r",
396 fCurrentFrame,
397 int64(fCurrentTime * _FrameRate() / 1000000.0 + 0.5),
398 fCurrentTime / 1000000.0, (float)fCurrentFrame / _FrameRate());
399 fflush(stdout);
401 #endif
402 } else {
403 ERROR("BMediaTrack::ReadFrames: decoder returned error %#" B_PRIx32
404 " (%s)\n", result, strerror(result));
405 *_frameCount = 0;
408 #if 0
409 PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, "
410 "%lld frames\n", fStream, _header->start_time / 1000000,
411 _header->start_time % 1000000, *out_frameCount);
412 #endif
414 return result;
418 status_t
419 BMediaTrack::ReplaceFrames(const void* inBuffer, int64* _frameCount,
420 const media_header* header)
422 UNIMPLEMENTED();
424 // TODO: Actually, a file is either open for reading or writing at the
425 // moment. Since the chunk size of encoded media data will change,
426 // implementing this call will only be possible for raw media tracks.
428 return B_NOT_SUPPORTED;
432 status_t
433 BMediaTrack::SeekToTime(bigtime_t* _time, int32 flags)
435 CALLED();
437 if (fDecoder == NULL || fExtractor == NULL)
438 return B_NO_INIT;
440 if (_time == NULL)
441 return B_BAD_VALUE;
443 // Make sure flags are valid
444 flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME;
446 #if DEBUG
447 bigtime_t requestedTime = *_time;
448 #endif
449 int64 frame = 0;
451 status_t result = fExtractor->Seek(fStream, flags, &frame, _time);
452 if (result != B_OK) {
453 ERROR("BMediaTrack::SeekToTime: extractor seek failed\n");
454 return result;
457 result = fDecoder->SeekedTo(frame, *_time);
458 if (result != B_OK) {
459 ERROR("BMediaTrack::SeekToTime: decoder seek failed\n");
460 return result;
463 if (fRawDecoder != NULL) {
464 result = fRawDecoder->SeekedTo(frame, *_time);
465 if (result != B_OK) {
466 ERROR("BMediaTrack::SeekToTime: raw decoder seek failed\n");
467 return result;
471 fCurrentFrame = frame;
472 fCurrentTime = *_time;
474 PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n",
475 requestedTime / 1000000.0, *_time / 1000000.0);
477 return B_OK;
481 status_t
482 BMediaTrack::SeekToFrame(int64* _frame, int32 flags)
484 CALLED();
486 if (fDecoder == NULL || fExtractor == NULL)
487 return B_NO_INIT;
489 if (_frame == NULL)
490 return B_BAD_VALUE;
492 // Make sure flags are valid
493 flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME;
495 #if DEBUG
496 int64 requestedFrame = *_frame;
497 #endif
498 bigtime_t time = 0;
500 status_t result = fExtractor->Seek(fStream, flags, _frame, &time);
501 if (result != B_OK) {
502 ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n");
503 return result;
506 result = fDecoder->SeekedTo(*_frame, time);
507 if (result != B_OK) {
508 ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n");
509 return result;
512 if (fRawDecoder != NULL) {
513 result = fRawDecoder->SeekedTo(*_frame, time);
514 if (result != B_OK) {
515 ERROR("BMediaTrack::SeekToFrame: raw decoder seek failed\n");
516 return result;
520 fCurrentFrame = *_frame;
521 fCurrentTime = time;
523 PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %lld, "
524 "result %lld\n", requestedFrame, *_frame);
526 return B_OK;
530 status_t
531 BMediaTrack::FindKeyFrameForTime(bigtime_t* _time, int32 flags) const
533 CALLED();
535 if (fExtractor == NULL)
536 return B_NO_INIT;
538 if (_time == NULL)
539 return B_BAD_VALUE;
541 // Make sure flags are valid
542 flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME;
544 int64 frame = 0;
545 // dummy frame, will be ignored because of flags
546 status_t result = fExtractor->FindKeyFrame(fStream, flags, &frame, _time);
547 if (result != B_OK) {
548 ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n",
549 strerror(result));
552 return result;
556 status_t
557 BMediaTrack::FindKeyFrameForFrame(int64* _frame, int32 flags) const
559 CALLED();
561 if (fExtractor == NULL)
562 return B_NO_INIT;
564 if (_frame == NULL)
565 return B_BAD_VALUE;
567 // Make sure flags are valid
568 flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME;
570 bigtime_t time = 0;
571 // dummy time, will be ignored because of flags
572 status_t result = fExtractor->FindKeyFrame(fStream, flags, _frame, &time);
573 if (result != B_OK) {
574 ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n",
575 strerror(result));
578 return result;
582 status_t
583 BMediaTrack::ReadChunk(char** _buffer, int32* _size, media_header* _header)
585 CALLED();
587 if (fExtractor == NULL)
588 return B_NO_INIT;
590 if (_buffer == NULL || _size == NULL)
591 return B_BAD_VALUE;
593 media_header header;
594 if (_header == NULL)
595 _header = &header;
597 // Always clear the header first, as the extractor may not set all fields.
598 memset(_header, 0, sizeof(media_header));
600 const void* buffer;
601 size_t size;
602 status_t result = fExtractor->GetNextChunk(fStream, &buffer, &size,
603 _header);
605 if (result == B_OK) {
606 *_buffer = const_cast<char*>(static_cast<const char*>(buffer));
607 // TODO: Change the pointer type when we break the API.
608 *_size = size;
609 // TODO: This changes the meaning of fCurrentTime from pointing
610 // to the next chunk start time (i.e. after seeking) to the start time
611 // of the last chunk. Asking the extractor for the current time will
612 // not work so well because of the chunk cache. But providing a
613 // "duration" field in the media_header could be useful.
614 fCurrentTime = _header->start_time;
615 fCurrentFrame = (int64)(fCurrentTime * _FrameRate() / 1000000LL);
619 return result;
623 status_t
624 BMediaTrack::AddCopyright(const char* copyright)
626 if (fWriter == NULL)
627 return B_NO_INIT;
629 return fWriter->SetCopyright(fStream, copyright);
633 status_t
634 BMediaTrack::AddTrackInfo(uint32 code, const void* data, size_t size,
635 uint32 flags)
637 if (fWriter == NULL)
638 return B_NO_INIT;
640 return fWriter->AddTrackInfo(fStream, code, data, size, flags);
644 status_t
645 BMediaTrack::WriteFrames(const void* data, int32 frameCount, int32 flags)
647 media_encode_info encodeInfo;
648 encodeInfo.flags = flags;
650 return WriteFrames(data, frameCount, &encodeInfo);
654 status_t
655 BMediaTrack::WriteFrames(const void* data, int64 frameCount,
656 media_encode_info* info)
658 if (fEncoder == NULL)
659 return B_NO_INIT;
661 return fEncoder->Encode(data, frameCount, info);
665 status_t
666 BMediaTrack::WriteChunk(const void* data, size_t size, uint32 flags)
668 media_encode_info encodeInfo;
669 encodeInfo.flags = flags;
671 return WriteChunk(data, size, &encodeInfo);
675 status_t
676 BMediaTrack::WriteChunk(const void* data, size_t size, media_encode_info* info)
678 if (fWriter == NULL)
679 return B_NO_INIT;
681 return fWriter->WriteChunk(fStream, data, size, info);
685 status_t
686 BMediaTrack::Flush()
688 if (fWriter == NULL)
689 return B_NO_INIT;
691 return fWriter->Flush();
695 // deprecated BeOS R5 API
696 BParameterWeb*
697 BMediaTrack::Web()
699 BParameterWeb* web;
700 if (GetParameterWeb(&web) == B_OK)
701 return web;
703 return NULL;
707 status_t
708 BMediaTrack::GetParameterWeb(BParameterWeb** outWeb)
710 if (outWeb == NULL)
711 return B_BAD_VALUE;
713 if (fEncoder == NULL)
714 return B_NO_INIT;
716 // TODO: This method is new in Haiku. The header mentions it returns a
717 // copy. But how could it even do that? How can one clone a web and make
718 // it point to the same BControllable?
719 *outWeb = fEncoder->ParameterWeb();
720 if (*outWeb != NULL)
721 return B_OK;
723 return B_NOT_SUPPORTED;
727 status_t
728 BMediaTrack::GetParameterValue(int32 id, void* value, size_t* size)
730 if (value == NULL || size == NULL)
731 return B_BAD_VALUE;
733 if (fEncoder == NULL)
734 return B_NO_INIT;
736 return fEncoder->GetParameterValue(id, value, size);
740 status_t
741 BMediaTrack::SetParameterValue(int32 id, const void* value, size_t size)
743 if (value == NULL || size == 0)
744 return B_BAD_VALUE;
746 if (fEncoder == NULL)
747 return B_NO_INIT;
749 return fEncoder->SetParameterValue(id, value, size);
753 BView*
754 BMediaTrack::GetParameterView()
756 if (fEncoder == NULL)
757 return NULL;
759 return fEncoder->ParameterView();
763 status_t
764 BMediaTrack::GetQuality(float* quality)
766 if (quality == NULL)
767 return B_BAD_VALUE;
769 encode_parameters parameters;
770 status_t result = GetEncodeParameters(&parameters);
771 if (result != B_OK)
772 return result;
774 *quality = parameters.quality;
776 return B_OK;
780 status_t
781 BMediaTrack::SetQuality(float quality)
783 encode_parameters parameters;
784 status_t result = GetEncodeParameters(&parameters);
785 if (result != B_OK)
786 return result;
788 if (quality < 0.0f)
789 quality = 0.0f;
791 if (quality > 1.0f)
792 quality = 1.0f;
794 parameters.quality = quality;
796 return SetEncodeParameters(&parameters);
800 status_t
801 BMediaTrack::GetEncodeParameters(encode_parameters* parameters) const
803 if (parameters == NULL)
804 return B_BAD_VALUE;
806 if (fEncoder == NULL)
807 return B_NO_INIT;
809 return fEncoder->GetEncodeParameters(parameters);
813 status_t
814 BMediaTrack::SetEncodeParameters(encode_parameters* parameters)
816 if (parameters == NULL)
817 return B_BAD_VALUE;
819 if (fEncoder == NULL)
820 return B_NO_INIT;
822 return fEncoder->SetEncodeParameters(parameters);
826 status_t
827 BMediaTrack::Perform(int32 selector, void* data)
829 return B_OK;
832 // #pragma mark - private
835 BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor* extractor,
836 int32 stream)
838 CALLED();
840 fWorkaroundFlags = 0;
841 fDecoder = NULL;
842 fRawDecoder = NULL;
843 fExtractor = extractor;
844 fStream = stream;
845 fInitStatus = B_OK;
847 SetupWorkaround();
849 status_t ret = fExtractor->CreateDecoder(fStream, &fDecoder, &fCodecInfo);
850 if (ret != B_OK) {
851 TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: "
852 "%s\n", strerror(ret));
853 // We do not set fInitStatus here, because ReadChunk should still work.
854 fDecoder = NULL;
857 fCurrentFrame = 0;
858 fCurrentTime = 0;
860 // not used:
861 fEncoder = NULL;
862 fEncoderID = 0;
863 fWriter = NULL;
867 BMediaTrack::BMediaTrack(BPrivate::media::MediaWriter* writer,
868 int32 streamIndex, media_format* format,
869 const media_codec_info* codecInfo)
871 CALLED();
873 fWorkaroundFlags = 0;
874 fEncoder = NULL;
875 fEncoderID = -1;
876 // TODO: Not yet sure what this was needed for...
877 fWriter = writer;
878 fStream = streamIndex;
879 fInitStatus = B_OK;
881 SetupWorkaround();
883 if (codecInfo != NULL) {
884 status_t ret = fWriter->CreateEncoder(&fEncoder, codecInfo, format);
885 if (ret != B_OK) {
886 TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: "
887 "%s\n", strerror(ret));
888 // We do not set fInitStatus here, because WriteChunk should still
889 // work.
890 fEncoder = NULL;
891 } else {
892 fCodecInfo = *codecInfo;
893 fInitStatus = fEncoder->SetUp(format);
897 fFormat = *format;
899 // not used:
900 fCurrentFrame = 0;
901 fCurrentTime = 0;
902 fDecoder = NULL;
903 fRawDecoder = NULL;
904 fExtractor = NULL;
908 // Does nothing, returns B_ERROR, for Zeta compatiblity only
909 status_t
910 BMediaTrack::ControlCodec(int32 selector, void* io_data, size_t size)
912 return B_ERROR;
916 void
917 BMediaTrack::SetupWorkaround()
919 app_info ainfo;
920 thread_info tinfo;
922 get_thread_info(find_thread(0), &tinfo);
923 be_roster->GetRunningAppInfo(tinfo.team, &ainfo);
925 if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) {
926 fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT
927 | FORCE_RAW_AUDIO_HOST_ENDIAN;
928 printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n");
930 if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) {
931 fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO;
932 printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n");
935 #if CONVERT_TO_INT32
936 // TODO: Test
937 if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT))
938 fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT;
939 #endif
943 bool
944 BMediaTrack::SetupFormatTranslation(const media_format &from, media_format* to)
946 gPluginManager.DestroyDecoder(fRawDecoder);
947 fRawDecoder = NULL;
949 #ifdef TRACE_MEDIA_TRACK
950 char s[200];
951 string_for_format(from, s, sizeof(s));
952 printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s);
953 #endif
955 status_t result = gPluginManager.CreateDecoder(&fRawDecoder, from);
956 if (result != B_OK) {
957 ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n");
958 return false;
961 // XXX video?
962 int buffer_size = from.u.raw_audio.buffer_size;
963 int frame_size = (from.u.raw_audio.format & 15)
964 * from.u.raw_audio.channel_count;
965 media_format fromNotConst = from;
967 ChunkProvider* chunkProvider
968 = new (std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size,
969 frame_size);
970 if (chunkProvider == NULL) {
971 ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk "
972 "provider\n");
973 goto error;
975 fRawDecoder->SetChunkProvider(chunkProvider);
977 result = fRawDecoder->Setup(&fromNotConst, 0, 0);
978 if (result != B_OK) {
979 ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n");
980 goto error;
983 #ifdef TRACE_MEDIA_TRACK
984 string_for_format(*to, s, sizeof(s));
985 printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s);
986 #endif
988 result = fRawDecoder->NegotiateOutputFormat(to);
989 if (result != B_OK) {
990 ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat "
991 "failed\n");
992 goto error;
995 #ifdef TRACE_MEDIA_TRACK
996 string_for_format(*to, s, sizeof(s));
997 printf("BMediaTrack::SetupFormatTranslation: result: %s\n", s);
998 #endif
1000 return true;
1002 error:
1003 gPluginManager.DestroyDecoder(fRawDecoder);
1004 fRawDecoder = NULL;
1005 return false;
1009 double
1010 BMediaTrack::_FrameRate() const
1012 switch (fFormat.type) {
1013 case B_MEDIA_RAW_VIDEO:
1014 return fFormat.u.raw_video.field_rate;
1015 case B_MEDIA_ENCODED_VIDEO:
1016 return fFormat.u.encoded_video.output.field_rate;
1017 case B_MEDIA_RAW_AUDIO:
1018 return fFormat.u.raw_audio.frame_rate;
1019 case B_MEDIA_ENCODED_AUDIO:
1020 return fFormat.u.encoded_audio.output.frame_rate;
1021 default:
1022 return 1.0;
1026 #if 0
1027 // unimplemented
1028 BMediaTrack::BMediaTrack()
1029 BMediaTrack::BMediaTrack(const BMediaTrack &)
1030 BMediaTrack &BMediaTrack::operator=(const BMediaTrack &)
1031 #endif
1033 status_t BMediaTrack::_Reserved_BMediaTrack_0(int32 arg, ...) { return B_ERROR; }
1034 status_t BMediaTrack::_Reserved_BMediaTrack_1(int32 arg, ...) { return B_ERROR; }
1035 status_t BMediaTrack::_Reserved_BMediaTrack_2(int32 arg, ...) { return B_ERROR; }
1036 status_t BMediaTrack::_Reserved_BMediaTrack_3(int32 arg, ...) { return B_ERROR; }
1037 status_t BMediaTrack::_Reserved_BMediaTrack_4(int32 arg, ...) { return B_ERROR; }
1038 status_t BMediaTrack::_Reserved_BMediaTrack_5(int32 arg, ...) { return B_ERROR; }
1039 status_t BMediaTrack::_Reserved_BMediaTrack_6(int32 arg, ...) { return B_ERROR; }
1040 status_t BMediaTrack::_Reserved_BMediaTrack_7(int32 arg, ...) { return B_ERROR; }
1041 status_t BMediaTrack::_Reserved_BMediaTrack_8(int32 arg, ...) { return B_ERROR; }
1042 status_t BMediaTrack::_Reserved_BMediaTrack_9(int32 arg, ...) { return B_ERROR; }
1043 status_t BMediaTrack::_Reserved_BMediaTrack_10(int32 arg, ...) { return B_ERROR; }
1044 status_t BMediaTrack::_Reserved_BMediaTrack_11(int32 arg, ...) { return B_ERROR; }
1045 status_t BMediaTrack::_Reserved_BMediaTrack_12(int32 arg, ...) { return B_ERROR; }
1046 status_t BMediaTrack::_Reserved_BMediaTrack_13(int32 arg, ...) { return B_ERROR; }
1047 status_t BMediaTrack::_Reserved_BMediaTrack_14(int32 arg, ...) { return B_ERROR; }
1048 status_t BMediaTrack::_Reserved_BMediaTrack_15(int32 arg, ...) { return B_ERROR; }
1049 status_t BMediaTrack::_Reserved_BMediaTrack_16(int32 arg, ...) { return B_ERROR; }
1050 status_t BMediaTrack::_Reserved_BMediaTrack_17(int32 arg, ...) { return B_ERROR; }
1051 status_t BMediaTrack::_Reserved_BMediaTrack_18(int32 arg, ...) { return B_ERROR; }
1052 status_t BMediaTrack::_Reserved_BMediaTrack_19(int32 arg, ...) { return B_ERROR; }
1053 status_t BMediaTrack::_Reserved_BMediaTrack_20(int32 arg, ...) { return B_ERROR; }
1054 status_t BMediaTrack::_Reserved_BMediaTrack_21(int32 arg, ...) { return B_ERROR; }
1055 status_t BMediaTrack::_Reserved_BMediaTrack_22(int32 arg, ...) { return B_ERROR; }
1056 status_t BMediaTrack::_Reserved_BMediaTrack_23(int32 arg, ...) { return B_ERROR; }
1057 status_t BMediaTrack::_Reserved_BMediaTrack_24(int32 arg, ...) { return B_ERROR; }
1058 status_t BMediaTrack::_Reserved_BMediaTrack_25(int32 arg, ...) { return B_ERROR; }
1059 status_t BMediaTrack::_Reserved_BMediaTrack_26(int32 arg, ...) { return B_ERROR; }
1060 status_t BMediaTrack::_Reserved_BMediaTrack_27(int32 arg, ...) { return B_ERROR; }
1061 status_t BMediaTrack::_Reserved_BMediaTrack_28(int32 arg, ...) { return B_ERROR; }
1062 status_t BMediaTrack::_Reserved_BMediaTrack_29(int32 arg, ...) { return B_ERROR; }
1063 status_t BMediaTrack::_Reserved_BMediaTrack_30(int32 arg, ...) { return B_ERROR; }
1064 status_t BMediaTrack::_Reserved_BMediaTrack_31(int32 arg, ...) { return B_ERROR; }
1065 status_t BMediaTrack::_Reserved_BMediaTrack_32(int32 arg, ...) { return B_ERROR; }
1066 status_t BMediaTrack::_Reserved_BMediaTrack_33(int32 arg, ...) { return B_ERROR; }
1067 status_t BMediaTrack::_Reserved_BMediaTrack_34(int32 arg, ...) { return B_ERROR; }
1068 status_t BMediaTrack::_Reserved_BMediaTrack_35(int32 arg, ...) { return B_ERROR; }
1069 status_t BMediaTrack::_Reserved_BMediaTrack_36(int32 arg, ...) { return B_ERROR; }
1070 status_t BMediaTrack::_Reserved_BMediaTrack_37(int32 arg, ...) { return B_ERROR; }
1071 status_t BMediaTrack::_Reserved_BMediaTrack_38(int32 arg, ...) { return B_ERROR; }
1072 status_t BMediaTrack::_Reserved_BMediaTrack_39(int32 arg, ...) { return B_ERROR; }
1073 status_t BMediaTrack::_Reserved_BMediaTrack_40(int32 arg, ...) { return B_ERROR; }
1074 status_t BMediaTrack::_Reserved_BMediaTrack_41(int32 arg, ...) { return B_ERROR; }
1075 status_t BMediaTrack::_Reserved_BMediaTrack_42(int32 arg, ...) { return B_ERROR; }
1076 status_t BMediaTrack::_Reserved_BMediaTrack_43(int32 arg, ...) { return B_ERROR; }
1077 status_t BMediaTrack::_Reserved_BMediaTrack_44(int32 arg, ...) { return B_ERROR; }
1078 status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR; }
1079 status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; }
1080 status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; }
1083 RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder* decoder,
1084 int buffer_size, int frame_size)
1086 // printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n",
1087 // buffer_size, frame_size);
1088 fDecoder = decoder;
1089 fFrameSize = frame_size;
1090 fBufferSize = buffer_size;
1091 fBuffer = malloc(buffer_size);
1095 RawDecoderChunkProvider::~RawDecoderChunkProvider()
1097 free(fBuffer);
1101 status_t
1102 RawDecoderChunkProvider::GetNextChunk(const void** chunkBuffer,
1103 size_t* chunkSize, media_header* header)
1105 int64 frames;
1106 media_decode_info info;
1107 status_t result = fDecoder->Decode(fBuffer, &frames, header, &info);
1108 if (result == B_OK) {
1109 *chunkBuffer = fBuffer;
1110 *chunkSize = frames * fFrameSize;
1111 // printf("RawDecoderChunkProvider::GetNextChunk, %lld frames, "
1112 // "%ld bytes, start-time %lld\n", frames, *chunkSize,
1113 // header->start_time);
1114 } else
1115 ERROR("RawDecoderChunkProvider::GetNextChunk failed\n");
1117 return result;