blob: 3d4e95597a5b8da2ee079a0703e6436b6eb96aac [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
christosts9aacf192023-03-09 14:12:36 +0000487void NuPlayer::Renderer::dump(AString& logString) {
488 Mutex::Autolock autoLock(mLock);
489 logString.append("paused(");
490 logString.append(mPaused);
491 logString.append("), offloading(");
492 logString.append(offloadingAudio());
493 logString.append("), wakelock(acquired=");
494 mWakelockAcquireEvent.dump(logString);
495 logString.append(", timeout=");
496 mWakelockTimeoutEvent.dump(logString);
497 logString.append(", release=");
498 mWakelockReleaseEvent.dump(logString);
499 logString.append(", cancel=");
500 mWakelockCancelEvent.dump(logString);
501 logString.append(")");
502}
503
Wei Jia9a3101b2016-11-08 14:34:24 -0800504void NuPlayer::Renderer::changeAudioFormat(
505 const sp<AMessage> &format,
506 bool offloadOnly,
507 bool hasVideo,
508 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530509 bool isStreaming,
Wei Jia9a3101b2016-11-08 14:34:24 -0800510 const sp<AMessage> &notify) {
511 sp<AMessage> meta = new AMessage;
512 meta->setMessage("format", format);
513 meta->setInt32("offload-only", offloadOnly);
514 meta->setInt32("has-video", hasVideo);
515 meta->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530516 meta->setInt32("isStreaming", isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -0800517
518 sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
519 msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
520 msg->setMessage("notify", notify);
521 msg->setMessage("meta", meta);
522 msg->post();
523}
524
Andreas Huberf9334412010-12-15 15:17:42 -0800525void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
526 switch (msg->what()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700527 case kWhatOpenAudioSink:
528 {
529 sp<AMessage> format;
530 CHECK(msg->findMessage("format", &format));
531
532 int32_t offloadOnly;
533 CHECK(msg->findInt32("offload-only", &offloadOnly));
534
535 int32_t hasVideo;
536 CHECK(msg->findInt32("has-video", &hasVideo));
537
538 uint32_t flags;
539 CHECK(msg->findInt32("flags", (int32_t *)&flags));
540
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530541 uint32_t isStreaming;
542 CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
543
544 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700545
546 sp<AMessage> response = new AMessage;
Andy Hung202bce12014-12-03 11:47:36 -0800547 response->setInt32("err", err);
548 response->setInt32("offload", offloadingAudio());
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700549
Lajos Molnar3f274362015-03-05 14:35:41 -0800550 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700551 CHECK(msg->senderAwaitsResponse(&replyID));
552 response->postReply(replyID);
553
554 break;
555 }
556
557 case kWhatCloseAudioSink:
558 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800559 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700560 CHECK(msg->senderAwaitsResponse(&replyID));
561
562 onCloseAudioSink();
563
564 sp<AMessage> response = new AMessage;
565 response->postReply(replyID);
566 break;
567 }
568
Wei Jiabc2fb722014-07-08 16:37:57 -0700569 case kWhatStopAudioSink:
570 {
571 mAudioSink->stop();
572 break;
573 }
574
Wei Jia9a3101b2016-11-08 14:34:24 -0800575 case kWhatChangeAudioFormat:
576 {
577 int32_t queueGeneration;
578 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
579
580 sp<AMessage> notify;
581 CHECK(msg->findMessage("notify", &notify));
582
583 if (offloadingAudio()) {
584 ALOGW("changeAudioFormat should NOT be called in offload mode");
585 notify->setInt32("err", INVALID_OPERATION);
586 notify->post();
587 break;
588 }
589
590 sp<AMessage> meta;
591 CHECK(msg->findMessage("meta", &meta));
592
593 if (queueGeneration != getQueueGeneration(true /* audio */)
594 || mAudioQueue.empty()) {
595 onChangeAudioFormat(meta, notify);
596 break;
597 }
598
599 QueueEntry entry;
600 entry.mNotifyConsumed = notify;
601 entry.mMeta = meta;
602
603 Mutex::Autolock autoLock(mLock);
604 mAudioQueue.push_back(entry);
605 postDrainAudioQueue_l();
606
607 break;
608 }
609
Andreas Huberf9334412010-12-15 15:17:42 -0800610 case kWhatDrainAudioQueue:
611 {
Wei Jia3ab25452015-06-10 09:37:47 -0700612 mDrainAudioQueuePending = false;
613
Andreas Huberf9334412010-12-15 15:17:42 -0800614 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800615 CHECK(msg->findInt32("drainGeneration", &generation));
616 if (generation != getDrainGeneration(true /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800617 break;
618 }
619
Andreas Huber078cfcf2011-09-15 12:25:04 -0700620 if (onDrainAudioQueue()) {
621 uint32_t numFramesPlayed;
622 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
623 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800624
Wei Jia1fb35b72017-09-25 16:08:13 -0700625 // Handle AudioTrack race when start is immediately called after flush.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700626 uint32_t numFramesPendingPlayout =
Wei Jia1fb35b72017-09-25 16:08:13 -0700627 (mNumFramesWritten > numFramesPlayed ?
628 mNumFramesWritten - numFramesPlayed : 0);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700629
630 // This is how long the audio sink will have data to
631 // play back.
632 int64_t delayUs =
633 mAudioSink->msecsPerFrame()
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800634 * numFramesPendingPlayout * 1000LL;
Wei Jiad9c2e9c2015-04-10 19:04:09 -0700635 if (mPlaybackRate > 1.0f) {
636 delayUs /= mPlaybackRate;
637 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700638
639 // Let's give it more data after about half that time
640 // has elapsed.
Andy Hungf2c87b32016-04-07 19:49:29 -0700641 delayUs /= 2;
642 // check the buffer size to estimate maximum delay permitted.
643 const int64_t maxDrainDelayUs = std::max(
644 mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
645 ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
646 (long long)delayUs, (long long)maxDrainDelayUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800647 Mutex::Autolock autoLock(mLock);
Andy Hungf2c87b32016-04-07 19:49:29 -0700648 postDrainAudioQueue_l(delayUs);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700649 }
Andreas Huberf9334412010-12-15 15:17:42 -0800650 break;
651 }
652
653 case kWhatDrainVideoQueue:
654 {
655 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800656 CHECK(msg->findInt32("drainGeneration", &generation));
657 if (generation != getDrainGeneration(false /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800658 break;
659 }
660
661 mDrainVideoQueuePending = false;
662
663 onDrainVideoQueue();
664
Wei Jia7b15cb32015-02-03 17:46:06 -0800665 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -0800666 break;
667 }
668
Lajos Molnard5923402014-10-20 17:47:54 -0700669 case kWhatPostDrainVideoQueue:
670 {
671 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800672 CHECK(msg->findInt32("drainGeneration", &generation));
673 if (generation != getDrainGeneration(false /* audio */)) {
Lajos Molnard5923402014-10-20 17:47:54 -0700674 break;
675 }
676
677 mDrainVideoQueuePending = false;
Wei Jia7b15cb32015-02-03 17:46:06 -0800678 postDrainVideoQueue();
Lajos Molnard5923402014-10-20 17:47:54 -0700679 break;
680 }
681
Andreas Huberf9334412010-12-15 15:17:42 -0800682 case kWhatQueueBuffer:
683 {
684 onQueueBuffer(msg);
685 break;
686 }
687
688 case kWhatQueueEOS:
689 {
690 onQueueEOS(msg);
691 break;
692 }
693
Wei Jia7c8d0e02015-08-27 17:40:21 -0700694 case kWhatEOS:
695 {
696 int32_t generation;
697 CHECK(msg->findInt32("audioEOSGeneration", &generation));
698 if (generation != mAudioEOSGeneration) {
699 break;
700 }
701 status_t finalResult;
702 CHECK(msg->findInt32("finalResult", &finalResult));
703 notifyEOS(true /* audio */, finalResult);
704 break;
705 }
706
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700707 case kWhatConfigPlayback:
Wei Jia98160162015-02-04 17:01:11 -0800708 {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700709 sp<AReplyToken> replyID;
710 CHECK(msg->senderAwaitsResponse(&replyID));
711 AudioPlaybackRate rate;
712 readFromAMessage(msg, &rate);
713 status_t err = onConfigPlayback(rate);
714 sp<AMessage> response = new AMessage;
715 response->setInt32("err", err);
716 response->postReply(replyID);
717 break;
718 }
719
720 case kWhatGetPlaybackSettings:
721 {
722 sp<AReplyToken> replyID;
723 CHECK(msg->senderAwaitsResponse(&replyID));
724 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
725 status_t err = onGetPlaybackSettings(&rate);
726 sp<AMessage> response = new AMessage;
727 if (err == OK) {
728 writeToAMessage(response, rate);
729 }
730 response->setInt32("err", err);
731 response->postReply(replyID);
732 break;
733 }
734
735 case kWhatConfigSync:
736 {
737 sp<AReplyToken> replyID;
738 CHECK(msg->senderAwaitsResponse(&replyID));
739 AVSyncSettings sync;
740 float videoFpsHint;
741 readFromAMessage(msg, &sync, &videoFpsHint);
742 status_t err = onConfigSync(sync, videoFpsHint);
743 sp<AMessage> response = new AMessage;
744 response->setInt32("err", err);
745 response->postReply(replyID);
746 break;
747 }
748
749 case kWhatGetSyncSettings:
750 {
751 sp<AReplyToken> replyID;
752 CHECK(msg->senderAwaitsResponse(&replyID));
753
754 ALOGV("kWhatGetSyncSettings");
755 AVSyncSettings sync;
756 float videoFps = -1.f;
757 status_t err = onGetSyncSettings(&sync, &videoFps);
758 sp<AMessage> response = new AMessage;
759 if (err == OK) {
760 writeToAMessage(response, sync, videoFps);
761 }
762 response->setInt32("err", err);
763 response->postReply(replyID);
Wei Jia98160162015-02-04 17:01:11 -0800764 break;
765 }
766
Andreas Huberf9334412010-12-15 15:17:42 -0800767 case kWhatFlush:
768 {
769 onFlush(msg);
770 break;
771 }
772
Wei Jiabc2fb722014-07-08 16:37:57 -0700773 case kWhatDisableOffloadAudio:
774 {
775 onDisableOffloadAudio();
776 break;
777 }
778
Ronghua Wua10fd232014-11-06 16:15:20 -0800779 case kWhatEnableOffloadAudio:
780 {
781 onEnableOffloadAudio();
782 break;
783 }
784
Andreas Huberb4082222011-01-20 15:23:04 -0800785 case kWhatPause:
786 {
787 onPause();
788 break;
789 }
790
791 case kWhatResume:
792 {
793 onResume();
794 break;
795 }
796
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700797 case kWhatSetVideoFrameRate:
798 {
799 float fps;
800 CHECK(msg->findFloat("frame-rate", &fps));
801 onSetVideoFrameRate(fps);
802 break;
803 }
804
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700805 case kWhatAudioTearDown:
Wei Jia3a2956d2014-07-22 16:01:33 -0700806 {
Wei Jiaa05f1e32016-03-25 16:31:22 -0700807 int32_t reason;
808 CHECK(msg->findInt32("reason", &reason));
809
810 onAudioTearDown((AudioTearDownReason)reason);
Wei Jia3a2956d2014-07-22 16:01:33 -0700811 break;
812 }
813
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700814 case kWhatAudioOffloadPauseTimeout:
815 {
816 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800817 CHECK(msg->findInt32("drainGeneration", &generation));
christosts9aacf192023-03-09 14:12:36 +0000818 mWakelockTimeoutEvent.updateValues(
819 uptimeMillis(),
820 generation,
821 mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700822 if (generation != mAudioOffloadPauseTimeoutGeneration) {
823 break;
824 }
Ronghua Wu08529172014-10-02 16:55:52 -0700825 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700826 onAudioTearDown(kDueToTimeout);
Eric Laurent8ca036a2022-07-01 16:42:48 +0200827 sp<AMessage> newMsg = new AMessage(kWhatReleaseWakeLock, this);
828 newMsg->setInt32("drainGeneration", generation);
829 newMsg->post(kWakelockReleaseDelayUs);
830 break;
831 }
832
833 case kWhatReleaseWakeLock:
834 {
835 int32_t generation;
836 CHECK(msg->findInt32("drainGeneration", &generation));
christosts9aacf192023-03-09 14:12:36 +0000837 mWakelockReleaseEvent.updateValues(
838 uptimeMillis(),
839 generation,
840 mAudioOffloadPauseTimeoutGeneration);
Eric Laurent8ca036a2022-07-01 16:42:48 +0200841 if (generation != mAudioOffloadPauseTimeoutGeneration) {
842 break;
843 }
844 ALOGV("releasing audio offload pause wakelock.");
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800845 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700846 break;
847 }
848
Andreas Huberf9334412010-12-15 15:17:42 -0800849 default:
850 TRESPASS();
851 break;
852 }
Wonsik Kimee8116b2019-07-19 15:55:44 -0700853 if (!mSyncFlag.test_and_set()) {
854 Mutex::Autolock syncLock(mSyncLock);
855 ++mSyncCount;
856 mSyncCondition.broadcast();
857 }
Andreas Huberf9334412010-12-15 15:17:42 -0800858}
859
Wei Jiabc2fb722014-07-08 16:37:57 -0700860void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700861 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800862 return;
863 }
864
865 if (mAudioQueue.empty()) {
866 return;
867 }
868
Andy Hungb03dcb32015-08-27 16:18:59 -0700869 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
870 if (mPaused) {
871 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
872 if (diffUs > delayUs) {
873 delayUs = diffUs;
874 }
875 }
876
Andreas Huberf9334412010-12-15 15:17:42 -0800877 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800878 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800879 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700880 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800881}
882
Wei Jia7b15cb32015-02-03 17:46:06 -0800883void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
884 mAudioRenderingStartGeneration = mAudioDrainGeneration;
885 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700886 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700887}
888
Wei Jia7b15cb32015-02-03 17:46:06 -0800889void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
890 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
891 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700892 mRenderingDataDelivered = true;
893 if (mPaused) {
894 return;
895 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700896 mVideoRenderingStartGeneration = -1;
897 mAudioRenderingStartGeneration = -1;
898
899 sp<AMessage> notify = mNotify->dup();
900 notify->setInt32("what", kWhatMediaRenderingStart);
901 notify->post();
902 }
903}
904
Wei Jiabc2fb722014-07-08 16:37:57 -0700905// static
906size_t NuPlayer::Renderer::AudioSinkCallback(
907 MediaPlayerBase::AudioSink * /* audioSink */,
908 void *buffer,
909 size_t size,
910 void *cookie,
911 MediaPlayerBase::AudioSink::cb_event_t event) {
912 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
913
914 switch (event) {
915 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
916 {
917 return me->fillAudioBuffer(buffer, size);
918 break;
919 }
920
921 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
922 {
Andy Hunga0b39712015-05-31 22:40:49 -0700923 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jia4c74fde2016-08-26 16:00:52 -0700924 me->notifyEOSCallback();
Wei Jiabc2fb722014-07-08 16:37:57 -0700925 break;
926 }
927
928 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
929 {
Andy Hunga0b39712015-05-31 22:40:49 -0700930 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Wei Jiaa05f1e32016-03-25 16:31:22 -0700931 me->notifyAudioTearDown(kDueToError);
Wei Jiabc2fb722014-07-08 16:37:57 -0700932 break;
933 }
934 }
935
936 return 0;
937}
938
Wei Jia4c74fde2016-08-26 16:00:52 -0700939void NuPlayer::Renderer::notifyEOSCallback() {
940 Mutex::Autolock autoLock(mLock);
941
942 if (!mUseAudioCallback) {
943 return;
944 }
945
Wei Jiad214a562017-07-10 13:20:55 -0700946 notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
Wei Jia4c74fde2016-08-26 16:00:52 -0700947}
948
Wei Jiabc2fb722014-07-08 16:37:57 -0700949size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
950 Mutex::Autolock autoLock(mLock);
951
Andy Hung85e48142015-05-31 23:04:15 -0700952 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700953 return 0;
954 }
955
956 bool hasEOS = false;
957
958 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700959 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700960 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700961 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700962 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700963
964 if (entry->mBuffer == NULL) { // EOS
965 hasEOS = true;
966 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700967 break;
968 }
969
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700970 if (firstEntry && entry->mOffset == 0) {
971 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700972 int64_t mediaTimeUs;
973 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Paras Nagda86dc6182020-10-27 13:01:47 +0530974 if (mediaTimeUs < 0) {
975 ALOGD("fillAudioBuffer: reset negative media time %.2f secs to zero",
976 mediaTimeUs / 1E6);
977 mediaTimeUs = 0;
978 }
Andy Hunga0b39712015-05-31 22:40:49 -0700979 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800980 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700981 }
982
983 size_t copy = entry->mBuffer->size() - entry->mOffset;
984 size_t sizeRemaining = size - sizeCopied;
985 if (copy > sizeRemaining) {
986 copy = sizeRemaining;
987 }
988
989 memcpy((char *)buffer + sizeCopied,
990 entry->mBuffer->data() + entry->mOffset,
991 copy);
992
993 entry->mOffset += copy;
994 if (entry->mOffset == entry->mBuffer->size()) {
995 entry->mNotifyConsumed->post();
996 mAudioQueue.erase(mAudioQueue.begin());
997 entry = NULL;
998 }
999 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -08001000
1001 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001002 }
1003
Lajos Molnarf5926712014-10-21 09:36:43 -07001004 if (mAudioFirstAnchorTimeMediaUs >= 0) {
1005 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -08001006 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -07001007 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -08001008 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -08001009 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -07001010 }
1011
Andy Hunga0b39712015-05-31 22:40:49 -07001012 // for non-offloaded audio, we need to compute the frames written because
1013 // there is no EVENT_STREAM_END notification. The frames written gives
1014 // an estimate on the pending played out duration.
1015 if (!offloadingAudio()) {
1016 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -07001017 }
1018
Andy Hunga0b39712015-05-31 22:40:49 -07001019 if (hasEOS) {
1020 (new AMessage(kWhatStopAudioSink, this))->post();
1021 // As there is currently no EVENT_STREAM_END callback notification for
1022 // non-offloaded audio tracks, we need to post the EOS ourselves.
1023 if (!offloadingAudio()) {
1024 int64_t postEOSDelayUs = 0;
1025 if (mAudioSink->needsTrailingPadding()) {
1026 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
1027 }
Wei Jiad214a562017-07-10 13:20:55 -07001028 ALOGV("fillAudioBuffer: notifyEOS_l "
Andy Hunga0b39712015-05-31 22:40:49 -07001029 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
1030 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001031 notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Andy Hunga0b39712015-05-31 22:40:49 -07001032 }
1033 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001034 return sizeCopied;
1035}
1036
Chong Zhang9da0ce42015-06-11 17:18:58 -07001037void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
1038 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
1039 bool foundEOS = false;
1040 while (it != mAudioQueue.end()) {
1041 int32_t eos;
1042 QueueEntry *entry = &*it++;
Wei Jia9a3101b2016-11-08 14:34:24 -08001043 if ((entry->mBuffer == nullptr && entry->mNotifyConsumed == nullptr)
Chong Zhang9da0ce42015-06-11 17:18:58 -07001044 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
1045 itEOS = it;
1046 foundEOS = true;
1047 }
1048 }
1049
1050 if (foundEOS) {
1051 // post all replies before EOS and drop the samples
1052 for (it = mAudioQueue.begin(); it != itEOS; it++) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001053 if (it->mBuffer == nullptr) {
1054 if (it->mNotifyConsumed == nullptr) {
1055 // delay doesn't matter as we don't even have an AudioTrack
1056 notifyEOS(true /* audio */, it->mFinalResult);
1057 } else {
1058 // TAG for re-opening audio sink.
1059 onChangeAudioFormat(it->mMeta, it->mNotifyConsumed);
1060 }
Chong Zhang9da0ce42015-06-11 17:18:58 -07001061 } else {
1062 it->mNotifyConsumed->post();
1063 }
1064 }
1065 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
1066 }
1067}
1068
Andreas Huber078cfcf2011-09-15 12:25:04 -07001069bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -07001070 // do not drain audio during teardown as queued buffers may be invalid.
1071 if (mAudioTornDown) {
1072 return false;
1073 }
Wei Jia230b1882015-03-19 15:13:51 -07001074 // TODO: This call to getPosition checks if AudioTrack has been created
1075 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
1076 // CHECKs on getPosition will fail.
1077 // We still need to figure out why AudioTrack is not created when
1078 // this function is called. One possible reason could be leftover
1079 // audio. Another possible place is to check whether decoder
1080 // has received INFO_FORMAT_CHANGED as the first buffer since
1081 // AudioSink is opened there, and possible interactions with flush
1082 // immediately after start. Investigate error message
1083 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -07001084 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -07001085 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -07001086 // When getPosition fails, renderer will not reschedule the draining
1087 // unless new samples are queued.
1088 // If we have pending EOS (or "eos" marker for discontinuities), we need
1089 // to post these now as NuPlayerDecoder might be waiting for it.
1090 drainAudioQueueUntilLastEOS();
1091
1092 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -07001093 return false;
1094 }
Andreas Huberc92fd242011-08-16 13:48:44 -07001095
Wei Jia230b1882015-03-19 15:13:51 -07001096#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -07001097 ssize_t numFramesAvailableToWrite =
1098 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
1099
Andreas Huber078cfcf2011-09-15 12:25:04 -07001100 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +00001101 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -07001102 } else {
Steve Block3856b092011-10-20 11:56:00 +01001103 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -07001104 mAudioSink->frameCount() - numFramesAvailableToWrite);
1105 }
1106#endif
1107
Andy Hung005e9d02015-05-31 23:16:07 -07001108 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -08001109 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -07001110 QueueEntry *entry = &*mAudioQueue.begin();
1111
1112 if (entry->mBuffer == NULL) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001113 if (entry->mNotifyConsumed != nullptr) {
1114 // TAG for re-open audio sink.
1115 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
1116 mAudioQueue.erase(mAudioQueue.begin());
1117 continue;
1118 }
1119
Andreas Huberc92fd242011-08-16 13:48:44 -07001120 // EOS
Haynes Mathew George62d4e072016-06-13 11:23:22 -07001121 if (mPaused) {
1122 // Do not notify EOS when paused.
1123 // This is needed to avoid switch to next clip while in pause.
1124 ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
1125 return false;
1126 }
1127
Ronghua Wu5095d702014-08-27 12:05:48 -07001128 int64_t postEOSDelayUs = 0;
1129 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -07001130 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -07001131 }
1132 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001133 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -07001134
1135 mAudioQueue.erase(mAudioQueue.begin());
1136 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -08001137 if (mAudioSink->needsTrailingPadding()) {
1138 // If we're not in gapless playback (i.e. through setNextPlayer), we
1139 // need to stop the track here, because that will play out the last
1140 // little bit at the end of the file. Otherwise short files won't play.
1141 mAudioSink->stop();
1142 mNumFramesWritten = 0;
1143 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001144 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -07001145 }
1146
Wei Jia9a3101b2016-11-08 14:34:24 -08001147 mLastAudioBufferDrained = entry->mBufferOrdinal;
1148
Chong Zhang81636762015-04-21 09:33:47 -07001149 // ignore 0-sized buffer which could be EOS marker with no data
1150 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -08001151 int64_t mediaTimeUs;
1152 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -07001153 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
1154 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -07001155 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001156 }
1157
1158 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -08001159
Wei Jia7d3f4df2015-03-03 15:28:00 -08001160 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
1161 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -07001162 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -08001163 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001164 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -07001165 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001166 } else {
1167 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -07001168 // This can only happen when AudioSink was opened with doNotReconnect flag set to
1169 // true, in which case the NuPlayer will handle the reconnect.
Wei Jiaa05f1e32016-03-25 16:31:22 -07001170 notifyAudioTearDown(kDueToError);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001171 }
Andy Hung202bce12014-12-03 11:47:36 -08001172 break;
Andy Hunga31335a2014-08-20 17:37:59 -07001173 }
Andreas Huberf9334412010-12-15 15:17:42 -08001174
Andy Hunga31335a2014-08-20 17:37:59 -07001175 entry->mOffset += written;
Wei Jia03cee242016-05-26 15:22:59 -07001176 size_t remainder = entry->mBuffer->size() - entry->mOffset;
1177 if ((ssize_t)remainder < mAudioSink->frameSize()) {
1178 if (remainder > 0) {
1179 ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
1180 remainder);
1181 entry->mOffset += remainder;
1182 copy -= remainder;
1183 }
1184
Andreas Huberf9334412010-12-15 15:17:42 -08001185 entry->mNotifyConsumed->post();
1186 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -07001187
Andreas Huberf9334412010-12-15 15:17:42 -08001188 entry = NULL;
1189 }
1190
Andy Hunga31335a2014-08-20 17:37:59 -07001191 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -07001192 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001193
Wei Jia7b15cb32015-02-03 17:46:06 -08001194 {
1195 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -07001196 int64_t maxTimeMedia;
1197 maxTimeMedia =
1198 mAnchorTimeMediaUs +
1199 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
1200 * 1000LL * mAudioSink->msecsPerFrame());
1201 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
1202
Wei Jia7b15cb32015-02-03 17:46:06 -08001203 notifyIfMediaRenderingStarted_l();
1204 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001205
Andy Hunga31335a2014-08-20 17:37:59 -07001206 if (written != (ssize_t)copy) {
1207 // A short count was received from AudioSink::write()
1208 //
Wei Jia7d3f4df2015-03-03 15:28:00 -08001209 // AudioSink write is called in non-blocking mode.
1210 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -07001211 //
Wei Jia03cee242016-05-26 15:22:59 -07001212 // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
1213 // discarded.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001214 // 2) The data to be copied exceeds the available buffer in AudioSink.
1215 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
1216 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -07001217
1218 // (Case 1)
1219 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
1220 // needs to fail, as we should not carry over fractional frames between calls.
Colin Cross0bdcf662017-04-27 16:15:51 -07001221 CHECK_EQ(copy % mAudioSink->frameSize(), 0u);
Andy Hunga31335a2014-08-20 17:37:59 -07001222
Wei Jia7d3f4df2015-03-03 15:28:00 -08001223 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -07001224 // Return early to the caller.
1225 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001226 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -07001227 break;
1228 }
1229 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001230
Andy Hung005e9d02015-05-31 23:16:07 -07001231 // calculate whether we need to reschedule another write.
1232 bool reschedule = !mAudioQueue.empty()
1233 && (!mPaused
1234 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1235 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1236 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1237 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001238}
1239
Wei Jia98160162015-02-04 17:01:11 -08001240int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1241 int32_t sampleRate = offloadingAudio() ?
1242 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001243 if (sampleRate == 0) {
1244 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1245 return 0;
1246 }
hyoungjun.byun2c2050c2019-01-31 12:11:38 +09001247
1248 return (int64_t)(numFrames * 1000000LL / sampleRate);
Wei Jia98160162015-02-04 17:01:11 -08001249}
1250
1251// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001252int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001253 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiad2f35de2016-02-17 16:48:06 -08001254 if (mUseVirtualAudioSink) {
1255 int64_t nowUs = ALooper::GetNowUs();
1256 int64_t mediaUs;
1257 if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001258 return 0LL;
Wei Jiad2f35de2016-02-17 16:48:06 -08001259 } else {
1260 return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1261 }
1262 }
Andy Hungffa36952017-08-17 10:41:51 -07001263
1264 const int64_t audioSinkPlayedUs = mAudioSink->getPlayedOutDurationUs(nowUs);
1265 int64_t pendingUs = writtenAudioDurationUs - audioSinkPlayedUs;
1266 if (pendingUs < 0) {
1267 // This shouldn't happen unless the timestamp is stale.
1268 ALOGW("%s: pendingUs %lld < 0, clamping to zero, potential resume after pause "
1269 "writtenAudioDurationUs: %lld, audioSinkPlayedUs: %lld",
1270 __func__, (long long)pendingUs,
1271 (long long)writtenAudioDurationUs, (long long)audioSinkPlayedUs);
1272 pendingUs = 0;
1273 }
1274 return pendingUs;
Ronghua Wu5095d702014-08-27 12:05:48 -07001275}
1276
Ronghua Wua73d9e02014-10-08 15:13:29 -07001277int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001278 int64_t realUs;
1279 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001280 // If failed to get current position, e.g. due to audio clock is
1281 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001282 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001283 }
Wei Jia98160162015-02-04 17:01:11 -08001284 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001285}
1286
Ronghua Wueecb7802014-10-19 23:12:50 -07001287void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001288 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001289 // TRICKY: vorbis decoder generates multiple frames with the same
1290 // timestamp, so only update on the first frame with a given timestamp
Ian Baker130bbc42023-08-09 18:19:50 +01001291 if (mediaTimeUs == mAudioAnchorTimeMediaUs) {
Ronghua Wueecb7802014-10-19 23:12:50 -07001292 return;
1293 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001294 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001295
Andy Hung528c8402016-01-12 12:39:34 -08001296 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1297 if (mNextAudioClockUpdateTimeUs == -1) {
1298 AudioTimestamp ts;
1299 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1300 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1301 }
1302 }
Wei Jia12b62652016-02-09 17:49:31 -08001303 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001304 if (mNextAudioClockUpdateTimeUs >= 0) {
1305 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1306 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1307 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001308 mUseVirtualAudioSink = false;
Andy Hung528c8402016-01-12 12:39:34 -08001309 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1310 }
Wei Jia12b62652016-02-09 17:49:31 -08001311 } else {
1312 int64_t unused;
1313 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1314 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1315 > kMaxAllowedAudioSinkDelayUs)) {
1316 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1317 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1318 // connected to audio out.
1319 // Switch to system clock. This essentially creates a virtual AudioSink with
1320 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1321 // This virtual AudioSink renders audio data starting from the very first sample
1322 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001323 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001324 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001325 mUseVirtualAudioSink = true;
Wei Jia12b62652016-02-09 17:49:31 -08001326 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001327 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001328 mAnchorNumFramesWritten = mNumFramesWritten;
Ian Baker130bbc42023-08-09 18:19:50 +01001329 mAudioAnchorTimeMediaUs = mediaTimeUs;
Wei Jia7b15cb32015-02-03 17:46:06 -08001330 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001331}
1332
Wei Jia7b15cb32015-02-03 17:46:06 -08001333// Called without mLock acquired.
1334void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001335 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001336 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001337 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001338 return;
1339 }
1340
1341 if (mVideoQueue.empty()) {
1342 return;
1343 }
1344
1345 QueueEntry &entry = *mVideoQueue.begin();
1346
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001347 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001348 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001349
Andreas Huberf9334412010-12-15 15:17:42 -08001350 if (entry.mBuffer == NULL) {
1351 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001352 msg->post();
1353 mDrainVideoQueuePending = true;
1354 return;
1355 }
1356
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001357 int64_t nowUs = ALooper::GetNowUs();
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001358 if (mFlags & FLAG_REAL_TIME) {
Wei Jia17648f32017-09-19 13:16:30 -07001359 int64_t realTimeUs;
1360 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &realTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001361
Wei Jia17648f32017-09-19 13:16:30 -07001362 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Lajos Molnard5923402014-10-20 17:47:54 -07001363
Wei Jia17648f32017-09-19 13:16:30 -07001364 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
Robert Shih00541e22015-12-18 17:04:00 -08001365
Wei Jia17648f32017-09-19 13:16:30 -07001366 int64_t delayUs = realTimeUs - nowUs;
1367
1368 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %lld", (long long)delayUs);
1369 // post 2 display refreshes before rendering is due
1370 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1371
1372 mDrainVideoQueuePending = true;
1373 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001374 }
1375
Wei Jia17648f32017-09-19 13:16:30 -07001376 int64_t mediaTimeUs;
1377 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001378
Wei Jia17648f32017-09-19 13:16:30 -07001379 {
1380 Mutex::Autolock autoLock(mLock);
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301381 if (mNeedVideoClearAnchor && !mHasAudio) {
1382 mNeedVideoClearAnchor = false;
1383 clearAnchorTime();
1384 }
Wei Jia17648f32017-09-19 13:16:30 -07001385 if (mAnchorTimeMediaUs < 0) {
1386 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1387 mAnchorTimeMediaUs = mediaTimeUs;
1388 }
1389 }
Wei Jia1225b932019-01-04 12:44:38 -08001390 mNextVideoTimeMediaUs = mediaTimeUs;
Wei Jia17648f32017-09-19 13:16:30 -07001391 if (!mHasAudio) {
1392 // smooth out videos >= 10fps
Wei Jiacc951512019-04-03 16:10:42 -07001393 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia17648f32017-09-19 13:16:30 -07001394 }
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001395
Wei Jia17648f32017-09-19 13:16:30 -07001396 if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
1397 msg->post();
1398 } else {
1399 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1400
1401 // post 2 display refreshes before rendering is due
1402 mMediaClock->addTimer(msg, mediaTimeUs, -twoVsyncsUs);
1403 }
Andreas Huberf9334412010-12-15 15:17:42 -08001404
1405 mDrainVideoQueuePending = true;
1406}
1407
1408void NuPlayer::Renderer::onDrainVideoQueue() {
1409 if (mVideoQueue.empty()) {
1410 return;
1411 }
1412
1413 QueueEntry *entry = &*mVideoQueue.begin();
1414
1415 if (entry->mBuffer == NULL) {
1416 // EOS
1417
Andreas Huberc92fd242011-08-16 13:48:44 -07001418 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001419
1420 mVideoQueue.erase(mVideoQueue.begin());
1421 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001422
Ronghua Wua73d9e02014-10-08 15:13:29 -07001423 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001424 return;
1425 }
1426
Wei Jia25d696f2015-11-19 10:57:15 -08001427 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001428 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001429 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001430 if (mFlags & FLAG_REAL_TIME) {
1431 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1432 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001433 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001434
Ronghua Wua73d9e02014-10-08 15:13:29 -07001435 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001436 }
Wei Jia17648f32017-09-19 13:16:30 -07001437 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Andreas Huberd5e56232013-03-12 11:01:43 -07001438
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001439 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001440
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001441 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001442 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001443 tooLate = (mVideoLateByUs > 40000);
1444
1445 if (tooLate) {
1446 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001447 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001448 } else {
Wei Jia98160162015-02-04 17:01:11 -08001449 int64_t mediaUs = 0;
1450 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001451 ALOGV("rendering video at media time %.2f secs",
1452 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001453 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001454
1455 if (!(mFlags & FLAG_REAL_TIME)
1456 && mLastAudioMediaTimeUs != -1
1457 && mediaTimeUs > mLastAudioMediaTimeUs) {
1458 // If audio ends before video, video continues to drive media clock.
1459 // Also smooth out videos >= 10fps.
Wei Jiacc951512019-04-03 16:10:42 -07001460 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001461 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001462 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001463 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001464 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001465 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001466 // This will ensure that the first frame after a flush won't be used as anchor
1467 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia9a3101b2016-11-08 14:34:24 -08001468 clearAnchorTime();
Wei Jia49966ff2014-10-08 18:44:45 -07001469 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001470 }
Andreas Huberf9334412010-12-15 15:17:42 -08001471
Wei Jia25d696f2015-11-19 10:57:15 -08001472 // Always render the first video frame while keeping stats on A/V sync.
1473 if (!mVideoSampleReceived) {
1474 realTimeUs = nowUs;
1475 tooLate = false;
1476 }
1477
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001478 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000LL);
Glenn Kasten683525b2011-11-04 18:05:35 -07001479 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001480 entry->mNotifyConsumed->post();
1481 mVideoQueue.erase(mVideoQueue.begin());
1482 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001483
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001484 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001485
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001486 if (!mPaused) {
1487 if (!mVideoRenderingStarted) {
1488 mVideoRenderingStarted = true;
1489 notifyVideoRenderingStart();
1490 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001491 Mutex::Autolock autoLock(mLock);
1492 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001493 }
Andreas Huberf9334412010-12-15 15:17:42 -08001494}
1495
James Dongf57b4ea2012-07-20 13:38:36 -07001496void NuPlayer::Renderer::notifyVideoRenderingStart() {
1497 sp<AMessage> notify = mNotify->dup();
1498 notify->setInt32("what", kWhatVideoRenderingStart);
1499 notify->post();
1500}
1501
Ronghua Wu5095d702014-08-27 12:05:48 -07001502void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jiad214a562017-07-10 13:20:55 -07001503 Mutex::Autolock autoLock(mLock);
1504 notifyEOS_l(audio, finalResult, delayUs);
1505}
1506
1507void NuPlayer::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001508 if (audio && delayUs > 0) {
1509 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1510 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1511 msg->setInt32("finalResult", finalResult);
1512 msg->post(delayUs);
1513 return;
1514 }
Andreas Huberf9334412010-12-15 15:17:42 -08001515 sp<AMessage> notify = mNotify->dup();
1516 notify->setInt32("what", kWhatEOS);
1517 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001518 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001519 notify->post(delayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001520
1521 if (audio) {
1522 // Video might outlive audio. Clear anchor to enable video only case.
1523 mAnchorTimeMediaUs = -1;
Wei Jiaaec8d822017-08-25 15:27:57 -07001524 mHasAudio = false;
Wei Jiadc293e32017-10-16 18:29:37 -07001525 if (mNextVideoTimeMediaUs >= 0) {
1526 int64_t mediaUs = 0;
Wei Jia1225b932019-01-04 12:44:38 -08001527 int64_t nowUs = ALooper::GetNowUs();
1528 status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
1529 if (result == OK) {
1530 if (mNextVideoTimeMediaUs > mediaUs) {
1531 mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
1532 }
1533 } else {
1534 mMediaClock->updateAnchor(
Wei Jiacc951512019-04-03 16:10:42 -07001535 mNextVideoTimeMediaUs, nowUs,
1536 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
Wei Jiadc293e32017-10-16 18:29:37 -07001537 }
1538 }
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301539 } else {
1540 mHasVideo = false;
Wei Jiad214a562017-07-10 13:20:55 -07001541 }
Andreas Huberf9334412010-12-15 15:17:42 -08001542}
1543
Wei Jiaa05f1e32016-03-25 16:31:22 -07001544void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1545 sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1546 msg->setInt32("reason", reason);
1547 msg->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001548}
1549
Andreas Huberf9334412010-12-15 15:17:42 -08001550void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1551 int32_t audio;
1552 CHECK(msg->findInt32("audio", &audio));
1553
Wei Jia7b15cb32015-02-03 17:46:06 -08001554 if (dropBufferIfStale(audio, msg)) {
1555 return;
1556 }
1557
1558 if (audio) {
1559 mHasAudio = true;
1560 } else {
1561 mHasVideo = true;
1562 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001563
1564 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001565 if (mVideoScheduler == NULL) {
1566 mVideoScheduler = new VideoFrameScheduler();
1567 mVideoScheduler->init();
1568 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001569 }
1570
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001571 sp<RefBase> obj;
1572 CHECK(msg->findObject("buffer", &obj));
1573 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
Andreas Huberf9334412010-12-15 15:17:42 -08001574
1575 sp<AMessage> notifyConsumed;
1576 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1577
1578 QueueEntry entry;
1579 entry.mBuffer = buffer;
1580 entry.mNotifyConsumed = notifyConsumed;
1581 entry.mOffset = 0;
1582 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001583 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001584
1585 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001586 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001587 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001588 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001589 } else {
1590 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001591 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001592 }
1593
Wei Jia7b15cb32015-02-03 17:46:06 -08001594 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001595 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1596 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001597 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001598
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001599 sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1600 sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
Andreas Hubercb67cd12011-08-26 16:02:19 -07001601
1602 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1603 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001604 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001605 return;
1606 }
1607
1608 int64_t firstAudioTimeUs;
1609 int64_t firstVideoTimeUs;
1610 CHECK(firstAudioBuffer->meta()
1611 ->findInt64("timeUs", &firstAudioTimeUs));
1612 CHECK(firstVideoBuffer->meta()
1613 ->findInt64("timeUs", &firstVideoTimeUs));
1614
1615 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1616
Steve Block3856b092011-10-20 11:56:00 +01001617 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001618
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001619 if (diff > 100000LL) {
Andreas Hubercb67cd12011-08-26 16:02:19 -07001620 // Audio data starts More than 0.1 secs before video.
1621 // Drop some audio.
1622
1623 (*mAudioQueue.begin()).mNotifyConsumed->post();
1624 mAudioQueue.erase(mAudioQueue.begin());
1625 return;
1626 }
1627
Wei Jiabc2fb722014-07-08 16:37:57 -07001628 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001629}
1630
Wei Jiabc2fb722014-07-08 16:37:57 -07001631void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001632 if (!mSyncQueues) {
1633 return;
1634 }
1635
1636 mSyncQueues = false;
1637
1638 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001639 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001640 }
1641
1642 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001643 mLock.unlock();
1644 postDrainVideoQueue();
1645 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001646 }
1647}
1648
1649void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1650 int32_t audio;
1651 CHECK(msg->findInt32("audio", &audio));
1652
Wei Jia7b15cb32015-02-03 17:46:06 -08001653 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001654 return;
1655 }
1656
1657 int32_t finalResult;
1658 CHECK(msg->findInt32("finalResult", &finalResult));
1659
1660 QueueEntry entry;
1661 entry.mOffset = 0;
1662 entry.mFinalResult = finalResult;
1663
1664 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001665 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001666 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001667 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001668 }
Andreas Huberf9334412010-12-15 15:17:42 -08001669 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001670 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001671 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001672 if (mVideoQueue.empty() && getSyncQueues()) {
1673 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001674 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001675 }
Andreas Huberf9334412010-12-15 15:17:42 -08001676 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001677 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001678 }
1679}
1680
1681void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001682 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001683 CHECK(msg->findInt32("audio", &audio));
1684
Wei Jia28a8a9f2014-08-18 11:29:50 -07001685 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001686 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001687 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001688 notifyComplete = mNotifyCompleteAudio;
1689 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001690 mLastAudioMediaTimeUs = -1;
Wei Jiacc951512019-04-03 16:10:42 -07001691
1692 mHasAudio = false;
1693 if (mNextVideoTimeMediaUs >= 0) {
1694 int64_t nowUs = ALooper::GetNowUs();
1695 mMediaClock->updateAnchor(
1696 mNextVideoTimeMediaUs, nowUs,
1697 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
1698 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001699 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001700 notifyComplete = mNotifyCompleteVideo;
1701 mNotifyCompleteVideo = false;
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301702 mHasVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001703 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001704
Wei Jia7b15cb32015-02-03 17:46:06 -08001705 // If we're currently syncing the queues, i.e. dropping audio while
1706 // aligning the first audio/video buffer times and only one of the
1707 // two queues has data, we may starve that queue by not requesting
1708 // more buffers from the decoder. If the other source then encounters
1709 // a discontinuity that leads to flushing, we'll never find the
1710 // corresponding discontinuity on the other queue.
1711 // Therefore we'll stop syncing the queues if at least one of them
1712 // is flushed.
1713 syncQueuesDone_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001714 }
Abdul Khalik Shaik32b396b2023-02-01 11:56:54 +05301715
1716 if (audio && mDrainVideoQueuePending) {
1717 // Audio should not clear anchor(MediaClock) directly, because video
1718 // postDrainVideoQueue sets msg kWhatDrainVideoQueue into MediaClock
1719 // timer, clear anchor without update immediately may block msg posting.
1720 // So, postpone clear action to video to ensure anchor can be updated
1721 // immediately after clear
1722 mNeedVideoClearAnchor = true;
1723 } else {
1724 clearAnchorTime();
1725 }
Andreas Huberf9334412010-12-15 15:17:42 -08001726
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001727 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001728 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001729 {
1730 Mutex::Autolock autoLock(mLock);
1731 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001732
Wei Jia7b15cb32015-02-03 17:46:06 -08001733 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001734 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001735 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001736
Andy Hunga0b39712015-05-31 22:40:49 -07001737 // the frame count will be reset after flush.
1738 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001739 }
Andreas Huberf9334412010-12-15 15:17:42 -08001740
Andreas Huberf9334412010-12-15 15:17:42 -08001741 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001742
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001743 mAudioSink->pause();
1744 mAudioSink->flush();
1745 if (!offloadingAudio()) {
Wei Jia9e7ed332015-05-01 16:35:43 -07001746 // Call stop() to signal to the AudioSink to completely fill the
1747 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001748 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001749 mAudioSink->stop();
Wei Jia9e7ed332015-05-01 16:35:43 -07001750 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001751 }
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001752 if (!mPaused) {
1753 mAudioSink->start();
1754 }
Andy Hung528c8402016-01-12 12:39:34 -08001755 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001756 } else {
1757 flushQueue(&mVideoQueue);
1758
Andreas Huberf9334412010-12-15 15:17:42 -08001759 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001760
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001761 if (mVideoScheduler != NULL) {
1762 mVideoScheduler->restart();
1763 }
1764
Wei Jia7b15cb32015-02-03 17:46:06 -08001765 Mutex::Autolock autoLock(mLock);
1766 ++mVideoDrainGeneration;
1767 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001768 }
1769
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001770 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001771
1772 if (notifyComplete) {
1773 notifyFlushComplete(audio);
1774 }
Andreas Huberf9334412010-12-15 15:17:42 -08001775}
1776
1777void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1778 while (!queue->empty()) {
1779 QueueEntry *entry = &*queue->begin();
1780
1781 if (entry->mBuffer != NULL) {
1782 entry->mNotifyConsumed->post();
Wei Jia9a3101b2016-11-08 14:34:24 -08001783 } else if (entry->mNotifyConsumed != nullptr) {
1784 // Is it needed to open audio sink now?
1785 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
Andreas Huberf9334412010-12-15 15:17:42 -08001786 }
1787
1788 queue->erase(queue->begin());
1789 entry = NULL;
1790 }
1791}
1792
1793void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1794 sp<AMessage> notify = mNotify->dup();
1795 notify->setInt32("what", kWhatFlushComplete);
1796 notify->setInt32("audio", static_cast<int32_t>(audio));
1797 notify->post();
1798}
1799
Wei Jia7b15cb32015-02-03 17:46:06 -08001800bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001801 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001802 int32_t queueGeneration;
1803 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001804
Wei Jia7b15cb32015-02-03 17:46:06 -08001805 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001806 return false;
1807 }
1808
1809 sp<AMessage> notifyConsumed;
1810 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1811 notifyConsumed->post();
1812 }
1813
1814 return true;
1815}
1816
Andreas Huber3831a062010-12-21 10:22:33 -08001817void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001818 if (offloadingAudio()) {
1819 return;
1820 }
Andreas Huber3831a062010-12-21 10:22:33 -08001821 CHECK(!mDrainAudioQueuePending);
1822 mNumFramesWritten = 0;
Wei Jia9a3101b2016-11-08 14:34:24 -08001823 mAnchorNumFramesWritten = -1;
Marco Nelissen4110c102012-03-29 09:31:28 -07001824 uint32_t written;
1825 if (mAudioSink->getFramesWritten(&written) == OK) {
1826 mNumFramesWritten = written;
1827 }
Andreas Huber3831a062010-12-21 10:22:33 -08001828}
1829
Wei Jiabc2fb722014-07-08 16:37:57 -07001830void NuPlayer::Renderer::onDisableOffloadAudio() {
1831 Mutex::Autolock autoLock(mLock);
1832 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001833 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001834 if (mAudioRenderingStartGeneration != -1) {
1835 prepareForMediaRenderingStart_l();
andysu36177952018-04-20 15:17:13 +08001836 // PauseTimeout is applied to offload mode only. Cancel pending timer.
1837 cancelAudioOffloadPauseTimeout();
Robert Shihe1d70192015-07-23 17:54:13 -07001838 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001839}
1840
Ronghua Wua10fd232014-11-06 16:15:20 -08001841void NuPlayer::Renderer::onEnableOffloadAudio() {
1842 Mutex::Autolock autoLock(mLock);
1843 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001844 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001845 if (mAudioRenderingStartGeneration != -1) {
1846 prepareForMediaRenderingStart_l();
1847 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001848}
1849
Andreas Huberb4082222011-01-20 15:23:04 -08001850void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001851 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001852 return;
1853 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001854
Eric Laurent8ca036a2022-07-01 16:42:48 +02001855 startAudioOffloadPauseTimeout();
1856
Wei Jia28a8a9f2014-08-18 11:29:50 -07001857 {
1858 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001859 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001860 ++mVideoDrainGeneration;
1861 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001862 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001863 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001864 }
1865
Andreas Huberb4082222011-01-20 15:23:04 -08001866 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001867 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001868
Andy Hung84200732015-12-03 14:41:06 -08001869 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1870 mAudioSink->pause();
Andreas Huberb4082222011-01-20 15:23:04 -08001871
Lajos Molnar6d339f12015-04-17 16:15:53 -07001872 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001873 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001874}
1875
1876void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001877 if (!mPaused) {
1878 return;
1879 }
Andreas Huberb4082222011-01-20 15:23:04 -08001880
Andy Hung84200732015-12-03 14:41:06 -08001881 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1882 cancelAudioOffloadPauseTimeout();
1883 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001884 status_t err = mAudioSink->start();
1885 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001886 ALOGE("cannot start AudioSink err %d", err);
Wei Jiaa05f1e32016-03-25 16:31:22 -07001887 notifyAudioTearDown(kDueToError);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001888 }
Andreas Huberb4082222011-01-20 15:23:04 -08001889 }
1890
Wei Jia7b15cb32015-02-03 17:46:06 -08001891 {
1892 Mutex::Autolock autoLock(mLock);
1893 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001894 // rendering started message may have been delayed if we were paused.
1895 if (mRenderingDataDelivered) {
1896 notifyIfMediaRenderingStarted_l();
1897 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001898 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001899 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001900 mAudioSink->setPlaybackRate(mPlaybackSettings);
1901 }
1902
Wei Jia98160162015-02-04 17:01:11 -08001903 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001904
Wei Jia7b15cb32015-02-03 17:46:06 -08001905 if (!mAudioQueue.empty()) {
1906 postDrainAudioQueue_l();
1907 }
Andreas Huberb4082222011-01-20 15:23:04 -08001908 }
1909
1910 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001911 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001912 }
1913}
1914
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001915void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1916 if (mVideoScheduler == NULL) {
1917 mVideoScheduler = new VideoFrameScheduler();
1918 }
1919 mVideoScheduler->init(fps);
1920}
1921
Wei Jia7b15cb32015-02-03 17:46:06 -08001922int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1923 Mutex::Autolock autoLock(mLock);
1924 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1925}
1926
1927int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1928 Mutex::Autolock autoLock(mLock);
1929 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1930}
1931
1932bool NuPlayer::Renderer::getSyncQueues() {
1933 Mutex::Autolock autoLock(mLock);
1934 return mSyncQueues;
1935}
1936
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001937void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1938 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001939 return;
1940 }
andysu36177952018-04-20 15:17:13 +08001941
1942 // TimeoutWhenPaused is only for offload mode.
1943 if (reason == kDueToTimeout && !offloadingAudio()) {
1944 return;
1945 }
1946
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001947 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001948
Ronghua Wua73d9e02014-10-08 15:13:29 -07001949 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001950 sp<AMessage> notify = mNotify->dup();
1951 if (getCurrentPosition(&currentPositionUs) == OK) {
1952 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001953 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001954
Wei Jia3a2956d2014-07-22 16:01:33 -07001955 mAudioSink->stop();
1956 mAudioSink->flush();
1957
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001958 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001959 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001960 notify->post();
1961}
1962
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001963void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1964 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001965 mWakeLock->acquire();
christosts9aacf192023-03-09 14:12:36 +00001966 mWakelockAcquireEvent.updateValues(uptimeMillis(),
1967 mAudioOffloadPauseTimeoutGeneration,
1968 mAudioOffloadPauseTimeoutGeneration);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001969 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001970 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001971 msg->post(kOffloadPauseMaxUs);
1972 }
1973}
1974
1975void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
Andy Hung21afe802016-04-21 14:52:05 -07001976 // We may have called startAudioOffloadPauseTimeout() without
1977 // the AudioSink open and with offloadingAudio enabled.
1978 //
1979 // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
1980 // we always release the wakelock and increment the pause timeout generation.
1981 //
1982 // Note: The acquired wakelock prevents the device from suspending
1983 // immediately after offload pause (in case a resume happens shortly thereafter).
1984 mWakeLock->release(true);
christosts9aacf192023-03-09 14:12:36 +00001985 mWakelockCancelEvent.updateValues(uptimeMillis(),
1986 mAudioOffloadPauseTimeoutGeneration,
1987 mAudioOffloadPauseTimeoutGeneration);
Andy Hung21afe802016-04-21 14:52:05 -07001988 ++mAudioOffloadPauseTimeoutGeneration;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001989}
1990
Andy Hung202bce12014-12-03 11:47:36 -08001991status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001992 const sp<AMessage> &format,
1993 bool offloadOnly,
1994 bool hasVideo,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05301995 uint32_t flags,
1996 bool isStreaming) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001997 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1998 offloadOnly, offloadingAudio());
1999 bool audioSinkChanged = false;
2000
2001 int32_t numChannels;
2002 CHECK(format->findInt32("channel-count", &numChannels));
2003
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00002004 // channel mask info as read from the audio format
Andy Hungf0fef6c2022-08-29 20:07:43 -07002005 int32_t mediaFormatChannelMask;
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00002006 // channel mask to use for native playback
2007 audio_channel_mask_t channelMask;
Andy Hungf0fef6c2022-08-29 20:07:43 -07002008 if (format->findInt32("channel-mask", &mediaFormatChannelMask)) {
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00002009 // KEY_CHANNEL_MASK follows the android.media.AudioFormat java mask
Andy Hungf0fef6c2022-08-29 20:07:43 -07002010 channelMask = audio_channel_mask_from_media_format_mask(mediaFormatChannelMask);
Jean-Michel Trivib0451e52022-07-08 18:18:07 +00002011 } else {
2012 // no mask found: the mask will be derived from the channel count
2013 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
2014 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002015
2016 int32_t sampleRate;
2017 CHECK(format->findInt32("sample-rate", &sampleRate));
2018
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002019 // read pcm encoding from MediaCodec output format, if available
2020 int32_t pcmEncoding;
2021 audio_format_t audioFormat =
2022 format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
2023 audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
2024
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002025 if (offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002026 AString mime;
2027 CHECK(format->findString("mime", &mime));
2028 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
2029
2030 if (err != OK) {
2031 ALOGE("Couldn't map mime \"%s\" to a valid "
2032 "audio_format", mime.c_str());
2033 onDisableOffloadAudio();
2034 } else {
2035 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
2036 mime.c_str(), audioFormat);
2037
Ajender Reddy55a85792021-02-25 21:01:35 +05302038 int avgBitRate = 0;
Lajos Molnar46f80162016-05-19 15:35:47 -07002039 format->findInt32("bitrate", &avgBitRate);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002040
2041 int32_t aacProfile = -1;
2042 if (audioFormat == AUDIO_FORMAT_AAC
2043 && format->findInt32("aac-profile", &aacProfile)) {
2044 // Redefine AAC format as per aac profile
2045 mapAACProfileToAudioFormat(
2046 audioFormat,
2047 aacProfile);
2048 }
2049
2050 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
2051 offloadInfo.duration_us = -1;
2052 format->findInt64(
2053 "durationUs", &offloadInfo.duration_us);
2054 offloadInfo.sample_rate = sampleRate;
2055 offloadInfo.channel_mask = channelMask;
2056 offloadInfo.format = audioFormat;
2057 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
2058 offloadInfo.bit_rate = avgBitRate;
2059 offloadInfo.has_video = hasVideo;
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302060 offloadInfo.is_streaming = isStreaming;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002061
2062 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
2063 ALOGV("openAudioSink: no change in offload mode");
2064 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08002065 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002066 }
Andy Hungf0e83642014-12-19 17:55:56 -08002067 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
2068
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002069 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002070 uint32_t offloadFlags = flags;
2071 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
2072 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002073 audioSinkChanged = true;
2074 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07002075
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002076 err = mAudioSink->open(
2077 sampleRate,
2078 numChannels,
2079 (audio_channel_mask_t)channelMask,
2080 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002081 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002082 &NuPlayer::Renderer::AudioSinkCallback,
2083 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002084 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002085 &offloadInfo);
2086
2087 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002088 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
2089 }
2090
2091 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002092 // If the playback is offloaded to h/w, we pass
2093 // the HAL some metadata information.
2094 // We don't want to do this for PCM because it
2095 // will be going through the AudioFlinger mixer
2096 // before reaching the hardware.
2097 // TODO
2098 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07002099 if (!mPaused) { // for preview mode, don't start if paused
2100 err = mAudioSink->start();
2101 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002102 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
2103 }
2104 if (err != OK) {
2105 // Clean up, fall back to non offload mode.
2106 mAudioSink->close();
2107 onDisableOffloadAudio();
2108 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
2109 ALOGV("openAudioSink: offload failed");
Wei Jiaa05f1e32016-03-25 16:31:22 -07002110 if (offloadOnly) {
2111 notifyAudioTearDown(kForceNonOffload);
2112 }
Wei Jia3ab25452015-06-10 09:37:47 -07002113 } else {
2114 mUseAudioCallback = true; // offload mode transfers data through callback
2115 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002116 }
2117 }
2118 }
2119 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002120 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002121 uint32_t pcmFlags = flags;
2122 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08002123
2124 const PcmInfo info = {
2125 (audio_channel_mask_t)channelMask,
2126 (audio_output_flags_t)pcmFlags,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002127 audioFormat,
Andy Hungf0e83642014-12-19 17:55:56 -08002128 numChannels,
2129 sampleRate
2130 };
2131 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
2132 ALOGV("openAudioSink: no change in pcm mode");
2133 // no change from previous configuration, everything ok.
2134 return OK;
2135 }
2136
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002137 audioSinkChanged = true;
2138 mAudioSink->close();
2139 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07002140 // Note: It is possible to set up the callback, but not use it to send audio data.
2141 // This requires a fix in AudioSink to explicitly specify the transfer mode.
2142 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07002143 if (mUseAudioCallback) {
2144 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
2145 }
Andy Hung179652e2015-05-31 22:49:46 -07002146
2147 // Compute the desired buffer size.
2148 // For callback mode, the amount of time before wakeup is about half the buffer size.
2149 const uint32_t frameCount =
2150 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
2151
Ronghua Wu7665f582015-09-02 10:15:30 -07002152 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
2153 // AudioSink. We don't want this when there's video because it will cause a video seek to
2154 // the previous I frame. But we do want this when there's only audio because it will give
2155 // NuPlayer a chance to switch from non-offload mode to offload mode.
2156 // So we only set doNotReconnect when there's no video.
2157 const bool doNotReconnect = !hasVideo;
Andy Hungff874dc2016-04-11 16:49:09 -07002158
2159 // We should always be able to set our playback settings if the sink is closed.
2160 LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
2161 "onOpenAudioSink: can't set playback rate on closed sink");
Andy Hung202bce12014-12-03 11:47:36 -08002162 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002163 sampleRate,
2164 numChannels,
2165 (audio_channel_mask_t)channelMask,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002166 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002167 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07002168 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
2169 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002170 (audio_output_flags_t)pcmFlags,
2171 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07002172 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07002173 frameCount);
Andy Hung202bce12014-12-03 11:47:36 -08002174 if (err != OK) {
2175 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07002176 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08002177 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08002178 return err;
2179 }
Andy Hungf0e83642014-12-19 17:55:56 -08002180 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07002181 if (!mPaused) { // for preview mode, don't start if paused
2182 mAudioSink->start();
2183 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002184 }
2185 if (audioSinkChanged) {
2186 onAudioSinkChanged();
2187 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002188 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08002189 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002190}
2191
2192void NuPlayer::Renderer::onCloseAudioSink() {
2193 mAudioSink->close();
2194 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08002195 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002196}
2197
Wei Jia9a3101b2016-11-08 14:34:24 -08002198void NuPlayer::Renderer::onChangeAudioFormat(
2199 const sp<AMessage> &meta, const sp<AMessage> &notify) {
2200 sp<AMessage> format;
2201 CHECK(meta->findMessage("format", &format));
2202
2203 int32_t offloadOnly;
2204 CHECK(meta->findInt32("offload-only", &offloadOnly));
2205
2206 int32_t hasVideo;
2207 CHECK(meta->findInt32("has-video", &hasVideo));
2208
2209 uint32_t flags;
2210 CHECK(meta->findInt32("flags", (int32_t *)&flags));
2211
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302212 uint32_t isStreaming;
2213 CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
2214
2215 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -08002216
2217 if (err != OK) {
2218 notify->setInt32("err", err);
2219 }
2220 notify->post();
2221}
2222
christosts9aacf192023-03-09 14:12:36 +00002223void NuPlayer::Renderer::WakeLockEvent::dump(AString& logString) {
2224 logString.append("[");
2225 logString.append(mTimeMs);
2226 logString.append(",");
2227 logString.append(mEventTimeoutGeneration);
2228 logString.append(",");
2229 logString.append(mRendererTimeoutGeneration);
2230 logString.append("]");
2231}
2232
Andreas Huberf9334412010-12-15 15:17:42 -08002233} // namespace android