blob: 9dae16e40b191dc53ad02ae62a274baee7bb9aa8 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayerRenderer"
19#include <utils/Log.h>
20
Dongwon Kang3dced072017-10-09 08:55:22 -070021#include "AWakeLock.h"
Andreas Huberf9334412010-12-15 15:17:42 -080022#include "NuPlayerRenderer.h"
Andy Hungf2c87b32016-04-07 19:49:29 -070023#include <algorithm>
Andy Hunga0b39712015-05-31 22:40:49 -070024#include <cutils/properties.h>
Andreas Huberf9334412010-12-15 15:17:42 -080025#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080026#include <media/stagefright/foundation/AMessage.h>
Ronghua Wua73d9e02014-10-08 15:13:29 -070027#include <media/stagefright/foundation/AUtils.h>
Wei Jia5833b6a2015-03-09 17:01:47 -070028#include <media/stagefright/MediaClock.h>
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -070029#include <media/stagefright/MediaCodecConstants.h>
30#include <media/stagefright/MediaDefs.h>
Wei Jiabc2fb722014-07-08 16:37:57 -070031#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MetaData.h>
Chong Zhang3b9eb1f2014-10-15 17:05:08 -070033#include <media/stagefright/Utils.h>
Lajos Molnara3725d72015-07-01 16:47:22 -070034#include <media/stagefright/VideoFrameScheduler.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090035#include <media/MediaCodecBuffer.h>
Wonsik Kimee8116b2019-07-19 15:55:44 -070036#include <utils/SystemClock.h>
Lajos Molnardc43dfa2014-05-07 15:33:04 -070037
Lajos Molnar09524832014-07-17 14:29:51 -070038#include <inttypes.h>
39
Andreas Huberf9334412010-12-15 15:17:42 -080040namespace android {
41
Andy Hunga0b39712015-05-31 22:40:49 -070042/*
43 * Example of common configuration settings in shell script form
44
45 #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
46 adb shell setprop audio.offload.disable 1
47
48 #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
49 adb shell setprop audio.offload.video 1
50
51 #Use audio callbacks for PCM data
52 adb shell setprop media.stagefright.audio.cbk 1
53
Andy Hung288da022015-05-31 22:55:59 -070054 #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
55 adb shell setprop media.stagefright.audio.deep 1
56
Andy Hung179652e2015-05-31 22:49:46 -070057 #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
58 adb shell setprop media.stagefright.audio.sink 1000
59
Andy Hunga0b39712015-05-31 22:40:49 -070060 * These configurations take effect for the next track played (not the current track).
61 */
62
63static inline bool getUseAudioCallbackSetting() {
64 return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
65}
66
Andy Hung179652e2015-05-31 22:49:46 -070067static inline int32_t getAudioSinkPcmMsSetting() {
68 return property_get_int32(
69 "media.stagefright.audio.sink", 500 /* default_value */);
70}
71
Ronghua Wuf5b1db12014-09-09 10:11:08 -070072// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
73// is closed to allow the audio DSP to power down.
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -080074static const int64_t kOffloadPauseMaxUs = 10000000LL;
Ronghua Wuf5b1db12014-09-09 10:11:08 -070075
Eric Laurent7fb51272022-07-01 16:42:48 +020076// Additional delay after teardown before releasing the wake lock to allow time for the audio path
77// to be completely released
78static const int64_t kWakelockReleaseDelayUs = 2000000LL;
79
Wei Jia12b62652016-02-09 17:49:31 -080080// Maximum allowed delay from AudioSink, 1.5 seconds.
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -080081static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000LL;
Wei Jia12b62652016-02-09 17:49:31 -080082
Andy Hung528c8402016-01-12 12:39:34 -080083static const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
84
Wei Jiacc951512019-04-03 16:10:42 -070085// Default video frame display duration when only video exists.
86// Used to set max media time in MediaClock.
87static const int64_t kDefaultVideoFrameIntervalUs = 100000LL;
88
Andreas Huber714aa7b2011-09-13 08:28:38 -070089// static
Andy Hungf0e83642014-12-19 17:55:56 -080090const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
91 AUDIO_CHANNEL_NONE,
92 AUDIO_OUTPUT_FLAG_NONE,
93 AUDIO_FORMAT_INVALID,
94 0, // mNumChannels
95 0 // mSampleRate
96};
97
98// static
Andreas Huber714aa7b2011-09-13 08:28:38 -070099const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
100
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -0700101static audio_format_t constexpr audioFormatFromEncoding(int32_t pcmEncoding) {
102 switch (pcmEncoding) {
103 case kAudioEncodingPcmFloat:
104 return AUDIO_FORMAT_PCM_FLOAT;
105 case kAudioEncodingPcm16bit:
106 return AUDIO_FORMAT_PCM_16_BIT;
107 case kAudioEncodingPcm8bit:
108 return AUDIO_FORMAT_PCM_8_BIT; // TODO: do we want to support this?
109 default:
110 ALOGE("%s: Invalid encoding: %d", __func__, pcmEncoding);
111 return AUDIO_FORMAT_INVALID;
112 }
113}
114
Andreas Huberf9334412010-12-15 15:17:42 -0800115NuPlayer::Renderer::Renderer(
116 const sp<MediaPlayerBase::AudioSink> &sink,
Wei Jia0a68f662017-08-30 18:01:26 -0700117 const sp<MediaClock> &mediaClock,
Andreas Huberd5e56232013-03-12 11:01:43 -0700118 const sp<AMessage> &notify,
119 uint32_t flags)
Andreas Huberf9334412010-12-15 15:17:42 -0800120 : mAudioSink(sink),
Wei Jiad2f35de2016-02-17 16:48:06 -0800121 mUseVirtualAudioSink(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800122 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -0700123 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -0800124 mNumFramesWritten(0),
125 mDrainAudioQueuePending(false),
126 mDrainVideoQueuePending(false),
127 mAudioQueueGeneration(0),
128 mVideoQueueGeneration(0),
Wei Jia7b15cb32015-02-03 17:46:06 -0800129 mAudioDrainGeneration(0),
130 mVideoDrainGeneration(0),
Wei Jia7c8d0e02015-08-27 17:40:21 -0700131 mAudioEOSGeneration(0),
Wei Jia0a68f662017-08-30 18:01:26 -0700132 mMediaClock(mediaClock),
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700133 mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
Ronghua Wua73d9e02014-10-08 15:13:29 -0700134 mAudioFirstAnchorTimeMediaUs(-1),
Ronghua Wueecb7802014-10-19 23:12:50 -0700135 mAnchorTimeMediaUs(-1),
Lajos Molnarf5926712014-10-21 09:36:43 -0700136 mAnchorNumFramesWritten(-1),
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800137 mVideoLateByUs(0LL),
Wei Jiadc293e32017-10-16 18:29:37 -0700138 mNextVideoTimeMediaUs(-1),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800139 mHasAudio(false),
140 mHasVideo(false),
Chong Zhang7137ec72014-11-12 16:41:05 -0800141 mNotifyCompleteAudio(false),
142 mNotifyCompleteVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800143 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -0700144 mPaused(false),
Andy Hungb03dcb32015-08-27 16:18:59 -0700145 mPauseDrainAudioAllowedUs(0),
Andy Hung09e0c362014-09-12 15:12:16 -0700146 mVideoSampleReceived(false),
James Dongf57b4ea2012-07-20 13:38:36 -0700147 mVideoRenderingStarted(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700148 mVideoRenderingStartGeneration(0),
149 mAudioRenderingStartGeneration(0),
Andy Hungb12ea0b2015-09-03 15:13:01 -0700150 mRenderingDataDelivered(false),
Andy Hung528c8402016-01-12 12:39:34 -0800151 mNextAudioClockUpdateTimeUs(-1),
Wei Jia2995dc72015-07-24 16:00:33 -0700152 mLastAudioMediaTimeUs(-1),
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700153 mAudioOffloadPauseTimeoutGeneration(0),
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700154 mAudioTornDown(false),
Lajos Molnard5923402014-10-20 17:47:54 -0700155 mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
Andy Hungf0e83642014-12-19 17:55:56 -0800156 mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
Lajos Molnard5923402014-10-20 17:47:54 -0700157 mTotalBuffersQueued(0),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800158 mLastAudioBufferDrained(0),
Andy Hunga0b39712015-05-31 22:40:49 -0700159 mUseAudioCallback(false),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800160 mWakeLock(new AWakeLock()) {
Wei Jia0a68f662017-08-30 18:01:26 -0700161 CHECK(mediaClock != NULL);
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700162 mPlaybackRate = mPlaybackSettings.mSpeed;
163 mMediaClock->setPlaybackRate(mPlaybackRate);
Wonsik Kimee8116b2019-07-19 15:55:44 -0700164 (void)mSyncFlag.test_and_set();
Andreas Huberf9334412010-12-15 15:17:42 -0800165}
166
167NuPlayer::Renderer::~Renderer() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700168 if (offloadingAudio()) {
169 mAudioSink->stop();
170 mAudioSink->flush();
171 mAudioSink->close();
172 }
Wei Jia4c74fde2016-08-26 16:00:52 -0700173
174 // Try to avoid racing condition in case callback is still on.
175 Mutex::Autolock autoLock(mLock);
Wei Jia9a3101b2016-11-08 14:34:24 -0800176 if (mUseAudioCallback) {
177 flushQueue(&mAudioQueue);
178 flushQueue(&mVideoQueue);
179 }
Wei Jia4c74fde2016-08-26 16:00:52 -0700180 mWakeLock.clear();
Wei Jia4c74fde2016-08-26 16:00:52 -0700181 mVideoScheduler.clear();
182 mNotify.clear();
183 mAudioSink.clear();
Andreas Huberf9334412010-12-15 15:17:42 -0800184}
185
186void NuPlayer::Renderer::queueBuffer(
187 bool audio,
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900188 const sp<MediaCodecBuffer> &buffer,
Andreas Huberf9334412010-12-15 15:17:42 -0800189 const sp<AMessage> &notifyConsumed) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800190 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800191 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800192 msg->setInt32("audio", static_cast<int32_t>(audio));
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900193 msg->setObject("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -0800194 msg->setMessage("notifyConsumed", notifyConsumed);
195 msg->post();
196}
197
198void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
199 CHECK_NE(finalResult, (status_t)OK);
200
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800201 sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800202 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800203 msg->setInt32("audio", static_cast<int32_t>(audio));
204 msg->setInt32("finalResult", finalResult);
205 msg->post();
206}
207
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700208status_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
209 sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
210 writeToAMessage(msg, rate);
211 sp<AMessage> response;
212 status_t err = msg->postAndAwaitResponse(&response);
213 if (err == OK && response != NULL) {
214 CHECK(response->findInt32("err", &err));
215 }
216 return err;
217}
218
219status_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
220 if (rate.mSpeed == 0.f) {
221 onPause();
222 // don't call audiosink's setPlaybackRate if pausing, as pitch does not
223 // have to correspond to the any non-0 speed (e.g old speed). Keep
224 // settings nonetheless, using the old speed, in case audiosink changes.
225 AudioPlaybackRate newRate = rate;
226 newRate.mSpeed = mPlaybackSettings.mSpeed;
227 mPlaybackSettings = newRate;
228 return OK;
229 }
230
Wei Jia27ea08e2015-05-12 14:50:35 -0700231 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700232 status_t err = mAudioSink->setPlaybackRate(rate);
233 if (err != OK) {
234 return err;
235 }
236 }
237 mPlaybackSettings = rate;
238 mPlaybackRate = rate.mSpeed;
239 mMediaClock->setPlaybackRate(mPlaybackRate);
240 return OK;
241}
242
243status_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
244 sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
245 sp<AMessage> response;
246 status_t err = msg->postAndAwaitResponse(&response);
247 if (err == OK && response != NULL) {
248 CHECK(response->findInt32("err", &err));
249 if (err == OK) {
250 readFromAMessage(response, rate);
251 }
252 }
253 return err;
254}
255
256status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
Wei Jia27ea08e2015-05-12 14:50:35 -0700257 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700258 status_t err = mAudioSink->getPlaybackRate(rate);
259 if (err == OK) {
260 if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
261 ALOGW("correcting mismatch in internal/external playback rate");
262 }
263 // get playback settings used by audiosink, as it may be
264 // slightly off due to audiosink not taking small changes.
265 mPlaybackSettings = *rate;
266 if (mPaused) {
267 rate->mSpeed = 0.f;
268 }
269 }
270 return err;
271 }
272 *rate = mPlaybackSettings;
273 return OK;
274}
275
276status_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
277 sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
278 writeToAMessage(msg, sync, videoFpsHint);
279 sp<AMessage> response;
280 status_t err = msg->postAndAwaitResponse(&response);
281 if (err == OK && response != NULL) {
282 CHECK(response->findInt32("err", &err));
283 }
284 return err;
285}
286
287status_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
288 if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
289 return BAD_VALUE;
290 }
291 // TODO: support sync sources
292 return INVALID_OPERATION;
293}
294
295status_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
296 sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
297 sp<AMessage> response;
298 status_t err = msg->postAndAwaitResponse(&response);
299 if (err == OK && response != NULL) {
300 CHECK(response->findInt32("err", &err));
301 if (err == OK) {
302 readFromAMessage(response, sync, videoFps);
303 }
304 }
305 return err;
306}
307
308status_t NuPlayer::Renderer::onGetSyncSettings(
309 AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
310 *sync = mSyncSettings;
311 *videoFps = -1.f;
312 return OK;
Wei Jia98160162015-02-04 17:01:11 -0800313}
314
Chong Zhang7137ec72014-11-12 16:41:05 -0800315void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800316 {
Wei Jia7b15cb32015-02-03 17:46:06 -0800317 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800318 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800319 mNotifyCompleteAudio |= notifyComplete;
Wei Jia3b0cd262015-07-13 11:28:10 -0700320 clearAudioFirstAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800321 ++mAudioQueueGeneration;
322 ++mAudioDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800323 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -0800324 mNotifyCompleteVideo |= notifyComplete;
Wei Jia7b15cb32015-02-03 17:46:06 -0800325 ++mVideoQueueGeneration;
326 ++mVideoDrainGeneration;
Wei Jiacc951512019-04-03 16:10:42 -0700327 mNextVideoTimeMediaUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -0800328 }
Wei Jia7b15cb32015-02-03 17:46:06 -0800329
Wei Jia9a3101b2016-11-08 14:34:24 -0800330 mMediaClock->clearAnchor();
Wei Jia7b15cb32015-02-03 17:46:06 -0800331 mVideoLateByUs = 0;
332 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800333 }
334
Wonsik Kimee8116b2019-07-19 15:55:44 -0700335 // Wait until the current job in the message queue is done, to make sure
336 // buffer processing from the old generation is finished. After the current
337 // job is finished, access to buffers are protected by generation.
338 Mutex::Autolock syncLock(mSyncLock);
339 int64_t syncCount = mSyncCount;
340 mSyncFlag.clear();
341
342 // Make sure message queue is not empty after mSyncFlag is cleared.
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800343 sp<AMessage> msg = new AMessage(kWhatFlush, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800344 msg->setInt32("audio", static_cast<int32_t>(audio));
345 msg->post();
Wonsik Kimee8116b2019-07-19 15:55:44 -0700346
347 int64_t uptimeMs = uptimeMillis();
348 while (mSyncCount == syncCount) {
349 (void)mSyncCondition.waitRelative(mSyncLock, ms2ns(1000));
350 if (uptimeMillis() - uptimeMs > 1000) {
351 ALOGW("flush(): no wake-up from sync point for 1s; stop waiting to "
352 "prevent being stuck indefinitely.");
353 break;
354 }
355 }
Andreas Huberf9334412010-12-15 15:17:42 -0800356}
357
358void NuPlayer::Renderer::signalTimeDiscontinuity() {
Wei Jia28a8a9f2014-08-18 11:29:50 -0700359}
360
361void NuPlayer::Renderer::signalDisableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800362 (new AMessage(kWhatDisableOffloadAudio, this))->post();
Wei Jia28a8a9f2014-08-18 11:29:50 -0700363}
364
Ronghua Wua10fd232014-11-06 16:15:20 -0800365void NuPlayer::Renderer::signalEnableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800366 (new AMessage(kWhatEnableOffloadAudio, this))->post();
Ronghua Wua10fd232014-11-06 16:15:20 -0800367}
368
Andreas Huberb4082222011-01-20 15:23:04 -0800369void NuPlayer::Renderer::pause() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800370 (new AMessage(kWhatPause, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800371}
372
373void NuPlayer::Renderer::resume() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800374 (new AMessage(kWhatResume, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800375}
376
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700377void NuPlayer::Renderer::setVideoFrameRate(float fps) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800378 sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700379 msg->setFloat("frame-rate", fps);
380 msg->post();
381}
382
Wei Jia4ecbea32015-10-20 18:09:57 -0700383// Called on any threads without mLock acquired.
Wei Jia7b15cb32015-02-03 17:46:06 -0800384status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
Wei Jia4ecbea32015-10-20 18:09:57 -0700385 status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
386 if (result == OK) {
387 return result;
388 }
389
390 // MediaClock has not started yet. Try to start it if possible.
391 {
392 Mutex::Autolock autoLock(mLock);
393 if (mAudioFirstAnchorTimeMediaUs == -1) {
394 return result;
395 }
396
397 AudioTimestamp ts;
398 status_t res = mAudioSink->getTimestamp(ts);
399 if (res != OK) {
400 return result;
401 }
402
403 // AudioSink has rendered some frames.
404 int64_t nowUs = ALooper::GetNowUs();
zengjingdb131352018-03-19 17:23:49 +0800405 int64_t playedOutDurationUs = mAudioSink->getPlayedOutDurationUs(nowUs);
406 if (playedOutDurationUs == 0) {
407 *mediaUs = mAudioFirstAnchorTimeMediaUs;
408 return OK;
409 }
410 int64_t nowMediaUs = playedOutDurationUs + mAudioFirstAnchorTimeMediaUs;
Wei Jia4ecbea32015-10-20 18:09:57 -0700411 mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
412 }
413
Wei Jia98160162015-02-04 17:01:11 -0800414 return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700415}
416
Wei Jia7b15cb32015-02-03 17:46:06 -0800417void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
418 mAudioFirstAnchorTimeMediaUs = -1;
419 mMediaClock->setStartingTimeMedia(-1);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700420}
421
Wei Jia7b15cb32015-02-03 17:46:06 -0800422void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700423 if (mAudioFirstAnchorTimeMediaUs == -1) {
424 mAudioFirstAnchorTimeMediaUs = mediaUs;
Wei Jia7b15cb32015-02-03 17:46:06 -0800425 mMediaClock->setStartingTimeMedia(mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700426 }
427}
428
Wei Jia9a3101b2016-11-08 14:34:24 -0800429// Called on renderer looper.
430void NuPlayer::Renderer::clearAnchorTime() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800431 mMediaClock->clearAnchor();
432 mAnchorTimeMediaUs = -1;
433 mAnchorNumFramesWritten = -1;
Ronghua Wua73d9e02014-10-08 15:13:29 -0700434}
435
436void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800437 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700438 mVideoLateByUs = lateUs;
439}
440
441int64_t NuPlayer::Renderer::getVideoLateByUs() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800442 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700443 return mVideoLateByUs;
444}
445
Andy Hung202bce12014-12-03 11:47:36 -0800446status_t NuPlayer::Renderer::openAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700447 const sp<AMessage> &format,
448 bool offloadOnly,
449 bool hasVideo,
Andy Hung202bce12014-12-03 11:47:36 -0800450 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530451 bool *isOffloaded,
452 bool isStreaming) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800453 sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700454 msg->setMessage("format", format);
455 msg->setInt32("offload-only", offloadOnly);
456 msg->setInt32("has-video", hasVideo);
457 msg->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530458 msg->setInt32("isStreaming", isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700459
460 sp<AMessage> response;
Leena Winterrowd66e4c4772015-09-10 15:41:08 -0700461 status_t postStatus = msg->postAndAwaitResponse(&response);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700462
Andy Hung202bce12014-12-03 11:47:36 -0800463 int32_t err;
Leena Winterrowd66e4c4772015-09-10 15:41:08 -0700464 if (postStatus != OK || response.get() == nullptr || !response->findInt32("err", &err)) {
Andy Hung202bce12014-12-03 11:47:36 -0800465 err = INVALID_OPERATION;
466 } else if (err == OK && isOffloaded != NULL) {
467 int32_t offload;
468 CHECK(response->findInt32("offload", &offload));
469 *isOffloaded = (offload != 0);
470 }
471 return err;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700472}
473
474void NuPlayer::Renderer::closeAudioSink() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800475 sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700476
477 sp<AMessage> response;
478 msg->postAndAwaitResponse(&response);
479}
480
christosts9aacf192023-03-09 14:12:36 +0000481void NuPlayer::Renderer::dump(AString& logString) {
482 Mutex::Autolock autoLock(mLock);
483 logString.append("paused(");
484 logString.append(mPaused);
485 logString.append("), offloading(");
486 logString.append(offloadingAudio());
487 logString.append("), wakelock(acquired=");
488 mWakelockAcquireEvent.dump(logString);
489 logString.append(", timeout=");
490 mWakelockTimeoutEvent.dump(logString);
491 logString.append(", release=");
492 mWakelockReleaseEvent.dump(logString);
493 logString.append(", cancel=");
494 mWakelockCancelEvent.dump(logString);
495 logString.append(")");
496}
497
Wei Jia9a3101b2016-11-08 14:34:24 -0800498void NuPlayer::Renderer::changeAudioFormat(
499 const sp<AMessage> &format,
500 bool offloadOnly,
501 bool hasVideo,
502 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530503 bool isStreaming,
Wei Jia9a3101b2016-11-08 14:34:24 -0800504 const sp<AMessage> &notify) {
505 sp<AMessage> meta = new AMessage;
506 meta->setMessage("format", format);
507 meta->setInt32("offload-only", offloadOnly);
508 meta->setInt32("has-video", hasVideo);
509 meta->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530510 meta->setInt32("isStreaming", isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -0800511
512 sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
513 msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
514 msg->setMessage("notify", notify);
515 msg->setMessage("meta", meta);
516 msg->post();
517}
518
Andreas Huberf9334412010-12-15 15:17:42 -0800519void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
520 switch (msg->what()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700521 case kWhatOpenAudioSink:
522 {
523 sp<AMessage> format;
524 CHECK(msg->findMessage("format", &format));
525
526 int32_t offloadOnly;
527 CHECK(msg->findInt32("offload-only", &offloadOnly));
528
529 int32_t hasVideo;
530 CHECK(msg->findInt32("has-video", &hasVideo));
531
532 uint32_t flags;
533 CHECK(msg->findInt32("flags", (int32_t *)&flags));
534
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530535 uint32_t isStreaming;
536 CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
537
538 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700539
540 sp<AMessage> response = new AMessage;
Andy Hung202bce12014-12-03 11:47:36 -0800541 response->setInt32("err", err);
542 response->setInt32("offload", offloadingAudio());
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700543
Lajos Molnar3f274362015-03-05 14:35:41 -0800544 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700545 CHECK(msg->senderAwaitsResponse(&replyID));
546 response->postReply(replyID);
547
548 break;
549 }
550
551 case kWhatCloseAudioSink:
552 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800553 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700554 CHECK(msg->senderAwaitsResponse(&replyID));
555
556 onCloseAudioSink();
557
558 sp<AMessage> response = new AMessage;
559 response->postReply(replyID);
560 break;
561 }
562
Wei Jiabc2fb722014-07-08 16:37:57 -0700563 case kWhatStopAudioSink:
564 {
565 mAudioSink->stop();
566 break;
567 }
568
Wei Jia9a3101b2016-11-08 14:34:24 -0800569 case kWhatChangeAudioFormat:
570 {
571 int32_t queueGeneration;
572 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
573
574 sp<AMessage> notify;
575 CHECK(msg->findMessage("notify", &notify));
576
577 if (offloadingAudio()) {
578 ALOGW("changeAudioFormat should NOT be called in offload mode");
579 notify->setInt32("err", INVALID_OPERATION);
580 notify->post();
581 break;
582 }
583
584 sp<AMessage> meta;
585 CHECK(msg->findMessage("meta", &meta));
586
587 if (queueGeneration != getQueueGeneration(true /* audio */)
588 || mAudioQueue.empty()) {
589 onChangeAudioFormat(meta, notify);
590 break;
591 }
592
593 QueueEntry entry;
594 entry.mNotifyConsumed = notify;
595 entry.mMeta = meta;
596
597 Mutex::Autolock autoLock(mLock);
598 mAudioQueue.push_back(entry);
599 postDrainAudioQueue_l();
600
601 break;
602 }
603
Andreas Huberf9334412010-12-15 15:17:42 -0800604 case kWhatDrainAudioQueue:
605 {
Wei Jia3ab25452015-06-10 09:37:47 -0700606 mDrainAudioQueuePending = false;
607
Andreas Huberf9334412010-12-15 15:17:42 -0800608 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800609 CHECK(msg->findInt32("drainGeneration", &generation));
610 if (generation != getDrainGeneration(true /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800611 break;
612 }
613
Andreas Huber078cfcf2011-09-15 12:25:04 -0700614 if (onDrainAudioQueue()) {
615 uint32_t numFramesPlayed;
616 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
617 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800618
Wei Jia1fb35b72017-09-25 16:08:13 -0700619 // Handle AudioTrack race when start is immediately called after flush.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700620 uint32_t numFramesPendingPlayout =
Wei Jia1fb35b72017-09-25 16:08:13 -0700621 (mNumFramesWritten > numFramesPlayed ?
622 mNumFramesWritten - numFramesPlayed : 0);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700623
624 // This is how long the audio sink will have data to
625 // play back.
626 int64_t delayUs =
627 mAudioSink->msecsPerFrame()
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800628 * numFramesPendingPlayout * 1000LL;
Wei Jiad9c2e9c2015-04-10 19:04:09 -0700629 if (mPlaybackRate > 1.0f) {
630 delayUs /= mPlaybackRate;
631 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700632
633 // Let's give it more data after about half that time
634 // has elapsed.
Andy Hungf2c87b32016-04-07 19:49:29 -0700635 delayUs /= 2;
636 // check the buffer size to estimate maximum delay permitted.
637 const int64_t maxDrainDelayUs = std::max(
638 mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
639 ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
640 (long long)delayUs, (long long)maxDrainDelayUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800641 Mutex::Autolock autoLock(mLock);
Andy Hungf2c87b32016-04-07 19:49:29 -0700642 postDrainAudioQueue_l(delayUs);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700643 }
Andreas Huberf9334412010-12-15 15:17:42 -0800644 break;
645 }
646
647 case kWhatDrainVideoQueue:
648 {
649 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800650 CHECK(msg->findInt32("drainGeneration", &generation));
651 if (generation != getDrainGeneration(false /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800652 break;
653 }
654
655 mDrainVideoQueuePending = false;
656
657 onDrainVideoQueue();
658
Wei Jia7b15cb32015-02-03 17:46:06 -0800659 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -0800660 break;
661 }
662
Lajos Molnard5923402014-10-20 17:47:54 -0700663 case kWhatPostDrainVideoQueue:
664 {
665 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800666 CHECK(msg->findInt32("drainGeneration", &generation));
667 if (generation != getDrainGeneration(false /* audio */)) {
Lajos Molnard5923402014-10-20 17:47:54 -0700668 break;
669 }
670
671 mDrainVideoQueuePending = false;
Wei Jia7b15cb32015-02-03 17:46:06 -0800672 postDrainVideoQueue();
Lajos Molnard5923402014-10-20 17:47:54 -0700673 break;
674 }
675
Andreas Huberf9334412010-12-15 15:17:42 -0800676 case kWhatQueueBuffer:
677 {
678 onQueueBuffer(msg);
679 break;
680 }
681
682 case kWhatQueueEOS:
683 {
684 onQueueEOS(msg);
685 break;
686 }
687
Wei Jia7c8d0e02015-08-27 17:40:21 -0700688 case kWhatEOS:
689 {
690 int32_t generation;
691 CHECK(msg->findInt32("audioEOSGeneration", &generation));
692 if (generation != mAudioEOSGeneration) {
693 break;
694 }
695 status_t finalResult;
696 CHECK(msg->findInt32("finalResult", &finalResult));
697 notifyEOS(true /* audio */, finalResult);
698 break;
699 }
700
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700701 case kWhatConfigPlayback:
Wei Jia98160162015-02-04 17:01:11 -0800702 {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700703 sp<AReplyToken> replyID;
704 CHECK(msg->senderAwaitsResponse(&replyID));
705 AudioPlaybackRate rate;
706 readFromAMessage(msg, &rate);
707 status_t err = onConfigPlayback(rate);
708 sp<AMessage> response = new AMessage;
709 response->setInt32("err", err);
710 response->postReply(replyID);
711 break;
712 }
713
714 case kWhatGetPlaybackSettings:
715 {
716 sp<AReplyToken> replyID;
717 CHECK(msg->senderAwaitsResponse(&replyID));
718 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
719 status_t err = onGetPlaybackSettings(&rate);
720 sp<AMessage> response = new AMessage;
721 if (err == OK) {
722 writeToAMessage(response, rate);
723 }
724 response->setInt32("err", err);
725 response->postReply(replyID);
726 break;
727 }
728
729 case kWhatConfigSync:
730 {
731 sp<AReplyToken> replyID;
732 CHECK(msg->senderAwaitsResponse(&replyID));
733 AVSyncSettings sync;
734 float videoFpsHint;
735 readFromAMessage(msg, &sync, &videoFpsHint);
736 status_t err = onConfigSync(sync, videoFpsHint);
737 sp<AMessage> response = new AMessage;
738 response->setInt32("err", err);
739 response->postReply(replyID);
740 break;
741 }
742
743 case kWhatGetSyncSettings:
744 {
745 sp<AReplyToken> replyID;
746 CHECK(msg->senderAwaitsResponse(&replyID));
747
748 ALOGV("kWhatGetSyncSettings");
749 AVSyncSettings sync;
750 float videoFps = -1.f;
751 status_t err = onGetSyncSettings(&sync, &videoFps);
752 sp<AMessage> response = new AMessage;
753 if (err == OK) {
754 writeToAMessage(response, sync, videoFps);
755 }
756 response->setInt32("err", err);
757 response->postReply(replyID);
Wei Jia98160162015-02-04 17:01:11 -0800758 break;
759 }
760
Andreas Huberf9334412010-12-15 15:17:42 -0800761 case kWhatFlush:
762 {
763 onFlush(msg);
764 break;
765 }
766
Wei Jiabc2fb722014-07-08 16:37:57 -0700767 case kWhatDisableOffloadAudio:
768 {
769 onDisableOffloadAudio();
770 break;
771 }
772
Ronghua Wua10fd232014-11-06 16:15:20 -0800773 case kWhatEnableOffloadAudio:
774 {
775 onEnableOffloadAudio();
776 break;
777 }
778
Andreas Huberb4082222011-01-20 15:23:04 -0800779 case kWhatPause:
780 {
781 onPause();
782 break;
783 }
784
785 case kWhatResume:
786 {
787 onResume();
788 break;
789 }
790
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700791 case kWhatSetVideoFrameRate:
792 {
793 float fps;
794 CHECK(msg->findFloat("frame-rate", &fps));
795 onSetVideoFrameRate(fps);
796 break;
797 }
798
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700799 case kWhatAudioTearDown:
Wei Jia3a2956d2014-07-22 16:01:33 -0700800 {
Wei Jiaa05f1e32016-03-25 16:31:22 -0700801 int32_t reason;
802 CHECK(msg->findInt32("reason", &reason));
803
804 onAudioTearDown((AudioTearDownReason)reason);
Wei Jia3a2956d2014-07-22 16:01:33 -0700805 break;
806 }
807
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700808 case kWhatAudioOffloadPauseTimeout:
809 {
810 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800811 CHECK(msg->findInt32("drainGeneration", &generation));
christosts9aacf192023-03-09 14:12:36 +0000812 mWakelockTimeoutEvent.updateValues(
813 uptimeMillis(),
814 generation,
815 mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700816 if (generation != mAudioOffloadPauseTimeoutGeneration) {
817 break;
818 }
Ronghua Wu08529172014-10-02 16:55:52 -0700819 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700820 onAudioTearDown(kDueToTimeout);
Eric Laurent7fb51272022-07-01 16:42:48 +0200821 sp<AMessage> newMsg = new AMessage(kWhatReleaseWakeLock, this);
822 newMsg->setInt32("drainGeneration", generation);
823 newMsg->post(kWakelockReleaseDelayUs);
824 break;
825 }
826
827 case kWhatReleaseWakeLock:
828 {
829 int32_t generation;
830 CHECK(msg->findInt32("drainGeneration", &generation));
christosts9aacf192023-03-09 14:12:36 +0000831 mWakelockReleaseEvent.updateValues(
832 uptimeMillis(),
833 generation,
834 mAudioOffloadPauseTimeoutGeneration);
Eric Laurent7fb51272022-07-01 16:42:48 +0200835 if (generation != mAudioOffloadPauseTimeoutGeneration) {
836 break;
837 }
838 ALOGV("releasing audio offload pause wakelock.");
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800839 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700840 break;
841 }
842
Andreas Huberf9334412010-12-15 15:17:42 -0800843 default:
844 TRESPASS();
845 break;
846 }
Wonsik Kimee8116b2019-07-19 15:55:44 -0700847 if (!mSyncFlag.test_and_set()) {
848 Mutex::Autolock syncLock(mSyncLock);
849 ++mSyncCount;
850 mSyncCondition.broadcast();
851 }
Andreas Huberf9334412010-12-15 15:17:42 -0800852}
853
Wei Jiabc2fb722014-07-08 16:37:57 -0700854void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700855 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800856 return;
857 }
858
859 if (mAudioQueue.empty()) {
860 return;
861 }
862
Andy Hungb03dcb32015-08-27 16:18:59 -0700863 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
864 if (mPaused) {
865 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
866 if (diffUs > delayUs) {
867 delayUs = diffUs;
868 }
869 }
870
Andreas Huberf9334412010-12-15 15:17:42 -0800871 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800872 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800873 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700874 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800875}
876
Wei Jia7b15cb32015-02-03 17:46:06 -0800877void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
878 mAudioRenderingStartGeneration = mAudioDrainGeneration;
879 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700880 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700881}
882
Wei Jia7b15cb32015-02-03 17:46:06 -0800883void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
884 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
885 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700886 mRenderingDataDelivered = true;
887 if (mPaused) {
888 return;
889 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700890 mVideoRenderingStartGeneration = -1;
891 mAudioRenderingStartGeneration = -1;
892
893 sp<AMessage> notify = mNotify->dup();
894 notify->setInt32("what", kWhatMediaRenderingStart);
895 notify->post();
896 }
897}
898
Wei Jiabc2fb722014-07-08 16:37:57 -0700899// static
900size_t NuPlayer::Renderer::AudioSinkCallback(
901 MediaPlayerBase::AudioSink * /* audioSink */,
902 void *buffer,
903 size_t size,
904 void *cookie,
905 MediaPlayerBase::AudioSink::cb_event_t event) {
906 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
907
908 switch (event) {
909 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
910 {
911 return me->fillAudioBuffer(buffer, size);
912 break;
913 }
914
915 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
916 {
Andy Hunga0b39712015-05-31 22:40:49 -0700917 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jia4c74fde2016-08-26 16:00:52 -0700918 me->notifyEOSCallback();
Wei Jiabc2fb722014-07-08 16:37:57 -0700919 break;
920 }
921
922 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
923 {
Andy Hunga0b39712015-05-31 22:40:49 -0700924 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Wei Jiaa05f1e32016-03-25 16:31:22 -0700925 me->notifyAudioTearDown(kDueToError);
Wei Jiabc2fb722014-07-08 16:37:57 -0700926 break;
927 }
928 }
929
930 return 0;
931}
932
Wei Jia4c74fde2016-08-26 16:00:52 -0700933void NuPlayer::Renderer::notifyEOSCallback() {
934 Mutex::Autolock autoLock(mLock);
935
936 if (!mUseAudioCallback) {
937 return;
938 }
939
Wei Jiad214a562017-07-10 13:20:55 -0700940 notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
Wei Jia4c74fde2016-08-26 16:00:52 -0700941}
942
Wei Jiabc2fb722014-07-08 16:37:57 -0700943size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
944 Mutex::Autolock autoLock(mLock);
945
Andy Hung85e48142015-05-31 23:04:15 -0700946 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700947 return 0;
948 }
949
950 bool hasEOS = false;
951
952 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700953 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700954 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700955 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700956 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700957
958 if (entry->mBuffer == NULL) { // EOS
959 hasEOS = true;
960 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700961 break;
962 }
963
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700964 if (firstEntry && entry->mOffset == 0) {
965 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700966 int64_t mediaTimeUs;
967 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Paras Nagda86dc6182020-10-27 13:01:47 +0530968 if (mediaTimeUs < 0) {
969 ALOGD("fillAudioBuffer: reset negative media time %.2f secs to zero",
970 mediaTimeUs / 1E6);
971 mediaTimeUs = 0;
972 }
Andy Hunga0b39712015-05-31 22:40:49 -0700973 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800974 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700975 }
976
977 size_t copy = entry->mBuffer->size() - entry->mOffset;
978 size_t sizeRemaining = size - sizeCopied;
979 if (copy > sizeRemaining) {
980 copy = sizeRemaining;
981 }
982
983 memcpy((char *)buffer + sizeCopied,
984 entry->mBuffer->data() + entry->mOffset,
985 copy);
986
987 entry->mOffset += copy;
988 if (entry->mOffset == entry->mBuffer->size()) {
989 entry->mNotifyConsumed->post();
990 mAudioQueue.erase(mAudioQueue.begin());
991 entry = NULL;
992 }
993 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -0800994
995 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -0700996 }
997
Lajos Molnarf5926712014-10-21 09:36:43 -0700998 if (mAudioFirstAnchorTimeMediaUs >= 0) {
999 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -08001000 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -07001001 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -08001002 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -08001003 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -07001004 }
1005
Andy Hunga0b39712015-05-31 22:40:49 -07001006 // for non-offloaded audio, we need to compute the frames written because
1007 // there is no EVENT_STREAM_END notification. The frames written gives
1008 // an estimate on the pending played out duration.
1009 if (!offloadingAudio()) {
1010 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -07001011 }
1012
Andy Hunga0b39712015-05-31 22:40:49 -07001013 if (hasEOS) {
1014 (new AMessage(kWhatStopAudioSink, this))->post();
1015 // As there is currently no EVENT_STREAM_END callback notification for
1016 // non-offloaded audio tracks, we need to post the EOS ourselves.
1017 if (!offloadingAudio()) {
1018 int64_t postEOSDelayUs = 0;
1019 if (mAudioSink->needsTrailingPadding()) {
1020 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
1021 }
Wei Jiad214a562017-07-10 13:20:55 -07001022 ALOGV("fillAudioBuffer: notifyEOS_l "
Andy Hunga0b39712015-05-31 22:40:49 -07001023 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
1024 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001025 notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Andy Hunga0b39712015-05-31 22:40:49 -07001026 }
1027 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001028 return sizeCopied;
1029}
1030
Chong Zhang9da0ce42015-06-11 17:18:58 -07001031void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
1032 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
1033 bool foundEOS = false;
1034 while (it != mAudioQueue.end()) {
1035 int32_t eos;
1036 QueueEntry *entry = &*it++;
Wei Jia9a3101b2016-11-08 14:34:24 -08001037 if ((entry->mBuffer == nullptr && entry->mNotifyConsumed == nullptr)
Chong Zhang9da0ce42015-06-11 17:18:58 -07001038 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
1039 itEOS = it;
1040 foundEOS = true;
1041 }
1042 }
1043
1044 if (foundEOS) {
1045 // post all replies before EOS and drop the samples
1046 for (it = mAudioQueue.begin(); it != itEOS; it++) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001047 if (it->mBuffer == nullptr) {
1048 if (it->mNotifyConsumed == nullptr) {
1049 // delay doesn't matter as we don't even have an AudioTrack
1050 notifyEOS(true /* audio */, it->mFinalResult);
1051 } else {
1052 // TAG for re-opening audio sink.
1053 onChangeAudioFormat(it->mMeta, it->mNotifyConsumed);
1054 }
Chong Zhang9da0ce42015-06-11 17:18:58 -07001055 } else {
1056 it->mNotifyConsumed->post();
1057 }
1058 }
1059 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
1060 }
1061}
1062
Andreas Huber078cfcf2011-09-15 12:25:04 -07001063bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -07001064 // do not drain audio during teardown as queued buffers may be invalid.
1065 if (mAudioTornDown) {
1066 return false;
1067 }
Wei Jia230b1882015-03-19 15:13:51 -07001068 // TODO: This call to getPosition checks if AudioTrack has been created
1069 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
1070 // CHECKs on getPosition will fail.
1071 // We still need to figure out why AudioTrack is not created when
1072 // this function is called. One possible reason could be leftover
1073 // audio. Another possible place is to check whether decoder
1074 // has received INFO_FORMAT_CHANGED as the first buffer since
1075 // AudioSink is opened there, and possible interactions with flush
1076 // immediately after start. Investigate error message
1077 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -07001078 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -07001079 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -07001080 // When getPosition fails, renderer will not reschedule the draining
1081 // unless new samples are queued.
1082 // If we have pending EOS (or "eos" marker for discontinuities), we need
1083 // to post these now as NuPlayerDecoder might be waiting for it.
1084 drainAudioQueueUntilLastEOS();
1085
1086 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -07001087 return false;
1088 }
Andreas Huberc92fd242011-08-16 13:48:44 -07001089
Wei Jia230b1882015-03-19 15:13:51 -07001090#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -07001091 ssize_t numFramesAvailableToWrite =
1092 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
1093
Andreas Huber078cfcf2011-09-15 12:25:04 -07001094 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +00001095 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -07001096 } else {
Steve Block3856b092011-10-20 11:56:00 +01001097 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -07001098 mAudioSink->frameCount() - numFramesAvailableToWrite);
1099 }
1100#endif
1101
Andy Hung005e9d02015-05-31 23:16:07 -07001102 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -08001103 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -07001104 QueueEntry *entry = &*mAudioQueue.begin();
1105
1106 if (entry->mBuffer == NULL) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001107 if (entry->mNotifyConsumed != nullptr) {
1108 // TAG for re-open audio sink.
1109 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
1110 mAudioQueue.erase(mAudioQueue.begin());
1111 continue;
1112 }
1113
Andreas Huberc92fd242011-08-16 13:48:44 -07001114 // EOS
Haynes Mathew George62d4e072016-06-13 11:23:22 -07001115 if (mPaused) {
1116 // Do not notify EOS when paused.
1117 // This is needed to avoid switch to next clip while in pause.
1118 ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
1119 return false;
1120 }
1121
Ronghua Wu5095d702014-08-27 12:05:48 -07001122 int64_t postEOSDelayUs = 0;
1123 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -07001124 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -07001125 }
1126 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001127 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -07001128
1129 mAudioQueue.erase(mAudioQueue.begin());
1130 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -08001131 if (mAudioSink->needsTrailingPadding()) {
1132 // If we're not in gapless playback (i.e. through setNextPlayer), we
1133 // need to stop the track here, because that will play out the last
1134 // little bit at the end of the file. Otherwise short files won't play.
1135 mAudioSink->stop();
1136 mNumFramesWritten = 0;
1137 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001138 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -07001139 }
1140
Wei Jia9a3101b2016-11-08 14:34:24 -08001141 mLastAudioBufferDrained = entry->mBufferOrdinal;
1142
Chong Zhang81636762015-04-21 09:33:47 -07001143 // ignore 0-sized buffer which could be EOS marker with no data
1144 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -08001145 int64_t mediaTimeUs;
1146 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -07001147 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
1148 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -07001149 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001150 }
1151
1152 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -08001153
Wei Jia7d3f4df2015-03-03 15:28:00 -08001154 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
1155 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -07001156 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -08001157 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001158 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -07001159 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001160 } else {
1161 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -07001162 // This can only happen when AudioSink was opened with doNotReconnect flag set to
1163 // true, in which case the NuPlayer will handle the reconnect.
Wei Jiaa05f1e32016-03-25 16:31:22 -07001164 notifyAudioTearDown(kDueToError);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001165 }
Andy Hung202bce12014-12-03 11:47:36 -08001166 break;
Andy Hunga31335a2014-08-20 17:37:59 -07001167 }
Andreas Huberf9334412010-12-15 15:17:42 -08001168
Andy Hunga31335a2014-08-20 17:37:59 -07001169 entry->mOffset += written;
Wei Jia03cee242016-05-26 15:22:59 -07001170 size_t remainder = entry->mBuffer->size() - entry->mOffset;
1171 if ((ssize_t)remainder < mAudioSink->frameSize()) {
1172 if (remainder > 0) {
1173 ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
1174 remainder);
1175 entry->mOffset += remainder;
1176 copy -= remainder;
1177 }
1178
Andreas Huberf9334412010-12-15 15:17:42 -08001179 entry->mNotifyConsumed->post();
1180 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -07001181
Andreas Huberf9334412010-12-15 15:17:42 -08001182 entry = NULL;
1183 }
1184
Andy Hunga31335a2014-08-20 17:37:59 -07001185 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -07001186 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001187
Wei Jia7b15cb32015-02-03 17:46:06 -08001188 {
1189 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -07001190 int64_t maxTimeMedia;
1191 maxTimeMedia =
1192 mAnchorTimeMediaUs +
1193 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
1194 * 1000LL * mAudioSink->msecsPerFrame());
1195 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
1196
Wei Jia7b15cb32015-02-03 17:46:06 -08001197 notifyIfMediaRenderingStarted_l();
1198 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001199
Andy Hunga31335a2014-08-20 17:37:59 -07001200 if (written != (ssize_t)copy) {
1201 // A short count was received from AudioSink::write()
1202 //
Wei Jia7d3f4df2015-03-03 15:28:00 -08001203 // AudioSink write is called in non-blocking mode.
1204 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -07001205 //
Wei Jia03cee242016-05-26 15:22:59 -07001206 // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
1207 // discarded.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001208 // 2) The data to be copied exceeds the available buffer in AudioSink.
1209 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
1210 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -07001211
1212 // (Case 1)
1213 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
1214 // needs to fail, as we should not carry over fractional frames between calls.
Colin Cross0bdcf662017-04-27 16:15:51 -07001215 CHECK_EQ(copy % mAudioSink->frameSize(), 0u);
Andy Hunga31335a2014-08-20 17:37:59 -07001216
Wei Jia7d3f4df2015-03-03 15:28:00 -08001217 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -07001218 // Return early to the caller.
1219 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001220 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -07001221 break;
1222 }
1223 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001224
Andy Hung005e9d02015-05-31 23:16:07 -07001225 // calculate whether we need to reschedule another write.
1226 bool reschedule = !mAudioQueue.empty()
1227 && (!mPaused
1228 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1229 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1230 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1231 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001232}
1233
Wei Jia98160162015-02-04 17:01:11 -08001234int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1235 int32_t sampleRate = offloadingAudio() ?
1236 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001237 if (sampleRate == 0) {
1238 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1239 return 0;
1240 }
hyoungjun.byun2c2050c2019-01-31 12:11:38 +09001241
1242 return (int64_t)(numFrames * 1000000LL / sampleRate);
Wei Jia98160162015-02-04 17:01:11 -08001243}
1244
1245// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001246int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001247 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiad2f35de2016-02-17 16:48:06 -08001248 if (mUseVirtualAudioSink) {
1249 int64_t nowUs = ALooper::GetNowUs();
1250 int64_t mediaUs;
1251 if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001252 return 0LL;
Wei Jiad2f35de2016-02-17 16:48:06 -08001253 } else {
1254 return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1255 }
1256 }
Andy Hungffa36952017-08-17 10:41:51 -07001257
1258 const int64_t audioSinkPlayedUs = mAudioSink->getPlayedOutDurationUs(nowUs);
1259 int64_t pendingUs = writtenAudioDurationUs - audioSinkPlayedUs;
1260 if (pendingUs < 0) {
1261 // This shouldn't happen unless the timestamp is stale.
1262 ALOGW("%s: pendingUs %lld < 0, clamping to zero, potential resume after pause "
1263 "writtenAudioDurationUs: %lld, audioSinkPlayedUs: %lld",
1264 __func__, (long long)pendingUs,
1265 (long long)writtenAudioDurationUs, (long long)audioSinkPlayedUs);
1266 pendingUs = 0;
1267 }
1268 return pendingUs;
Ronghua Wu5095d702014-08-27 12:05:48 -07001269}
1270
Ronghua Wua73d9e02014-10-08 15:13:29 -07001271int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001272 int64_t realUs;
1273 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001274 // If failed to get current position, e.g. due to audio clock is
1275 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001276 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001277 }
Wei Jia98160162015-02-04 17:01:11 -08001278 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001279}
1280
Ronghua Wueecb7802014-10-19 23:12:50 -07001281void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001282 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001283 // TRICKY: vorbis decoder generates multiple frames with the same
1284 // timestamp, so only update on the first frame with a given timestamp
1285 if (mediaTimeUs == mAnchorTimeMediaUs) {
1286 return;
1287 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001288 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001289
Andy Hung528c8402016-01-12 12:39:34 -08001290 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1291 if (mNextAudioClockUpdateTimeUs == -1) {
1292 AudioTimestamp ts;
1293 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1294 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1295 }
1296 }
Wei Jia12b62652016-02-09 17:49:31 -08001297 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001298 if (mNextAudioClockUpdateTimeUs >= 0) {
1299 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1300 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1301 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001302 mUseVirtualAudioSink = false;
Andy Hung528c8402016-01-12 12:39:34 -08001303 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1304 }
Wei Jia12b62652016-02-09 17:49:31 -08001305 } else {
1306 int64_t unused;
1307 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1308 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1309 > kMaxAllowedAudioSinkDelayUs)) {
1310 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1311 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1312 // connected to audio out.
1313 // Switch to system clock. This essentially creates a virtual AudioSink with
1314 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1315 // This virtual AudioSink renders audio data starting from the very first sample
1316 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001317 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001318 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001319 mUseVirtualAudioSink = true;
Wei Jia12b62652016-02-09 17:49:31 -08001320 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001321 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001322 mAnchorNumFramesWritten = mNumFramesWritten;
Wei Jia7b15cb32015-02-03 17:46:06 -08001323 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001324}
1325
Wei Jia7b15cb32015-02-03 17:46:06 -08001326// Called without mLock acquired.
1327void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001328 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001329 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001330 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001331 return;
1332 }
1333
1334 if (mVideoQueue.empty()) {
1335 return;
1336 }
1337
1338 QueueEntry &entry = *mVideoQueue.begin();
1339
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001340 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001341 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001342
Andreas Huberf9334412010-12-15 15:17:42 -08001343 if (entry.mBuffer == NULL) {
1344 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001345 msg->post();
1346 mDrainVideoQueuePending = true;
1347 return;
1348 }
1349
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001350 int64_t nowUs = ALooper::GetNowUs();
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001351 if (mFlags & FLAG_REAL_TIME) {
Wei Jia17648f32017-09-19 13:16:30 -07001352 int64_t realTimeUs;
1353 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &realTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001354
Wei Jia17648f32017-09-19 13:16:30 -07001355 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Lajos Molnard5923402014-10-20 17:47:54 -07001356
Wei Jia17648f32017-09-19 13:16:30 -07001357 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
Robert Shih00541e22015-12-18 17:04:00 -08001358
Wei Jia17648f32017-09-19 13:16:30 -07001359 int64_t delayUs = realTimeUs - nowUs;
1360
1361 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %lld", (long long)delayUs);
1362 // post 2 display refreshes before rendering is due
1363 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1364
1365 mDrainVideoQueuePending = true;
1366 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001367 }
1368
Wei Jia17648f32017-09-19 13:16:30 -07001369 int64_t mediaTimeUs;
1370 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001371
Wei Jia17648f32017-09-19 13:16:30 -07001372 {
1373 Mutex::Autolock autoLock(mLock);
1374 if (mAnchorTimeMediaUs < 0) {
1375 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1376 mAnchorTimeMediaUs = mediaTimeUs;
1377 }
1378 }
Wei Jia1225b932019-01-04 12:44:38 -08001379 mNextVideoTimeMediaUs = mediaTimeUs;
Wei Jia17648f32017-09-19 13:16:30 -07001380 if (!mHasAudio) {
1381 // smooth out videos >= 10fps
Wei Jiacc951512019-04-03 16:10:42 -07001382 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia17648f32017-09-19 13:16:30 -07001383 }
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001384
Wei Jia17648f32017-09-19 13:16:30 -07001385 if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
1386 msg->post();
1387 } else {
1388 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1389
1390 // post 2 display refreshes before rendering is due
1391 mMediaClock->addTimer(msg, mediaTimeUs, -twoVsyncsUs);
1392 }
Andreas Huberf9334412010-12-15 15:17:42 -08001393
1394 mDrainVideoQueuePending = true;
1395}
1396
1397void NuPlayer::Renderer::onDrainVideoQueue() {
1398 if (mVideoQueue.empty()) {
1399 return;
1400 }
1401
1402 QueueEntry *entry = &*mVideoQueue.begin();
1403
1404 if (entry->mBuffer == NULL) {
1405 // EOS
1406
Andreas Huberc92fd242011-08-16 13:48:44 -07001407 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001408
1409 mVideoQueue.erase(mVideoQueue.begin());
1410 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001411
Ronghua Wua73d9e02014-10-08 15:13:29 -07001412 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001413 return;
1414 }
1415
Wei Jia25d696f2015-11-19 10:57:15 -08001416 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001417 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001418 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001419 if (mFlags & FLAG_REAL_TIME) {
1420 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1421 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001422 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001423
Ronghua Wua73d9e02014-10-08 15:13:29 -07001424 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001425 }
Wei Jia17648f32017-09-19 13:16:30 -07001426 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Andreas Huberd5e56232013-03-12 11:01:43 -07001427
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001428 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001429
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001430 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001431 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001432 tooLate = (mVideoLateByUs > 40000);
1433
1434 if (tooLate) {
1435 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001436 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001437 } else {
Wei Jia98160162015-02-04 17:01:11 -08001438 int64_t mediaUs = 0;
1439 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001440 ALOGV("rendering video at media time %.2f secs",
1441 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001442 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001443
1444 if (!(mFlags & FLAG_REAL_TIME)
1445 && mLastAudioMediaTimeUs != -1
1446 && mediaTimeUs > mLastAudioMediaTimeUs) {
1447 // If audio ends before video, video continues to drive media clock.
1448 // Also smooth out videos >= 10fps.
Wei Jiacc951512019-04-03 16:10:42 -07001449 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001450 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001451 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001452 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001453 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001454 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001455 // This will ensure that the first frame after a flush won't be used as anchor
1456 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia9a3101b2016-11-08 14:34:24 -08001457 clearAnchorTime();
Wei Jia49966ff2014-10-08 18:44:45 -07001458 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001459 }
Andreas Huberf9334412010-12-15 15:17:42 -08001460
Wei Jia25d696f2015-11-19 10:57:15 -08001461 // Always render the first video frame while keeping stats on A/V sync.
1462 if (!mVideoSampleReceived) {
1463 realTimeUs = nowUs;
1464 tooLate = false;
1465 }
1466
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001467 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000LL);
Glenn Kasten683525b2011-11-04 18:05:35 -07001468 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001469 entry->mNotifyConsumed->post();
1470 mVideoQueue.erase(mVideoQueue.begin());
1471 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001472
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001473 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001474
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001475 if (!mPaused) {
1476 if (!mVideoRenderingStarted) {
1477 mVideoRenderingStarted = true;
1478 notifyVideoRenderingStart();
1479 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001480 Mutex::Autolock autoLock(mLock);
1481 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001482 }
Andreas Huberf9334412010-12-15 15:17:42 -08001483}
1484
James Dongf57b4ea2012-07-20 13:38:36 -07001485void NuPlayer::Renderer::notifyVideoRenderingStart() {
1486 sp<AMessage> notify = mNotify->dup();
1487 notify->setInt32("what", kWhatVideoRenderingStart);
1488 notify->post();
1489}
1490
Ronghua Wu5095d702014-08-27 12:05:48 -07001491void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jiad214a562017-07-10 13:20:55 -07001492 Mutex::Autolock autoLock(mLock);
1493 notifyEOS_l(audio, finalResult, delayUs);
1494}
1495
1496void NuPlayer::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001497 if (audio && delayUs > 0) {
1498 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1499 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1500 msg->setInt32("finalResult", finalResult);
1501 msg->post(delayUs);
1502 return;
1503 }
Andreas Huberf9334412010-12-15 15:17:42 -08001504 sp<AMessage> notify = mNotify->dup();
1505 notify->setInt32("what", kWhatEOS);
1506 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001507 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001508 notify->post(delayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001509
1510 if (audio) {
1511 // Video might outlive audio. Clear anchor to enable video only case.
1512 mAnchorTimeMediaUs = -1;
Wei Jiaaec8d822017-08-25 15:27:57 -07001513 mHasAudio = false;
Wei Jiadc293e32017-10-16 18:29:37 -07001514 if (mNextVideoTimeMediaUs >= 0) {
1515 int64_t mediaUs = 0;
Wei Jia1225b932019-01-04 12:44:38 -08001516 int64_t nowUs = ALooper::GetNowUs();
1517 status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
1518 if (result == OK) {
1519 if (mNextVideoTimeMediaUs > mediaUs) {
1520 mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
1521 }
1522 } else {
1523 mMediaClock->updateAnchor(
Wei Jiacc951512019-04-03 16:10:42 -07001524 mNextVideoTimeMediaUs, nowUs,
1525 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
Wei Jiadc293e32017-10-16 18:29:37 -07001526 }
1527 }
Wei Jiad214a562017-07-10 13:20:55 -07001528 }
Andreas Huberf9334412010-12-15 15:17:42 -08001529}
1530
Wei Jiaa05f1e32016-03-25 16:31:22 -07001531void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1532 sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1533 msg->setInt32("reason", reason);
1534 msg->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001535}
1536
Andreas Huberf9334412010-12-15 15:17:42 -08001537void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1538 int32_t audio;
1539 CHECK(msg->findInt32("audio", &audio));
1540
Wei Jia7b15cb32015-02-03 17:46:06 -08001541 if (dropBufferIfStale(audio, msg)) {
1542 return;
1543 }
1544
1545 if (audio) {
1546 mHasAudio = true;
1547 } else {
1548 mHasVideo = true;
1549 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001550
1551 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001552 if (mVideoScheduler == NULL) {
1553 mVideoScheduler = new VideoFrameScheduler();
1554 mVideoScheduler->init();
1555 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001556 }
1557
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001558 sp<RefBase> obj;
1559 CHECK(msg->findObject("buffer", &obj));
1560 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
Andreas Huberf9334412010-12-15 15:17:42 -08001561
1562 sp<AMessage> notifyConsumed;
1563 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1564
1565 QueueEntry entry;
1566 entry.mBuffer = buffer;
1567 entry.mNotifyConsumed = notifyConsumed;
1568 entry.mOffset = 0;
1569 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001570 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001571
1572 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001573 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001574 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001575 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001576 } else {
1577 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001578 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001579 }
1580
Wei Jia7b15cb32015-02-03 17:46:06 -08001581 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001582 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1583 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001584 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001585
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001586 sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1587 sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
Andreas Hubercb67cd12011-08-26 16:02:19 -07001588
1589 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1590 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001591 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001592 return;
1593 }
1594
1595 int64_t firstAudioTimeUs;
1596 int64_t firstVideoTimeUs;
1597 CHECK(firstAudioBuffer->meta()
1598 ->findInt64("timeUs", &firstAudioTimeUs));
1599 CHECK(firstVideoBuffer->meta()
1600 ->findInt64("timeUs", &firstVideoTimeUs));
1601
1602 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1603
Steve Block3856b092011-10-20 11:56:00 +01001604 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001605
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001606 if (diff > 100000LL) {
Andreas Hubercb67cd12011-08-26 16:02:19 -07001607 // Audio data starts More than 0.1 secs before video.
1608 // Drop some audio.
1609
1610 (*mAudioQueue.begin()).mNotifyConsumed->post();
1611 mAudioQueue.erase(mAudioQueue.begin());
1612 return;
1613 }
1614
Wei Jiabc2fb722014-07-08 16:37:57 -07001615 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001616}
1617
Wei Jiabc2fb722014-07-08 16:37:57 -07001618void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001619 if (!mSyncQueues) {
1620 return;
1621 }
1622
1623 mSyncQueues = false;
1624
1625 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001626 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001627 }
1628
1629 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001630 mLock.unlock();
1631 postDrainVideoQueue();
1632 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001633 }
1634}
1635
1636void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1637 int32_t audio;
1638 CHECK(msg->findInt32("audio", &audio));
1639
Wei Jia7b15cb32015-02-03 17:46:06 -08001640 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001641 return;
1642 }
1643
1644 int32_t finalResult;
1645 CHECK(msg->findInt32("finalResult", &finalResult));
1646
1647 QueueEntry entry;
1648 entry.mOffset = 0;
1649 entry.mFinalResult = finalResult;
1650
1651 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001652 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001653 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001654 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001655 }
Andreas Huberf9334412010-12-15 15:17:42 -08001656 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001657 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001658 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001659 if (mVideoQueue.empty() && getSyncQueues()) {
1660 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001661 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001662 }
Andreas Huberf9334412010-12-15 15:17:42 -08001663 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001664 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001665 }
1666}
1667
1668void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001669 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001670 CHECK(msg->findInt32("audio", &audio));
1671
Wei Jia28a8a9f2014-08-18 11:29:50 -07001672 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001673 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001674 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001675 notifyComplete = mNotifyCompleteAudio;
1676 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001677 mLastAudioMediaTimeUs = -1;
Wei Jiacc951512019-04-03 16:10:42 -07001678
1679 mHasAudio = false;
1680 if (mNextVideoTimeMediaUs >= 0) {
1681 int64_t nowUs = ALooper::GetNowUs();
1682 mMediaClock->updateAnchor(
1683 mNextVideoTimeMediaUs, nowUs,
1684 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
1685 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001686 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001687 notifyComplete = mNotifyCompleteVideo;
1688 mNotifyCompleteVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001689 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001690
Wei Jia7b15cb32015-02-03 17:46:06 -08001691 // If we're currently syncing the queues, i.e. dropping audio while
1692 // aligning the first audio/video buffer times and only one of the
1693 // two queues has data, we may starve that queue by not requesting
1694 // more buffers from the decoder. If the other source then encounters
1695 // a discontinuity that leads to flushing, we'll never find the
1696 // corresponding discontinuity on the other queue.
1697 // Therefore we'll stop syncing the queues if at least one of them
1698 // is flushed.
1699 syncQueuesDone_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001700 }
Wei Jia9a3101b2016-11-08 14:34:24 -08001701 clearAnchorTime();
Andreas Huberf9334412010-12-15 15:17:42 -08001702
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001703 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001704 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001705 {
1706 Mutex::Autolock autoLock(mLock);
1707 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001708
Wei Jia7b15cb32015-02-03 17:46:06 -08001709 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001710 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001711 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001712
Andy Hunga0b39712015-05-31 22:40:49 -07001713 // the frame count will be reset after flush.
1714 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001715 }
Andreas Huberf9334412010-12-15 15:17:42 -08001716
Andreas Huberf9334412010-12-15 15:17:42 -08001717 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001718
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001719 mAudioSink->pause();
1720 mAudioSink->flush();
1721 if (!offloadingAudio()) {
Wei Jia9e7ed332015-05-01 16:35:43 -07001722 // Call stop() to signal to the AudioSink to completely fill the
1723 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001724 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001725 mAudioSink->stop();
Wei Jia9e7ed332015-05-01 16:35:43 -07001726 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001727 }
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001728 if (!mPaused) {
1729 mAudioSink->start();
1730 }
Andy Hung528c8402016-01-12 12:39:34 -08001731 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001732 } else {
1733 flushQueue(&mVideoQueue);
1734
Andreas Huberf9334412010-12-15 15:17:42 -08001735 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001736
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001737 if (mVideoScheduler != NULL) {
1738 mVideoScheduler->restart();
1739 }
1740
Wei Jia7b15cb32015-02-03 17:46:06 -08001741 Mutex::Autolock autoLock(mLock);
1742 ++mVideoDrainGeneration;
1743 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001744 }
1745
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001746 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001747
1748 if (notifyComplete) {
1749 notifyFlushComplete(audio);
1750 }
Andreas Huberf9334412010-12-15 15:17:42 -08001751}
1752
1753void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1754 while (!queue->empty()) {
1755 QueueEntry *entry = &*queue->begin();
1756
1757 if (entry->mBuffer != NULL) {
1758 entry->mNotifyConsumed->post();
Wei Jia9a3101b2016-11-08 14:34:24 -08001759 } else if (entry->mNotifyConsumed != nullptr) {
1760 // Is it needed to open audio sink now?
1761 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
Andreas Huberf9334412010-12-15 15:17:42 -08001762 }
1763
1764 queue->erase(queue->begin());
1765 entry = NULL;
1766 }
1767}
1768
1769void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1770 sp<AMessage> notify = mNotify->dup();
1771 notify->setInt32("what", kWhatFlushComplete);
1772 notify->setInt32("audio", static_cast<int32_t>(audio));
1773 notify->post();
1774}
1775
Wei Jia7b15cb32015-02-03 17:46:06 -08001776bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001777 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001778 int32_t queueGeneration;
1779 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001780
Wei Jia7b15cb32015-02-03 17:46:06 -08001781 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001782 return false;
1783 }
1784
1785 sp<AMessage> notifyConsumed;
1786 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1787 notifyConsumed->post();
1788 }
1789
1790 return true;
1791}
1792
Andreas Huber3831a062010-12-21 10:22:33 -08001793void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001794 if (offloadingAudio()) {
1795 return;
1796 }
Andreas Huber3831a062010-12-21 10:22:33 -08001797 CHECK(!mDrainAudioQueuePending);
1798 mNumFramesWritten = 0;
Wei Jia9a3101b2016-11-08 14:34:24 -08001799 mAnchorNumFramesWritten = -1;
Marco Nelissen4110c102012-03-29 09:31:28 -07001800 uint32_t written;
1801 if (mAudioSink->getFramesWritten(&written) == OK) {
1802 mNumFramesWritten = written;
1803 }
Andreas Huber3831a062010-12-21 10:22:33 -08001804}
1805
Wei Jiabc2fb722014-07-08 16:37:57 -07001806void NuPlayer::Renderer::onDisableOffloadAudio() {
1807 Mutex::Autolock autoLock(mLock);
1808 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001809 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001810 if (mAudioRenderingStartGeneration != -1) {
1811 prepareForMediaRenderingStart_l();
andysu36177952018-04-20 15:17:13 +08001812 // PauseTimeout is applied to offload mode only. Cancel pending timer.
1813 cancelAudioOffloadPauseTimeout();
Robert Shihe1d70192015-07-23 17:54:13 -07001814 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001815}
1816
Ronghua Wua10fd232014-11-06 16:15:20 -08001817void NuPlayer::Renderer::onEnableOffloadAudio() {
1818 Mutex::Autolock autoLock(mLock);
1819 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001820 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001821 if (mAudioRenderingStartGeneration != -1) {
1822 prepareForMediaRenderingStart_l();
1823 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001824}
1825
Andreas Huberb4082222011-01-20 15:23:04 -08001826void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001827 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001828 return;
1829 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001830
Eric Laurent7fb51272022-07-01 16:42:48 +02001831 startAudioOffloadPauseTimeout();
1832
Wei Jia28a8a9f2014-08-18 11:29:50 -07001833 {
1834 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001835 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001836 ++mVideoDrainGeneration;
1837 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001838 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001839 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001840 }
1841
Andreas Huberb4082222011-01-20 15:23:04 -08001842 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001843 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001844
Andy Hung84200732015-12-03 14:41:06 -08001845 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1846 mAudioSink->pause();
Andreas Huberb4082222011-01-20 15:23:04 -08001847
Lajos Molnar6d339f12015-04-17 16:15:53 -07001848 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001849 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001850}
1851
1852void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001853 if (!mPaused) {
1854 return;
1855 }
Andreas Huberb4082222011-01-20 15:23:04 -08001856
Andy Hung84200732015-12-03 14:41:06 -08001857 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1858 cancelAudioOffloadPauseTimeout();
1859 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001860 status_t err = mAudioSink->start();
1861 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001862 ALOGE("cannot start AudioSink err %d", err);
Wei Jiaa05f1e32016-03-25 16:31:22 -07001863 notifyAudioTearDown(kDueToError);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001864 }
Andreas Huberb4082222011-01-20 15:23:04 -08001865 }
1866
Wei Jia7b15cb32015-02-03 17:46:06 -08001867 {
1868 Mutex::Autolock autoLock(mLock);
1869 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001870 // rendering started message may have been delayed if we were paused.
1871 if (mRenderingDataDelivered) {
1872 notifyIfMediaRenderingStarted_l();
1873 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001874 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001875 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001876 mAudioSink->setPlaybackRate(mPlaybackSettings);
1877 }
1878
Wei Jia98160162015-02-04 17:01:11 -08001879 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001880
Wei Jia7b15cb32015-02-03 17:46:06 -08001881 if (!mAudioQueue.empty()) {
1882 postDrainAudioQueue_l();
1883 }
Andreas Huberb4082222011-01-20 15:23:04 -08001884 }
1885
1886 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001887 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001888 }
1889}
1890
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001891void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1892 if (mVideoScheduler == NULL) {
1893 mVideoScheduler = new VideoFrameScheduler();
1894 }
1895 mVideoScheduler->init(fps);
1896}
1897
Wei Jia7b15cb32015-02-03 17:46:06 -08001898int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1899 Mutex::Autolock autoLock(mLock);
1900 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1901}
1902
1903int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1904 Mutex::Autolock autoLock(mLock);
1905 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1906}
1907
1908bool NuPlayer::Renderer::getSyncQueues() {
1909 Mutex::Autolock autoLock(mLock);
1910 return mSyncQueues;
1911}
1912
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001913void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1914 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001915 return;
1916 }
andysu36177952018-04-20 15:17:13 +08001917
1918 // TimeoutWhenPaused is only for offload mode.
1919 if (reason == kDueToTimeout && !offloadingAudio()) {
1920 return;
1921 }
1922
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001923 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001924
Ronghua Wua73d9e02014-10-08 15:13:29 -07001925 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001926 sp<AMessage> notify = mNotify->dup();
1927 if (getCurrentPosition(&currentPositionUs) == OK) {
1928 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001929 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001930
Wei Jia3a2956d2014-07-22 16:01:33 -07001931 mAudioSink->stop();
1932 mAudioSink->flush();
1933
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001934 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001935 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001936 notify->post();
1937}
1938
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001939void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1940 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001941 mWakeLock->acquire();
christosts9aacf192023-03-09 14:12:36 +00001942 mWakelockAcquireEvent.updateValues(uptimeMillis(),
1943 mAudioOffloadPauseTimeoutGeneration,
1944 mAudioOffloadPauseTimeoutGeneration);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001945 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001946 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001947 msg->post(kOffloadPauseMaxUs);
1948 }
1949}
1950
1951void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
Andy Hung21afe802016-04-21 14:52:05 -07001952 // We may have called startAudioOffloadPauseTimeout() without
1953 // the AudioSink open and with offloadingAudio enabled.
1954 //
1955 // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
1956 // we always release the wakelock and increment the pause timeout generation.
1957 //
1958 // Note: The acquired wakelock prevents the device from suspending
1959 // immediately after offload pause (in case a resume happens shortly thereafter).
1960 mWakeLock->release(true);
christosts9aacf192023-03-09 14:12:36 +00001961 mWakelockCancelEvent.updateValues(uptimeMillis(),
1962 mAudioOffloadPauseTimeoutGeneration,
1963 mAudioOffloadPauseTimeoutGeneration);
Andy Hung21afe802016-04-21 14:52:05 -07001964 ++mAudioOffloadPauseTimeoutGeneration;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001965}
1966
Andy Hung202bce12014-12-03 11:47:36 -08001967status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001968 const sp<AMessage> &format,
1969 bool offloadOnly,
1970 bool hasVideo,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05301971 uint32_t flags,
1972 bool isStreaming) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001973 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1974 offloadOnly, offloadingAudio());
1975 bool audioSinkChanged = false;
1976
1977 int32_t numChannels;
1978 CHECK(format->findInt32("channel-count", &numChannels));
1979
Jean-Michel Trivic18a9762022-07-08 18:18:07 +00001980 // channel mask info as read from the audio format
Andy Hung66b2da52022-08-29 20:07:43 -07001981 int32_t mediaFormatChannelMask;
Jean-Michel Trivic18a9762022-07-08 18:18:07 +00001982 // channel mask to use for native playback
1983 audio_channel_mask_t channelMask;
Andy Hung66b2da52022-08-29 20:07:43 -07001984 if (format->findInt32("channel-mask", &mediaFormatChannelMask)) {
Jean-Michel Trivic18a9762022-07-08 18:18:07 +00001985 // KEY_CHANNEL_MASK follows the android.media.AudioFormat java mask
Andy Hung66b2da52022-08-29 20:07:43 -07001986 channelMask = audio_channel_mask_from_media_format_mask(mediaFormatChannelMask);
Jean-Michel Trivic18a9762022-07-08 18:18:07 +00001987 } else {
1988 // no mask found: the mask will be derived from the channel count
1989 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
1990 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001991
1992 int32_t sampleRate;
1993 CHECK(format->findInt32("sample-rate", &sampleRate));
1994
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07001995 // read pcm encoding from MediaCodec output format, if available
1996 int32_t pcmEncoding;
1997 audio_format_t audioFormat =
1998 format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
1999 audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
2000
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002001 if (offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002002 AString mime;
2003 CHECK(format->findString("mime", &mime));
2004 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
2005
2006 if (err != OK) {
2007 ALOGE("Couldn't map mime \"%s\" to a valid "
2008 "audio_format", mime.c_str());
2009 onDisableOffloadAudio();
2010 } else {
2011 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
2012 mime.c_str(), audioFormat);
2013
Ajender Reddy55a85792021-02-25 21:01:35 +05302014 int avgBitRate = 0;
Lajos Molnar46f80162016-05-19 15:35:47 -07002015 format->findInt32("bitrate", &avgBitRate);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002016
2017 int32_t aacProfile = -1;
2018 if (audioFormat == AUDIO_FORMAT_AAC
2019 && format->findInt32("aac-profile", &aacProfile)) {
2020 // Redefine AAC format as per aac profile
2021 mapAACProfileToAudioFormat(
2022 audioFormat,
2023 aacProfile);
2024 }
2025
2026 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
2027 offloadInfo.duration_us = -1;
2028 format->findInt64(
2029 "durationUs", &offloadInfo.duration_us);
2030 offloadInfo.sample_rate = sampleRate;
2031 offloadInfo.channel_mask = channelMask;
2032 offloadInfo.format = audioFormat;
2033 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
2034 offloadInfo.bit_rate = avgBitRate;
2035 offloadInfo.has_video = hasVideo;
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302036 offloadInfo.is_streaming = isStreaming;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002037
2038 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
2039 ALOGV("openAudioSink: no change in offload mode");
2040 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08002041 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002042 }
Andy Hungf0e83642014-12-19 17:55:56 -08002043 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
2044
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002045 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002046 uint32_t offloadFlags = flags;
2047 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
2048 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002049 audioSinkChanged = true;
2050 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07002051
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002052 err = mAudioSink->open(
2053 sampleRate,
2054 numChannels,
2055 (audio_channel_mask_t)channelMask,
2056 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002057 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002058 &NuPlayer::Renderer::AudioSinkCallback,
2059 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002060 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002061 &offloadInfo);
2062
2063 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002064 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
2065 }
2066
2067 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002068 // If the playback is offloaded to h/w, we pass
2069 // the HAL some metadata information.
2070 // We don't want to do this for PCM because it
2071 // will be going through the AudioFlinger mixer
2072 // before reaching the hardware.
2073 // TODO
2074 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07002075 if (!mPaused) { // for preview mode, don't start if paused
2076 err = mAudioSink->start();
2077 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002078 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
2079 }
2080 if (err != OK) {
2081 // Clean up, fall back to non offload mode.
2082 mAudioSink->close();
2083 onDisableOffloadAudio();
2084 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
2085 ALOGV("openAudioSink: offload failed");
Wei Jiaa05f1e32016-03-25 16:31:22 -07002086 if (offloadOnly) {
2087 notifyAudioTearDown(kForceNonOffload);
2088 }
Wei Jia3ab25452015-06-10 09:37:47 -07002089 } else {
2090 mUseAudioCallback = true; // offload mode transfers data through callback
2091 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002092 }
2093 }
2094 }
2095 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002096 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002097 uint32_t pcmFlags = flags;
2098 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08002099
2100 const PcmInfo info = {
2101 (audio_channel_mask_t)channelMask,
2102 (audio_output_flags_t)pcmFlags,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002103 audioFormat,
Andy Hungf0e83642014-12-19 17:55:56 -08002104 numChannels,
2105 sampleRate
2106 };
2107 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
2108 ALOGV("openAudioSink: no change in pcm mode");
2109 // no change from previous configuration, everything ok.
2110 return OK;
2111 }
2112
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002113 audioSinkChanged = true;
2114 mAudioSink->close();
2115 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07002116 // Note: It is possible to set up the callback, but not use it to send audio data.
2117 // This requires a fix in AudioSink to explicitly specify the transfer mode.
2118 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07002119 if (mUseAudioCallback) {
2120 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
2121 }
Andy Hung179652e2015-05-31 22:49:46 -07002122
2123 // Compute the desired buffer size.
2124 // For callback mode, the amount of time before wakeup is about half the buffer size.
2125 const uint32_t frameCount =
2126 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
2127
Ronghua Wu7665f582015-09-02 10:15:30 -07002128 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
2129 // AudioSink. We don't want this when there's video because it will cause a video seek to
2130 // the previous I frame. But we do want this when there's only audio because it will give
2131 // NuPlayer a chance to switch from non-offload mode to offload mode.
2132 // So we only set doNotReconnect when there's no video.
2133 const bool doNotReconnect = !hasVideo;
Andy Hungff874dc2016-04-11 16:49:09 -07002134
2135 // We should always be able to set our playback settings if the sink is closed.
2136 LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
2137 "onOpenAudioSink: can't set playback rate on closed sink");
Andy Hung202bce12014-12-03 11:47:36 -08002138 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002139 sampleRate,
2140 numChannels,
2141 (audio_channel_mask_t)channelMask,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002142 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002143 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07002144 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
2145 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002146 (audio_output_flags_t)pcmFlags,
2147 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07002148 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07002149 frameCount);
Andy Hung202bce12014-12-03 11:47:36 -08002150 if (err != OK) {
2151 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07002152 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08002153 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08002154 return err;
2155 }
Andy Hungf0e83642014-12-19 17:55:56 -08002156 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07002157 if (!mPaused) { // for preview mode, don't start if paused
2158 mAudioSink->start();
2159 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002160 }
2161 if (audioSinkChanged) {
2162 onAudioSinkChanged();
2163 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002164 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08002165 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002166}
2167
2168void NuPlayer::Renderer::onCloseAudioSink() {
2169 mAudioSink->close();
2170 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08002171 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002172}
2173
Wei Jia9a3101b2016-11-08 14:34:24 -08002174void NuPlayer::Renderer::onChangeAudioFormat(
2175 const sp<AMessage> &meta, const sp<AMessage> &notify) {
2176 sp<AMessage> format;
2177 CHECK(meta->findMessage("format", &format));
2178
2179 int32_t offloadOnly;
2180 CHECK(meta->findInt32("offload-only", &offloadOnly));
2181
2182 int32_t hasVideo;
2183 CHECK(meta->findInt32("has-video", &hasVideo));
2184
2185 uint32_t flags;
2186 CHECK(meta->findInt32("flags", (int32_t *)&flags));
2187
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302188 uint32_t isStreaming;
2189 CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
2190
2191 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -08002192
2193 if (err != OK) {
2194 notify->setInt32("err", err);
2195 }
2196 notify->post();
2197}
2198
christosts9aacf192023-03-09 14:12:36 +00002199void NuPlayer::Renderer::WakeLockEvent::dump(AString& logString) {
2200 logString.append("[");
2201 logString.append(mTimeMs);
2202 logString.append(",");
2203 logString.append(mEventTimeoutGeneration);
2204 logString.append(",");
2205 logString.append(mRendererTimeoutGeneration);
2206 logString.append("]");
2207}
2208
Andreas Huberf9334412010-12-15 15:17:42 -08002209} // namespace android