blob: b37a1314de22b1396646099f0c885af9a559abc1 [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 Laurent8ca036a2022-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),
Ian Baker130bbc42023-08-09 18:19:50 +0100135 mAudioAnchorTimeMediaUs(-1),
Ronghua Wueecb7802014-10-19 23:12:50 -0700136 mAnchorTimeMediaUs(-1),
Lajos Molnarf5926712014-10-21 09:36:43 -0700137 mAnchorNumFramesWritten(-1),
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800138 mVideoLateByUs(0LL),
Wei Jiadc293e32017-10-16 18:29:37 -0700139 mNextVideoTimeMediaUs(-1),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800140 mHasAudio(false),
141 mHasVideo(false),
Chong Zhang7137ec72014-11-12 16:41:05 -0800142 mNotifyCompleteAudio(false),
143 mNotifyCompleteVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800144 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -0700145 mPaused(false),
Andy Hungb03dcb32015-08-27 16:18:59 -0700146 mPauseDrainAudioAllowedUs(0),
Andy Hung09e0c362014-09-12 15:12:16 -0700147 mVideoSampleReceived(false),
James Dongf57b4ea2012-07-20 13:38:36 -0700148 mVideoRenderingStarted(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700149 mVideoRenderingStartGeneration(0),
150 mAudioRenderingStartGeneration(0),
Andy Hungb12ea0b2015-09-03 15:13:01 -0700151 mRenderingDataDelivered(false),
Andy Hung528c8402016-01-12 12:39:34 -0800152 mNextAudioClockUpdateTimeUs(-1),
Wei Jia2995dc72015-07-24 16:00:33 -0700153 mLastAudioMediaTimeUs(-1),
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700154 mAudioOffloadPauseTimeoutGeneration(0),
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700155 mAudioTornDown(false),
Lajos Molnard5923402014-10-20 17:47:54 -0700156 mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
Andy Hungf0e83642014-12-19 17:55:56 -0800157 mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
Lajos Molnard5923402014-10-20 17:47:54 -0700158 mTotalBuffersQueued(0),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800159 mLastAudioBufferDrained(0),
Andy Hunga0b39712015-05-31 22:40:49 -0700160 mUseAudioCallback(false),
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +0530161 mWakeLock(new AWakeLock()),
162 mNeedVideoClearAnchor(false) {
Wei Jia0a68f662017-08-30 18:01:26 -0700163 CHECK(mediaClock != NULL);
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700164 mPlaybackRate = mPlaybackSettings.mSpeed;
165 mMediaClock->setPlaybackRate(mPlaybackRate);
Wonsik Kimee8116b2019-07-19 15:55:44 -0700166 (void)mSyncFlag.test_and_set();
Andreas Huberf9334412010-12-15 15:17:42 -0800167}
168
169NuPlayer::Renderer::~Renderer() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700170 if (offloadingAudio()) {
171 mAudioSink->stop();
172 mAudioSink->flush();
173 mAudioSink->close();
174 }
Wei Jia4c74fde2016-08-26 16:00:52 -0700175
176 // Try to avoid racing condition in case callback is still on.
177 Mutex::Autolock autoLock(mLock);
Wei Jia9a3101b2016-11-08 14:34:24 -0800178 if (mUseAudioCallback) {
179 flushQueue(&mAudioQueue);
180 flushQueue(&mVideoQueue);
181 }
Wei Jia4c74fde2016-08-26 16:00:52 -0700182 mWakeLock.clear();
Wei Jia4c74fde2016-08-26 16:00:52 -0700183 mVideoScheduler.clear();
184 mNotify.clear();
185 mAudioSink.clear();
Andreas Huberf9334412010-12-15 15:17:42 -0800186}
187
188void NuPlayer::Renderer::queueBuffer(
189 bool audio,
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900190 const sp<MediaCodecBuffer> &buffer,
Andreas Huberf9334412010-12-15 15:17:42 -0800191 const sp<AMessage> &notifyConsumed) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800192 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800193 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800194 msg->setInt32("audio", static_cast<int32_t>(audio));
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900195 msg->setObject("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -0800196 msg->setMessage("notifyConsumed", notifyConsumed);
197 msg->post();
198}
199
200void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
201 CHECK_NE(finalResult, (status_t)OK);
202
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800203 sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800204 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800205 msg->setInt32("audio", static_cast<int32_t>(audio));
206 msg->setInt32("finalResult", finalResult);
207 msg->post();
208}
209
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700210status_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
211 sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
212 writeToAMessage(msg, rate);
213 sp<AMessage> response;
214 status_t err = msg->postAndAwaitResponse(&response);
215 if (err == OK && response != NULL) {
216 CHECK(response->findInt32("err", &err));
217 }
218 return err;
219}
220
221status_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
222 if (rate.mSpeed == 0.f) {
223 onPause();
224 // don't call audiosink's setPlaybackRate if pausing, as pitch does not
225 // have to correspond to the any non-0 speed (e.g old speed). Keep
226 // settings nonetheless, using the old speed, in case audiosink changes.
227 AudioPlaybackRate newRate = rate;
228 newRate.mSpeed = mPlaybackSettings.mSpeed;
229 mPlaybackSettings = newRate;
230 return OK;
231 }
232
Wei Jia27ea08e2015-05-12 14:50:35 -0700233 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700234 status_t err = mAudioSink->setPlaybackRate(rate);
235 if (err != OK) {
236 return err;
237 }
238 }
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +0530239
240 if (!mHasAudio && mHasVideo) {
241 mNeedVideoClearAnchor = true;
242 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700243 mPlaybackSettings = rate;
244 mPlaybackRate = rate.mSpeed;
245 mMediaClock->setPlaybackRate(mPlaybackRate);
246 return OK;
247}
248
249status_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
250 sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
251 sp<AMessage> response;
252 status_t err = msg->postAndAwaitResponse(&response);
253 if (err == OK && response != NULL) {
254 CHECK(response->findInt32("err", &err));
255 if (err == OK) {
256 readFromAMessage(response, rate);
257 }
258 }
259 return err;
260}
261
262status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
Wei Jia27ea08e2015-05-12 14:50:35 -0700263 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700264 status_t err = mAudioSink->getPlaybackRate(rate);
265 if (err == OK) {
266 if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
267 ALOGW("correcting mismatch in internal/external playback rate");
268 }
269 // get playback settings used by audiosink, as it may be
270 // slightly off due to audiosink not taking small changes.
271 mPlaybackSettings = *rate;
272 if (mPaused) {
273 rate->mSpeed = 0.f;
274 }
275 }
276 return err;
277 }
278 *rate = mPlaybackSettings;
279 return OK;
280}
281
282status_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
283 sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
284 writeToAMessage(msg, sync, videoFpsHint);
285 sp<AMessage> response;
286 status_t err = msg->postAndAwaitResponse(&response);
287 if (err == OK && response != NULL) {
288 CHECK(response->findInt32("err", &err));
289 }
290 return err;
291}
292
293status_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
294 if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
295 return BAD_VALUE;
296 }
297 // TODO: support sync sources
298 return INVALID_OPERATION;
299}
300
301status_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
302 sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
303 sp<AMessage> response;
304 status_t err = msg->postAndAwaitResponse(&response);
305 if (err == OK && response != NULL) {
306 CHECK(response->findInt32("err", &err));
307 if (err == OK) {
308 readFromAMessage(response, sync, videoFps);
309 }
310 }
311 return err;
312}
313
314status_t NuPlayer::Renderer::onGetSyncSettings(
315 AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
316 *sync = mSyncSettings;
317 *videoFps = -1.f;
318 return OK;
Wei Jia98160162015-02-04 17:01:11 -0800319}
320
Chong Zhang7137ec72014-11-12 16:41:05 -0800321void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800322 {
Wei Jia7b15cb32015-02-03 17:46:06 -0800323 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800324 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800325 mNotifyCompleteAudio |= notifyComplete;
Wei Jia3b0cd262015-07-13 11:28:10 -0700326 clearAudioFirstAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800327 ++mAudioQueueGeneration;
328 ++mAudioDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800329 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -0800330 mNotifyCompleteVideo |= notifyComplete;
Wei Jia7b15cb32015-02-03 17:46:06 -0800331 ++mVideoQueueGeneration;
332 ++mVideoDrainGeneration;
Wei Jiacc951512019-04-03 16:10:42 -0700333 mNextVideoTimeMediaUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -0800334 }
Wei Jia7b15cb32015-02-03 17:46:06 -0800335
Wei Jia7b15cb32015-02-03 17:46:06 -0800336 mVideoLateByUs = 0;
337 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800338 }
339
Wonsik Kimee8116b2019-07-19 15:55:44 -0700340 // Wait until the current job in the message queue is done, to make sure
341 // buffer processing from the old generation is finished. After the current
342 // job is finished, access to buffers are protected by generation.
343 Mutex::Autolock syncLock(mSyncLock);
344 int64_t syncCount = mSyncCount;
345 mSyncFlag.clear();
346
347 // Make sure message queue is not empty after mSyncFlag is cleared.
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800348 sp<AMessage> msg = new AMessage(kWhatFlush, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800349 msg->setInt32("audio", static_cast<int32_t>(audio));
350 msg->post();
Wonsik Kimee8116b2019-07-19 15:55:44 -0700351
352 int64_t uptimeMs = uptimeMillis();
353 while (mSyncCount == syncCount) {
354 (void)mSyncCondition.waitRelative(mSyncLock, ms2ns(1000));
355 if (uptimeMillis() - uptimeMs > 1000) {
356 ALOGW("flush(): no wake-up from sync point for 1s; stop waiting to "
357 "prevent being stuck indefinitely.");
358 break;
359 }
360 }
Andreas Huberf9334412010-12-15 15:17:42 -0800361}
362
363void NuPlayer::Renderer::signalTimeDiscontinuity() {
Wei Jia28a8a9f2014-08-18 11:29:50 -0700364}
365
366void NuPlayer::Renderer::signalDisableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800367 (new AMessage(kWhatDisableOffloadAudio, this))->post();
Wei Jia28a8a9f2014-08-18 11:29:50 -0700368}
369
Ronghua Wua10fd232014-11-06 16:15:20 -0800370void NuPlayer::Renderer::signalEnableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800371 (new AMessage(kWhatEnableOffloadAudio, this))->post();
Ronghua Wua10fd232014-11-06 16:15:20 -0800372}
373
Andreas Huberb4082222011-01-20 15:23:04 -0800374void NuPlayer::Renderer::pause() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800375 (new AMessage(kWhatPause, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800376}
377
378void NuPlayer::Renderer::resume() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800379 (new AMessage(kWhatResume, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800380}
381
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700382void NuPlayer::Renderer::setVideoFrameRate(float fps) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800383 sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700384 msg->setFloat("frame-rate", fps);
385 msg->post();
386}
387
Wei Jia4ecbea32015-10-20 18:09:57 -0700388// Called on any threads without mLock acquired.
Wei Jia7b15cb32015-02-03 17:46:06 -0800389status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
Wei Jia4ecbea32015-10-20 18:09:57 -0700390 status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
391 if (result == OK) {
392 return result;
393 }
394
395 // MediaClock has not started yet. Try to start it if possible.
396 {
397 Mutex::Autolock autoLock(mLock);
398 if (mAudioFirstAnchorTimeMediaUs == -1) {
399 return result;
400 }
401
402 AudioTimestamp ts;
403 status_t res = mAudioSink->getTimestamp(ts);
404 if (res != OK) {
405 return result;
406 }
407
408 // AudioSink has rendered some frames.
409 int64_t nowUs = ALooper::GetNowUs();
zengjingdb131352018-03-19 17:23:49 +0800410 int64_t playedOutDurationUs = mAudioSink->getPlayedOutDurationUs(nowUs);
411 if (playedOutDurationUs == 0) {
412 *mediaUs = mAudioFirstAnchorTimeMediaUs;
413 return OK;
414 }
415 int64_t nowMediaUs = playedOutDurationUs + mAudioFirstAnchorTimeMediaUs;
Wei Jia4ecbea32015-10-20 18:09:57 -0700416 mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
417 }
418
Wei Jia98160162015-02-04 17:01:11 -0800419 return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700420}
421
Wei Jia7b15cb32015-02-03 17:46:06 -0800422void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
423 mAudioFirstAnchorTimeMediaUs = -1;
424 mMediaClock->setStartingTimeMedia(-1);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700425}
426
Wei Jia7b15cb32015-02-03 17:46:06 -0800427void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700428 if (mAudioFirstAnchorTimeMediaUs == -1) {
429 mAudioFirstAnchorTimeMediaUs = mediaUs;
Wei Jia7b15cb32015-02-03 17:46:06 -0800430 mMediaClock->setStartingTimeMedia(mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700431 }
432}
433
Wei Jia9a3101b2016-11-08 14:34:24 -0800434// Called on renderer looper.
435void NuPlayer::Renderer::clearAnchorTime() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800436 mMediaClock->clearAnchor();
Ian Baker130bbc42023-08-09 18:19:50 +0100437 mAudioAnchorTimeMediaUs = -1;
Wei Jia7b15cb32015-02-03 17:46:06 -0800438 mAnchorTimeMediaUs = -1;
439 mAnchorNumFramesWritten = -1;
Ronghua Wua73d9e02014-10-08 15:13:29 -0700440}
441
442void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800443 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700444 mVideoLateByUs = lateUs;
445}
446
447int64_t NuPlayer::Renderer::getVideoLateByUs() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800448 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700449 return mVideoLateByUs;
450}
451
Andy Hung202bce12014-12-03 11:47:36 -0800452status_t NuPlayer::Renderer::openAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700453 const sp<AMessage> &format,
454 bool offloadOnly,
455 bool hasVideo,
Andy Hung202bce12014-12-03 11:47:36 -0800456 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530457 bool *isOffloaded,
458 bool isStreaming) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800459 sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700460 msg->setMessage("format", format);
461 msg->setInt32("offload-only", offloadOnly);
462 msg->setInt32("has-video", hasVideo);
463 msg->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530464 msg->setInt32("isStreaming", isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700465
466 sp<AMessage> response;
Leena Winterrowd66e4c4772015-09-10 15:41:08 -0700467 status_t postStatus = msg->postAndAwaitResponse(&response);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700468
Andy Hung202bce12014-12-03 11:47:36 -0800469 int32_t err;
Leena Winterrowd66e4c4772015-09-10 15:41:08 -0700470 if (postStatus != OK || response.get() == nullptr || !response->findInt32("err", &err)) {
Andy Hung202bce12014-12-03 11:47:36 -0800471 err = INVALID_OPERATION;
472 } else if (err == OK && isOffloaded != NULL) {
473 int32_t offload;
474 CHECK(response->findInt32("offload", &offload));
475 *isOffloaded = (offload != 0);
476 }
477 return err;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700478}
479
480void NuPlayer::Renderer::closeAudioSink() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800481 sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700482
483 sp<AMessage> response;
484 msg->postAndAwaitResponse(&response);
485}
486
Wei Jia9a3101b2016-11-08 14:34:24 -0800487void NuPlayer::Renderer::changeAudioFormat(
488 const sp<AMessage> &format,
489 bool offloadOnly,
490 bool hasVideo,
491 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530492 bool isStreaming,
Wei Jia9a3101b2016-11-08 14:34:24 -0800493 const sp<AMessage> &notify) {
494 sp<AMessage> meta = new AMessage;
495 meta->setMessage("format", format);
496 meta->setInt32("offload-only", offloadOnly);
497 meta->setInt32("has-video", hasVideo);
498 meta->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530499 meta->setInt32("isStreaming", isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -0800500
501 sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
502 msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
503 msg->setMessage("notify", notify);
504 msg->setMessage("meta", meta);
505 msg->post();
506}
507
Andreas Huberf9334412010-12-15 15:17:42 -0800508void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
509 switch (msg->what()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700510 case kWhatOpenAudioSink:
511 {
512 sp<AMessage> format;
513 CHECK(msg->findMessage("format", &format));
514
515 int32_t offloadOnly;
516 CHECK(msg->findInt32("offload-only", &offloadOnly));
517
518 int32_t hasVideo;
519 CHECK(msg->findInt32("has-video", &hasVideo));
520
521 uint32_t flags;
522 CHECK(msg->findInt32("flags", (int32_t *)&flags));
523
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530524 uint32_t isStreaming;
525 CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
526
527 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700528
529 sp<AMessage> response = new AMessage;
Andy Hung202bce12014-12-03 11:47:36 -0800530 response->setInt32("err", err);
531 response->setInt32("offload", offloadingAudio());
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700532
Lajos Molnar3f274362015-03-05 14:35:41 -0800533 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700534 CHECK(msg->senderAwaitsResponse(&replyID));
535 response->postReply(replyID);
536
537 break;
538 }
539
540 case kWhatCloseAudioSink:
541 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800542 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700543 CHECK(msg->senderAwaitsResponse(&replyID));
544
545 onCloseAudioSink();
546
547 sp<AMessage> response = new AMessage;
548 response->postReply(replyID);
549 break;
550 }
551
Wei Jiabc2fb722014-07-08 16:37:57 -0700552 case kWhatStopAudioSink:
553 {
554 mAudioSink->stop();
555 break;
556 }
557
Wei Jia9a3101b2016-11-08 14:34:24 -0800558 case kWhatChangeAudioFormat:
559 {
560 int32_t queueGeneration;
561 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
562
563 sp<AMessage> notify;
564 CHECK(msg->findMessage("notify", &notify));
565
566 if (offloadingAudio()) {
567 ALOGW("changeAudioFormat should NOT be called in offload mode");
568 notify->setInt32("err", INVALID_OPERATION);
569 notify->post();
570 break;
571 }
572
573 sp<AMessage> meta;
574 CHECK(msg->findMessage("meta", &meta));
575
576 if (queueGeneration != getQueueGeneration(true /* audio */)
577 || mAudioQueue.empty()) {
578 onChangeAudioFormat(meta, notify);
579 break;
580 }
581
582 QueueEntry entry;
583 entry.mNotifyConsumed = notify;
584 entry.mMeta = meta;
585
586 Mutex::Autolock autoLock(mLock);
587 mAudioQueue.push_back(entry);
588 postDrainAudioQueue_l();
589
590 break;
591 }
592
Andreas Huberf9334412010-12-15 15:17:42 -0800593 case kWhatDrainAudioQueue:
594 {
Wei Jia3ab25452015-06-10 09:37:47 -0700595 mDrainAudioQueuePending = false;
596
Andreas Huberf9334412010-12-15 15:17:42 -0800597 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800598 CHECK(msg->findInt32("drainGeneration", &generation));
599 if (generation != getDrainGeneration(true /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800600 break;
601 }
602
Andreas Huber078cfcf2011-09-15 12:25:04 -0700603 if (onDrainAudioQueue()) {
604 uint32_t numFramesPlayed;
605 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
606 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800607
Wei Jia1fb35b72017-09-25 16:08:13 -0700608 // Handle AudioTrack race when start is immediately called after flush.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700609 uint32_t numFramesPendingPlayout =
Wei Jia1fb35b72017-09-25 16:08:13 -0700610 (mNumFramesWritten > numFramesPlayed ?
611 mNumFramesWritten - numFramesPlayed : 0);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700612
613 // This is how long the audio sink will have data to
614 // play back.
615 int64_t delayUs =
616 mAudioSink->msecsPerFrame()
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800617 * numFramesPendingPlayout * 1000LL;
Wei Jiad9c2e9c2015-04-10 19:04:09 -0700618 if (mPlaybackRate > 1.0f) {
619 delayUs /= mPlaybackRate;
620 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700621
622 // Let's give it more data after about half that time
623 // has elapsed.
Andy Hungf2c87b32016-04-07 19:49:29 -0700624 delayUs /= 2;
625 // check the buffer size to estimate maximum delay permitted.
626 const int64_t maxDrainDelayUs = std::max(
627 mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
628 ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
629 (long long)delayUs, (long long)maxDrainDelayUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800630 Mutex::Autolock autoLock(mLock);
Andy Hungf2c87b32016-04-07 19:49:29 -0700631 postDrainAudioQueue_l(delayUs);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700632 }
Andreas Huberf9334412010-12-15 15:17:42 -0800633 break;
634 }
635
636 case kWhatDrainVideoQueue:
637 {
638 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800639 CHECK(msg->findInt32("drainGeneration", &generation));
640 if (generation != getDrainGeneration(false /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800641 break;
642 }
643
644 mDrainVideoQueuePending = false;
645
646 onDrainVideoQueue();
647
Wei Jia7b15cb32015-02-03 17:46:06 -0800648 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -0800649 break;
650 }
651
Lajos Molnard5923402014-10-20 17:47:54 -0700652 case kWhatPostDrainVideoQueue:
653 {
654 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800655 CHECK(msg->findInt32("drainGeneration", &generation));
656 if (generation != getDrainGeneration(false /* audio */)) {
Lajos Molnard5923402014-10-20 17:47:54 -0700657 break;
658 }
659
660 mDrainVideoQueuePending = false;
Wei Jia7b15cb32015-02-03 17:46:06 -0800661 postDrainVideoQueue();
Lajos Molnard5923402014-10-20 17:47:54 -0700662 break;
663 }
664
Andreas Huberf9334412010-12-15 15:17:42 -0800665 case kWhatQueueBuffer:
666 {
667 onQueueBuffer(msg);
668 break;
669 }
670
671 case kWhatQueueEOS:
672 {
673 onQueueEOS(msg);
674 break;
675 }
676
Wei Jia7c8d0e02015-08-27 17:40:21 -0700677 case kWhatEOS:
678 {
679 int32_t generation;
680 CHECK(msg->findInt32("audioEOSGeneration", &generation));
681 if (generation != mAudioEOSGeneration) {
682 break;
683 }
684 status_t finalResult;
685 CHECK(msg->findInt32("finalResult", &finalResult));
686 notifyEOS(true /* audio */, finalResult);
687 break;
688 }
689
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700690 case kWhatConfigPlayback:
Wei Jia98160162015-02-04 17:01:11 -0800691 {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700692 sp<AReplyToken> replyID;
693 CHECK(msg->senderAwaitsResponse(&replyID));
694 AudioPlaybackRate rate;
695 readFromAMessage(msg, &rate);
696 status_t err = onConfigPlayback(rate);
697 sp<AMessage> response = new AMessage;
698 response->setInt32("err", err);
699 response->postReply(replyID);
700 break;
701 }
702
703 case kWhatGetPlaybackSettings:
704 {
705 sp<AReplyToken> replyID;
706 CHECK(msg->senderAwaitsResponse(&replyID));
707 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
708 status_t err = onGetPlaybackSettings(&rate);
709 sp<AMessage> response = new AMessage;
710 if (err == OK) {
711 writeToAMessage(response, rate);
712 }
713 response->setInt32("err", err);
714 response->postReply(replyID);
715 break;
716 }
717
718 case kWhatConfigSync:
719 {
720 sp<AReplyToken> replyID;
721 CHECK(msg->senderAwaitsResponse(&replyID));
722 AVSyncSettings sync;
723 float videoFpsHint;
724 readFromAMessage(msg, &sync, &videoFpsHint);
725 status_t err = onConfigSync(sync, videoFpsHint);
726 sp<AMessage> response = new AMessage;
727 response->setInt32("err", err);
728 response->postReply(replyID);
729 break;
730 }
731
732 case kWhatGetSyncSettings:
733 {
734 sp<AReplyToken> replyID;
735 CHECK(msg->senderAwaitsResponse(&replyID));
736
737 ALOGV("kWhatGetSyncSettings");
738 AVSyncSettings sync;
739 float videoFps = -1.f;
740 status_t err = onGetSyncSettings(&sync, &videoFps);
741 sp<AMessage> response = new AMessage;
742 if (err == OK) {
743 writeToAMessage(response, sync, videoFps);
744 }
745 response->setInt32("err", err);
746 response->postReply(replyID);
Wei Jia98160162015-02-04 17:01:11 -0800747 break;
748 }
749
Andreas Huberf9334412010-12-15 15:17:42 -0800750 case kWhatFlush:
751 {
752 onFlush(msg);
753 break;
754 }
755
Wei Jiabc2fb722014-07-08 16:37:57 -0700756 case kWhatDisableOffloadAudio:
757 {
758 onDisableOffloadAudio();
759 break;
760 }
761
Ronghua Wua10fd232014-11-06 16:15:20 -0800762 case kWhatEnableOffloadAudio:
763 {
764 onEnableOffloadAudio();
765 break;
766 }
767
Andreas Huberb4082222011-01-20 15:23:04 -0800768 case kWhatPause:
769 {
770 onPause();
771 break;
772 }
773
774 case kWhatResume:
775 {
776 onResume();
777 break;
778 }
779
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700780 case kWhatSetVideoFrameRate:
781 {
782 float fps;
783 CHECK(msg->findFloat("frame-rate", &fps));
784 onSetVideoFrameRate(fps);
785 break;
786 }
787
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700788 case kWhatAudioTearDown:
Wei Jia3a2956d2014-07-22 16:01:33 -0700789 {
Wei Jiaa05f1e32016-03-25 16:31:22 -0700790 int32_t reason;
791 CHECK(msg->findInt32("reason", &reason));
792
793 onAudioTearDown((AudioTearDownReason)reason);
Wei Jia3a2956d2014-07-22 16:01:33 -0700794 break;
795 }
796
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700797 case kWhatAudioOffloadPauseTimeout:
798 {
799 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800800 CHECK(msg->findInt32("drainGeneration", &generation));
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700801 if (generation != mAudioOffloadPauseTimeoutGeneration) {
802 break;
803 }
Ronghua Wu08529172014-10-02 16:55:52 -0700804 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700805 onAudioTearDown(kDueToTimeout);
Eric Laurent8ca036a2022-07-01 16:42:48 +0200806 sp<AMessage> newMsg = new AMessage(kWhatReleaseWakeLock, this);
807 newMsg->setInt32("drainGeneration", generation);
808 newMsg->post(kWakelockReleaseDelayUs);
809 break;
810 }
811
812 case kWhatReleaseWakeLock:
813 {
814 int32_t generation;
815 CHECK(msg->findInt32("drainGeneration", &generation));
816 if (generation != mAudioOffloadPauseTimeoutGeneration) {
817 break;
818 }
819 ALOGV("releasing audio offload pause wakelock.");
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800820 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700821 break;
822 }
823
Andreas Huberf9334412010-12-15 15:17:42 -0800824 default:
825 TRESPASS();
826 break;
827 }
Wonsik Kimee8116b2019-07-19 15:55:44 -0700828 if (!mSyncFlag.test_and_set()) {
829 Mutex::Autolock syncLock(mSyncLock);
830 ++mSyncCount;
831 mSyncCondition.broadcast();
832 }
Andreas Huberf9334412010-12-15 15:17:42 -0800833}
834
Wei Jiabc2fb722014-07-08 16:37:57 -0700835void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700836 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800837 return;
838 }
839
840 if (mAudioQueue.empty()) {
841 return;
842 }
843
Andy Hungb03dcb32015-08-27 16:18:59 -0700844 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
845 if (mPaused) {
846 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
847 if (diffUs > delayUs) {
848 delayUs = diffUs;
849 }
850 }
851
Andreas Huberf9334412010-12-15 15:17:42 -0800852 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800853 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800854 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700855 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800856}
857
Wei Jia7b15cb32015-02-03 17:46:06 -0800858void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
859 mAudioRenderingStartGeneration = mAudioDrainGeneration;
860 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700861 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700862}
863
Wei Jia7b15cb32015-02-03 17:46:06 -0800864void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
865 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
866 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700867 mRenderingDataDelivered = true;
868 if (mPaused) {
869 return;
870 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700871 mVideoRenderingStartGeneration = -1;
872 mAudioRenderingStartGeneration = -1;
873
874 sp<AMessage> notify = mNotify->dup();
875 notify->setInt32("what", kWhatMediaRenderingStart);
876 notify->post();
877 }
878}
879
Wei Jiabc2fb722014-07-08 16:37:57 -0700880// static
881size_t NuPlayer::Renderer::AudioSinkCallback(
882 MediaPlayerBase::AudioSink * /* audioSink */,
883 void *buffer,
884 size_t size,
885 void *cookie,
886 MediaPlayerBase::AudioSink::cb_event_t event) {
887 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
888
889 switch (event) {
890 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
891 {
892 return me->fillAudioBuffer(buffer, size);
893 break;
894 }
895
896 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
897 {
Andy Hunga0b39712015-05-31 22:40:49 -0700898 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jia4c74fde2016-08-26 16:00:52 -0700899 me->notifyEOSCallback();
Wei Jiabc2fb722014-07-08 16:37:57 -0700900 break;
901 }
902
903 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
904 {
Andy Hunga0b39712015-05-31 22:40:49 -0700905 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Wei Jiaa05f1e32016-03-25 16:31:22 -0700906 me->notifyAudioTearDown(kDueToError);
Wei Jiabc2fb722014-07-08 16:37:57 -0700907 break;
908 }
909 }
910
911 return 0;
912}
913
Wei Jia4c74fde2016-08-26 16:00:52 -0700914void NuPlayer::Renderer::notifyEOSCallback() {
915 Mutex::Autolock autoLock(mLock);
916
917 if (!mUseAudioCallback) {
918 return;
919 }
920
Wei Jiad214a562017-07-10 13:20:55 -0700921 notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
Wei Jia4c74fde2016-08-26 16:00:52 -0700922}
923
Wei Jiabc2fb722014-07-08 16:37:57 -0700924size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
925 Mutex::Autolock autoLock(mLock);
926
Andy Hung85e48142015-05-31 23:04:15 -0700927 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700928 return 0;
929 }
930
931 bool hasEOS = false;
932
933 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700934 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700935 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700936 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700937 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700938
939 if (entry->mBuffer == NULL) { // EOS
940 hasEOS = true;
941 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700942 break;
943 }
944
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700945 if (firstEntry && entry->mOffset == 0) {
946 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700947 int64_t mediaTimeUs;
948 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Paras Nagda86dc6182020-10-27 13:01:47 +0530949 if (mediaTimeUs < 0) {
950 ALOGD("fillAudioBuffer: reset negative media time %.2f secs to zero",
951 mediaTimeUs / 1E6);
952 mediaTimeUs = 0;
953 }
Andy Hunga0b39712015-05-31 22:40:49 -0700954 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800955 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700956 }
957
958 size_t copy = entry->mBuffer->size() - entry->mOffset;
959 size_t sizeRemaining = size - sizeCopied;
960 if (copy > sizeRemaining) {
961 copy = sizeRemaining;
962 }
963
964 memcpy((char *)buffer + sizeCopied,
965 entry->mBuffer->data() + entry->mOffset,
966 copy);
967
968 entry->mOffset += copy;
969 if (entry->mOffset == entry->mBuffer->size()) {
970 entry->mNotifyConsumed->post();
971 mAudioQueue.erase(mAudioQueue.begin());
972 entry = NULL;
973 }
974 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -0800975
976 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -0700977 }
978
Lajos Molnarf5926712014-10-21 09:36:43 -0700979 if (mAudioFirstAnchorTimeMediaUs >= 0) {
980 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -0800981 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -0700982 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800983 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -0800984 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -0700985 }
986
Andy Hunga0b39712015-05-31 22:40:49 -0700987 // for non-offloaded audio, we need to compute the frames written because
988 // there is no EVENT_STREAM_END notification. The frames written gives
989 // an estimate on the pending played out duration.
990 if (!offloadingAudio()) {
991 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -0700992 }
993
Andy Hunga0b39712015-05-31 22:40:49 -0700994 if (hasEOS) {
995 (new AMessage(kWhatStopAudioSink, this))->post();
996 // As there is currently no EVENT_STREAM_END callback notification for
997 // non-offloaded audio tracks, we need to post the EOS ourselves.
998 if (!offloadingAudio()) {
999 int64_t postEOSDelayUs = 0;
1000 if (mAudioSink->needsTrailingPadding()) {
1001 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
1002 }
Wei Jiad214a562017-07-10 13:20:55 -07001003 ALOGV("fillAudioBuffer: notifyEOS_l "
Andy Hunga0b39712015-05-31 22:40:49 -07001004 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
1005 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001006 notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Andy Hunga0b39712015-05-31 22:40:49 -07001007 }
1008 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001009 return sizeCopied;
1010}
1011
Chong Zhang9da0ce42015-06-11 17:18:58 -07001012void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
1013 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
1014 bool foundEOS = false;
1015 while (it != mAudioQueue.end()) {
1016 int32_t eos;
1017 QueueEntry *entry = &*it++;
Wei Jia9a3101b2016-11-08 14:34:24 -08001018 if ((entry->mBuffer == nullptr && entry->mNotifyConsumed == nullptr)
Chong Zhang9da0ce42015-06-11 17:18:58 -07001019 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
1020 itEOS = it;
1021 foundEOS = true;
1022 }
1023 }
1024
1025 if (foundEOS) {
1026 // post all replies before EOS and drop the samples
1027 for (it = mAudioQueue.begin(); it != itEOS; it++) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001028 if (it->mBuffer == nullptr) {
1029 if (it->mNotifyConsumed == nullptr) {
1030 // delay doesn't matter as we don't even have an AudioTrack
1031 notifyEOS(true /* audio */, it->mFinalResult);
1032 } else {
1033 // TAG for re-opening audio sink.
1034 onChangeAudioFormat(it->mMeta, it->mNotifyConsumed);
1035 }
Chong Zhang9da0ce42015-06-11 17:18:58 -07001036 } else {
1037 it->mNotifyConsumed->post();
1038 }
1039 }
1040 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
1041 }
1042}
1043
Andreas Huber078cfcf2011-09-15 12:25:04 -07001044bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -07001045 // do not drain audio during teardown as queued buffers may be invalid.
1046 if (mAudioTornDown) {
1047 return false;
1048 }
Wei Jia230b1882015-03-19 15:13:51 -07001049 // TODO: This call to getPosition checks if AudioTrack has been created
1050 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
1051 // CHECKs on getPosition will fail.
1052 // We still need to figure out why AudioTrack is not created when
1053 // this function is called. One possible reason could be leftover
1054 // audio. Another possible place is to check whether decoder
1055 // has received INFO_FORMAT_CHANGED as the first buffer since
1056 // AudioSink is opened there, and possible interactions with flush
1057 // immediately after start. Investigate error message
1058 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -07001059 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -07001060 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -07001061 // When getPosition fails, renderer will not reschedule the draining
1062 // unless new samples are queued.
1063 // If we have pending EOS (or "eos" marker for discontinuities), we need
1064 // to post these now as NuPlayerDecoder might be waiting for it.
1065 drainAudioQueueUntilLastEOS();
1066
1067 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -07001068 return false;
1069 }
Andreas Huberc92fd242011-08-16 13:48:44 -07001070
Wei Jia230b1882015-03-19 15:13:51 -07001071#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -07001072 ssize_t numFramesAvailableToWrite =
1073 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
1074
Andreas Huber078cfcf2011-09-15 12:25:04 -07001075 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +00001076 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -07001077 } else {
Steve Block3856b092011-10-20 11:56:00 +01001078 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -07001079 mAudioSink->frameCount() - numFramesAvailableToWrite);
1080 }
1081#endif
1082
Andy Hung005e9d02015-05-31 23:16:07 -07001083 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -08001084 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -07001085 QueueEntry *entry = &*mAudioQueue.begin();
1086
1087 if (entry->mBuffer == NULL) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001088 if (entry->mNotifyConsumed != nullptr) {
1089 // TAG for re-open audio sink.
1090 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
1091 mAudioQueue.erase(mAudioQueue.begin());
1092 continue;
1093 }
1094
Andreas Huberc92fd242011-08-16 13:48:44 -07001095 // EOS
Haynes Mathew George62d4e072016-06-13 11:23:22 -07001096 if (mPaused) {
1097 // Do not notify EOS when paused.
1098 // This is needed to avoid switch to next clip while in pause.
1099 ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
1100 return false;
1101 }
1102
Ronghua Wu5095d702014-08-27 12:05:48 -07001103 int64_t postEOSDelayUs = 0;
1104 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -07001105 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -07001106 }
1107 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001108 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -07001109
1110 mAudioQueue.erase(mAudioQueue.begin());
1111 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -08001112 if (mAudioSink->needsTrailingPadding()) {
1113 // If we're not in gapless playback (i.e. through setNextPlayer), we
1114 // need to stop the track here, because that will play out the last
1115 // little bit at the end of the file. Otherwise short files won't play.
1116 mAudioSink->stop();
1117 mNumFramesWritten = 0;
1118 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001119 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -07001120 }
1121
Wei Jia9a3101b2016-11-08 14:34:24 -08001122 mLastAudioBufferDrained = entry->mBufferOrdinal;
1123
Chong Zhang81636762015-04-21 09:33:47 -07001124 // ignore 0-sized buffer which could be EOS marker with no data
1125 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -08001126 int64_t mediaTimeUs;
1127 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -07001128 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
1129 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -07001130 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001131 }
1132
1133 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -08001134
Wei Jia7d3f4df2015-03-03 15:28:00 -08001135 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
1136 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -07001137 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -08001138 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001139 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -07001140 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001141 } else {
1142 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -07001143 // This can only happen when AudioSink was opened with doNotReconnect flag set to
1144 // true, in which case the NuPlayer will handle the reconnect.
Wei Jiaa05f1e32016-03-25 16:31:22 -07001145 notifyAudioTearDown(kDueToError);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001146 }
Andy Hung202bce12014-12-03 11:47:36 -08001147 break;
Andy Hunga31335a2014-08-20 17:37:59 -07001148 }
Andreas Huberf9334412010-12-15 15:17:42 -08001149
Andy Hunga31335a2014-08-20 17:37:59 -07001150 entry->mOffset += written;
Wei Jia03cee242016-05-26 15:22:59 -07001151 size_t remainder = entry->mBuffer->size() - entry->mOffset;
1152 if ((ssize_t)remainder < mAudioSink->frameSize()) {
1153 if (remainder > 0) {
1154 ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
1155 remainder);
1156 entry->mOffset += remainder;
1157 copy -= remainder;
1158 }
1159
Andreas Huberf9334412010-12-15 15:17:42 -08001160 entry->mNotifyConsumed->post();
1161 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -07001162
Andreas Huberf9334412010-12-15 15:17:42 -08001163 entry = NULL;
1164 }
1165
Andy Hunga31335a2014-08-20 17:37:59 -07001166 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -07001167 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001168
Wei Jia7b15cb32015-02-03 17:46:06 -08001169 {
1170 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -07001171 int64_t maxTimeMedia;
1172 maxTimeMedia =
1173 mAnchorTimeMediaUs +
1174 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
1175 * 1000LL * mAudioSink->msecsPerFrame());
1176 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
1177
Wei Jia7b15cb32015-02-03 17:46:06 -08001178 notifyIfMediaRenderingStarted_l();
1179 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001180
Andy Hunga31335a2014-08-20 17:37:59 -07001181 if (written != (ssize_t)copy) {
1182 // A short count was received from AudioSink::write()
1183 //
Wei Jia7d3f4df2015-03-03 15:28:00 -08001184 // AudioSink write is called in non-blocking mode.
1185 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -07001186 //
Wei Jia03cee242016-05-26 15:22:59 -07001187 // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
1188 // discarded.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001189 // 2) The data to be copied exceeds the available buffer in AudioSink.
1190 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
1191 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -07001192
1193 // (Case 1)
1194 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
1195 // needs to fail, as we should not carry over fractional frames between calls.
Colin Cross0bdcf662017-04-27 16:15:51 -07001196 CHECK_EQ(copy % mAudioSink->frameSize(), 0u);
Andy Hunga31335a2014-08-20 17:37:59 -07001197
Wei Jia7d3f4df2015-03-03 15:28:00 -08001198 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -07001199 // Return early to the caller.
1200 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001201 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -07001202 break;
1203 }
1204 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001205
Andy Hung005e9d02015-05-31 23:16:07 -07001206 // calculate whether we need to reschedule another write.
1207 bool reschedule = !mAudioQueue.empty()
1208 && (!mPaused
1209 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1210 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1211 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1212 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001213}
1214
Wei Jia98160162015-02-04 17:01:11 -08001215int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1216 int32_t sampleRate = offloadingAudio() ?
1217 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001218 if (sampleRate == 0) {
1219 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1220 return 0;
1221 }
hyoungjun.byun2c2050c2019-01-31 12:11:38 +09001222
1223 return (int64_t)(numFrames * 1000000LL / sampleRate);
Wei Jia98160162015-02-04 17:01:11 -08001224}
1225
1226// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001227int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001228 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiad2f35de2016-02-17 16:48:06 -08001229 if (mUseVirtualAudioSink) {
1230 int64_t nowUs = ALooper::GetNowUs();
1231 int64_t mediaUs;
1232 if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001233 return 0LL;
Wei Jiad2f35de2016-02-17 16:48:06 -08001234 } else {
1235 return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1236 }
1237 }
Andy Hungffa36952017-08-17 10:41:51 -07001238
1239 const int64_t audioSinkPlayedUs = mAudioSink->getPlayedOutDurationUs(nowUs);
1240 int64_t pendingUs = writtenAudioDurationUs - audioSinkPlayedUs;
1241 if (pendingUs < 0) {
1242 // This shouldn't happen unless the timestamp is stale.
1243 ALOGW("%s: pendingUs %lld < 0, clamping to zero, potential resume after pause "
1244 "writtenAudioDurationUs: %lld, audioSinkPlayedUs: %lld",
1245 __func__, (long long)pendingUs,
1246 (long long)writtenAudioDurationUs, (long long)audioSinkPlayedUs);
1247 pendingUs = 0;
1248 }
1249 return pendingUs;
Ronghua Wu5095d702014-08-27 12:05:48 -07001250}
1251
Ronghua Wua73d9e02014-10-08 15:13:29 -07001252int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001253 int64_t realUs;
1254 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001255 // If failed to get current position, e.g. due to audio clock is
1256 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001257 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001258 }
Wei Jia98160162015-02-04 17:01:11 -08001259 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001260}
1261
Ronghua Wueecb7802014-10-19 23:12:50 -07001262void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001263 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001264 // TRICKY: vorbis decoder generates multiple frames with the same
1265 // timestamp, so only update on the first frame with a given timestamp
Ian Baker130bbc42023-08-09 18:19:50 +01001266 if (mediaTimeUs == mAudioAnchorTimeMediaUs) {
Ronghua Wueecb7802014-10-19 23:12:50 -07001267 return;
1268 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001269 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001270
Andy Hung528c8402016-01-12 12:39:34 -08001271 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1272 if (mNextAudioClockUpdateTimeUs == -1) {
1273 AudioTimestamp ts;
1274 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1275 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1276 }
1277 }
Wei Jia12b62652016-02-09 17:49:31 -08001278 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001279 if (mNextAudioClockUpdateTimeUs >= 0) {
1280 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1281 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1282 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001283 mUseVirtualAudioSink = false;
Andy Hung528c8402016-01-12 12:39:34 -08001284 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1285 }
Wei Jia12b62652016-02-09 17:49:31 -08001286 } else {
1287 int64_t unused;
1288 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1289 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1290 > kMaxAllowedAudioSinkDelayUs)) {
1291 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1292 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1293 // connected to audio out.
1294 // Switch to system clock. This essentially creates a virtual AudioSink with
1295 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1296 // This virtual AudioSink renders audio data starting from the very first sample
1297 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001298 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001299 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001300 mUseVirtualAudioSink = true;
Wei Jia12b62652016-02-09 17:49:31 -08001301 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001302 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001303 mAnchorNumFramesWritten = mNumFramesWritten;
Ian Baker130bbc42023-08-09 18:19:50 +01001304 mAudioAnchorTimeMediaUs = mediaTimeUs;
Wei Jia7b15cb32015-02-03 17:46:06 -08001305 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001306}
1307
Wei Jia7b15cb32015-02-03 17:46:06 -08001308// Called without mLock acquired.
1309void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001310 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001311 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001312 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001313 return;
1314 }
1315
1316 if (mVideoQueue.empty()) {
1317 return;
1318 }
1319
1320 QueueEntry &entry = *mVideoQueue.begin();
1321
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001322 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001323 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001324
Andreas Huberf9334412010-12-15 15:17:42 -08001325 if (entry.mBuffer == NULL) {
1326 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001327 msg->post();
1328 mDrainVideoQueuePending = true;
1329 return;
1330 }
1331
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001332 int64_t nowUs = ALooper::GetNowUs();
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001333 if (mFlags & FLAG_REAL_TIME) {
Wei Jia17648f32017-09-19 13:16:30 -07001334 int64_t realTimeUs;
1335 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &realTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001336
Wei Jia17648f32017-09-19 13:16:30 -07001337 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Lajos Molnard5923402014-10-20 17:47:54 -07001338
Wei Jia17648f32017-09-19 13:16:30 -07001339 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
Robert Shih00541e22015-12-18 17:04:00 -08001340
Wei Jia17648f32017-09-19 13:16:30 -07001341 int64_t delayUs = realTimeUs - nowUs;
1342
1343 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %lld", (long long)delayUs);
1344 // post 2 display refreshes before rendering is due
1345 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1346
1347 mDrainVideoQueuePending = true;
1348 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001349 }
1350
Wei Jia17648f32017-09-19 13:16:30 -07001351 int64_t mediaTimeUs;
1352 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001353
Wei Jia17648f32017-09-19 13:16:30 -07001354 {
1355 Mutex::Autolock autoLock(mLock);
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301356 if (mNeedVideoClearAnchor && !mHasAudio) {
1357 mNeedVideoClearAnchor = false;
1358 clearAnchorTime();
1359 }
Wei Jia17648f32017-09-19 13:16:30 -07001360 if (mAnchorTimeMediaUs < 0) {
1361 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1362 mAnchorTimeMediaUs = mediaTimeUs;
1363 }
1364 }
Wei Jia1225b932019-01-04 12:44:38 -08001365 mNextVideoTimeMediaUs = mediaTimeUs;
Wei Jia17648f32017-09-19 13:16:30 -07001366 if (!mHasAudio) {
1367 // smooth out videos >= 10fps
Wei Jiacc951512019-04-03 16:10:42 -07001368 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia17648f32017-09-19 13:16:30 -07001369 }
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001370
Wei Jia17648f32017-09-19 13:16:30 -07001371 if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
1372 msg->post();
1373 } else {
1374 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1375
1376 // post 2 display refreshes before rendering is due
1377 mMediaClock->addTimer(msg, mediaTimeUs, -twoVsyncsUs);
1378 }
Andreas Huberf9334412010-12-15 15:17:42 -08001379
1380 mDrainVideoQueuePending = true;
1381}
1382
1383void NuPlayer::Renderer::onDrainVideoQueue() {
1384 if (mVideoQueue.empty()) {
1385 return;
1386 }
1387
1388 QueueEntry *entry = &*mVideoQueue.begin();
1389
1390 if (entry->mBuffer == NULL) {
1391 // EOS
1392
Andreas Huberc92fd242011-08-16 13:48:44 -07001393 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001394
1395 mVideoQueue.erase(mVideoQueue.begin());
1396 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001397
Ronghua Wua73d9e02014-10-08 15:13:29 -07001398 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001399 return;
1400 }
1401
Wei Jia25d696f2015-11-19 10:57:15 -08001402 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001403 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001404 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001405 if (mFlags & FLAG_REAL_TIME) {
1406 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1407 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001408 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001409
Ronghua Wua73d9e02014-10-08 15:13:29 -07001410 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001411 }
Wei Jia17648f32017-09-19 13:16:30 -07001412 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Andreas Huberd5e56232013-03-12 11:01:43 -07001413
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001414 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001415
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001416 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001417 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001418 tooLate = (mVideoLateByUs > 40000);
1419
1420 if (tooLate) {
1421 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001422 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001423 } else {
Wei Jia98160162015-02-04 17:01:11 -08001424 int64_t mediaUs = 0;
1425 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001426 ALOGV("rendering video at media time %.2f secs",
1427 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001428 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001429
1430 if (!(mFlags & FLAG_REAL_TIME)
1431 && mLastAudioMediaTimeUs != -1
1432 && mediaTimeUs > mLastAudioMediaTimeUs) {
1433 // If audio ends before video, video continues to drive media clock.
1434 // Also smooth out videos >= 10fps.
Wei Jiacc951512019-04-03 16:10:42 -07001435 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001436 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001437 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001438 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001439 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001440 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001441 // This will ensure that the first frame after a flush won't be used as anchor
1442 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia9a3101b2016-11-08 14:34:24 -08001443 clearAnchorTime();
Wei Jia49966ff2014-10-08 18:44:45 -07001444 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001445 }
Andreas Huberf9334412010-12-15 15:17:42 -08001446
Wei Jia25d696f2015-11-19 10:57:15 -08001447 // Always render the first video frame while keeping stats on A/V sync.
1448 if (!mVideoSampleReceived) {
1449 realTimeUs = nowUs;
1450 tooLate = false;
1451 }
1452
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001453 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000LL);
Glenn Kasten683525b2011-11-04 18:05:35 -07001454 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001455 entry->mNotifyConsumed->post();
1456 mVideoQueue.erase(mVideoQueue.begin());
1457 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001458
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001459 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001460
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001461 if (!mPaused) {
1462 if (!mVideoRenderingStarted) {
1463 mVideoRenderingStarted = true;
1464 notifyVideoRenderingStart();
1465 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001466 Mutex::Autolock autoLock(mLock);
1467 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001468 }
Andreas Huberf9334412010-12-15 15:17:42 -08001469}
1470
James Dongf57b4ea2012-07-20 13:38:36 -07001471void NuPlayer::Renderer::notifyVideoRenderingStart() {
1472 sp<AMessage> notify = mNotify->dup();
1473 notify->setInt32("what", kWhatVideoRenderingStart);
1474 notify->post();
1475}
1476
Ronghua Wu5095d702014-08-27 12:05:48 -07001477void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jiad214a562017-07-10 13:20:55 -07001478 Mutex::Autolock autoLock(mLock);
1479 notifyEOS_l(audio, finalResult, delayUs);
1480}
1481
1482void NuPlayer::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001483 if (audio && delayUs > 0) {
1484 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1485 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1486 msg->setInt32("finalResult", finalResult);
1487 msg->post(delayUs);
1488 return;
1489 }
Andreas Huberf9334412010-12-15 15:17:42 -08001490 sp<AMessage> notify = mNotify->dup();
1491 notify->setInt32("what", kWhatEOS);
1492 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001493 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001494 notify->post(delayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001495
1496 if (audio) {
1497 // Video might outlive audio. Clear anchor to enable video only case.
1498 mAnchorTimeMediaUs = -1;
Wei Jiaaec8d822017-08-25 15:27:57 -07001499 mHasAudio = false;
Wei Jiadc293e32017-10-16 18:29:37 -07001500 if (mNextVideoTimeMediaUs >= 0) {
1501 int64_t mediaUs = 0;
Wei Jia1225b932019-01-04 12:44:38 -08001502 int64_t nowUs = ALooper::GetNowUs();
1503 status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
1504 if (result == OK) {
1505 if (mNextVideoTimeMediaUs > mediaUs) {
1506 mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
1507 }
1508 } else {
1509 mMediaClock->updateAnchor(
Wei Jiacc951512019-04-03 16:10:42 -07001510 mNextVideoTimeMediaUs, nowUs,
1511 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
Wei Jiadc293e32017-10-16 18:29:37 -07001512 }
1513 }
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301514 } else {
1515 mHasVideo = false;
Wei Jiad214a562017-07-10 13:20:55 -07001516 }
Andreas Huberf9334412010-12-15 15:17:42 -08001517}
1518
Wei Jiaa05f1e32016-03-25 16:31:22 -07001519void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1520 sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1521 msg->setInt32("reason", reason);
1522 msg->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001523}
1524
Andreas Huberf9334412010-12-15 15:17:42 -08001525void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1526 int32_t audio;
1527 CHECK(msg->findInt32("audio", &audio));
1528
Wei Jia7b15cb32015-02-03 17:46:06 -08001529 if (dropBufferIfStale(audio, msg)) {
1530 return;
1531 }
1532
1533 if (audio) {
1534 mHasAudio = true;
1535 } else {
1536 mHasVideo = true;
1537 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001538
1539 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001540 if (mVideoScheduler == NULL) {
1541 mVideoScheduler = new VideoFrameScheduler();
1542 mVideoScheduler->init();
1543 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001544 }
1545
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001546 sp<RefBase> obj;
1547 CHECK(msg->findObject("buffer", &obj));
1548 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
Andreas Huberf9334412010-12-15 15:17:42 -08001549
1550 sp<AMessage> notifyConsumed;
1551 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1552
1553 QueueEntry entry;
1554 entry.mBuffer = buffer;
1555 entry.mNotifyConsumed = notifyConsumed;
1556 entry.mOffset = 0;
1557 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001558 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001559
1560 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001561 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001562 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001563 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001564 } else {
1565 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001566 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001567 }
1568
Wei Jia7b15cb32015-02-03 17:46:06 -08001569 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001570 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1571 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001572 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001573
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001574 sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1575 sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
Andreas Hubercb67cd12011-08-26 16:02:19 -07001576
1577 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1578 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001579 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001580 return;
1581 }
1582
1583 int64_t firstAudioTimeUs;
1584 int64_t firstVideoTimeUs;
1585 CHECK(firstAudioBuffer->meta()
1586 ->findInt64("timeUs", &firstAudioTimeUs));
1587 CHECK(firstVideoBuffer->meta()
1588 ->findInt64("timeUs", &firstVideoTimeUs));
1589
1590 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1591
Steve Block3856b092011-10-20 11:56:00 +01001592 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001593
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001594 if (diff > 100000LL) {
Andreas Hubercb67cd12011-08-26 16:02:19 -07001595 // Audio data starts More than 0.1 secs before video.
1596 // Drop some audio.
1597
1598 (*mAudioQueue.begin()).mNotifyConsumed->post();
1599 mAudioQueue.erase(mAudioQueue.begin());
1600 return;
1601 }
1602
Wei Jiabc2fb722014-07-08 16:37:57 -07001603 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001604}
1605
Wei Jiabc2fb722014-07-08 16:37:57 -07001606void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001607 if (!mSyncQueues) {
1608 return;
1609 }
1610
1611 mSyncQueues = false;
1612
1613 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001614 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001615 }
1616
1617 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001618 mLock.unlock();
1619 postDrainVideoQueue();
1620 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001621 }
1622}
1623
1624void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1625 int32_t audio;
1626 CHECK(msg->findInt32("audio", &audio));
1627
Wei Jia7b15cb32015-02-03 17:46:06 -08001628 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001629 return;
1630 }
1631
1632 int32_t finalResult;
1633 CHECK(msg->findInt32("finalResult", &finalResult));
1634
1635 QueueEntry entry;
1636 entry.mOffset = 0;
1637 entry.mFinalResult = finalResult;
1638
1639 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001640 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001641 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001642 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001643 }
Andreas Huberf9334412010-12-15 15:17:42 -08001644 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001645 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001646 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001647 if (mVideoQueue.empty() && getSyncQueues()) {
1648 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001649 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001650 }
Andreas Huberf9334412010-12-15 15:17:42 -08001651 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001652 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001653 }
1654}
1655
1656void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001657 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001658 CHECK(msg->findInt32("audio", &audio));
1659
Wei Jia28a8a9f2014-08-18 11:29:50 -07001660 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001661 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001662 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001663 notifyComplete = mNotifyCompleteAudio;
1664 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001665 mLastAudioMediaTimeUs = -1;
Wei Jiacc951512019-04-03 16:10:42 -07001666
1667 mHasAudio = false;
1668 if (mNextVideoTimeMediaUs >= 0) {
1669 int64_t nowUs = ALooper::GetNowUs();
1670 mMediaClock->updateAnchor(
1671 mNextVideoTimeMediaUs, nowUs,
1672 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
1673 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001674 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001675 notifyComplete = mNotifyCompleteVideo;
1676 mNotifyCompleteVideo = false;
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301677 mHasVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001678 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001679
Wei Jia7b15cb32015-02-03 17:46:06 -08001680 // If we're currently syncing the queues, i.e. dropping audio while
1681 // aligning the first audio/video buffer times and only one of the
1682 // two queues has data, we may starve that queue by not requesting
1683 // more buffers from the decoder. If the other source then encounters
1684 // a discontinuity that leads to flushing, we'll never find the
1685 // corresponding discontinuity on the other queue.
1686 // Therefore we'll stop syncing the queues if at least one of them
1687 // is flushed.
1688 syncQueuesDone_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001689 }
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301690
1691 if (audio && mDrainVideoQueuePending) {
1692 // Audio should not clear anchor(MediaClock) directly, because video
1693 // postDrainVideoQueue sets msg kWhatDrainVideoQueue into MediaClock
1694 // timer, clear anchor without update immediately may block msg posting.
1695 // So, postpone clear action to video to ensure anchor can be updated
1696 // immediately after clear
1697 mNeedVideoClearAnchor = true;
1698 } else {
1699 clearAnchorTime();
1700 }
Andreas Huberf9334412010-12-15 15:17:42 -08001701
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001702 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001703 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001704 {
1705 Mutex::Autolock autoLock(mLock);
1706 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001707
Wei Jia7b15cb32015-02-03 17:46:06 -08001708 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001709 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001710 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001711
Andy Hunga0b39712015-05-31 22:40:49 -07001712 // the frame count will be reset after flush.
1713 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001714 }
Andreas Huberf9334412010-12-15 15:17:42 -08001715
Andreas Huberf9334412010-12-15 15:17:42 -08001716 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001717
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001718 mAudioSink->pause();
1719 mAudioSink->flush();
1720 if (!offloadingAudio()) {
Wei Jia9e7ed332015-05-01 16:35:43 -07001721 // Call stop() to signal to the AudioSink to completely fill the
1722 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001723 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001724 mAudioSink->stop();
Wei Jia9e7ed332015-05-01 16:35:43 -07001725 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001726 }
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001727 if (!mPaused) {
1728 mAudioSink->start();
1729 }
Andy Hung528c8402016-01-12 12:39:34 -08001730 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001731 } else {
1732 flushQueue(&mVideoQueue);
1733
Andreas Huberf9334412010-12-15 15:17:42 -08001734 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001735
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001736 if (mVideoScheduler != NULL) {
1737 mVideoScheduler->restart();
1738 }
1739
Wei Jia7b15cb32015-02-03 17:46:06 -08001740 Mutex::Autolock autoLock(mLock);
1741 ++mVideoDrainGeneration;
1742 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001743 }
1744
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001745 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001746
1747 if (notifyComplete) {
1748 notifyFlushComplete(audio);
1749 }
Andreas Huberf9334412010-12-15 15:17:42 -08001750}
1751
1752void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1753 while (!queue->empty()) {
1754 QueueEntry *entry = &*queue->begin();
1755
1756 if (entry->mBuffer != NULL) {
1757 entry->mNotifyConsumed->post();
Wei Jia9a3101b2016-11-08 14:34:24 -08001758 } else if (entry->mNotifyConsumed != nullptr) {
1759 // Is it needed to open audio sink now?
1760 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
Andreas Huberf9334412010-12-15 15:17:42 -08001761 }
1762
1763 queue->erase(queue->begin());
1764 entry = NULL;
1765 }
1766}
1767
1768void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1769 sp<AMessage> notify = mNotify->dup();
1770 notify->setInt32("what", kWhatFlushComplete);
1771 notify->setInt32("audio", static_cast<int32_t>(audio));
1772 notify->post();
1773}
1774
Wei Jia7b15cb32015-02-03 17:46:06 -08001775bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001776 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001777 int32_t queueGeneration;
1778 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001779
Wei Jia7b15cb32015-02-03 17:46:06 -08001780 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001781 return false;
1782 }
1783
1784 sp<AMessage> notifyConsumed;
1785 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1786 notifyConsumed->post();
1787 }
1788
1789 return true;
1790}
1791
Andreas Huber3831a062010-12-21 10:22:33 -08001792void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001793 if (offloadingAudio()) {
1794 return;
1795 }
Andreas Huber3831a062010-12-21 10:22:33 -08001796 CHECK(!mDrainAudioQueuePending);
1797 mNumFramesWritten = 0;
Wei Jia9a3101b2016-11-08 14:34:24 -08001798 mAnchorNumFramesWritten = -1;
Marco Nelissen4110c102012-03-29 09:31:28 -07001799 uint32_t written;
1800 if (mAudioSink->getFramesWritten(&written) == OK) {
1801 mNumFramesWritten = written;
1802 }
Andreas Huber3831a062010-12-21 10:22:33 -08001803}
1804
Wei Jiabc2fb722014-07-08 16:37:57 -07001805void NuPlayer::Renderer::onDisableOffloadAudio() {
1806 Mutex::Autolock autoLock(mLock);
1807 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001808 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001809 if (mAudioRenderingStartGeneration != -1) {
1810 prepareForMediaRenderingStart_l();
andysu36177952018-04-20 15:17:13 +08001811 // PauseTimeout is applied to offload mode only. Cancel pending timer.
1812 cancelAudioOffloadPauseTimeout();
Robert Shihe1d70192015-07-23 17:54:13 -07001813 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001814}
1815
Ronghua Wua10fd232014-11-06 16:15:20 -08001816void NuPlayer::Renderer::onEnableOffloadAudio() {
1817 Mutex::Autolock autoLock(mLock);
1818 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001819 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001820 if (mAudioRenderingStartGeneration != -1) {
1821 prepareForMediaRenderingStart_l();
1822 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001823}
1824
Andreas Huberb4082222011-01-20 15:23:04 -08001825void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001826 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001827 return;
1828 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001829
Eric Laurent8ca036a2022-07-01 16:42:48 +02001830 startAudioOffloadPauseTimeout();
1831
Wei Jia28a8a9f2014-08-18 11:29:50 -07001832 {
1833 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001834 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001835 ++mVideoDrainGeneration;
1836 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001837 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001838 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001839 }
1840
Andreas Huberb4082222011-01-20 15:23:04 -08001841 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001842 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001843
Andy Hung84200732015-12-03 14:41:06 -08001844 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1845 mAudioSink->pause();
Andreas Huberb4082222011-01-20 15:23:04 -08001846
Lajos Molnar6d339f12015-04-17 16:15:53 -07001847 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001848 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001849}
1850
1851void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001852 if (!mPaused) {
1853 return;
1854 }
Andreas Huberb4082222011-01-20 15:23:04 -08001855
Andy Hung84200732015-12-03 14:41:06 -08001856 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1857 cancelAudioOffloadPauseTimeout();
1858 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001859 status_t err = mAudioSink->start();
1860 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001861 ALOGE("cannot start AudioSink err %d", err);
Wei Jiaa05f1e32016-03-25 16:31:22 -07001862 notifyAudioTearDown(kDueToError);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001863 }
Andreas Huberb4082222011-01-20 15:23:04 -08001864 }
1865
Wei Jia7b15cb32015-02-03 17:46:06 -08001866 {
1867 Mutex::Autolock autoLock(mLock);
1868 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001869 // rendering started message may have been delayed if we were paused.
1870 if (mRenderingDataDelivered) {
1871 notifyIfMediaRenderingStarted_l();
1872 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001873 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001874 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001875 mAudioSink->setPlaybackRate(mPlaybackSettings);
1876 }
1877
Wei Jia98160162015-02-04 17:01:11 -08001878 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001879
Wei Jia7b15cb32015-02-03 17:46:06 -08001880 if (!mAudioQueue.empty()) {
1881 postDrainAudioQueue_l();
1882 }
Andreas Huberb4082222011-01-20 15:23:04 -08001883 }
1884
1885 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001886 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001887 }
1888}
1889
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001890void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1891 if (mVideoScheduler == NULL) {
1892 mVideoScheduler = new VideoFrameScheduler();
1893 }
1894 mVideoScheduler->init(fps);
1895}
1896
Wei Jia7b15cb32015-02-03 17:46:06 -08001897int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1898 Mutex::Autolock autoLock(mLock);
1899 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1900}
1901
1902int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1903 Mutex::Autolock autoLock(mLock);
1904 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1905}
1906
1907bool NuPlayer::Renderer::getSyncQueues() {
1908 Mutex::Autolock autoLock(mLock);
1909 return mSyncQueues;
1910}
1911
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001912void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1913 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001914 return;
1915 }
andysu36177952018-04-20 15:17:13 +08001916
1917 // TimeoutWhenPaused is only for offload mode.
1918 if (reason == kDueToTimeout && !offloadingAudio()) {
1919 return;
1920 }
1921
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001922 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001923
Ronghua Wua73d9e02014-10-08 15:13:29 -07001924 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001925 sp<AMessage> notify = mNotify->dup();
1926 if (getCurrentPosition(&currentPositionUs) == OK) {
1927 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001928 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001929
Wei Jia3a2956d2014-07-22 16:01:33 -07001930 mAudioSink->stop();
1931 mAudioSink->flush();
1932
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001933 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001934 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001935 notify->post();
1936}
1937
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001938void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1939 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001940 mWakeLock->acquire();
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001941 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001942 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001943 msg->post(kOffloadPauseMaxUs);
1944 }
1945}
1946
1947void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
Andy Hung21afe802016-04-21 14:52:05 -07001948 // We may have called startAudioOffloadPauseTimeout() without
1949 // the AudioSink open and with offloadingAudio enabled.
1950 //
1951 // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
1952 // we always release the wakelock and increment the pause timeout generation.
1953 //
1954 // Note: The acquired wakelock prevents the device from suspending
1955 // immediately after offload pause (in case a resume happens shortly thereafter).
1956 mWakeLock->release(true);
1957 ++mAudioOffloadPauseTimeoutGeneration;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001958}
1959
Andy Hung202bce12014-12-03 11:47:36 -08001960status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001961 const sp<AMessage> &format,
1962 bool offloadOnly,
1963 bool hasVideo,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05301964 uint32_t flags,
1965 bool isStreaming) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001966 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1967 offloadOnly, offloadingAudio());
1968 bool audioSinkChanged = false;
1969
1970 int32_t numChannels;
1971 CHECK(format->findInt32("channel-count", &numChannels));
1972
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00001973 // channel mask info as read from the audio format
Andy Hungf0fef6c2022-08-29 20:07:43 -07001974 int32_t mediaFormatChannelMask;
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00001975 // channel mask to use for native playback
1976 audio_channel_mask_t channelMask;
Andy Hungf0fef6c2022-08-29 20:07:43 -07001977 if (format->findInt32("channel-mask", &mediaFormatChannelMask)) {
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00001978 // KEY_CHANNEL_MASK follows the android.media.AudioFormat java mask
Andy Hungf0fef6c2022-08-29 20:07:43 -07001979 channelMask = audio_channel_mask_from_media_format_mask(mediaFormatChannelMask);
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00001980 } else {
1981 // no mask found: the mask will be derived from the channel count
1982 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
1983 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001984
1985 int32_t sampleRate;
1986 CHECK(format->findInt32("sample-rate", &sampleRate));
1987
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07001988 // read pcm encoding from MediaCodec output format, if available
1989 int32_t pcmEncoding;
1990 audio_format_t audioFormat =
1991 format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
1992 audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
1993
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001994 if (offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001995 AString mime;
1996 CHECK(format->findString("mime", &mime));
1997 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
1998
1999 if (err != OK) {
2000 ALOGE("Couldn't map mime \"%s\" to a valid "
2001 "audio_format", mime.c_str());
2002 onDisableOffloadAudio();
2003 } else {
2004 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
2005 mime.c_str(), audioFormat);
2006
Ajender Reddy55a85792021-02-25 21:01:35 +05302007 int avgBitRate = 0;
Lajos Molnar46f80162016-05-19 15:35:47 -07002008 format->findInt32("bitrate", &avgBitRate);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002009
2010 int32_t aacProfile = -1;
2011 if (audioFormat == AUDIO_FORMAT_AAC
2012 && format->findInt32("aac-profile", &aacProfile)) {
2013 // Redefine AAC format as per aac profile
2014 mapAACProfileToAudioFormat(
2015 audioFormat,
2016 aacProfile);
2017 }
2018
2019 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
2020 offloadInfo.duration_us = -1;
2021 format->findInt64(
2022 "durationUs", &offloadInfo.duration_us);
2023 offloadInfo.sample_rate = sampleRate;
2024 offloadInfo.channel_mask = channelMask;
2025 offloadInfo.format = audioFormat;
2026 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
2027 offloadInfo.bit_rate = avgBitRate;
2028 offloadInfo.has_video = hasVideo;
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302029 offloadInfo.is_streaming = isStreaming;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002030
2031 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
2032 ALOGV("openAudioSink: no change in offload mode");
2033 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08002034 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002035 }
Andy Hungf0e83642014-12-19 17:55:56 -08002036 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
2037
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002038 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002039 uint32_t offloadFlags = flags;
2040 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
2041 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002042 audioSinkChanged = true;
2043 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07002044
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002045 err = mAudioSink->open(
2046 sampleRate,
2047 numChannels,
2048 (audio_channel_mask_t)channelMask,
2049 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002050 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002051 &NuPlayer::Renderer::AudioSinkCallback,
2052 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002053 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002054 &offloadInfo);
2055
2056 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002057 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
2058 }
2059
2060 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002061 // If the playback is offloaded to h/w, we pass
2062 // the HAL some metadata information.
2063 // We don't want to do this for PCM because it
2064 // will be going through the AudioFlinger mixer
2065 // before reaching the hardware.
2066 // TODO
2067 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07002068 if (!mPaused) { // for preview mode, don't start if paused
2069 err = mAudioSink->start();
2070 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002071 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
2072 }
2073 if (err != OK) {
2074 // Clean up, fall back to non offload mode.
2075 mAudioSink->close();
2076 onDisableOffloadAudio();
2077 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
2078 ALOGV("openAudioSink: offload failed");
Wei Jiaa05f1e32016-03-25 16:31:22 -07002079 if (offloadOnly) {
2080 notifyAudioTearDown(kForceNonOffload);
2081 }
Wei Jia3ab25452015-06-10 09:37:47 -07002082 } else {
2083 mUseAudioCallback = true; // offload mode transfers data through callback
2084 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002085 }
2086 }
2087 }
2088 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002089 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002090 uint32_t pcmFlags = flags;
2091 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08002092
2093 const PcmInfo info = {
2094 (audio_channel_mask_t)channelMask,
2095 (audio_output_flags_t)pcmFlags,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002096 audioFormat,
Andy Hungf0e83642014-12-19 17:55:56 -08002097 numChannels,
2098 sampleRate
2099 };
2100 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
2101 ALOGV("openAudioSink: no change in pcm mode");
2102 // no change from previous configuration, everything ok.
2103 return OK;
2104 }
2105
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002106 audioSinkChanged = true;
2107 mAudioSink->close();
2108 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07002109 // Note: It is possible to set up the callback, but not use it to send audio data.
2110 // This requires a fix in AudioSink to explicitly specify the transfer mode.
2111 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07002112 if (mUseAudioCallback) {
2113 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
2114 }
Andy Hung179652e2015-05-31 22:49:46 -07002115
2116 // Compute the desired buffer size.
2117 // For callback mode, the amount of time before wakeup is about half the buffer size.
2118 const uint32_t frameCount =
2119 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
2120
Ronghua Wu7665f582015-09-02 10:15:30 -07002121 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
2122 // AudioSink. We don't want this when there's video because it will cause a video seek to
2123 // the previous I frame. But we do want this when there's only audio because it will give
2124 // NuPlayer a chance to switch from non-offload mode to offload mode.
2125 // So we only set doNotReconnect when there's no video.
2126 const bool doNotReconnect = !hasVideo;
Andy Hungff874dc2016-04-11 16:49:09 -07002127
2128 // We should always be able to set our playback settings if the sink is closed.
2129 LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
2130 "onOpenAudioSink: can't set playback rate on closed sink");
Andy Hung202bce12014-12-03 11:47:36 -08002131 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002132 sampleRate,
2133 numChannels,
2134 (audio_channel_mask_t)channelMask,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002135 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002136 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07002137 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
2138 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002139 (audio_output_flags_t)pcmFlags,
2140 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07002141 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07002142 frameCount);
Andy Hung202bce12014-12-03 11:47:36 -08002143 if (err != OK) {
2144 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07002145 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08002146 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08002147 return err;
2148 }
Andy Hungf0e83642014-12-19 17:55:56 -08002149 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07002150 if (!mPaused) { // for preview mode, don't start if paused
2151 mAudioSink->start();
2152 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002153 }
2154 if (audioSinkChanged) {
2155 onAudioSinkChanged();
2156 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002157 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08002158 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002159}
2160
2161void NuPlayer::Renderer::onCloseAudioSink() {
2162 mAudioSink->close();
2163 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08002164 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002165}
2166
Wei Jia9a3101b2016-11-08 14:34:24 -08002167void NuPlayer::Renderer::onChangeAudioFormat(
2168 const sp<AMessage> &meta, const sp<AMessage> &notify) {
2169 sp<AMessage> format;
2170 CHECK(meta->findMessage("format", &format));
2171
2172 int32_t offloadOnly;
2173 CHECK(meta->findInt32("offload-only", &offloadOnly));
2174
2175 int32_t hasVideo;
2176 CHECK(meta->findInt32("has-video", &hasVideo));
2177
2178 uint32_t flags;
2179 CHECK(meta->findInt32("flags", (int32_t *)&flags));
2180
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302181 uint32_t isStreaming;
2182 CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
2183
2184 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -08002185
2186 if (err != OK) {
2187 notify->setInt32("err", err);
2188 }
2189 notify->post();
2190}
2191
Andreas Huberf9334412010-12-15 15:17:42 -08002192} // namespace android