• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <android/log.h>
17 
18 #include <oboe/Oboe.h>
19 
20 #include "OboeStream.h"
21 
22 static const char * const TAG = "OboeStream(native)";
23 static const bool LOG = true;
24 
25 using namespace oboe;
26 
OboeErrorToMegaAudioError(oboe::Result oboeError)27 StreamBase::Result OboeStream::OboeErrorToMegaAudioError(oboe::Result oboeError) {
28 
29     StreamBase::Result maErr = ERROR_UNKNOWN;
30 
31     switch (oboeError) {
32         case oboe::Result::OK:
33             maErr = OK;
34             break;
35         case oboe::Result::ErrorInternal:
36             maErr = ERROR_UNKNOWN;
37             break;
38         case oboe::Result::ErrorClosed:
39             maErr = ERROR_INVALID_STATE;
40             break;
41         default:
42             maErr = ERROR_UNKNOWN;
43             break;
44     }
45 
46     return maErr;
47 }
48 
startStream()49 StreamBase::Result OboeStream::startStream() {
50     if (LOG) {
51         __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()", this, __FUNCTION__);
52     }
53     // Don't cover up (potential) bugs in AAudio
54     oboe::OboeGlobals::setWorkaroundsEnabled(false);
55 
56     std::lock_guard<std::mutex> lock(mStreamLock);
57 
58     oboe::Result result = oboe::Result::ErrorInternal;
59     if (mAudioStream != nullptr) {
60         result = mAudioStream->requestStart();
61         if (result != oboe::Result::OK){
62             __android_log_print(
63                     ANDROID_LOG_ERROR,
64                     TAG,
65                     "requestStart failed. Error: %s", convertToText(result));
66         }
67     }
68     mStreamStarted = result == oboe::Result::OK;
69 
70     if (LOG) {
71         __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()  returns:%d",
72                             this, __FUNCTION__, OboeErrorToMegaAudioError(result));
73     }
74     return OboeErrorToMegaAudioError(result);
75 }
76 
closeStream()77 StreamBase::Result OboeStream::closeStream() {
78     // We might have gotten an error because the stream is already stopped,
79     // but we still want to try to close it to avoid a resource leak
80     if (LOG) {
81         __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s() mAudioStream:%p",
82                             this, __FUNCTION__, mAudioStream.get());
83     }
84 
85     oboe::Result result = oboe::Result::OK;
86     if (mAudioStream != nullptr) {
87         result = mAudioStream->close();
88     }
89 
90     return OboeErrorToMegaAudioError(result);
91 }
92 
stopStream()93 StreamBase::Result OboeStream::stopStream() {
94     if (LOG) {
95         __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s() mAudioStream:%p",
96                             this, __FUNCTION__, mAudioStream.get());
97     }
98 
99     std::lock_guard<std::mutex> lock(mStreamLock);
100 
101     Result errCode = ERROR_UNKNOWN;
102     if (mAudioStream == nullptr) {
103         errCode = ERROR_INVALID_STATE;
104     } else {
105         oboe::Result result = mAudioStream->stop();
106         mStreamStarted = false;
107 
108         errCode = OboeErrorToMegaAudioError(result);
109     }
110     return errCode;
111 }
112 
teardownStream()113 StreamBase::Result OboeStream::teardownStream() {
114     if (LOG) {
115         __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()", this, __FUNCTION__);
116     }
117     std::lock_guard<std::mutex> lock(mStreamLock);
118     return teardownStream_l();
119 }
120 
teardownStream_l()121 StreamBase::Result OboeStream::teardownStream_l() {
122     // tear down the stream for this player/recorder
123     if (LOG) {
124         __android_log_print(ANDROID_LOG_DEBUG, TAG, "[%p]::%s()", this, __FUNCTION__);
125     }
126 
127     if (mAudioStream == nullptr) {
128         return ERROR_INVALID_STATE;
129     } else {
130         oboe::Result resultStop = mAudioStream->stop();
131 
132         // We might have gotten an error because the stream is already stopped,
133         // but we still want to try to close it to avoid a resource leak
134         oboe::Result resultClose = mAudioStream->close();
135 
136         mAudioStream = nullptr;
137 
138         return OboeErrorToMegaAudioError(
139                 resultStop != oboe::Result::OK ? resultStop : resultClose);
140     }
141 }
142 
getTimeStamp(oboe::FrameTimestamp * timeStamp)143 StreamBase::Result OboeStream::getTimeStamp(oboe::FrameTimestamp* timeStamp) {
144     Result errCode = ERROR_UNKNOWN;
145     if (mAudioStream == nullptr) {
146         __android_log_print(ANDROID_LOG_ERROR, TAG, "ERROR_INVALID_STATE");
147         errCode = ERROR_INVALID_STATE;
148     } else {
149         ResultWithValue<oboe::FrameTimestamp> result = mAudioStream->getTimestamp(CLOCK_MONOTONIC);
150 
151         *timeStamp = result.value();
152 
153         errCode = OK;
154     }
155 
156     return errCode;
157 }
158 
getState() const159 oboe::StreamState OboeStream::getState() const {
160     return mAudioStream != nullptr ? mAudioStream->getState() : oboe::StreamState::Unknown;
161 }
162 
getLastErrorCallbackResult()163 int OboeStream::getLastErrorCallbackResult() {
164     return (int) (mAudioStream != nullptr
165                     ? (int) mAudioStream->getLastErrorCallbackResult() : StreamBase::ERROR_INVALID_STATE);
166 }
167 
getRoutedDeviceId()168 int32_t OboeStream::getRoutedDeviceId() {
169     return (int32_t) (mAudioStream != nullptr
170                                ? (int32_t) mAudioStream->getDeviceId()
171                                : ROUTING_DEVICE_NONE);
172 }
173 
getSharingMode()174 int32_t OboeStream::getSharingMode() {
175     return (int32_t) (mAudioStream != nullptr
176                                ? (int32_t) mAudioStream->getSharingMode()
177                                : SHARING_MODE_INVALID);
178 }
179 
getChannelCount()180 int32_t OboeStream::getChannelCount() {
181     return (int32_t) (mAudioStream != nullptr
182                                ? (int32_t) mAudioStream->getChannelCount()
183                                : -1);
184 }
185 
isMMap()186 bool OboeStream::isMMap() {
187     return OboeExtensions::isMMapUsed(mAudioStream.get());
188 }
189 
190