/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "OboeStream.h" static const char * const TAG = "OboeStream(native)"; static const bool LOG = true; using namespace oboe; StreamBase::Result OboeStream::OboeErrorToMegaAudioError(oboe::Result oboeError) { StreamBase::Result maErr = ERROR_UNKNOWN; switch (oboeError) { case oboe::Result::OK: maErr = OK; break; case oboe::Result::ErrorInternal: maErr = ERROR_UNKNOWN; break; case oboe::Result::ErrorClosed: maErr = ERROR_INVALID_STATE; break; default: maErr = ERROR_UNKNOWN; break; } return maErr; } StreamBase::Result OboeStream::startStream() { if (LOG) { __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()", this, __FUNCTION__); } // Don't cover up (potential) bugs in AAudio oboe::OboeGlobals::setWorkaroundsEnabled(false); std::lock_guard lock(mStreamLock); oboe::Result result = oboe::Result::ErrorInternal; if (mAudioStream != nullptr) { result = mAudioStream->requestStart(); if (result != oboe::Result::OK){ __android_log_print( ANDROID_LOG_ERROR, TAG, "requestStart failed. Error: %s", convertToText(result)); } } mStreamStarted = result == oboe::Result::OK; if (LOG) { __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s() returns:%d", this, __FUNCTION__, OboeErrorToMegaAudioError(result)); } return OboeErrorToMegaAudioError(result); } StreamBase::Result OboeStream::closeStream() { // We might have gotten an error because the stream is already stopped, // but we still want to try to close it to avoid a resource leak if (LOG) { __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s() mAudioStream:%p", this, __FUNCTION__, mAudioStream.get()); } oboe::Result result = oboe::Result::OK; if (mAudioStream != nullptr) { result = mAudioStream->close(); } return OboeErrorToMegaAudioError(result); } StreamBase::Result OboeStream::stopStream() { if (LOG) { __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s() mAudioStream:%p", this, __FUNCTION__, mAudioStream.get()); } std::lock_guard lock(mStreamLock); Result errCode = ERROR_UNKNOWN; if (mAudioStream == nullptr) { errCode = ERROR_INVALID_STATE; } else { oboe::Result result = mAudioStream->stop(); mStreamStarted = false; errCode = OboeErrorToMegaAudioError(result); } return errCode; } StreamBase::Result OboeStream::teardownStream() { if (LOG) { __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()", this, __FUNCTION__); } std::lock_guard lock(mStreamLock); return teardownStream_l(); } StreamBase::Result OboeStream::teardownStream_l() { // tear down the stream for this player/recorder if (LOG) { __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()", this, __FUNCTION__); } if (mAudioStream == nullptr) { return ERROR_INVALID_STATE; } else { oboe::Result resultStop = mAudioStream->stop(); // We might have gotten an error because the stream is already stopped, // but we still want to try to close it to avoid a resource leak oboe::Result resultClose = mAudioStream->close(); mAudioStream = nullptr; return OboeErrorToMegaAudioError( resultStop != oboe::Result::OK ? resultStop : resultClose); } } StreamBase::Result OboeStream::getTimeStamp(oboe::FrameTimestamp* timeStamp) { Result errCode = ERROR_UNKNOWN; if (mAudioStream == nullptr) { __android_log_print(ANDROID_LOG_ERROR, TAG, "ERROR_INVALID_STATE"); errCode = ERROR_INVALID_STATE; } else { ResultWithValue result = mAudioStream->getTimestamp(CLOCK_MONOTONIC); *timeStamp = result.value(); errCode = OK; } return errCode; } oboe::StreamState OboeStream::getState() const { return mAudioStream != nullptr ? mAudioStream->getState() : oboe::StreamState::Unknown; } int OboeStream::getLastErrorCallbackResult() { return (int) (mAudioStream != nullptr ? (int) mAudioStream->getLastErrorCallbackResult() : StreamBase::ERROR_INVALID_STATE); } int32_t OboeStream::getRoutedDeviceId() { return (int32_t) (mAudioStream != nullptr ? (int32_t) mAudioStream->getDeviceId() : ROUTING_DEVICE_NONE); } int32_t OboeStream::getSharingMode() { return (int32_t) (mAudioStream != nullptr ? (int32_t) mAudioStream->getSharingMode() : SHARING_MODE_INVALID); } int32_t OboeStream::getChannelCount() { return (int32_t) (mAudioStream != nullptr ? (int32_t) mAudioStream->getChannelCount() : -1); } bool OboeStream::isMMap() { return OboeExtensions::isMMapUsed(mAudioStream.get()); }