blob: f7e8a9d3182eeba2568d156d21447af94fce3fef [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 Zhangc2465c52018-11-12 11:56:05 -080063 const jobject attributes, std::vector<jobject>& routingDelegatesBackup)
Dichen Zhangf8726912018-10-17 13:31:26 -070064 : 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 Zhangc2465c52018-11-12 11:56:05 -080079
80 if (mAttributes != nullptr) {
81 mAttributes->~JObjectHolder();
82 }
83 if (attributes != nullptr) {
84 mAttributes = new JObjectHolder(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -080085 }
86
87 setMinBufferCount();
Dichen Zhangf8726912018-10-17 13:31:26 -070088 mRoutingDelegates.clear();
89 for (auto routingDelegate : routingDelegatesBackup) {
90 mRoutingDelegates.push_back(std::pair<jobject, jobject>(
91 JAudioTrack::getListener(routingDelegate), routingDelegate));
92 }
93 routingDelegatesBackup.clear();
Wei Jiaec044b02018-02-19 12:41:23 -080094}
95
96MediaPlayer2AudioOutput::~MediaPlayer2AudioOutput() {
Dichen Zhangf8726912018-10-17 13:31:26 -070097 for (auto routingDelegate : mRoutingDelegates) {
98 JAudioTrack::removeGlobalRef(routingDelegate.second);
99 }
Wei Jiaec044b02018-02-19 12:41:23 -0800100 close();
Wei Jiaec044b02018-02-19 12:41:23 -0800101 delete mCallbackData;
102}
103
104//static
105void MediaPlayer2AudioOutput::setMinBufferCount() {
106 char value[PROPERTY_VALUE_MAX];
107 if (property_get("ro.kernel.qemu", value, 0)) {
108 mIsOnEmulator = true;
109 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
110 }
111}
112
113// static
114bool MediaPlayer2AudioOutput::isOnEmulator() {
115 setMinBufferCount(); // benign race wrt other threads
116 return mIsOnEmulator;
117}
118
119// static
120int MediaPlayer2AudioOutput::getMinBufferCount() {
121 setMinBufferCount(); // benign race wrt other threads
122 return mMinBufferCount;
123}
124
125ssize_t MediaPlayer2AudioOutput::bufferSize() const {
126 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700127 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800128 return NO_INIT;
129 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700130 return mJAudioTrack->frameCount() * mFrameSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800131}
132
133ssize_t MediaPlayer2AudioOutput::frameCount() const {
134 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700135 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800136 return NO_INIT;
137 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700138 return mJAudioTrack->frameCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800139}
140
141ssize_t MediaPlayer2AudioOutput::channelCount() const {
142 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700143 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800144 return NO_INIT;
145 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700146 return mJAudioTrack->channelCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800147}
148
149ssize_t MediaPlayer2AudioOutput::frameSize() const {
150 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700151 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800152 return NO_INIT;
153 }
154 return mFrameSize;
155}
156
157uint32_t MediaPlayer2AudioOutput::latency () const {
158 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700159 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800160 return 0;
161 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700162 return mJAudioTrack->latency();
Wei Jiaec044b02018-02-19 12:41:23 -0800163}
164
165float MediaPlayer2AudioOutput::msecsPerFrame() const {
166 Mutex::Autolock lock(mLock);
167 return mMsecsPerFrame;
168}
169
170status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
171 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700172 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800173 return NO_INIT;
174 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700175 return mJAudioTrack->getPosition(position);
Wei Jiaec044b02018-02-19 12:41:23 -0800176}
177
178status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
179 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700180 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800181 return NO_INIT;
182 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700183 return mJAudioTrack->getTimestamp(ts);
Wei Jiaec044b02018-02-19 12:41:23 -0800184}
185
186// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
187// as it acquires locks and may query the audio driver.
188//
189// Some calls could conceivably retrieve extrapolated data instead of
190// accessing getTimestamp() or getPosition() every time a data buffer with
191// a media time is received.
192//
193// Calculate duration of played samples if played at normal rate (i.e., 1.0).
194int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
195 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700196 if (mJAudioTrack == nullptr || mSampleRateHz == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800197 return 0;
198 }
199
200 uint32_t numFramesPlayed;
201 int64_t numFramesPlayedAtUs;
202 AudioTimestamp ts;
203
Dichen Zhangf8726912018-10-17 13:31:26 -0700204 status_t res = mJAudioTrack->getTimestamp(ts);
205
Wei Jiaec044b02018-02-19 12:41:23 -0800206 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
207 numFramesPlayed = ts.mPosition;
208 numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
209 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
Dichen Zhangf8726912018-10-17 13:31:26 -0700210 } else { // case 2: transitory state on start of a new track
211 // case 3: transitory at new track or audio fast tracks.
Wei Jiaec044b02018-02-19 12:41:23 -0800212 numFramesPlayed = 0;
213 numFramesPlayedAtUs = nowUs;
214 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
215 // numFramesPlayed, (long long)numFramesPlayedAtUs);
Wei Jiaec044b02018-02-19 12:41:23 -0800216 }
217
218 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
219 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
220 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
221 + nowUs - numFramesPlayedAtUs;
222 if (durationUs < 0) {
223 // Occurs when numFramesPlayed position is very small and the following:
224 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
225 // numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
226 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
227 // numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
228 //
229 // Both of these are transitory conditions.
230 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
231 durationUs = 0;
232 }
233 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
234 (long long)durationUs, (long long)nowUs,
235 numFramesPlayed, (long long)numFramesPlayedAtUs);
236 return durationUs;
237}
238
239status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
240 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700241 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800242 return NO_INIT;
243 }
244 ExtendedTimestamp ets;
Dichen Zhangf8726912018-10-17 13:31:26 -0700245 status_t status = mJAudioTrack->getTimestamp(&ets);
Wei Jiaec044b02018-02-19 12:41:23 -0800246 if (status == OK || status == WOULD_BLOCK) {
247 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
248 }
249 return status;
250}
251
Dichen Zhangc2465c52018-11-12 11:56:05 -0800252void MediaPlayer2AudioOutput::setAudioAttributes(const jobject attributes) {
Wei Jiaec044b02018-02-19 12:41:23 -0800253 Mutex::Autolock lock(mLock);
Dichen Zhangc2465c52018-11-12 11:56:05 -0800254 if (mAttributes != nullptr) {
255 mAttributes->~JObjectHolder();
256 }
257 if (attributes != nullptr) {
258 mAttributes = new JObjectHolder(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800259 }
260}
261
Dichen Zhangf8726912018-10-17 13:31:26 -0700262audio_stream_type_t MediaPlayer2AudioOutput::getAudioStreamType() const {
263 ALOGV("getAudioStreamType");
Wei Jiaec044b02018-02-19 12:41:23 -0800264 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700265 if (mJAudioTrack == nullptr) {
266 return AUDIO_STREAM_DEFAULT;
Wei Jiaec044b02018-02-19 12:41:23 -0800267 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700268 return mJAudioTrack->getAudioStreamType();
Wei Jiaec044b02018-02-19 12:41:23 -0800269}
270
271void MediaPlayer2AudioOutput::close_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700272 mJAudioTrack.clear();
Wei Jiaec044b02018-02-19 12:41:23 -0800273}
274
275status_t MediaPlayer2AudioOutput::open(
276 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700277 audio_format_t format,
Wei Jiaec044b02018-02-19 12:41:23 -0800278 AudioCallback cb, void *cookie,
279 audio_output_flags_t flags,
280 const audio_offload_info_t *offloadInfo,
Wei Jiaec044b02018-02-19 12:41:23 -0800281 uint32_t suggestedFrameCount) {
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700282 ALOGV("open(%u, %d, 0x%x, 0x%x, %d 0x%x)", sampleRate, channelCount, channelMask,
283 format, mSessionId, flags);
Wei Jiaec044b02018-02-19 12:41:23 -0800284
285 // offloading is only supported in callback mode for now.
286 // offloadInfo must be present if offload flag is set
287 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
Dichen Zhangf8726912018-10-17 13:31:26 -0700288 ((cb == nullptr) || (offloadInfo == nullptr))) {
Wei Jiaec044b02018-02-19 12:41:23 -0800289 return BAD_VALUE;
290 }
291
292 // compute frame count for the AudioTrack internal buffer
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700293 const size_t frameCount =
294 ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) ? 0 : suggestedFrameCount;
Wei Jiaec044b02018-02-19 12:41:23 -0800295
296 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
297 channelMask = audio_channel_out_mask_from_count(channelCount);
298 if (0 == channelMask) {
299 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
300 return NO_INIT;
301 }
302 }
303
304 Mutex::Autolock lock(mLock);
305 mCallback = cb;
306 mCallbackCookie = cookie;
307
Dichen Zhangf8726912018-10-17 13:31:26 -0700308 sp<JAudioTrack> jT;
309 CallbackData *newcbd = nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800310
Dichen Zhangf8726912018-10-17 13:31:26 -0700311 ALOGV("creating new JAudioTrack");
Wei Jiaec044b02018-02-19 12:41:23 -0800312
Dichen Zhangf8726912018-10-17 13:31:26 -0700313 if (mCallback != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800314 newcbd = new CallbackData(this);
Dichen Zhangf8726912018-10-17 13:31:26 -0700315 jT = new JAudioTrack(
316 sampleRate,
317 format,
318 channelMask,
319 CallbackWrapper,
320 newcbd,
321 frameCount,
322 mSessionId,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800323 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
Dichen Zhangf8726912018-10-17 13:31:26 -0700324 1.0f); // default value for maxRequiredSpeed
Wei Jiaec044b02018-02-19 12:41:23 -0800325 } else {
326 // TODO: Due to buffer memory concerns, we use a max target playback speed
327 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
328 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
329 const float targetSpeed =
330 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
331 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
332 "track target speed:%f clamped from playback speed:%f",
333 targetSpeed, mPlaybackRate.mSpeed);
Dichen Zhangf8726912018-10-17 13:31:26 -0700334 jT = new JAudioTrack(
335 sampleRate,
336 format,
337 channelMask,
338 nullptr,
339 nullptr,
340 frameCount,
341 mSessionId,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800342 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
Dichen Zhangf8726912018-10-17 13:31:26 -0700343 targetSpeed);
Wei Jiaec044b02018-02-19 12:41:23 -0800344 }
345
Dichen Zhangf8726912018-10-17 13:31:26 -0700346 if (jT == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800347 ALOGE("Unable to create audio track");
348 delete newcbd;
349 // t goes out of scope, so reference count drops to zero
350 return NO_INIT;
Wei Jiaec044b02018-02-19 12:41:23 -0800351 }
352
Dichen Zhangf8726912018-10-17 13:31:26 -0700353 CHECK((jT != nullptr) && ((mCallback == nullptr) || (newcbd != nullptr)));
Wei Jiaec044b02018-02-19 12:41:23 -0800354
355 mCallbackData = newcbd;
356 ALOGV("setVolume");
Dichen Zhangf8726912018-10-17 13:31:26 -0700357 jT->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800358
359 mSampleRateHz = sampleRate;
360 mFlags = flags;
361 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Dichen Zhangf8726912018-10-17 13:31:26 -0700362 mFrameSize = jT->frameSize();
363 mJAudioTrack = jT;
Wei Jiaec044b02018-02-19 12:41:23 -0800364
365 return updateTrack_l();
366}
367
368status_t MediaPlayer2AudioOutput::updateTrack_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700369 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800370 return NO_ERROR;
371 }
372
373 status_t res = NO_ERROR;
374 // Note some output devices may give us a direct track even though we don't specify it.
375 // Example: Line application b/17459982.
Dichen Zhangf8726912018-10-17 13:31:26 -0700376 if ((mJAudioTrack->getFlags()
Wei Jiaec044b02018-02-19 12:41:23 -0800377 & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700378 res = mJAudioTrack->setPlaybackRate(mPlaybackRate);
Wei Jiaec044b02018-02-19 12:41:23 -0800379 if (res == NO_ERROR) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700380 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
381 res = mJAudioTrack->attachAuxEffect(mAuxEffectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800382 }
383 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700384 if (mPreferredDevice != nullptr) {
385 mJAudioTrack->setPreferredDevice(mPreferredDevice->getJObject());
386 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700387
388 mJAudioTrack->registerRoutingDelegates(mRoutingDelegates);
389
Wei Jiaec044b02018-02-19 12:41:23 -0800390 ALOGV("updateTrack_l() DONE status %d", res);
391 return res;
392}
393
394status_t MediaPlayer2AudioOutput::start() {
395 ALOGV("start");
396 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700397 if (mCallbackData != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800398 mCallbackData->endTrackSwitch();
399 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700400 if (mJAudioTrack != nullptr) {
401 mJAudioTrack->setVolume(mVolume);
402 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
403 status_t status = mJAudioTrack->start();
Wei Jiaec044b02018-02-19 12:41:23 -0800404 return status;
405 }
406 return NO_INIT;
407}
408
409ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
410 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700411 LOG_ALWAYS_FATAL_IF(mCallback != nullptr, "Don't call write if supplying a callback.");
Wei Jiaec044b02018-02-19 12:41:23 -0800412
413 //ALOGV("write(%p, %u)", buffer, size);
Dichen Zhangf8726912018-10-17 13:31:26 -0700414 if (mJAudioTrack != nullptr) {
415 return mJAudioTrack->write(buffer, size, blocking);
Wei Jiaec044b02018-02-19 12:41:23 -0800416 }
417 return NO_INIT;
418}
419
420void MediaPlayer2AudioOutput::stop() {
421 ALOGV("stop");
422 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700423 if (mJAudioTrack != nullptr) {
424 mJAudioTrack->stop();
Wei Jiaec044b02018-02-19 12:41:23 -0800425 }
426}
427
428void MediaPlayer2AudioOutput::flush() {
429 ALOGV("flush");
430 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700431 if (mJAudioTrack != nullptr) {
432 mJAudioTrack->flush();
Wei Jiaec044b02018-02-19 12:41:23 -0800433 }
434}
435
436void MediaPlayer2AudioOutput::pause() {
437 ALOGV("pause");
438 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700439 if (mJAudioTrack != nullptr) {
440 mJAudioTrack->pause();
Wei Jiaec044b02018-02-19 12:41:23 -0800441 }
442}
443
444void MediaPlayer2AudioOutput::close() {
445 ALOGV("close");
Dichen Zhangf8726912018-10-17 13:31:26 -0700446 sp<JAudioTrack> track;
Wei Jiaec044b02018-02-19 12:41:23 -0800447 {
448 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700449 track = mJAudioTrack;
450 close_l(); // clears mJAudioTrack
Wei Jiaec044b02018-02-19 12:41:23 -0800451 }
452 // destruction of the track occurs outside of mutex.
453}
454
Dichen Zhang7398ca02018-10-15 10:25:12 -0700455void MediaPlayer2AudioOutput::setVolume(float volume) {
456 ALOGV("setVolume(%f)", volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800457 Mutex::Autolock lock(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700458 mVolume = volume;
Dichen Zhangf8726912018-10-17 13:31:26 -0700459 if (mJAudioTrack != nullptr) {
460 mJAudioTrack->setVolume(volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800461 }
462}
463
464status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
465 ALOGV("setPlaybackRate(%f %f %d %d)",
466 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
467 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700468 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800469 // remember rate so that we can set it when the track is opened
470 mPlaybackRate = rate;
471 return OK;
472 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700473 status_t res = mJAudioTrack->setPlaybackRate(rate);
Wei Jiaec044b02018-02-19 12:41:23 -0800474 if (res != NO_ERROR) {
475 return res;
476 }
477 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
478 CHECK_GT(rate.mSpeed, 0.f);
479 mPlaybackRate = rate;
480 if (mSampleRateHz != 0) {
481 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
482 }
483 return res;
484}
485
486status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
Dichen Zhang790249b2018-09-13 15:08:14 -0700487 ALOGV("getPlaybackRate");
Wei Jiaec044b02018-02-19 12:41:23 -0800488 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700489 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800490 return NO_INIT;
491 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700492 *rate = mJAudioTrack->getPlaybackRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800493 return NO_ERROR;
494}
495
496status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
497 ALOGV("setAuxEffectSendLevel(%f)", level);
498 Mutex::Autolock lock(mLock);
499 mSendLevel = level;
Dichen Zhangf8726912018-10-17 13:31:26 -0700500 if (mJAudioTrack != nullptr) {
501 return mJAudioTrack->setAuxEffectSendLevel(level);
Wei Jiaec044b02018-02-19 12:41:23 -0800502 }
503 return NO_ERROR;
504}
505
506status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
507 ALOGV("attachAuxEffect(%d)", effectId);
508 Mutex::Autolock lock(mLock);
509 mAuxEffectId = effectId;
Dichen Zhangf8726912018-10-17 13:31:26 -0700510 if (mJAudioTrack != nullptr) {
511 return mJAudioTrack->attachAuxEffect(effectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800512 }
513 return NO_ERROR;
514}
515
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700516status_t MediaPlayer2AudioOutput::setPreferredDevice(jobject device) {
517 ALOGV("setPreferredDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800518 Mutex::Autolock lock(mLock);
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700519 status_t ret = NO_ERROR;
Dichen Zhangf8726912018-10-17 13:31:26 -0700520 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700521 ret = mJAudioTrack->setPreferredDevice(device);
Wei Jiaec044b02018-02-19 12:41:23 -0800522 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700523 if (ret == NO_ERROR) {
524 mPreferredDevice = new JObjectHolder(device);
525 }
526 return ret;
Wei Jiaec044b02018-02-19 12:41:23 -0800527}
528
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700529jobject MediaPlayer2AudioOutput::getRoutedDevice() {
530 ALOGV("getRoutedDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800531 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700532 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700533 return mJAudioTrack->getRoutedDevice();
Wei Jiaec044b02018-02-19 12:41:23 -0800534 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700535 return nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800536}
537
Dichen Zhangf8726912018-10-17 13:31:26 -0700538status_t MediaPlayer2AudioOutput::addAudioDeviceCallback(jobject jRoutingDelegate) {
539 ALOGV("addAudioDeviceCallback");
Wei Jiaec044b02018-02-19 12:41:23 -0800540 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700541 jobject listener = JAudioTrack::getListener(jRoutingDelegate);
542 if (mJAudioTrack != nullptr &&
543 JAudioTrack::findByKey(mRoutingDelegates, listener) == nullptr) {
544 jobject handler = JAudioTrack::getHandler(jRoutingDelegate);
545 jobject routingDelegate = JAudioTrack::addGlobalRef(jRoutingDelegate);
546 mRoutingDelegates.push_back(std::pair<jobject, jobject>(listener, routingDelegate));
547 return mJAudioTrack->addAudioDeviceCallback(routingDelegate, handler);
Wei Jiaec044b02018-02-19 12:41:23 -0800548 }
549 return NO_ERROR;
550}
551
Dichen Zhangf8726912018-10-17 13:31:26 -0700552status_t MediaPlayer2AudioOutput::removeAudioDeviceCallback(jobject listener) {
553 ALOGV("removeAudioDeviceCallback");
554 Mutex::Autolock lock(mLock);
555 jobject routingDelegate = nullptr;
556 if (mJAudioTrack != nullptr &&
557 (routingDelegate = JAudioTrack::findByKey(mRoutingDelegates, listener)) != nullptr) {
558 mJAudioTrack->removeAudioDeviceCallback(routingDelegate);
559 JAudioTrack::eraseByKey(mRoutingDelegates, listener);
560 if (JAudioTrack::removeGlobalRef(routingDelegate) != NO_ERROR) {
561 return BAD_VALUE;
562 }
563 }
564 return NO_ERROR;
565}
566
567void MediaPlayer2AudioOutput::copyAudioDeviceCallback(
568 std::vector<jobject>& routingDelegateTarget) {
569 ALOGV("copyAudioDeviceCallback");
570 for (std::vector<std::pair<jobject, jobject>>::iterator it = mRoutingDelegates.begin();
571 it != mRoutingDelegates.end(); it++) {
572 routingDelegateTarget.push_back(it->second);
573 }
574}
575
Wei Jiaec044b02018-02-19 12:41:23 -0800576// static
577void MediaPlayer2AudioOutput::CallbackWrapper(
578 int event, void *cookie, void *info) {
579 //ALOGV("callbackwrapper");
580 CallbackData *data = (CallbackData*)cookie;
581 // lock to ensure we aren't caught in the middle of a track switch.
582 data->lock();
583 MediaPlayer2AudioOutput *me = data->getOutput();
Dichen Zhangf8726912018-10-17 13:31:26 -0700584 JAudioTrack::Buffer *buffer = (JAudioTrack::Buffer *)info;
585 if (me == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800586 // no output set, likely because the track was scheduled to be reused
587 // by another player, but the format turned out to be incompatible.
588 data->unlock();
Dichen Zhangf8726912018-10-17 13:31:26 -0700589 if (buffer != nullptr) {
590 buffer->mSize = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800591 }
592 return;
593 }
594
595 switch(event) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700596 case JAudioTrack::EVENT_MORE_DATA: {
Wei Jiaec044b02018-02-19 12:41:23 -0800597 size_t actualSize = (*me->mCallback)(
Dichen Zhangf8726912018-10-17 13:31:26 -0700598 me, buffer->mData, buffer->mSize, me->mCallbackCookie,
Wei Jiaec044b02018-02-19 12:41:23 -0800599 CB_EVENT_FILL_BUFFER);
600
601 // Log when no data is returned from the callback.
602 // (1) We may have no data (especially with network streaming sources).
603 // (2) We may have reached the EOS and the audio track is not stopped yet.
604 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
605 // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
606 //
607 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
608 // nevertheless for power reasons, we don't want to see too many of these.
609
Dichen Zhangf8726912018-10-17 13:31:26 -0700610 ALOGV_IF(actualSize == 0 && buffer->mSize > 0, "callbackwrapper: empty buffer returned");
Wei Jiaec044b02018-02-19 12:41:23 -0800611
Dichen Zhangf8726912018-10-17 13:31:26 -0700612 buffer->mSize = actualSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800613 } break;
614
Dichen Zhangf8726912018-10-17 13:31:26 -0700615 case JAudioTrack::EVENT_STREAM_END:
Wei Jiaec044b02018-02-19 12:41:23 -0800616 // currently only occurs for offloaded callbacks
617 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
Dichen Zhangf8726912018-10-17 13:31:26 -0700618 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800619 me->mCallbackCookie, CB_EVENT_STREAM_END);
620 break;
621
Dichen Zhangf8726912018-10-17 13:31:26 -0700622 case JAudioTrack::EVENT_NEW_IAUDIOTRACK :
Wei Jiaec044b02018-02-19 12:41:23 -0800623 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
Dichen Zhangf8726912018-10-17 13:31:26 -0700624 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800625 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
626 break;
627
Dichen Zhangf8726912018-10-17 13:31:26 -0700628 case JAudioTrack::EVENT_UNDERRUN:
Wei Jiaec044b02018-02-19 12:41:23 -0800629 // This occurs when there is no data available, typically
630 // when there is a failure to supply data to the AudioTrack. It can also
631 // occur in non-offloaded mode when the audio device comes out of standby.
632 //
633 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
634 // it may sound like an audible pop or glitch.
635 //
636 // The underrun event is sent once per track underrun; the condition is reset
637 // when more data is sent to the AudioTrack.
638 ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
639 break;
640
641 default:
642 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
643 }
644
645 data->unlock();
646}
647
Dichen Zhangf8726912018-10-17 13:31:26 -0700648audio_session_t MediaPlayer2AudioOutput::getSessionId() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800649 Mutex::Autolock lock(mLock);
650 return mSessionId;
651}
652
Dichen Zhangf8726912018-10-17 13:31:26 -0700653uint32_t MediaPlayer2AudioOutput::getSampleRate() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800654 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700655 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800656 return 0;
657 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700658 return mJAudioTrack->getSampleRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800659}
660
Dichen Zhangf8726912018-10-17 13:31:26 -0700661int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800662 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700663 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800664 return 0;
665 }
666 int64_t duration;
Dichen Zhangf8726912018-10-17 13:31:26 -0700667 if (mJAudioTrack->getBufferDurationInUs(&duration) != OK) {
Wei Jiaec044b02018-02-19 12:41:23 -0800668 return 0;
669 }
670 return duration;
671}
672
673} // namespace android