blob: 4de92ad13f80e607cada03aa0344f2a26e504ff4 [file] [log] [blame]
Wei Jiaec044b02018-02-19 12:41:23 -08001/*
2**
3** Copyright 2018, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "MediaPlayer2AudioOutput"
20#include <mediaplayer2/MediaPlayer2AudioOutput.h>
21
22#include <cutils/properties.h> // for property_get
23#include <utils/Log.h>
24
Wei Jiaec044b02018-02-19 12:41:23 -080025#include <media/stagefright/foundation/ADebug.h>
26
27namespace {
28
29const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
30
31} // anonymous namespace
32
33namespace android {
34
35// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
36/* static */ int MediaPlayer2AudioOutput::mMinBufferCount = 4;
37/* static */ bool MediaPlayer2AudioOutput::mIsOnEmulator = false;
38
39status_t MediaPlayer2AudioOutput::dump(int fd, const Vector<String16>& args) const {
40 const size_t SIZE = 256;
41 char buffer[SIZE];
42 String8 result;
43
44 result.append(" MediaPlayer2AudioOutput\n");
Dichen Zhangf8726912018-10-17 13:31:26 -070045 snprintf(buffer, 255, " volume(%f)\n", mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -080046 result.append(buffer);
47 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Dichen Zhangf8726912018-10-17 13:31:26 -070048 mMsecsPerFrame, (mJAudioTrack != nullptr) ? mJAudioTrack->latency() : -1);
Wei Jiaec044b02018-02-19 12:41:23 -080049 result.append(buffer);
50 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
51 mAuxEffectId, mSendLevel);
52 result.append(buffer);
53
54 ::write(fd, result.string(), result.size());
Dichen Zhangf8726912018-10-17 13:31:26 -070055 if (mJAudioTrack != nullptr) {
56 mJAudioTrack->dump(fd, args);
Wei Jiaec044b02018-02-19 12:41:23 -080057 }
58 return NO_ERROR;
59}
60
Dichen Zhang23658642018-11-15 10:26:16 -080061MediaPlayer2AudioOutput::MediaPlayer2AudioOutput(int32_t sessionId, uid_t uid, int pid,
Dichen Zhanga60eaa82018-11-13 17:14:34 +000062 const jobject attributes)
Dichen Zhangf8726912018-10-17 13:31:26 -070063 : mCallback(nullptr),
64 mCallbackCookie(nullptr),
65 mCallbackData(nullptr),
Dichen Zhang7398ca02018-10-15 10:25:12 -070066 mVolume(1.0),
Wei Jiaec044b02018-02-19 12:41:23 -080067 mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
68 mSampleRateHz(0),
69 mMsecsPerFrame(0),
70 mFrameSize(0),
71 mSessionId(sessionId),
72 mUid(uid),
73 mPid(pid),
74 mSendLevel(0.0),
75 mAuxEffectId(0),
Dongwon Kang0d7042d2018-10-12 16:52:14 -070076 mFlags(AUDIO_OUTPUT_FLAG_NONE) {
Wei Jiaec044b02018-02-19 12:41:23 -080077 ALOGV("MediaPlayer2AudioOutput(%d)", sessionId);
Dichen Zhangc2465c52018-11-12 11:56:05 -080078
Dichen Zhangc2465c52018-11-12 11:56:05 -080079 if (attributes != nullptr) {
80 mAttributes = new JObjectHolder(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -080081 }
82
83 setMinBufferCount();
Dichen Zhangf8726912018-10-17 13:31:26 -070084 mRoutingDelegates.clear();
Wei Jiaec044b02018-02-19 12:41:23 -080085}
86
87MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
Dichen Zhangf8726912018-10-17 13:31:26 -070088 for (auto routingDelegate : mRoutingDelegates) {
89 JAudioTrack::removeGlobalRef(routingDelegate.second);
90 }
Wei Jiaec044b02018-02-19 12:41:23 -080091 close();
Wei Jiaec044b02018-02-19 12:41:23 -080092 delete mCallbackData;
93}
94
95//static
96void MediaPlayer2AudioOutput::setMinBufferCount() {
97 char value[PROPERTY_VALUE_MAX];
98 if (property_get("ro.kernel.qemu", value, 0)) {
99 mIsOnEmulator = true;
100 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
101 }
102}
103
104// static
105bool MediaPlayer2AudioOutput::isOnEmulator() {
106 setMinBufferCount(); // benign race wrt other threads
107 return mIsOnEmulator;
108}
109
110// static
111int MediaPlayer2AudioOutput::getMinBufferCount() {
112 setMinBufferCount(); // benign race wrt other threads
113 return mMinBufferCount;
114}
115
116ssize_t MediaPlayer2AudioOutput::bufferSize() const {
117 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700118 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800119 return NO_INIT;
120 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700121 return mJAudioTrack->frameCount() * mFrameSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800122}
123
124ssize_t MediaPlayer2AudioOutput::frameCount() const {
125 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700126 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800127 return NO_INIT;
128 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700129 return mJAudioTrack->frameCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800130}
131
132ssize_t MediaPlayer2AudioOutput::channelCount() const {
133 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700134 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800135 return NO_INIT;
136 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700137 return mJAudioTrack->channelCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800138}
139
140ssize_t MediaPlayer2AudioOutput::frameSize() const {
141 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700142 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800143 return NO_INIT;
144 }
145 return mFrameSize;
146}
147
148uint32_t MediaPlayer2AudioOutput::latency () const {
149 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700150 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800151 return 0;
152 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700153 return mJAudioTrack->latency();
Wei Jiaec044b02018-02-19 12:41:23 -0800154}
155
156float MediaPlayer2AudioOutput::msecsPerFrame() const {
157 Mutex::Autolock lock(mLock);
158 return mMsecsPerFrame;
159}
160
161status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
162 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700163 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800164 return NO_INIT;
165 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700166 return mJAudioTrack->getPosition(position);
Wei Jiaec044b02018-02-19 12:41:23 -0800167}
168
169status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
170 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700171 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800172 return NO_INIT;
173 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700174 return mJAudioTrack->getTimestamp(ts);
Wei Jiaec044b02018-02-19 12:41:23 -0800175}
176
177// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
178// as it acquires locks and may query the audio driver.
179//
180// Some calls could conceivably retrieve extrapolated data instead of
181// accessing getTimestamp() or getPosition() every time a data buffer with
182// a media time is received.
183//
184// Calculate duration of played samples if played at normal rate (i.e., 1.0).
185int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
186 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700187 if (mJAudioTrack == nullptr || mSampleRateHz == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800188 return 0;
189 }
190
191 uint32_t numFramesPlayed;
192 int64_t numFramesPlayedAtUs;
193 AudioTimestamp ts;
194
Dichen Zhangf8726912018-10-17 13:31:26 -0700195 status_t res = mJAudioTrack->getTimestamp(ts);
196
Wei Jiaec044b02018-02-19 12:41:23 -0800197 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
198 numFramesPlayed = ts.mPosition;
199 numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
200 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
Dichen Zhangf8726912018-10-17 13:31:26 -0700201 } else { // case 2: transitory state on start of a new track
202 // case 3: transitory at new track or audio fast tracks.
Wei Jiaec044b02018-02-19 12:41:23 -0800203 numFramesPlayed = 0;
204 numFramesPlayedAtUs = nowUs;
205 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
206 // numFramesPlayed, (long long)numFramesPlayedAtUs);
Wei Jiaec044b02018-02-19 12:41:23 -0800207 }
208
209 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
210 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
211 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
212 + nowUs - numFramesPlayedAtUs;
213 if (durationUs < 0) {
214 // Occurs when numFramesPlayed position is very small and the following:
215 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
216 // numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
217 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
218 // numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
219 //
220 // Both of these are transitory conditions.
221 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
222 durationUs = 0;
223 }
224 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
225 (long long)durationUs, (long long)nowUs,
226 numFramesPlayed, (long long)numFramesPlayedAtUs);
227 return durationUs;
228}
229
230status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
231 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700232 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800233 return NO_INIT;
234 }
235 ExtendedTimestamp ets;
Dichen Zhangf8726912018-10-17 13:31:26 -0700236 status_t status = mJAudioTrack->getTimestamp(&ets);
Wei Jiaec044b02018-02-19 12:41:23 -0800237 if (status == OK || status == WOULD_BLOCK) {
238 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
239 }
240 return status;
241}
242
Dichen Zhangc2465c52018-11-12 11:56:05 -0800243void MediaPlayer2AudioOutput::setAudioAttributes(const jobject attributes) {
Wei Jiaec044b02018-02-19 12:41:23 -0800244 Mutex::Autolock lock(mLock);
Dongwon Kang203b0532018-11-14 10:51:37 -0800245 mAttributes = (attributes == nullptr) ? nullptr : new JObjectHolder(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800246}
247
Dichen Zhangf8726912018-10-17 13:31:26 -0700248audio_stream_type_t MediaPlayer2AudioOutput::getAudioStreamType() const {
249 ALOGV("getAudioStreamType");
Wei Jiaec044b02018-02-19 12:41:23 -0800250 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700251 if (mJAudioTrack == nullptr) {
252 return AUDIO_STREAM_DEFAULT;
Wei Jiaec044b02018-02-19 12:41:23 -0800253 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700254 return mJAudioTrack->getAudioStreamType();
Wei Jiaec044b02018-02-19 12:41:23 -0800255}
256
257void MediaPlayer2AudioOutput::close_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700258 mJAudioTrack.clear();
Wei Jiaec044b02018-02-19 12:41:23 -0800259}
260
261status_t MediaPlayer2AudioOutput::open(
262 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700263 audio_format_t format,
Wei Jiaec044b02018-02-19 12:41:23 -0800264 AudioCallback cb, void *cookie,
265 audio_output_flags_t flags,
266 const audio_offload_info_t *offloadInfo,
Wei Jiaec044b02018-02-19 12:41:23 -0800267 uint32_t suggestedFrameCount) {
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700268 ALOGV("open(%u, %d, 0x%x, 0x%x, %d 0x%x)", sampleRate, channelCount, channelMask,
269 format, mSessionId, flags);
Wei Jiaec044b02018-02-19 12:41:23 -0800270
271 // offloading is only supported in callback mode for now.
272 // offloadInfo must be present if offload flag is set
273 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
Dichen Zhangf8726912018-10-17 13:31:26 -0700274 ((cb == nullptr) || (offloadInfo == nullptr))) {
Wei Jiaec044b02018-02-19 12:41:23 -0800275 return BAD_VALUE;
276 }
277
278 // compute frame count for the AudioTrack internal buffer
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700279 const size_t frameCount =
280 ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) ? 0 : suggestedFrameCount;
Wei Jiaec044b02018-02-19 12:41:23 -0800281
282 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
283 channelMask = audio_channel_out_mask_from_count(channelCount);
284 if (0 == channelMask) {
285 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
286 return NO_INIT;
287 }
288 }
289
290 Mutex::Autolock lock(mLock);
291 mCallback = cb;
292 mCallbackCookie = cookie;
293
Dichen Zhangf8726912018-10-17 13:31:26 -0700294 sp<JAudioTrack> jT;
295 CallbackData *newcbd = nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800296
Dichen Zhangf8726912018-10-17 13:31:26 -0700297 ALOGV("creating new JAudioTrack");
Wei Jiaec044b02018-02-19 12:41:23 -0800298
Dichen Zhangf8726912018-10-17 13:31:26 -0700299 if (mCallback != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800300 newcbd = new CallbackData(this);
Dichen Zhangf8726912018-10-17 13:31:26 -0700301 jT = new JAudioTrack(
302 sampleRate,
303 format,
304 channelMask,
305 CallbackWrapper,
306 newcbd,
307 frameCount,
308 mSessionId,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800309 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
Dichen Zhangf8726912018-10-17 13:31:26 -0700310 1.0f); // default value for maxRequiredSpeed
Wei Jiaec044b02018-02-19 12:41:23 -0800311 } else {
312 // TODO: Due to buffer memory concerns, we use a max target playback speed
313 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
314 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
315 const float targetSpeed =
316 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
317 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
318 "track target speed:%f clamped from playback speed:%f",
319 targetSpeed, mPlaybackRate.mSpeed);
Dichen Zhangf8726912018-10-17 13:31:26 -0700320 jT = new JAudioTrack(
321 sampleRate,
322 format,
323 channelMask,
324 nullptr,
325 nullptr,
326 frameCount,
327 mSessionId,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800328 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
Dichen Zhangf8726912018-10-17 13:31:26 -0700329 targetSpeed);
Wei Jiaec044b02018-02-19 12:41:23 -0800330 }
331
Dichen Zhangf8726912018-10-17 13:31:26 -0700332 if (jT == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800333 ALOGE("Unable to create audio track");
334 delete newcbd;
335 // t goes out of scope, so reference count drops to zero
336 return NO_INIT;
Wei Jiaec044b02018-02-19 12:41:23 -0800337 }
338
Dichen Zhangf8726912018-10-17 13:31:26 -0700339 CHECK((jT != nullptr) && ((mCallback == nullptr) || (newcbd != nullptr)));
Wei Jiaec044b02018-02-19 12:41:23 -0800340
341 mCallbackData = newcbd;
342 ALOGV("setVolume");
Dichen Zhangf8726912018-10-17 13:31:26 -0700343 jT->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800344
345 mSampleRateHz = sampleRate;
346 mFlags = flags;
347 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Dichen Zhangf8726912018-10-17 13:31:26 -0700348 mFrameSize = jT->frameSize();
349 mJAudioTrack = jT;
Wei Jiaec044b02018-02-19 12:41:23 -0800350
351 return updateTrack_l();
352}
353
354status_t MediaPlayer2AudioOutput::updateTrack_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700355 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800356 return NO_ERROR;
357 }
358
359 status_t res = NO_ERROR;
360 // Note some output devices may give us a direct track even though we don't specify it.
361 // Example: Line application b/17459982.
Dichen Zhangf8726912018-10-17 13:31:26 -0700362 if ((mJAudioTrack->getFlags()
Wei Jiaec044b02018-02-19 12:41:23 -0800363 & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700364 res = mJAudioTrack->setPlaybackRate(mPlaybackRate);
Wei Jiaec044b02018-02-19 12:41:23 -0800365 if (res == NO_ERROR) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700366 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
367 res = mJAudioTrack->attachAuxEffect(mAuxEffectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800368 }
369 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700370 if (mPreferredDevice != nullptr) {
371 mJAudioTrack->setPreferredDevice(mPreferredDevice->getJObject());
372 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700373
374 mJAudioTrack->registerRoutingDelegates(mRoutingDelegates);
375
Wei Jiaec044b02018-02-19 12:41:23 -0800376 ALOGV("updateTrack_l() DONE status %d", res);
377 return res;
378}
379
380status_t MediaPlayer2AudioOutput::start() {
381 ALOGV("start");
382 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700383 if (mCallbackData != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800384 mCallbackData->endTrackSwitch();
385 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700386 if (mJAudioTrack != nullptr) {
387 mJAudioTrack->setVolume(mVolume);
388 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
389 status_t status = mJAudioTrack->start();
Wei Jiaec044b02018-02-19 12:41:23 -0800390 return status;
391 }
392 return NO_INIT;
393}
394
395ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
396 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700397 LOG_ALWAYS_FATAL_IF(mCallback != nullptr, "Don't call write if supplying a callback.");
Wei Jiaec044b02018-02-19 12:41:23 -0800398
399 //ALOGV("write(%p, %u)", buffer, size);
Dichen Zhangf8726912018-10-17 13:31:26 -0700400 if (mJAudioTrack != nullptr) {
401 return mJAudioTrack->write(buffer, size, blocking);
Wei Jiaec044b02018-02-19 12:41:23 -0800402 }
403 return NO_INIT;
404}
405
406void MediaPlayer2AudioOutput::stop() {
407 ALOGV("stop");
408 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700409 if (mJAudioTrack != nullptr) {
410 mJAudioTrack->stop();
Wei Jiaec044b02018-02-19 12:41:23 -0800411 }
412}
413
414void MediaPlayer2AudioOutput::flush() {
415 ALOGV("flush");
416 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700417 if (mJAudioTrack != nullptr) {
418 mJAudioTrack->flush();
Wei Jiaec044b02018-02-19 12:41:23 -0800419 }
420}
421
422void MediaPlayer2AudioOutput::pause() {
423 ALOGV("pause");
424 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700425 if (mJAudioTrack != nullptr) {
426 mJAudioTrack->pause();
Wei Jiaec044b02018-02-19 12:41:23 -0800427 }
428}
429
430void MediaPlayer2AudioOutput::close() {
431 ALOGV("close");
Dichen Zhangf8726912018-10-17 13:31:26 -0700432 sp<JAudioTrack> track;
Wei Jiaec044b02018-02-19 12:41:23 -0800433 {
434 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700435 track = mJAudioTrack;
436 close_l(); // clears mJAudioTrack
Wei Jiaec044b02018-02-19 12:41:23 -0800437 }
438 // destruction of the track occurs outside of mutex.
439}
440
Dichen Zhang7398ca02018-10-15 10:25:12 -0700441void MediaPlayer2AudioOutput::setVolume(float volume) {
442 ALOGV("setVolume(%f)", volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800443 Mutex::Autolock lock(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700444 mVolume = volume;
Dichen Zhangf8726912018-10-17 13:31:26 -0700445 if (mJAudioTrack != nullptr) {
446 mJAudioTrack->setVolume(volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800447 }
448}
449
450status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
451 ALOGV("setPlaybackRate(%f %f %d %d)",
452 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
453 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700454 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800455 // remember rate so that we can set it when the track is opened
456 mPlaybackRate = rate;
457 return OK;
458 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700459 status_t res = mJAudioTrack->setPlaybackRate(rate);
Wei Jiaec044b02018-02-19 12:41:23 -0800460 if (res != NO_ERROR) {
461 return res;
462 }
463 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
464 CHECK_GT(rate.mSpeed, 0.f);
465 mPlaybackRate = rate;
466 if (mSampleRateHz != 0) {
467 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
468 }
469 return res;
470}
471
472status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
Dichen Zhang790249b2018-09-13 15:08:14 -0700473 ALOGV("getPlaybackRate");
Wei Jiaec044b02018-02-19 12:41:23 -0800474 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700475 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800476 return NO_INIT;
477 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700478 *rate = mJAudioTrack->getPlaybackRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800479 return NO_ERROR;
480}
481
482status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
483 ALOGV("setAuxEffectSendLevel(%f)", level);
484 Mutex::Autolock lock(mLock);
485 mSendLevel = level;
Dichen Zhangf8726912018-10-17 13:31:26 -0700486 if (mJAudioTrack != nullptr) {
487 return mJAudioTrack->setAuxEffectSendLevel(level);
Wei Jiaec044b02018-02-19 12:41:23 -0800488 }
489 return NO_ERROR;
490}
491
492status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
493 ALOGV("attachAuxEffect(%d)", effectId);
494 Mutex::Autolock lock(mLock);
495 mAuxEffectId = effectId;
Dichen Zhangf8726912018-10-17 13:31:26 -0700496 if (mJAudioTrack != nullptr) {
497 return mJAudioTrack->attachAuxEffect(effectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800498 }
499 return NO_ERROR;
500}
501
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700502status_t MediaPlayer2AudioOutput::setPreferredDevice(jobject device) {
503 ALOGV("setPreferredDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800504 Mutex::Autolock lock(mLock);
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700505 status_t ret = NO_ERROR;
Dichen Zhangf8726912018-10-17 13:31:26 -0700506 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700507 ret = mJAudioTrack->setPreferredDevice(device);
Wei Jiaec044b02018-02-19 12:41:23 -0800508 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700509 if (ret == NO_ERROR) {
510 mPreferredDevice = new JObjectHolder(device);
511 }
512 return ret;
Wei Jiaec044b02018-02-19 12:41:23 -0800513}
514
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700515jobject MediaPlayer2AudioOutput::getRoutedDevice() {
516 ALOGV("getRoutedDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800517 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700518 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700519 return mJAudioTrack->getRoutedDevice();
Wei Jiaec044b02018-02-19 12:41:23 -0800520 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700521 return nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800522}
523
Dichen Zhangf8726912018-10-17 13:31:26 -0700524status_t MediaPlayer2AudioOutput::addAudioDeviceCallback(jobject jRoutingDelegate) {
525 ALOGV("addAudioDeviceCallback");
Wei Jiaec044b02018-02-19 12:41:23 -0800526 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700527 jobject listener = JAudioTrack::getListener(jRoutingDelegate);
528 if (mJAudioTrack != nullptr &&
529 JAudioTrack::findByKey(mRoutingDelegates, listener) == nullptr) {
530 jobject handler = JAudioTrack::getHandler(jRoutingDelegate);
531 jobject routingDelegate = JAudioTrack::addGlobalRef(jRoutingDelegate);
532 mRoutingDelegates.push_back(std::pair<jobject, jobject>(listener, routingDelegate));
533 return mJAudioTrack->addAudioDeviceCallback(routingDelegate, handler);
Wei Jiaec044b02018-02-19 12:41:23 -0800534 }
535 return NO_ERROR;
536}
537
Dichen Zhangf8726912018-10-17 13:31:26 -0700538status_t MediaPlayer2AudioOutput::removeAudioDeviceCallback(jobject listener) {
539 ALOGV("removeAudioDeviceCallback");
540 Mutex::Autolock lock(mLock);
541 jobject routingDelegate = nullptr;
542 if (mJAudioTrack != nullptr &&
543 (routingDelegate = JAudioTrack::findByKey(mRoutingDelegates, listener)) != nullptr) {
544 mJAudioTrack->removeAudioDeviceCallback(routingDelegate);
545 JAudioTrack::eraseByKey(mRoutingDelegates, listener);
546 if (JAudioTrack::removeGlobalRef(routingDelegate) != NO_ERROR) {
547 return BAD_VALUE;
548 }
549 }
550 return NO_ERROR;
551}
552
Wei Jiaec044b02018-02-19 12:41:23 -0800553// static
554void MediaPlayer2AudioOutput::CallbackWrapper(
555 int event, void *cookie, void *info) {
556 //ALOGV("callbackwrapper");
557 CallbackData *data = (CallbackData*)cookie;
558 // lock to ensure we aren't caught in the middle of a track switch.
559 data->lock();
560 MediaPlayer2AudioOutput *me = data->getOutput();
Dichen Zhangf8726912018-10-17 13:31:26 -0700561 JAudioTrack::Buffer *buffer = (JAudioTrack::Buffer *)info;
562 if (me == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800563 // no output set, likely because the track was scheduled to be reused
564 // by another player, but the format turned out to be incompatible.
565 data->unlock();
Dichen Zhangf8726912018-10-17 13:31:26 -0700566 if (buffer != nullptr) {
567 buffer->mSize = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800568 }
569 return;
570 }
571
572 switch(event) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700573 case JAudioTrack::EVENT_MORE_DATA: {
Wei Jiaec044b02018-02-19 12:41:23 -0800574 size_t actualSize = (*me->mCallback)(
Dichen Zhangf8726912018-10-17 13:31:26 -0700575 me, buffer->mData, buffer->mSize, me->mCallbackCookie,
Wei Jiaec044b02018-02-19 12:41:23 -0800576 CB_EVENT_FILL_BUFFER);
577
578 // Log when no data is returned from the callback.
579 // (1) We may have no data (especially with network streaming sources).
580 // (2) We may have reached the EOS and the audio track is not stopped yet.
581 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
582 // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
583 //
584 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
585 // nevertheless for power reasons, we don't want to see too many of these.
586
Dichen Zhangf8726912018-10-17 13:31:26 -0700587 ALOGV_IF(actualSize == 0 && buffer->mSize > 0, "callbackwrapper: empty buffer returned");
Wei Jiaec044b02018-02-19 12:41:23 -0800588
Dichen Zhangf8726912018-10-17 13:31:26 -0700589 buffer->mSize = actualSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800590 } break;
591
Dichen Zhangf8726912018-10-17 13:31:26 -0700592 case JAudioTrack::EVENT_STREAM_END:
Wei Jiaec044b02018-02-19 12:41:23 -0800593 // currently only occurs for offloaded callbacks
594 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
Dichen Zhangf8726912018-10-17 13:31:26 -0700595 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800596 me->mCallbackCookie, CB_EVENT_STREAM_END);
597 break;
598
Dichen Zhangf8726912018-10-17 13:31:26 -0700599 case JAudioTrack::EVENT_NEW_IAUDIOTRACK :
Wei Jiaec044b02018-02-19 12:41:23 -0800600 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
Dichen Zhangf8726912018-10-17 13:31:26 -0700601 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800602 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
603 break;
604
Dichen Zhangf8726912018-10-17 13:31:26 -0700605 case JAudioTrack::EVENT_UNDERRUN:
Wei Jiaec044b02018-02-19 12:41:23 -0800606 // This occurs when there is no data available, typically
607 // when there is a failure to supply data to the AudioTrack. It can also
608 // occur in non-offloaded mode when the audio device comes out of standby.
609 //
610 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
611 // it may sound like an audible pop or glitch.
612 //
613 // The underrun event is sent once per track underrun; the condition is reset
614 // when more data is sent to the AudioTrack.
615 ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
616 break;
617
618 default:
619 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
620 }
621
622 data->unlock();
623}
624
Dichen Zhang23658642018-11-15 10:26:16 -0800625int32_t MediaPlayer2AudioOutput::getSessionId() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800626 Mutex::Autolock lock(mLock);
627 return mSessionId;
628}
629
Dichen Zhang23658642018-11-15 10:26:16 -0800630void MediaPlayer2AudioOutput::setSessionId(const int32_t sessionId) {
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000631 Mutex::Autolock lock(mLock);
Dichen Zhang23658642018-11-15 10:26:16 -0800632 mSessionId = sessionId;
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000633}
634
Dichen Zhangf8726912018-10-17 13:31:26 -0700635uint32_t MediaPlayer2AudioOutput::getSampleRate() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800636 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700637 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800638 return 0;
639 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700640 return mJAudioTrack->getSampleRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800641}
642
Dichen Zhangf8726912018-10-17 13:31:26 -0700643int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800644 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700645 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800646 return 0;
647 }
648 int64_t duration;
Dichen Zhangf8726912018-10-17 13:31:26 -0700649 if (mJAudioTrack->getBufferDurationInUs(&duration) != OK) {
Wei Jiaec044b02018-02-19 12:41:23 -0800650 return 0;
651 }
652 return duration;
653}
654
655} // namespace android