blob: 149f24386644335bb203391b517f7fc767cee508 [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
25#include <media/AudioPolicyHelper.h>
Wei Jiaec044b02018-02-19 12:41:23 -080026#include <media/stagefright/foundation/ADebug.h>
27
28namespace {
29
30const float kMaxRequiredSpeed = 8.0f; // for PCM tracks allow up to 8x speedup.
31
32} // anonymous namespace
33
34namespace android {
35
36// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
37/* static */ int MediaPlayer2AudioOutput::mMinBufferCount = 4;
38/* static */ bool MediaPlayer2AudioOutput::mIsOnEmulator = false;
39
40status_t MediaPlayer2AudioOutput::dump(int fd, const Vector<String16>& args) const {
41 const size_t SIZE = 256;
42 char buffer[SIZE];
43 String8 result;
44
45 result.append(" MediaPlayer2AudioOutput\n");
Dichen Zhangf8726912018-10-17 13:31:26 -070046 snprintf(buffer, 255, " volume(%f)\n", mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -080047 result.append(buffer);
48 snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
Dichen Zhangf8726912018-10-17 13:31:26 -070049 mMsecsPerFrame, (mJAudioTrack != nullptr) ? mJAudioTrack->latency() : -1);
Wei Jiaec044b02018-02-19 12:41:23 -080050 result.append(buffer);
51 snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
52 mAuxEffectId, mSendLevel);
53 result.append(buffer);
54
55 ::write(fd, result.string(), result.size());
Dichen Zhangf8726912018-10-17 13:31:26 -070056 if (mJAudioTrack != nullptr) {
57 mJAudioTrack->dump(fd, args);
Wei Jiaec044b02018-02-19 12:41:23 -080058 }
59 return NO_ERROR;
60}
61
62MediaPlayer2AudioOutput::MediaPlayer2AudioOutput(audio_session_t sessionId, uid_t uid, int pid,
Dichen Zhangf8726912018-10-17 13:31:26 -070063 const audio_attributes_t* attr, std::vector<jobject>& routingDelegatesBackup)
64 : mCallback(nullptr),
65 mCallbackCookie(nullptr),
66 mCallbackData(nullptr),
Dichen Zhang7398ca02018-10-15 10:25:12 -070067 mVolume(1.0),
Wei Jiaec044b02018-02-19 12:41:23 -080068 mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
69 mSampleRateHz(0),
70 mMsecsPerFrame(0),
71 mFrameSize(0),
72 mSessionId(sessionId),
73 mUid(uid),
74 mPid(pid),
75 mSendLevel(0.0),
76 mAuxEffectId(0),
Dongwon Kang0d7042d2018-10-12 16:52:14 -070077 mFlags(AUDIO_OUTPUT_FLAG_NONE) {
Wei Jiaec044b02018-02-19 12:41:23 -080078 ALOGV("MediaPlayer2AudioOutput(%d)", sessionId);
Dichen Zhangf8726912018-10-17 13:31:26 -070079 if (attr != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -080080 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
Dichen Zhangf8726912018-10-17 13:31:26 -070081 if (mAttributes != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -080082 memcpy(mAttributes, attr, sizeof(audio_attributes_t));
Wei Jiaec044b02018-02-19 12:41:23 -080083 }
84 } else {
Dichen Zhangf8726912018-10-17 13:31:26 -070085 mAttributes = nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -080086 }
87
88 setMinBufferCount();
Dichen Zhangf8726912018-10-17 13:31:26 -070089 mRoutingDelegates.clear();
90 for (auto routingDelegate : routingDelegatesBackup) {
91 mRoutingDelegates.push_back(std::pair<jobject, jobject>(
92 JAudioTrack::getListener(routingDelegate), routingDelegate));
93 }
94 routingDelegatesBackup.clear();
Wei Jiaec044b02018-02-19 12:41:23 -080095}
96
97MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
Dichen Zhangf8726912018-10-17 13:31:26 -070098 for (auto routingDelegate : mRoutingDelegates) {
99 JAudioTrack::removeGlobalRef(routingDelegate.second);
100 }
Wei Jiaec044b02018-02-19 12:41:23 -0800101 close();
102 free(mAttributes);
103 delete mCallbackData;
104}
105
106//static
107void MediaPlayer2AudioOutput::setMinBufferCount() {
108 char value[PROPERTY_VALUE_MAX];
109 if (property_get("ro.kernel.qemu", value, 0)) {
110 mIsOnEmulator = true;
111 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
112 }
113}
114
115// static
116bool MediaPlayer2AudioOutput::isOnEmulator() {
117 setMinBufferCount(); // benign race wrt other threads
118 return mIsOnEmulator;
119}
120
121// static
122int MediaPlayer2AudioOutput::getMinBufferCount() {
123 setMinBufferCount(); // benign race wrt other threads
124 return mMinBufferCount;
125}
126
127ssize_t MediaPlayer2AudioOutput::bufferSize() const {
128 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700129 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800130 return NO_INIT;
131 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700132 return mJAudioTrack->frameCount() * mFrameSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800133}
134
135ssize_t MediaPlayer2AudioOutput::frameCount() const {
136 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700137 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800138 return NO_INIT;
139 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700140 return mJAudioTrack->frameCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800141}
142
143ssize_t MediaPlayer2AudioOutput::channelCount() const {
144 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700145 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800146 return NO_INIT;
147 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700148 return mJAudioTrack->channelCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800149}
150
151ssize_t MediaPlayer2AudioOutput::frameSize() const {
152 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700153 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800154 return NO_INIT;
155 }
156 return mFrameSize;
157}
158
159uint32_t MediaPlayer2AudioOutput::latency () const {
160 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700161 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800162 return 0;
163 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700164 return mJAudioTrack->latency();
Wei Jiaec044b02018-02-19 12:41:23 -0800165}
166
167float MediaPlayer2AudioOutput::msecsPerFrame() const {
168 Mutex::Autolock lock(mLock);
169 return mMsecsPerFrame;
170}
171
172status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
173 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700174 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800175 return NO_INIT;
176 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700177 return mJAudioTrack->getPosition(position);
Wei Jiaec044b02018-02-19 12:41:23 -0800178}
179
180status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
181 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700182 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800183 return NO_INIT;
184 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700185 return mJAudioTrack->getTimestamp(ts);
Wei Jiaec044b02018-02-19 12:41:23 -0800186}
187
188// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
189// as it acquires locks and may query the audio driver.
190//
191// Some calls could conceivably retrieve extrapolated data instead of
192// accessing getTimestamp() or getPosition() every time a data buffer with
193// a media time is received.
194//
195// Calculate duration of played samples if played at normal rate (i.e., 1.0).
196int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
197 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700198 if (mJAudioTrack == nullptr || mSampleRateHz == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800199 return 0;
200 }
201
202 uint32_t numFramesPlayed;
203 int64_t numFramesPlayedAtUs;
204 AudioTimestamp ts;
205
Dichen Zhangf8726912018-10-17 13:31:26 -0700206 status_t res = mJAudioTrack->getTimestamp(ts);
207
Wei Jiaec044b02018-02-19 12:41:23 -0800208 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
209 numFramesPlayed = ts.mPosition;
210 numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
211 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
Dichen Zhangf8726912018-10-17 13:31:26 -0700212 } else { // case 2: transitory state on start of a new track
213 // case 3: transitory at new track or audio fast tracks.
Wei Jiaec044b02018-02-19 12:41:23 -0800214 numFramesPlayed = 0;
215 numFramesPlayedAtUs = nowUs;
216 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
217 // numFramesPlayed, (long long)numFramesPlayedAtUs);
Wei Jiaec044b02018-02-19 12:41:23 -0800218 }
219
220 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
221 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
222 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
223 + nowUs - numFramesPlayedAtUs;
224 if (durationUs < 0) {
225 // Occurs when numFramesPlayed position is very small and the following:
226 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
227 // numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
228 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
229 // numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
230 //
231 // Both of these are transitory conditions.
232 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
233 durationUs = 0;
234 }
235 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
236 (long long)durationUs, (long long)nowUs,
237 numFramesPlayed, (long long)numFramesPlayedAtUs);
238 return durationUs;
239}
240
241status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
242 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700243 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800244 return NO_INIT;
245 }
246 ExtendedTimestamp ets;
Dichen Zhangf8726912018-10-17 13:31:26 -0700247 status_t status = mJAudioTrack->getTimestamp(&ets);
Wei Jiaec044b02018-02-19 12:41:23 -0800248 if (status == OK || status == WOULD_BLOCK) {
249 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
250 }
251 return status;
252}
253
Wei Jiaec044b02018-02-19 12:41:23 -0800254void MediaPlayer2AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
255 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700256 if (attributes == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800257 free(mAttributes);
Dichen Zhangf8726912018-10-17 13:31:26 -0700258 mAttributes = nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800259 } else {
Dichen Zhangf8726912018-10-17 13:31:26 -0700260 if (mAttributes == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800261 mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
262 }
263 memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
Wei Jiaec044b02018-02-19 12:41:23 -0800264 }
265}
266
Dichen Zhangf8726912018-10-17 13:31:26 -0700267audio_stream_type_t MediaPlayer2AudioOutput::getAudioStreamType() const {
268 ALOGV("getAudioStreamType");
Wei Jiaec044b02018-02-19 12:41:23 -0800269 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700270 if (mJAudioTrack == nullptr) {
271 return AUDIO_STREAM_DEFAULT;
Wei Jiaec044b02018-02-19 12:41:23 -0800272 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700273 return mJAudioTrack->getAudioStreamType();
Wei Jiaec044b02018-02-19 12:41:23 -0800274}
275
276void MediaPlayer2AudioOutput::close_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700277 mJAudioTrack.clear();
Wei Jiaec044b02018-02-19 12:41:23 -0800278}
279
280status_t MediaPlayer2AudioOutput::open(
281 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700282 audio_format_t format,
Wei Jiaec044b02018-02-19 12:41:23 -0800283 AudioCallback cb, void *cookie,
284 audio_output_flags_t flags,
285 const audio_offload_info_t *offloadInfo,
Wei Jiaec044b02018-02-19 12:41:23 -0800286 uint32_t suggestedFrameCount) {
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700287 ALOGV("open(%u, %d, 0x%x, 0x%x, %d 0x%x)", sampleRate, channelCount, channelMask,
288 format, mSessionId, flags);
Wei Jiaec044b02018-02-19 12:41:23 -0800289
290 // offloading is only supported in callback mode for now.
291 // offloadInfo must be present if offload flag is set
292 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
Dichen Zhangf8726912018-10-17 13:31:26 -0700293 ((cb == nullptr) || (offloadInfo == nullptr))) {
Wei Jiaec044b02018-02-19 12:41:23 -0800294 return BAD_VALUE;
295 }
296
297 // compute frame count for the AudioTrack internal buffer
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700298 const size_t frameCount =
299 ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) ? 0 : suggestedFrameCount;
Wei Jiaec044b02018-02-19 12:41:23 -0800300
301 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
302 channelMask = audio_channel_out_mask_from_count(channelCount);
303 if (0 == channelMask) {
304 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
305 return NO_INIT;
306 }
307 }
308
309 Mutex::Autolock lock(mLock);
310 mCallback = cb;
311 mCallbackCookie = cookie;
312
Dichen Zhangf8726912018-10-17 13:31:26 -0700313 sp<JAudioTrack> jT;
314 CallbackData *newcbd = nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800315
Dichen Zhangf8726912018-10-17 13:31:26 -0700316 ALOGV("creating new JAudioTrack");
Wei Jiaec044b02018-02-19 12:41:23 -0800317
Dichen Zhangf8726912018-10-17 13:31:26 -0700318 if (mCallback != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800319 newcbd = new CallbackData(this);
Dichen Zhangf8726912018-10-17 13:31:26 -0700320 jT = new JAudioTrack(
321 sampleRate,
322 format,
323 channelMask,
324 CallbackWrapper,
325 newcbd,
326 frameCount,
327 mSessionId,
328 mAttributes,
329 1.0f); // default value for maxRequiredSpeed
Wei Jiaec044b02018-02-19 12:41:23 -0800330 } else {
331 // TODO: Due to buffer memory concerns, we use a max target playback speed
332 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
333 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
334 const float targetSpeed =
335 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
336 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
337 "track target speed:%f clamped from playback speed:%f",
338 targetSpeed, mPlaybackRate.mSpeed);
Dichen Zhangf8726912018-10-17 13:31:26 -0700339 jT = new JAudioTrack(
340 sampleRate,
341 format,
342 channelMask,
343 nullptr,
344 nullptr,
345 frameCount,
346 mSessionId,
347 mAttributes,
348 targetSpeed);
Wei Jiaec044b02018-02-19 12:41:23 -0800349 }
350
Dichen Zhangf8726912018-10-17 13:31:26 -0700351 if (jT == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800352 ALOGE("Unable to create audio track");
353 delete newcbd;
354 // t goes out of scope, so reference count drops to zero
355 return NO_INIT;
Wei Jiaec044b02018-02-19 12:41:23 -0800356 }
357
Dichen Zhangf8726912018-10-17 13:31:26 -0700358 CHECK((jT != nullptr) && ((mCallback == nullptr) || (newcbd != nullptr)));
Wei Jiaec044b02018-02-19 12:41:23 -0800359
360 mCallbackData = newcbd;
361 ALOGV("setVolume");
Dichen Zhangf8726912018-10-17 13:31:26 -0700362 jT->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800363
364 mSampleRateHz = sampleRate;
365 mFlags = flags;
366 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Dichen Zhangf8726912018-10-17 13:31:26 -0700367 mFrameSize = jT->frameSize();
368 mJAudioTrack = jT;
Wei Jiaec044b02018-02-19 12:41:23 -0800369
370 return updateTrack_l();
371}
372
373status_t MediaPlayer2AudioOutput::updateTrack_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700374 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800375 return NO_ERROR;
376 }
377
378 status_t res = NO_ERROR;
379 // Note some output devices may give us a direct track even though we don't specify it.
380 // Example: Line application b/17459982.
Dichen Zhangf8726912018-10-17 13:31:26 -0700381 if ((mJAudioTrack->getFlags()
Wei Jiaec044b02018-02-19 12:41:23 -0800382 & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700383 res = mJAudioTrack->setPlaybackRate(mPlaybackRate);
Wei Jiaec044b02018-02-19 12:41:23 -0800384 if (res == NO_ERROR) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700385 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
386 res = mJAudioTrack->attachAuxEffect(mAuxEffectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800387 }
388 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700389 if (mPreferredDevice != nullptr) {
390 mJAudioTrack->setPreferredDevice(mPreferredDevice->getJObject());
391 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700392
393 mJAudioTrack->registerRoutingDelegates(mRoutingDelegates);
394
Wei Jiaec044b02018-02-19 12:41:23 -0800395 ALOGV("updateTrack_l() DONE status %d", res);
396 return res;
397}
398
399status_t MediaPlayer2AudioOutput::start() {
400 ALOGV("start");
401 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700402 if (mCallbackData != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800403 mCallbackData->endTrackSwitch();
404 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700405 if (mJAudioTrack != nullptr) {
406 mJAudioTrack->setVolume(mVolume);
407 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
408 status_t status = mJAudioTrack->start();
Wei Jiaec044b02018-02-19 12:41:23 -0800409 return status;
410 }
411 return NO_INIT;
412}
413
414ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
415 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700416 LOG_ALWAYS_FATAL_IF(mCallback != nullptr, "Don't call write if supplying a callback.");
Wei Jiaec044b02018-02-19 12:41:23 -0800417
418 //ALOGV("write(%p, %u)", buffer, size);
Dichen Zhangf8726912018-10-17 13:31:26 -0700419 if (mJAudioTrack != nullptr) {
420 return mJAudioTrack->write(buffer, size, blocking);
Wei Jiaec044b02018-02-19 12:41:23 -0800421 }
422 return NO_INIT;
423}
424
425void MediaPlayer2AudioOutput::stop() {
426 ALOGV("stop");
427 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700428 if (mJAudioTrack != nullptr) {
429 mJAudioTrack->stop();
Wei Jiaec044b02018-02-19 12:41:23 -0800430 }
431}
432
433void MediaPlayer2AudioOutput::flush() {
434 ALOGV("flush");
435 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700436 if (mJAudioTrack != nullptr) {
437 mJAudioTrack->flush();
Wei Jiaec044b02018-02-19 12:41:23 -0800438 }
439}
440
441void MediaPlayer2AudioOutput::pause() {
442 ALOGV("pause");
443 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700444 if (mJAudioTrack != nullptr) {
445 mJAudioTrack->pause();
Wei Jiaec044b02018-02-19 12:41:23 -0800446 }
447}
448
449void MediaPlayer2AudioOutput::close() {
450 ALOGV("close");
Dichen Zhangf8726912018-10-17 13:31:26 -0700451 sp<JAudioTrack> track;
Wei Jiaec044b02018-02-19 12:41:23 -0800452 {
453 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700454 track = mJAudioTrack;
455 close_l(); // clears mJAudioTrack
Wei Jiaec044b02018-02-19 12:41:23 -0800456 }
457 // destruction of the track occurs outside of mutex.
458}
459
Dichen Zhang7398ca02018-10-15 10:25:12 -0700460void MediaPlayer2AudioOutput::setVolume(float volume) {
461 ALOGV("setVolume(%f)", volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800462 Mutex::Autolock lock(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700463 mVolume = volume;
Dichen Zhangf8726912018-10-17 13:31:26 -0700464 if (mJAudioTrack != nullptr) {
465 mJAudioTrack->setVolume(volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800466 }
467}
468
469status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
470 ALOGV("setPlaybackRate(%f %f %d %d)",
471 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
472 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700473 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800474 // remember rate so that we can set it when the track is opened
475 mPlaybackRate = rate;
476 return OK;
477 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700478 status_t res = mJAudioTrack->setPlaybackRate(rate);
Wei Jiaec044b02018-02-19 12:41:23 -0800479 if (res != NO_ERROR) {
480 return res;
481 }
482 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
483 CHECK_GT(rate.mSpeed, 0.f);
484 mPlaybackRate = rate;
485 if (mSampleRateHz != 0) {
486 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
487 }
488 return res;
489}
490
491status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
Dichen Zhang790249b2018-09-13 15:08:14 -0700492 ALOGV("getPlaybackRate");
Wei Jiaec044b02018-02-19 12:41:23 -0800493 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700494 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800495 return NO_INIT;
496 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700497 *rate = mJAudioTrack->getPlaybackRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800498 return NO_ERROR;
499}
500
501status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
502 ALOGV("setAuxEffectSendLevel(%f)", level);
503 Mutex::Autolock lock(mLock);
504 mSendLevel = level;
Dichen Zhangf8726912018-10-17 13:31:26 -0700505 if (mJAudioTrack != nullptr) {
506 return mJAudioTrack->setAuxEffectSendLevel(level);
Wei Jiaec044b02018-02-19 12:41:23 -0800507 }
508 return NO_ERROR;
509}
510
511status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
512 ALOGV("attachAuxEffect(%d)", effectId);
513 Mutex::Autolock lock(mLock);
514 mAuxEffectId = effectId;
Dichen Zhangf8726912018-10-17 13:31:26 -0700515 if (mJAudioTrack != nullptr) {
516 return mJAudioTrack->attachAuxEffect(effectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800517 }
518 return NO_ERROR;
519}
520
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700521status_t MediaPlayer2AudioOutput::setPreferredDevice(jobject device) {
522 ALOGV("setPreferredDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800523 Mutex::Autolock lock(mLock);
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700524 status_t ret = NO_ERROR;
Dichen Zhangf8726912018-10-17 13:31:26 -0700525 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700526 ret = mJAudioTrack->setPreferredDevice(device);
Wei Jiaec044b02018-02-19 12:41:23 -0800527 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700528 if (ret == NO_ERROR) {
529 mPreferredDevice = new JObjectHolder(device);
530 }
531 return ret;
Wei Jiaec044b02018-02-19 12:41:23 -0800532}
533
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700534jobject MediaPlayer2AudioOutput::getRoutedDevice() {
535 ALOGV("getRoutedDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800536 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700537 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700538 return mJAudioTrack->getRoutedDevice();
Wei Jiaec044b02018-02-19 12:41:23 -0800539 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700540 return nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800541}
542
Dichen Zhangf8726912018-10-17 13:31:26 -0700543status_t MediaPlayer2AudioOutput::addAudioDeviceCallback(jobject jRoutingDelegate) {
544 ALOGV("addAudioDeviceCallback");
Wei Jiaec044b02018-02-19 12:41:23 -0800545 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700546 jobject listener = JAudioTrack::getListener(jRoutingDelegate);
547 if (mJAudioTrack != nullptr &&
548 JAudioTrack::findByKey(mRoutingDelegates, listener) == nullptr) {
549 jobject handler = JAudioTrack::getHandler(jRoutingDelegate);
550 jobject routingDelegate = JAudioTrack::addGlobalRef(jRoutingDelegate);
551 mRoutingDelegates.push_back(std::pair<jobject, jobject>(listener, routingDelegate));
552 return mJAudioTrack->addAudioDeviceCallback(routingDelegate, handler);
Wei Jiaec044b02018-02-19 12:41:23 -0800553 }
554 return NO_ERROR;
555}
556
Dichen Zhangf8726912018-10-17 13:31:26 -0700557status_t MediaPlayer2AudioOutput::removeAudioDeviceCallback(jobject listener) {
558 ALOGV("removeAudioDeviceCallback");
559 Mutex::Autolock lock(mLock);
560 jobject routingDelegate = nullptr;
561 if (mJAudioTrack != nullptr &&
562 (routingDelegate = JAudioTrack::findByKey(mRoutingDelegates, listener)) != nullptr) {
563 mJAudioTrack->removeAudioDeviceCallback(routingDelegate);
564 JAudioTrack::eraseByKey(mRoutingDelegates, listener);
565 if (JAudioTrack::removeGlobalRef(routingDelegate) != NO_ERROR) {
566 return BAD_VALUE;
567 }
568 }
569 return NO_ERROR;
570}
571
572void MediaPlayer2AudioOutput::copyAudioDeviceCallback(
573 std::vector<jobject>& routingDelegateTarget) {
574 ALOGV("copyAudioDeviceCallback");
575 for (std::vector<std::pair<jobject, jobject>>::iterator it = mRoutingDelegates.begin();
576 it != mRoutingDelegates.end(); it++) {
577 routingDelegateTarget.push_back(it->second);
578 }
579}
580
Wei Jiaec044b02018-02-19 12:41:23 -0800581// static
582void MediaPlayer2AudioOutput::CallbackWrapper(
583 int event, void *cookie, void *info) {
584 //ALOGV("callbackwrapper");
585 CallbackData *data = (CallbackData*)cookie;
586 // lock to ensure we aren't caught in the middle of a track switch.
587 data->lock();
588 MediaPlayer2AudioOutput *me = data->getOutput();
Dichen Zhangf8726912018-10-17 13:31:26 -0700589 JAudioTrack::Buffer *buffer = (JAudioTrack::Buffer *)info;
590 if (me == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800591 // no output set, likely because the track was scheduled to be reused
592 // by another player, but the format turned out to be incompatible.
593 data->unlock();
Dichen Zhangf8726912018-10-17 13:31:26 -0700594 if (buffer != nullptr) {
595 buffer->mSize = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800596 }
597 return;
598 }
599
600 switch(event) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700601 case JAudioTrack::EVENT_MORE_DATA: {
Wei Jiaec044b02018-02-19 12:41:23 -0800602 size_t actualSize = (*me->mCallback)(
Dichen Zhangf8726912018-10-17 13:31:26 -0700603 me, buffer->mData, buffer->mSize, me->mCallbackCookie,
Wei Jiaec044b02018-02-19 12:41:23 -0800604 CB_EVENT_FILL_BUFFER);
605
606 // Log when no data is returned from the callback.
607 // (1) We may have no data (especially with network streaming sources).
608 // (2) We may have reached the EOS and the audio track is not stopped yet.
609 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
610 // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
611 //
612 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
613 // nevertheless for power reasons, we don't want to see too many of these.
614
Dichen Zhangf8726912018-10-17 13:31:26 -0700615 ALOGV_IF(actualSize == 0 && buffer->mSize > 0, "callbackwrapper: empty buffer returned");
Wei Jiaec044b02018-02-19 12:41:23 -0800616
Dichen Zhangf8726912018-10-17 13:31:26 -0700617 buffer->mSize = actualSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800618 } break;
619
Dichen Zhangf8726912018-10-17 13:31:26 -0700620 case JAudioTrack::EVENT_STREAM_END:
Wei Jiaec044b02018-02-19 12:41:23 -0800621 // currently only occurs for offloaded callbacks
622 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
Dichen Zhangf8726912018-10-17 13:31:26 -0700623 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800624 me->mCallbackCookie, CB_EVENT_STREAM_END);
625 break;
626
Dichen Zhangf8726912018-10-17 13:31:26 -0700627 case JAudioTrack::EVENT_NEW_IAUDIOTRACK :
Wei Jiaec044b02018-02-19 12:41:23 -0800628 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
Dichen Zhangf8726912018-10-17 13:31:26 -0700629 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800630 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
631 break;
632
Dichen Zhangf8726912018-10-17 13:31:26 -0700633 case JAudioTrack::EVENT_UNDERRUN:
Wei Jiaec044b02018-02-19 12:41:23 -0800634 // This occurs when there is no data available, typically
635 // when there is a failure to supply data to the AudioTrack. It can also
636 // occur in non-offloaded mode when the audio device comes out of standby.
637 //
638 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
639 // it may sound like an audible pop or glitch.
640 //
641 // The underrun event is sent once per track underrun; the condition is reset
642 // when more data is sent to the AudioTrack.
643 ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
644 break;
645
646 default:
647 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
648 }
649
650 data->unlock();
651}
652
Dichen Zhangf8726912018-10-17 13:31:26 -0700653audio_session_t MediaPlayer2AudioOutput::getSessionId() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800654 Mutex::Autolock lock(mLock);
655 return mSessionId;
656}
657
Dichen Zhangf8726912018-10-17 13:31:26 -0700658uint32_t MediaPlayer2AudioOutput::getSampleRate() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800659 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700660 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800661 return 0;
662 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700663 return mJAudioTrack->getSampleRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800664}
665
Dichen Zhangf8726912018-10-17 13:31:26 -0700666int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800667 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700668 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800669 return 0;
670 }
671 int64_t duration;
Dichen Zhangf8726912018-10-17 13:31:26 -0700672 if (mJAudioTrack->getBufferDurationInUs(&duration) != OK) {
Wei Jiaec044b02018-02-19 12:41:23 -0800673 return 0;
674 }
675 return duration;
676}
677
678} // namespace android