/* * Copyright 2002-2007, Marcus Overhagen * Copyright 2009-2010, Stephan Aßmus * Copyright 2013, Haiku, Inc. All Rights Reserved. * All rights reserved. Distributed under the terms of the MIT license. * * Authors: * Stephan Aßmus, superstippi@gmx.de * Marcus Overhagen, marcus@overhagen.de */ #include #include #include #include #include #include #include "MediaExtractor.h" #include "MediaWriter.h" #include "PluginManager.h" //#define TRACE_MEDIA_TRACK #ifdef TRACE_MEDIA_TRACK # ifndef TRACE # define TRACE printf # endif #else # ifndef TRACE # define TRACE(a...) # endif #endif #define ERROR(a...) fprintf(stderr, a) #define CONVERT_TO_INT32 0 // TODO: Test! This triggers a few bugs! // flags used for workarounds enum { FORCE_RAW_AUDIO = 0x0001, FORCE_RAW_VIDEO = 0x0002, FORCE_RAW_AUDIO_INT16_FORMAT = 0x0010, FORCE_RAW_AUDIO_INT32_FORMAT = 0x0020, FORCE_RAW_AUDIO_FLOAT_FORMAT = 0x0040, FORCE_RAW_AUDIO_HOST_ENDIAN = 0x0100, IGNORE_ENCODED_AUDIO = 0x1000, IGNORE_ENCODED_VIDEO = 0x2000, }; #define B_MEDIA_DISABLE_FORMAT_TRANSLATION 0x4000 // TODO: move this (after name change?) to MediaDefs.h class RawDecoderChunkProvider : public ChunkProvider { public: RawDecoderChunkProvider(Decoder* decoder, int buffer_size, int frame_size); virtual ~RawDecoderChunkProvider(); status_t GetNextChunk(const void** chunkBuffer, size_t* chunkSize, media_header* mediaHeader); private: Decoder* fDecoder; void* fBuffer; int fBufferSize; int fFrameSize; }; /************************************************************* * protected BMediaTrack *************************************************************/ BMediaTrack::~BMediaTrack() { CALLED(); gPluginManager.DestroyDecoder(fRawDecoder); gPluginManager.DestroyDecoder(fDecoder); gPluginManager.DestroyEncoder(fEncoder); } /************************************************************* * public BMediaTrack *************************************************************/ status_t BMediaTrack::InitCheck() const { CALLED(); return fInitStatus; } status_t BMediaTrack::GetCodecInfo(media_codec_info* _codecInfo) const { CALLED(); if (fDecoder == NULL) return B_NO_INIT; *_codecInfo = fCodecInfo; strlcpy(_codecInfo->pretty_name, fCodecInfo.pretty_name, sizeof(_codecInfo->pretty_name)); return B_OK; } status_t BMediaTrack::EncodedFormat(media_format* _format) const { CALLED(); if (_format == NULL) return B_BAD_VALUE; if (fExtractor == NULL) return B_NO_INIT; *_format = *fExtractor->EncodedFormat(fStream); #ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(*_format, s, sizeof(s)); printf("BMediaTrack::EncodedFormat: %s\n", s); #endif return B_OK; } // for BeOS R5 compatibility extern "C" status_t DecodedFormat__11BMediaTrackP12media_format( BMediaTrack* self, media_format* _format); status_t DecodedFormat__11BMediaTrackP12media_format(BMediaTrack* self, media_format* _format) { return self->DecodedFormat(_format, 0); } status_t BMediaTrack::DecodedFormat(media_format* _format, uint32 flags) { CALLED(); if (_format == NULL) return B_BAD_VALUE; if (fExtractor == NULL || fDecoder == NULL) return B_NO_INIT; gPluginManager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; #ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(*_format, s, sizeof(s)); printf("BMediaTrack::DecodedFormat: req1: %s\n", s); #endif if ((fWorkaroundFlags & FORCE_RAW_AUDIO) || ((fWorkaroundFlags & IGNORE_ENCODED_AUDIO) && _format->type == B_MEDIA_ENCODED_AUDIO)) { _format->type = B_MEDIA_RAW_AUDIO; _format->u.raw_audio = media_multi_audio_format::wildcard; } if ((fWorkaroundFlags & FORCE_RAW_VIDEO) || ((fWorkaroundFlags & IGNORE_ENCODED_VIDEO) && _format->type == B_MEDIA_ENCODED_VIDEO)) { _format->type = B_MEDIA_RAW_VIDEO; _format->u.raw_video = media_raw_video_format::wildcard; } if (_format->type == B_MEDIA_RAW_AUDIO) { if (fWorkaroundFlags & FORCE_RAW_AUDIO_HOST_ENDIAN) _format->u.raw_audio.byte_order = B_MEDIA_HOST_ENDIAN; if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT) { _format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_SHORT; } if (fWorkaroundFlags & FORCE_RAW_AUDIO_INT32_FORMAT) { _format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_INT; } if (fWorkaroundFlags & FORCE_RAW_AUDIO_FLOAT_FORMAT) { _format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; } } #ifdef TRACE_MEDIA_TRACK string_for_format(*_format, s, sizeof(s)); printf("BMediaTrack::DecodedFormat: req2: %s\n", s); #endif fFormat = *_format; status_t result = fDecoder->NegotiateOutputFormat(_format); #ifdef TRACE_MEDIA_TRACK string_for_format(*_format, s, sizeof(s)); printf("BMediaTrack::DecodedFormat: nego: %s\n", s); #endif if (_format->type == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set output format " "type.\n"); #endif } if (_format->type == B_MEDIA_RAW_AUDIO) { if (_format->u.raw_audio.byte_order == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw audio " "output byte order.\n"); #endif } if (_format->u.raw_audio.format == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw audio " "output sample format.\n"); #endif } if (_format->u.raw_audio.buffer_size <= 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw audio " "output buffer size.\n"); #endif } } if (_format->type == B_MEDIA_RAW_VIDEO) { if (_format->u.raw_video.display.format == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video " "output color space.\n"); #endif } if (_format->u.raw_video.display.line_width == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video " "output line_width.\n"); #endif } if (_format->u.raw_video.display.line_count == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video " "output line_count.\n"); #endif } if (_format->u.raw_video.display.bytes_per_row == 0) { #ifdef TRACE_MEDIA_TRACK printf("BMediaTrack::DecodedFormat: Decoder didn't set raw video " "output bytes_per_row.\n"); #endif } } if ((flags & B_MEDIA_DISABLE_FORMAT_TRANSLATION) == 0) { if (fFormat.type == B_MEDIA_RAW_AUDIO && _format->type == B_MEDIA_RAW_AUDIO && fFormat.u.raw_audio.format != 0 && fFormat.u.raw_audio.format != _format->u.raw_audio.format) { if (SetupFormatTranslation(*_format, &fFormat)) *_format = fFormat; } } fFormat = *_format; // string_for_format(*_format, s, sizeof(s)); // printf("BMediaTrack::DecodedFormat: status: %s\n", s); return result; } status_t BMediaTrack::GetMetaData(BMessage* _data) const { CALLED(); if (fExtractor == NULL) return B_NO_INIT; if (_data == NULL) return B_BAD_VALUE; _data->MakeEmpty(); return fExtractor->GetStreamMetaData(fStream, _data); } int64 BMediaTrack::CountFrames() const { CALLED(); int64 frames = fExtractor ? fExtractor->CountFrames(fStream) : 0; // printf("BMediaTrack::CountFrames: %lld\n", frames); return frames; } bigtime_t BMediaTrack::Duration() const { CALLED(); bigtime_t duration = fExtractor ? fExtractor->Duration(fStream) : 0; // printf("BMediaTrack::Duration: %lld\n", duration); return duration; } int64 BMediaTrack::CurrentFrame() const { return fCurrentFrame; } bigtime_t BMediaTrack::CurrentTime() const { return fCurrentTime; } // BMediaTrack::ReadFrames(char*, long long*, media_header*) // Compatibility for R5 and below. Required by Corum III and Civ:CTP. #if __GNUC__ < 3 extern "C" status_t ReadFrames__11BMediaTrackPcPxP12media_header(BMediaTrack* self, char* _buffer, int64* _frameCount, media_header* header) { return self->ReadFrames(_buffer, _frameCount, header, 0); } #endif // __GNUC__ < 3 status_t BMediaTrack::ReadFrames(void* buffer, int64* _frameCount, media_header* header) { return ReadFrames(buffer, _frameCount, header, NULL); } status_t BMediaTrack::ReadFrames(void* buffer, int64* _frameCount, media_header* _header, media_decode_info* info) { // CALLED(); if (fDecoder == NULL) return B_NO_INIT; if (buffer == NULL || _frameCount == NULL) return B_BAD_VALUE; media_header header; if (_header == NULL) _header = &header; // Always clear the header first, as the decoder may not set all fields. memset(_header, 0, sizeof(media_header)); status_t result = fRawDecoder != NULL ? fRawDecoder->Decode(buffer, _frameCount, _header, info) : fDecoder->Decode(buffer, _frameCount, _header, info); if (result == B_OK) { fCurrentFrame += *_frameCount; bigtime_t framesDuration = (bigtime_t)(*_frameCount * 1000000 / _FrameRate()); fCurrentTime = _header->start_time + framesDuration; #if 0 // This debug output shows drift between calculated fCurrentFrame and // time-based current frame, if there is any. if (fFormat.type == B_MEDIA_RAW_AUDIO) { printf("current frame: %lld / calculated: %lld (%.2f/%.2f)\r", fCurrentFrame, int64(fCurrentTime * _FrameRate() / 1000000.0 + 0.5), fCurrentTime / 1000000.0, (float)fCurrentFrame / _FrameRate()); fflush(stdout); } #endif } else { ERROR("BMediaTrack::ReadFrames: decoder returned error %#" B_PRIx32 " (%s)\n", result, strerror(result)); *_frameCount = 0; } #if 0 PRINT(1, "BMediaTrack::ReadFrames: stream %ld, start-time %5Ld.%06Ld, " "%lld frames\n", fStream, _header->start_time / 1000000, _header->start_time % 1000000, *out_frameCount); #endif return result; } status_t BMediaTrack::ReplaceFrames(const void* inBuffer, int64* _frameCount, const media_header* header) { UNIMPLEMENTED(); // TODO: Actually, a file is either open for reading or writing at the // moment. Since the chunk size of encoded media data will change, // implementing this call will only be possible for raw media tracks. return B_NOT_SUPPORTED; } status_t BMediaTrack::SeekToTime(bigtime_t* _time, int32 flags) { CALLED(); if (fDecoder == NULL || fExtractor == NULL) return B_NO_INIT; if (_time == NULL) return B_BAD_VALUE; // Make sure flags are valid flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME; #if DEBUG bigtime_t requestedTime = *_time; #endif int64 frame = 0; status_t result = fExtractor->Seek(fStream, flags, &frame, _time); if (result != B_OK) { ERROR("BMediaTrack::SeekToTime: extractor seek failed\n"); return result; } result = fDecoder->SeekedTo(frame, *_time); if (result != B_OK) { ERROR("BMediaTrack::SeekToTime: decoder seek failed\n"); return result; } if (fRawDecoder != NULL) { result = fRawDecoder->SeekedTo(frame, *_time); if (result != B_OK) { ERROR("BMediaTrack::SeekToTime: raw decoder seek failed\n"); return result; } } fCurrentFrame = frame; fCurrentTime = *_time; PRINT(1, "BMediaTrack::SeekToTime finished, requested %.6f, result %.6f\n", requestedTime / 1000000.0, *_time / 1000000.0); return B_OK; } status_t BMediaTrack::SeekToFrame(int64* _frame, int32 flags) { CALLED(); if (fDecoder == NULL || fExtractor == NULL) return B_NO_INIT; if (_frame == NULL) return B_BAD_VALUE; // Make sure flags are valid flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME; #if DEBUG int64 requestedFrame = *_frame; #endif bigtime_t time = 0; status_t result = fExtractor->Seek(fStream, flags, _frame, &time); if (result != B_OK) { ERROR("BMediaTrack::SeekToFrame: extractor seek failed\n"); return result; } result = fDecoder->SeekedTo(*_frame, time); if (result != B_OK) { ERROR("BMediaTrack::SeekToFrame: decoder seek failed\n"); return result; } if (fRawDecoder != NULL) { result = fRawDecoder->SeekedTo(*_frame, time); if (result != B_OK) { ERROR("BMediaTrack::SeekToFrame: raw decoder seek failed\n"); return result; } } fCurrentFrame = *_frame; fCurrentTime = time; PRINT(1, "BMediaTrack::SeekToTime SeekToFrame, requested %lld, " "result %lld\n", requestedFrame, *_frame); return B_OK; } status_t BMediaTrack::FindKeyFrameForTime(bigtime_t* _time, int32 flags) const { CALLED(); if (fExtractor == NULL) return B_NO_INIT; if (_time == NULL) return B_BAD_VALUE; // Make sure flags are valid flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_TIME; int64 frame = 0; // dummy frame, will be ignored because of flags status_t result = fExtractor->FindKeyFrame(fStream, flags, &frame, _time); if (result != B_OK) { ERROR("BMediaTrack::FindKeyFrameForTime: extractor seek failed: %s\n", strerror(result)); } return result; } status_t BMediaTrack::FindKeyFrameForFrame(int64* _frame, int32 flags) const { CALLED(); if (fExtractor == NULL) return B_NO_INIT; if (_frame == NULL) return B_BAD_VALUE; // Make sure flags are valid flags = (flags & B_MEDIA_SEEK_DIRECTION_MASK) | B_MEDIA_SEEK_TO_FRAME; bigtime_t time = 0; // dummy time, will be ignored because of flags status_t result = fExtractor->FindKeyFrame(fStream, flags, _frame, &time); if (result != B_OK) { ERROR("BMediaTrack::FindKeyFrameForFrame: extractor seek failed: %s\n", strerror(result)); } return result; } status_t BMediaTrack::ReadChunk(char** _buffer, int32* _size, media_header* _header) { CALLED(); if (fExtractor == NULL) return B_NO_INIT; if (_buffer == NULL || _size == NULL) return B_BAD_VALUE; media_header header; if (_header == NULL) _header = &header; // Always clear the header first, as the extractor may not set all fields. memset(_header, 0, sizeof(media_header)); const void* buffer; size_t size; status_t result = fExtractor->GetNextChunk(fStream, &buffer, &size, _header); if (result == B_OK) { *_buffer = const_cast(static_cast(buffer)); // TODO: Change the pointer type when we break the API. *_size = size; // TODO: This changes the meaning of fCurrentTime from pointing // to the next chunk start time (i.e. after seeking) to the start time // of the last chunk. Asking the extractor for the current time will // not work so well because of the chunk cache. But providing a // "duration" field in the media_header could be useful. fCurrentTime = _header->start_time; fCurrentFrame = (int64)(fCurrentTime * _FrameRate() / 1000000LL); } return result; } status_t BMediaTrack::AddCopyright(const char* copyright) { if (fWriter == NULL) return B_NO_INIT; return fWriter->SetCopyright(fStream, copyright); } status_t BMediaTrack::AddTrackInfo(uint32 code, const void* data, size_t size, uint32 flags) { if (fWriter == NULL) return B_NO_INIT; return fWriter->AddTrackInfo(fStream, code, data, size, flags); } status_t BMediaTrack::WriteFrames(const void* data, int32 frameCount, int32 flags) { media_encode_info encodeInfo; encodeInfo.flags = flags; return WriteFrames(data, frameCount, &encodeInfo); } status_t BMediaTrack::WriteFrames(const void* data, int64 frameCount, media_encode_info* info) { if (fEncoder == NULL) return B_NO_INIT; return fEncoder->Encode(data, frameCount, info); } status_t BMediaTrack::WriteChunk(const void* data, size_t size, uint32 flags) { media_encode_info encodeInfo; encodeInfo.flags = flags; return WriteChunk(data, size, &encodeInfo); } status_t BMediaTrack::WriteChunk(const void* data, size_t size, media_encode_info* info) { if (fWriter == NULL) return B_NO_INIT; return fWriter->WriteChunk(fStream, data, size, info); } status_t BMediaTrack::Flush() { if (fWriter == NULL) return B_NO_INIT; return fWriter->Flush(); } // deprecated BeOS R5 API BParameterWeb* BMediaTrack::Web() { BParameterWeb* web; if (GetParameterWeb(&web) == B_OK) return web; return NULL; } status_t BMediaTrack::GetParameterWeb(BParameterWeb** outWeb) { if (outWeb == NULL) return B_BAD_VALUE; if (fEncoder == NULL) return B_NO_INIT; // TODO: This method is new in Haiku. The header mentions it returns a // copy. But how could it even do that? How can one clone a web and make // it point to the same BControllable? *outWeb = fEncoder->ParameterWeb(); if (*outWeb != NULL) return B_OK; return B_NOT_SUPPORTED; } status_t BMediaTrack::GetParameterValue(int32 id, void* value, size_t* size) { if (value == NULL || size == NULL) return B_BAD_VALUE; if (fEncoder == NULL) return B_NO_INIT; return fEncoder->GetParameterValue(id, value, size); } status_t BMediaTrack::SetParameterValue(int32 id, const void* value, size_t size) { if (value == NULL || size == 0) return B_BAD_VALUE; if (fEncoder == NULL) return B_NO_INIT; return fEncoder->SetParameterValue(id, value, size); } BView* BMediaTrack::GetParameterView() { if (fEncoder == NULL) return NULL; return fEncoder->ParameterView(); } status_t BMediaTrack::GetQuality(float* quality) { if (quality == NULL) return B_BAD_VALUE; encode_parameters parameters; status_t result = GetEncodeParameters(¶meters); if (result != B_OK) return result; *quality = parameters.quality; return B_OK; } status_t BMediaTrack::SetQuality(float quality) { encode_parameters parameters; status_t result = GetEncodeParameters(¶meters); if (result != B_OK) return result; if (quality < 0.0f) quality = 0.0f; if (quality > 1.0f) quality = 1.0f; parameters.quality = quality; return SetEncodeParameters(¶meters); } status_t BMediaTrack::GetEncodeParameters(encode_parameters* parameters) const { if (parameters == NULL) return B_BAD_VALUE; if (fEncoder == NULL) return B_NO_INIT; return fEncoder->GetEncodeParameters(parameters); } status_t BMediaTrack::SetEncodeParameters(encode_parameters* parameters) { if (parameters == NULL) return B_BAD_VALUE; if (fEncoder == NULL) return B_NO_INIT; return fEncoder->SetEncodeParameters(parameters); } status_t BMediaTrack::Perform(int32 selector, void* data) { return B_OK; } // #pragma mark - private BMediaTrack::BMediaTrack(BPrivate::media::MediaExtractor* extractor, int32 stream) { CALLED(); fWorkaroundFlags = 0; fDecoder = NULL; fRawDecoder = NULL; fExtractor = extractor; fStream = stream; fInitStatus = B_OK; SetupWorkaround(); status_t ret = fExtractor->CreateDecoder(fStream, &fDecoder, &fCodecInfo); if (ret != B_OK) { TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: " "%s\n", strerror(ret)); // We do not set fInitStatus here, because ReadChunk should still work. fDecoder = NULL; } fCurrentFrame = 0; fCurrentTime = 0; // not used: fEncoder = NULL; fEncoderID = 0; fWriter = NULL; } BMediaTrack::BMediaTrack(BPrivate::media::MediaWriter* writer, int32 streamIndex, media_format* format, const media_codec_info* codecInfo) { CALLED(); fWorkaroundFlags = 0; fEncoder = NULL; fEncoderID = -1; // TODO: Not yet sure what this was needed for... fWriter = writer; fStream = streamIndex; fInitStatus = B_OK; SetupWorkaround(); if (codecInfo != NULL) { status_t ret = fWriter->CreateEncoder(&fEncoder, codecInfo, format); if (ret != B_OK) { TRACE("BMediaTrack::BMediaTrack: Error: creating decoder failed: " "%s\n", strerror(ret)); // We do not set fInitStatus here, because WriteChunk should still // work. fEncoder = NULL; } else { fCodecInfo = *codecInfo; fInitStatus = fEncoder->SetUp(format); } } fFormat = *format; // not used: fCurrentFrame = 0; fCurrentTime = 0; fDecoder = NULL; fRawDecoder = NULL; fExtractor = NULL; } // Does nothing, returns B_ERROR, for Zeta compatiblity only status_t BMediaTrack::ControlCodec(int32 selector, void* io_data, size_t size) { return B_ERROR; } void BMediaTrack::SetupWorkaround() { app_info ainfo; thread_info tinfo; get_thread_info(find_thread(0), &tinfo); be_roster->GetRunningAppInfo(tinfo.team, &ainfo); if (strcmp(ainfo.signature, "application/x-vnd.marcone-soundplay") == 0) { fWorkaroundFlags = FORCE_RAW_AUDIO | FORCE_RAW_AUDIO_INT16_FORMAT | FORCE_RAW_AUDIO_HOST_ENDIAN; printf("BMediaTrack::SetupWorkaround: SoundPlay workaround active\n"); } if (strcmp(ainfo.signature, "application/x-vnd.Be.MediaPlayer") == 0) { fWorkaroundFlags = IGNORE_ENCODED_AUDIO | IGNORE_ENCODED_VIDEO; printf("BMediaTrack::SetupWorkaround: MediaPlayer workaround active\n"); } #if CONVERT_TO_INT32 // TODO: Test if (!(fWorkaroundFlags & FORCE_RAW_AUDIO_INT16_FORMAT)) fWorkaroundFlags |= FORCE_RAW_AUDIO_INT32_FORMAT; #endif } bool BMediaTrack::SetupFormatTranslation(const media_format &from, media_format* to) { gPluginManager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; #ifdef TRACE_MEDIA_TRACK char s[200]; string_for_format(from, s, sizeof(s)); printf("BMediaTrack::SetupFormatTranslation: from: %s\n", s); #endif status_t result = gPluginManager.CreateDecoder(&fRawDecoder, from); if (result != B_OK) { ERROR("BMediaTrack::SetupFormatTranslation: CreateDecoder failed\n"); return false; } // XXX video? int buffer_size = from.u.raw_audio.buffer_size; int frame_size = (from.u.raw_audio.format & 15) * from.u.raw_audio.channel_count; media_format fromNotConst = from; ChunkProvider* chunkProvider = new (std::nothrow) RawDecoderChunkProvider(fDecoder, buffer_size, frame_size); if (chunkProvider == NULL) { ERROR("BMediaTrack::SetupFormatTranslation: can't create chunk " "provider\n"); goto error; } fRawDecoder->SetChunkProvider(chunkProvider); result = fRawDecoder->Setup(&fromNotConst, 0, 0); if (result != B_OK) { ERROR("BMediaTrack::SetupFormatTranslation: Setup failed\n"); goto error; } #ifdef TRACE_MEDIA_TRACK string_for_format(*to, s, sizeof(s)); printf("BMediaTrack::SetupFormatTranslation: to: %s\n", s); #endif result = fRawDecoder->NegotiateOutputFormat(to); if (result != B_OK) { ERROR("BMediaTrack::SetupFormatTranslation: NegotiateOutputFormat " "failed\n"); goto error; } #ifdef TRACE_MEDIA_TRACK string_for_format(*to, s, sizeof(s)); printf("BMediaTrack::SetupFormatTranslation: result: %s\n", s); #endif return true; error: gPluginManager.DestroyDecoder(fRawDecoder); fRawDecoder = NULL; return false; } double BMediaTrack::_FrameRate() const { switch (fFormat.type) { case B_MEDIA_RAW_VIDEO: return fFormat.u.raw_video.field_rate; case B_MEDIA_ENCODED_VIDEO: return fFormat.u.encoded_video.output.field_rate; case B_MEDIA_RAW_AUDIO: return fFormat.u.raw_audio.frame_rate; case B_MEDIA_ENCODED_AUDIO: return fFormat.u.encoded_audio.output.frame_rate; default: return 1.0; } } #if 0 // unimplemented BMediaTrack::BMediaTrack() BMediaTrack::BMediaTrack(const BMediaTrack &) BMediaTrack &BMediaTrack::operator=(const BMediaTrack &) #endif status_t BMediaTrack::_Reserved_BMediaTrack_0(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_1(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_2(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_3(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_4(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_5(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_6(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_7(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_8(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_9(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_10(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_11(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_12(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_13(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_14(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_15(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_16(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_17(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_18(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_19(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_20(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_21(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_22(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_23(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_24(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_25(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_26(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_27(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_28(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_29(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_30(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_31(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_32(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_33(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_34(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_35(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_36(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_37(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_38(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_39(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_40(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_41(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_42(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_43(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_44(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_45(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_46(int32 arg, ...) { return B_ERROR; } status_t BMediaTrack::_Reserved_BMediaTrack_47(int32 arg, ...) { return B_ERROR; } RawDecoderChunkProvider::RawDecoderChunkProvider(Decoder* decoder, int buffer_size, int frame_size) { // printf("RawDecoderChunkProvider: buffer_size %d, frame_size %d\n", // buffer_size, frame_size); fDecoder = decoder; fFrameSize = frame_size; fBufferSize = buffer_size; fBuffer = malloc(buffer_size); } RawDecoderChunkProvider::~RawDecoderChunkProvider() { free(fBuffer); } status_t RawDecoderChunkProvider::GetNextChunk(const void** chunkBuffer, size_t* chunkSize, media_header* header) { int64 frames; media_decode_info info; status_t result = fDecoder->Decode(fBuffer, &frames, header, &info); if (result == B_OK) { *chunkBuffer = fBuffer; *chunkSize = frames * fFrameSize; // printf("RawDecoderChunkProvider::GetNextChunk, %lld frames, " // "%ld bytes, start-time %lld\n", frames, *chunkSize, // header->start_time); } else ERROR("RawDecoderChunkProvider::GetNextChunk failed\n"); return result; }