blob: b4fa0c1cf50bccb88a3510076670655b9fae213b [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() {
88 close();
Wei Jiaec044b02018-02-19 12:41:23 -080089 delete mCallbackData;
90}
91
92//static
93void MediaPlayer2AudioOutput::setMinBufferCount() {
94 char value[PROPERTY_VALUE_MAX];
95 if (property_get("ro.kernel.qemu", value, 0)) {
96 mIsOnEmulator = true;
97 mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
98 }
99}
100
101// static
102bool MediaPlayer2AudioOutput::isOnEmulator() {
103 setMinBufferCount(); // benign race wrt other threads
104 return mIsOnEmulator;
105}
106
107// static
108int MediaPlayer2AudioOutput::getMinBufferCount() {
109 setMinBufferCount(); // benign race wrt other threads
110 return mMinBufferCount;
111}
112
113ssize_t MediaPlayer2AudioOutput::bufferSize() const {
114 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700115 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800116 return NO_INIT;
117 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700118 return mJAudioTrack->frameCount() * mFrameSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800119}
120
121ssize_t MediaPlayer2AudioOutput::frameCount() const {
122 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700123 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800124 return NO_INIT;
125 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700126 return mJAudioTrack->frameCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800127}
128
129ssize_t MediaPlayer2AudioOutput::channelCount() const {
130 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700131 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800132 return NO_INIT;
133 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700134 return mJAudioTrack->channelCount();
Wei Jiaec044b02018-02-19 12:41:23 -0800135}
136
137ssize_t MediaPlayer2AudioOutput::frameSize() const {
138 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700139 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800140 return NO_INIT;
141 }
142 return mFrameSize;
143}
144
145uint32_t MediaPlayer2AudioOutput::latency () const {
146 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700147 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800148 return 0;
149 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700150 return mJAudioTrack->latency();
Wei Jiaec044b02018-02-19 12:41:23 -0800151}
152
153float MediaPlayer2AudioOutput::msecsPerFrame() const {
154 Mutex::Autolock lock(mLock);
155 return mMsecsPerFrame;
156}
157
158status_t MediaPlayer2AudioOutput::getPosition(uint32_t *position) const {
159 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700160 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800161 return NO_INIT;
162 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700163 return mJAudioTrack->getPosition(position);
Wei Jiaec044b02018-02-19 12:41:23 -0800164}
165
166status_t MediaPlayer2AudioOutput::getTimestamp(AudioTimestamp &ts) const {
167 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700168 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800169 return NO_INIT;
170 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700171 return mJAudioTrack->getTimestamp(ts);
Wei Jiaec044b02018-02-19 12:41:23 -0800172}
173
174// TODO: Remove unnecessary calls to getPlayedOutDurationUs()
175// as it acquires locks and may query the audio driver.
176//
177// Some calls could conceivably retrieve extrapolated data instead of
178// accessing getTimestamp() or getPosition() every time a data buffer with
179// a media time is received.
180//
181// Calculate duration of played samples if played at normal rate (i.e., 1.0).
182int64_t MediaPlayer2AudioOutput::getPlayedOutDurationUs(int64_t nowUs) const {
183 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700184 if (mJAudioTrack == nullptr || mSampleRateHz == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800185 return 0;
186 }
187
188 uint32_t numFramesPlayed;
189 int64_t numFramesPlayedAtUs;
190 AudioTimestamp ts;
191
Dichen Zhangf8726912018-10-17 13:31:26 -0700192 status_t res = mJAudioTrack->getTimestamp(ts);
193
Wei Jiaec044b02018-02-19 12:41:23 -0800194 if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
195 numFramesPlayed = ts.mPosition;
196 numFramesPlayedAtUs = ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
197 //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAtUs);
Dichen Zhangf8726912018-10-17 13:31:26 -0700198 } else { // case 2: transitory state on start of a new track
199 // case 3: transitory at new track or audio fast tracks.
Wei Jiaec044b02018-02-19 12:41:23 -0800200 numFramesPlayed = 0;
201 numFramesPlayedAtUs = nowUs;
202 //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
203 // numFramesPlayed, (long long)numFramesPlayedAtUs);
Wei Jiaec044b02018-02-19 12:41:23 -0800204 }
205
206 // CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
207 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
208 int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000000LL / mSampleRateHz)
209 + nowUs - numFramesPlayedAtUs;
210 if (durationUs < 0) {
211 // Occurs when numFramesPlayed position is very small and the following:
212 // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
213 // numFramesPlayedAtUs is greater than nowUs by time more than numFramesPlayed.
214 // (2) In case 3, using getPosition and adding mAudioSink->latency() to
215 // numFramesPlayedAtUs, by a time amount greater than numFramesPlayed.
216 //
217 // Both of these are transitory conditions.
218 ALOGV("getPlayedOutDurationUs: negative duration %lld set to zero", (long long)durationUs);
219 durationUs = 0;
220 }
221 ALOGV("getPlayedOutDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
222 (long long)durationUs, (long long)nowUs,
223 numFramesPlayed, (long long)numFramesPlayedAtUs);
224 return durationUs;
225}
226
227status_t MediaPlayer2AudioOutput::getFramesWritten(uint32_t *frameswritten) const {
228 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700229 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800230 return NO_INIT;
231 }
232 ExtendedTimestamp ets;
Dichen Zhangf8726912018-10-17 13:31:26 -0700233 status_t status = mJAudioTrack->getTimestamp(&ets);
Wei Jiaec044b02018-02-19 12:41:23 -0800234 if (status == OK || status == WOULD_BLOCK) {
235 *frameswritten = (uint32_t)ets.mPosition[ExtendedTimestamp::LOCATION_CLIENT];
236 }
237 return status;
238}
239
Dichen Zhangc2465c52018-11-12 11:56:05 -0800240void MediaPlayer2AudioOutput::setAudioAttributes(const jobject attributes) {
Wei Jiaec044b02018-02-19 12:41:23 -0800241 Mutex::Autolock lock(mLock);
Dongwon Kang203b0532018-11-14 10:51:37 -0800242 mAttributes = (attributes == nullptr) ? nullptr : new JObjectHolder(attributes);
Wei Jiaec044b02018-02-19 12:41:23 -0800243}
244
Dichen Zhangf8726912018-10-17 13:31:26 -0700245audio_stream_type_t MediaPlayer2AudioOutput::getAudioStreamType() const {
246 ALOGV("getAudioStreamType");
Wei Jiaec044b02018-02-19 12:41:23 -0800247 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700248 if (mJAudioTrack == nullptr) {
249 return AUDIO_STREAM_DEFAULT;
Wei Jiaec044b02018-02-19 12:41:23 -0800250 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700251 return mJAudioTrack->getAudioStreamType();
Wei Jiaec044b02018-02-19 12:41:23 -0800252}
253
254void MediaPlayer2AudioOutput::close_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700255 mJAudioTrack.clear();
Wei Jiaec044b02018-02-19 12:41:23 -0800256}
257
258status_t MediaPlayer2AudioOutput::open(
259 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700260 audio_format_t format,
Wei Jiaec044b02018-02-19 12:41:23 -0800261 AudioCallback cb, void *cookie,
262 audio_output_flags_t flags,
263 const audio_offload_info_t *offloadInfo,
Wei Jiaec044b02018-02-19 12:41:23 -0800264 uint32_t suggestedFrameCount) {
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700265 ALOGV("open(%u, %d, 0x%x, 0x%x, %d 0x%x)", sampleRate, channelCount, channelMask,
266 format, mSessionId, flags);
Wei Jiaec044b02018-02-19 12:41:23 -0800267
268 // offloading is only supported in callback mode for now.
269 // offloadInfo must be present if offload flag is set
270 if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) &&
Dichen Zhangf8726912018-10-17 13:31:26 -0700271 ((cb == nullptr) || (offloadInfo == nullptr))) {
Wei Jiaec044b02018-02-19 12:41:23 -0800272 return BAD_VALUE;
273 }
274
275 // compute frame count for the AudioTrack internal buffer
Dichen Zhang303bd2d2018-09-28 12:52:49 -0700276 const size_t frameCount =
277 ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) ? 0 : suggestedFrameCount;
Wei Jiaec044b02018-02-19 12:41:23 -0800278
279 if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
280 channelMask = audio_channel_out_mask_from_count(channelCount);
281 if (0 == channelMask) {
282 ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
283 return NO_INIT;
284 }
285 }
286
287 Mutex::Autolock lock(mLock);
288 mCallback = cb;
289 mCallbackCookie = cookie;
290
Dichen Zhangf8726912018-10-17 13:31:26 -0700291 sp<JAudioTrack> jT;
292 CallbackData *newcbd = nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800293
Dichen Zhangf8726912018-10-17 13:31:26 -0700294 ALOGV("creating new JAudioTrack");
Wei Jiaec044b02018-02-19 12:41:23 -0800295
Dichen Zhangf8726912018-10-17 13:31:26 -0700296 if (mCallback != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800297 newcbd = new CallbackData(this);
Dichen Zhangf8726912018-10-17 13:31:26 -0700298 jT = new JAudioTrack(
299 sampleRate,
300 format,
301 channelMask,
302 CallbackWrapper,
303 newcbd,
304 frameCount,
305 mSessionId,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800306 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
Dichen Zhangf8726912018-10-17 13:31:26 -0700307 1.0f); // default value for maxRequiredSpeed
Wei Jiaec044b02018-02-19 12:41:23 -0800308 } else {
309 // TODO: Due to buffer memory concerns, we use a max target playback speed
310 // based on mPlaybackRate at the time of open (instead of kMaxRequiredSpeed),
311 // also clamping the target speed to 1.0 <= targetSpeed <= kMaxRequiredSpeed.
312 const float targetSpeed =
313 std::min(std::max(mPlaybackRate.mSpeed, 1.0f), kMaxRequiredSpeed);
314 ALOGW_IF(targetSpeed != mPlaybackRate.mSpeed,
315 "track target speed:%f clamped from playback speed:%f",
316 targetSpeed, mPlaybackRate.mSpeed);
Dichen Zhangf8726912018-10-17 13:31:26 -0700317 jT = new JAudioTrack(
318 sampleRate,
319 format,
320 channelMask,
321 nullptr,
322 nullptr,
323 frameCount,
324 mSessionId,
Dichen Zhangc2465c52018-11-12 11:56:05 -0800325 mAttributes != nullptr ? mAttributes->getJObject() : nullptr,
Dichen Zhangf8726912018-10-17 13:31:26 -0700326 targetSpeed);
Wei Jiaec044b02018-02-19 12:41:23 -0800327 }
328
Dichen Zhangf8726912018-10-17 13:31:26 -0700329 if (jT == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800330 ALOGE("Unable to create audio track");
331 delete newcbd;
332 // t goes out of scope, so reference count drops to zero
333 return NO_INIT;
Wei Jiaec044b02018-02-19 12:41:23 -0800334 }
335
Dichen Zhangf8726912018-10-17 13:31:26 -0700336 CHECK((jT != nullptr) && ((mCallback == nullptr) || (newcbd != nullptr)));
Wei Jiaec044b02018-02-19 12:41:23 -0800337
338 mCallbackData = newcbd;
339 ALOGV("setVolume");
Dichen Zhangf8726912018-10-17 13:31:26 -0700340 jT->setVolume(mVolume);
Wei Jiaec044b02018-02-19 12:41:23 -0800341
342 mSampleRateHz = sampleRate;
343 mFlags = flags;
344 mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
Dichen Zhangf8726912018-10-17 13:31:26 -0700345 mFrameSize = jT->frameSize();
346 mJAudioTrack = jT;
Wei Jiaec044b02018-02-19 12:41:23 -0800347
348 return updateTrack_l();
349}
350
351status_t MediaPlayer2AudioOutput::updateTrack_l() {
Dichen Zhangf8726912018-10-17 13:31:26 -0700352 if (mJAudioTrack == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800353 return NO_ERROR;
354 }
355
356 status_t res = NO_ERROR;
357 // Note some output devices may give us a direct track even though we don't specify it.
358 // Example: Line application b/17459982.
Dichen Zhangf8726912018-10-17 13:31:26 -0700359 if ((mJAudioTrack->getFlags()
Wei Jiaec044b02018-02-19 12:41:23 -0800360 & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT)) == 0) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700361 res = mJAudioTrack->setPlaybackRate(mPlaybackRate);
Wei Jiaec044b02018-02-19 12:41:23 -0800362 if (res == NO_ERROR) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700363 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
364 res = mJAudioTrack->attachAuxEffect(mAuxEffectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800365 }
366 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700367 if (mPreferredDevice != nullptr) {
368 mJAudioTrack->setPreferredDevice(mPreferredDevice->getJObject());
369 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700370
371 mJAudioTrack->registerRoutingDelegates(mRoutingDelegates);
372
Wei Jiaec044b02018-02-19 12:41:23 -0800373 ALOGV("updateTrack_l() DONE status %d", res);
374 return res;
375}
376
377status_t MediaPlayer2AudioOutput::start() {
378 ALOGV("start");
379 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700380 if (mCallbackData != nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800381 mCallbackData->endTrackSwitch();
382 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700383 if (mJAudioTrack != nullptr) {
384 mJAudioTrack->setVolume(mVolume);
385 mJAudioTrack->setAuxEffectSendLevel(mSendLevel);
386 status_t status = mJAudioTrack->start();
Wei Jiaec044b02018-02-19 12:41:23 -0800387 return status;
388 }
389 return NO_INIT;
390}
391
392ssize_t MediaPlayer2AudioOutput::write(const void* buffer, size_t size, bool blocking) {
393 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700394 LOG_ALWAYS_FATAL_IF(mCallback != nullptr, "Don't call write if supplying a callback.");
Wei Jiaec044b02018-02-19 12:41:23 -0800395
396 //ALOGV("write(%p, %u)", buffer, size);
Dichen Zhangf8726912018-10-17 13:31:26 -0700397 if (mJAudioTrack != nullptr) {
398 return mJAudioTrack->write(buffer, size, blocking);
Wei Jiaec044b02018-02-19 12:41:23 -0800399 }
400 return NO_INIT;
401}
402
403void MediaPlayer2AudioOutput::stop() {
404 ALOGV("stop");
405 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700406 if (mJAudioTrack != nullptr) {
407 mJAudioTrack->stop();
Wei Jiaec044b02018-02-19 12:41:23 -0800408 }
409}
410
411void MediaPlayer2AudioOutput::flush() {
412 ALOGV("flush");
413 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700414 if (mJAudioTrack != nullptr) {
415 mJAudioTrack->flush();
Wei Jiaec044b02018-02-19 12:41:23 -0800416 }
417}
418
419void MediaPlayer2AudioOutput::pause() {
420 ALOGV("pause");
421 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700422 if (mJAudioTrack != nullptr) {
423 mJAudioTrack->pause();
Wei Jiaec044b02018-02-19 12:41:23 -0800424 }
425}
426
427void MediaPlayer2AudioOutput::close() {
428 ALOGV("close");
Dichen Zhangf8726912018-10-17 13:31:26 -0700429 sp<JAudioTrack> track;
Wei Jiaec044b02018-02-19 12:41:23 -0800430 {
431 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700432 track = mJAudioTrack;
433 close_l(); // clears mJAudioTrack
Wei Jiaec044b02018-02-19 12:41:23 -0800434 }
435 // destruction of the track occurs outside of mutex.
436}
437
Dichen Zhang7398ca02018-10-15 10:25:12 -0700438void MediaPlayer2AudioOutput::setVolume(float volume) {
439 ALOGV("setVolume(%f)", volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800440 Mutex::Autolock lock(mLock);
Dichen Zhang7398ca02018-10-15 10:25:12 -0700441 mVolume = volume;
Dichen Zhangf8726912018-10-17 13:31:26 -0700442 if (mJAudioTrack != nullptr) {
443 mJAudioTrack->setVolume(volume);
Wei Jiaec044b02018-02-19 12:41:23 -0800444 }
445}
446
447status_t MediaPlayer2AudioOutput::setPlaybackRate(const AudioPlaybackRate &rate) {
448 ALOGV("setPlaybackRate(%f %f %d %d)",
449 rate.mSpeed, rate.mPitch, rate.mFallbackMode, rate.mStretchMode);
450 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700451 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800452 // remember rate so that we can set it when the track is opened
453 mPlaybackRate = rate;
454 return OK;
455 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700456 status_t res = mJAudioTrack->setPlaybackRate(rate);
Wei Jiaec044b02018-02-19 12:41:23 -0800457 if (res != NO_ERROR) {
458 return res;
459 }
460 // rate.mSpeed is always greater than 0 if setPlaybackRate succeeded
461 CHECK_GT(rate.mSpeed, 0.f);
462 mPlaybackRate = rate;
463 if (mSampleRateHz != 0) {
464 mMsecsPerFrame = 1E3f / (rate.mSpeed * mSampleRateHz);
465 }
466 return res;
467}
468
469status_t MediaPlayer2AudioOutput::getPlaybackRate(AudioPlaybackRate *rate) {
Dichen Zhang790249b2018-09-13 15:08:14 -0700470 ALOGV("getPlaybackRate");
Wei Jiaec044b02018-02-19 12:41:23 -0800471 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700472 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800473 return NO_INIT;
474 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700475 *rate = mJAudioTrack->getPlaybackRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800476 return NO_ERROR;
477}
478
479status_t MediaPlayer2AudioOutput::setAuxEffectSendLevel(float level) {
480 ALOGV("setAuxEffectSendLevel(%f)", level);
481 Mutex::Autolock lock(mLock);
482 mSendLevel = level;
Dichen Zhangf8726912018-10-17 13:31:26 -0700483 if (mJAudioTrack != nullptr) {
484 return mJAudioTrack->setAuxEffectSendLevel(level);
Wei Jiaec044b02018-02-19 12:41:23 -0800485 }
486 return NO_ERROR;
487}
488
489status_t MediaPlayer2AudioOutput::attachAuxEffect(int effectId) {
490 ALOGV("attachAuxEffect(%d)", effectId);
491 Mutex::Autolock lock(mLock);
492 mAuxEffectId = effectId;
Dichen Zhangf8726912018-10-17 13:31:26 -0700493 if (mJAudioTrack != nullptr) {
494 return mJAudioTrack->attachAuxEffect(effectId);
Wei Jiaec044b02018-02-19 12:41:23 -0800495 }
496 return NO_ERROR;
497}
498
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700499status_t MediaPlayer2AudioOutput::setPreferredDevice(jobject device) {
500 ALOGV("setPreferredDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800501 Mutex::Autolock lock(mLock);
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700502 status_t ret = NO_ERROR;
Dichen Zhangf8726912018-10-17 13:31:26 -0700503 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700504 ret = mJAudioTrack->setPreferredDevice(device);
Wei Jiaec044b02018-02-19 12:41:23 -0800505 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700506 if (ret == NO_ERROR) {
507 mPreferredDevice = new JObjectHolder(device);
508 }
509 return ret;
Wei Jiaec044b02018-02-19 12:41:23 -0800510}
511
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700512jobject MediaPlayer2AudioOutput::getRoutedDevice() {
513 ALOGV("getRoutedDevice");
Wei Jiaec044b02018-02-19 12:41:23 -0800514 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700515 if (mJAudioTrack != nullptr) {
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700516 return mJAudioTrack->getRoutedDevice();
Wei Jiaec044b02018-02-19 12:41:23 -0800517 }
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700518 return nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -0800519}
520
Dichen Zhangf8726912018-10-17 13:31:26 -0700521status_t MediaPlayer2AudioOutput::addAudioDeviceCallback(jobject jRoutingDelegate) {
522 ALOGV("addAudioDeviceCallback");
Wei Jiaec044b02018-02-19 12:41:23 -0800523 Mutex::Autolock lock(mLock);
Dichen Zhang2a1a52c2019-03-14 16:57:47 -0700524 jobject listener = JAudioTrack::getListener(jRoutingDelegate);
Dichen Zhang4e9bfa02019-03-06 16:33:59 -0800525 if (JAudioTrack::findByKey(mRoutingDelegates, listener) == nullptr) {
Dichen Zhang2a1a52c2019-03-14 16:57:47 -0700526 sp<JObjectHolder> listenerHolder = new JObjectHolder(listener);
527 jobject handler = JAudioTrack::getHandler(jRoutingDelegate);
528 sp<JObjectHolder> routingDelegateHolder = new JObjectHolder(jRoutingDelegate);
529
530 mRoutingDelegates.push_back(std::pair<sp<JObjectHolder>, sp<JObjectHolder>>(
531 listenerHolder, routingDelegateHolder));
532
Dichen Zhang4e9bfa02019-03-06 16:33:59 -0800533 if (mJAudioTrack != nullptr) {
Dichen Zhang2a1a52c2019-03-14 16:57:47 -0700534 return mJAudioTrack->addAudioDeviceCallback(
535 routingDelegateHolder->getJObject(), handler);
Dichen Zhang4e9bfa02019-03-06 16:33:59 -0800536 }
Wei Jiaec044b02018-02-19 12:41:23 -0800537 }
538 return NO_ERROR;
539}
540
Dichen Zhangf8726912018-10-17 13:31:26 -0700541status_t MediaPlayer2AudioOutput::removeAudioDeviceCallback(jobject listener) {
542 ALOGV("removeAudioDeviceCallback");
543 Mutex::Autolock lock(mLock);
544 jobject routingDelegate = nullptr;
Dichen Zhang4e9bfa02019-03-06 16:33:59 -0800545 if ((routingDelegate = JAudioTrack::findByKey(mRoutingDelegates, listener)) != nullptr) {
546 if (mJAudioTrack != nullptr) {
547 mJAudioTrack->removeAudioDeviceCallback(routingDelegate);
Dichen Zhangf8726912018-10-17 13:31:26 -0700548 }
Dichen Zhang4e9bfa02019-03-06 16:33:59 -0800549 JAudioTrack::eraseByKey(mRoutingDelegates, listener);
Dichen Zhangf8726912018-10-17 13:31:26 -0700550 }
551 return NO_ERROR;
552}
553
Wei Jiaec044b02018-02-19 12:41:23 -0800554// static
555void MediaPlayer2AudioOutput::CallbackWrapper(
556 int event, void *cookie, void *info) {
557 //ALOGV("callbackwrapper");
558 CallbackData *data = (CallbackData*)cookie;
559 // lock to ensure we aren't caught in the middle of a track switch.
560 data->lock();
561 MediaPlayer2AudioOutput *me = data->getOutput();
Dichen Zhangf8726912018-10-17 13:31:26 -0700562 JAudioTrack::Buffer *buffer = (JAudioTrack::Buffer *)info;
563 if (me == nullptr) {
Wei Jiaec044b02018-02-19 12:41:23 -0800564 // no output set, likely because the track was scheduled to be reused
565 // by another player, but the format turned out to be incompatible.
566 data->unlock();
Dichen Zhangf8726912018-10-17 13:31:26 -0700567 if (buffer != nullptr) {
568 buffer->mSize = 0;
Wei Jiaec044b02018-02-19 12:41:23 -0800569 }
570 return;
571 }
572
573 switch(event) {
Dichen Zhangf8726912018-10-17 13:31:26 -0700574 case JAudioTrack::EVENT_MORE_DATA: {
Wei Jiaec044b02018-02-19 12:41:23 -0800575 size_t actualSize = (*me->mCallback)(
Dichen Zhangf8726912018-10-17 13:31:26 -0700576 me, buffer->mData, buffer->mSize, me->mCallbackCookie,
Wei Jiaec044b02018-02-19 12:41:23 -0800577 CB_EVENT_FILL_BUFFER);
578
579 // Log when no data is returned from the callback.
580 // (1) We may have no data (especially with network streaming sources).
581 // (2) We may have reached the EOS and the audio track is not stopped yet.
582 // Note that AwesomePlayer/AudioPlayer will only return zero size when it reaches the EOS.
583 // NuPlayer2Renderer will return zero when it doesn't have data (it doesn't block to fill).
584 //
585 // This is a benign busy-wait, with the next data request generated 10 ms or more later;
586 // nevertheless for power reasons, we don't want to see too many of these.
587
Dichen Zhangf8726912018-10-17 13:31:26 -0700588 ALOGV_IF(actualSize == 0 && buffer->mSize > 0, "callbackwrapper: empty buffer returned");
Wei Jiaec044b02018-02-19 12:41:23 -0800589
Dichen Zhangf8726912018-10-17 13:31:26 -0700590 buffer->mSize = actualSize;
Wei Jiaec044b02018-02-19 12:41:23 -0800591 } break;
592
Dichen Zhangf8726912018-10-17 13:31:26 -0700593 case JAudioTrack::EVENT_STREAM_END:
Wei Jiaec044b02018-02-19 12:41:23 -0800594 // currently only occurs for offloaded callbacks
595 ALOGV("callbackwrapper: deliver EVENT_STREAM_END");
Dichen Zhangf8726912018-10-17 13:31:26 -0700596 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800597 me->mCallbackCookie, CB_EVENT_STREAM_END);
598 break;
599
Dichen Zhangf8726912018-10-17 13:31:26 -0700600 case JAudioTrack::EVENT_NEW_IAUDIOTRACK :
Wei Jiaec044b02018-02-19 12:41:23 -0800601 ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN");
Dichen Zhangf8726912018-10-17 13:31:26 -0700602 (*me->mCallback)(me, nullptr /* buffer */, 0 /* size */,
Wei Jiaec044b02018-02-19 12:41:23 -0800603 me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
604 break;
605
Dichen Zhangf8726912018-10-17 13:31:26 -0700606 case JAudioTrack::EVENT_UNDERRUN:
Wei Jiaec044b02018-02-19 12:41:23 -0800607 // This occurs when there is no data available, typically
608 // when there is a failure to supply data to the AudioTrack. It can also
609 // occur in non-offloaded mode when the audio device comes out of standby.
610 //
611 // If an AudioTrack underruns it outputs silence. Since this happens suddenly
612 // it may sound like an audible pop or glitch.
613 //
614 // The underrun event is sent once per track underrun; the condition is reset
615 // when more data is sent to the AudioTrack.
616 ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
617 break;
618
619 default:
620 ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
621 }
622
623 data->unlock();
624}
625
Dichen Zhang23658642018-11-15 10:26:16 -0800626int32_t MediaPlayer2AudioOutput::getSessionId() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800627 Mutex::Autolock lock(mLock);
628 return mSessionId;
629}
630
Dichen Zhang23658642018-11-15 10:26:16 -0800631void MediaPlayer2AudioOutput::setSessionId(const int32_t sessionId) {
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000632 Mutex::Autolock lock(mLock);
Dichen Zhang23658642018-11-15 10:26:16 -0800633 mSessionId = sessionId;
Dichen Zhanga60eaa82018-11-13 17:14:34 +0000634}
635
Dichen Zhangf8726912018-10-17 13:31:26 -0700636uint32_t MediaPlayer2AudioOutput::getSampleRate() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800637 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700638 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800639 return 0;
640 }
Dichen Zhangf8726912018-10-17 13:31:26 -0700641 return mJAudioTrack->getSampleRate();
Wei Jiaec044b02018-02-19 12:41:23 -0800642}
643
Dichen Zhangf8726912018-10-17 13:31:26 -0700644int64_t MediaPlayer2AudioOutput::getBufferDurationInUs() const {
Wei Jiaec044b02018-02-19 12:41:23 -0800645 Mutex::Autolock lock(mLock);
Dichen Zhangf8726912018-10-17 13:31:26 -0700646 if (mJAudioTrack == 0) {
Wei Jiaec044b02018-02-19 12:41:23 -0800647 return 0;
648 }
649 int64_t duration;
Dichen Zhangf8726912018-10-17 13:31:26 -0700650 if (mJAudioTrack->getBufferDurationInUs(&duration) != OK) {
Wei Jiaec044b02018-02-19 12:41:23 -0800651 return 0;
652 }
653 return duration;
654}
655
656} // namespace android