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
24 using namespace oboe;
25
OboeErrorToMegaAudioError(oboe::Result oboeError)26 StreamBase::Result OboeStream::OboeErrorToMegaAudioError(oboe::Result oboeError) {
27
28 StreamBase::Result maErr = ERROR_UNKNOWN;
29
30 switch (oboeError) {
31 case oboe::Result::OK:
32 maErr = OK;
33 break;
34 case oboe::Result::ErrorInternal:
35 maErr = ERROR_UNKNOWN;
36 break;
37 case oboe::Result::ErrorClosed:
38 maErr = ERROR_INVALID_STATE;
39 break;
40 default:
41 maErr = ERROR_UNKNOWN;
42 break;
43 }
44
45 return maErr;
46 }
47
teardownStream()48 StreamBase::Result OboeStream::teardownStream() {
49 __android_log_print(ANDROID_LOG_INFO, TAG, "teardownStream()");
50
51 std::lock_guard<std::mutex> lock(mStreamLock);
52 return teardownStream_l();
53 }
54
teardownStream_l()55 StreamBase::Result OboeStream::teardownStream_l() {
56 // tear down the player
57 if (mAudioStream == nullptr) {
58 return ERROR_INVALID_STATE;
59 } else {
60 oboe::Result result = oboe::Result::OK;
61 result = mAudioStream->stop();
62 if (result == oboe::Result::OK) {
63 result = mAudioStream->close();
64 }
65 mAudioStream = nullptr;
66 return OboeErrorToMegaAudioError(result);
67 }
68 }
69
startStream()70 StreamBase::Result OboeStream::startStream() {
71 __android_log_print(ANDROID_LOG_INFO, TAG, "startStream()");
72
73 // Don't cover up (potential) bugs in AAudio
74 oboe::OboeGlobals::setWorkaroundsEnabled(false);
75
76 std::lock_guard<std::mutex> lock(mStreamLock);
77
78 oboe::Result result = oboe::Result::ErrorInternal;
79 if (mAudioStream != nullptr) {
80 result = mAudioStream->requestStart();
81 if (result != oboe::Result::OK){
82 __android_log_print(
83 ANDROID_LOG_ERROR,
84 TAG,
85 "requestStart failed. Error: %s", convertToText(result));
86
87 // clean up
88 teardownStream_l();
89 }
90 }
91 mStreamStarted = result == oboe::Result::OK;
92
93 return OboeErrorToMegaAudioError(result);
94 }
95
stopStream()96 StreamBase::Result OboeStream::stopStream() {
97 std::lock_guard<std::mutex> lock(mStreamLock);
98
99 Result errCode = ERROR_UNKNOWN;
100 if (mAudioStream == nullptr) {
101 errCode = ERROR_INVALID_STATE;
102 } else {
103 oboe::Result result = mAudioStream->stop();
104 mStreamStarted = false;
105
106 errCode = OboeErrorToMegaAudioError(result);
107 }
108
109 mStreamStarted = false;
110 return errCode;
111 }
112
getTimeStamp(oboe::FrameTimestamp * timeStamp)113 StreamBase::Result OboeStream::getTimeStamp(oboe::FrameTimestamp* timeStamp) {
114 __android_log_print(ANDROID_LOG_INFO, TAG, "getTimeStamp()");
115 Result errCode = ERROR_UNKNOWN;
116 if (mAudioStream == nullptr) {
117 __android_log_print(ANDROID_LOG_INFO, TAG, "ERROR_INVALID_STATE");
118 errCode = ERROR_INVALID_STATE;
119 } else {
120 ResultWithValue<oboe::FrameTimestamp> result = mAudioStream->getTimestamp(CLOCK_MONOTONIC);
121
122 *timeStamp = result.value();
123
124 errCode = OK;
125 }
126
127 return errCode;
128 }
129