blob: cb050f9b50ec514e06b49e0410f017af37402742 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayerRenderer"
19#include <utils/Log.h>
20
Dongwon Kang3dced072017-10-09 08:55:22 -070021#include "AWakeLock.h"
Andreas Huberf9334412010-12-15 15:17:42 -080022#include "NuPlayerRenderer.h"
Andy Hungf2c87b32016-04-07 19:49:29 -070023#include <algorithm>
Andy Hunga0b39712015-05-31 22:40:49 -070024#include <cutils/properties.h>
Andreas Huberf9334412010-12-15 15:17:42 -080025#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080026#include <media/stagefright/foundation/AMessage.h>
Ronghua Wua73d9e02014-10-08 15:13:29 -070027#include <media/stagefright/foundation/AUtils.h>
Wei Jia5833b6a2015-03-09 17:01:47 -070028#include <media/stagefright/MediaClock.h>
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -070029#include <media/stagefright/MediaCodecConstants.h>
30#include <media/stagefright/MediaDefs.h>
Wei Jiabc2fb722014-07-08 16:37:57 -070031#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MetaData.h>
Chong Zhang3b9eb1f2014-10-15 17:05:08 -070033#include <media/stagefright/Utils.h>
Lajos Molnara3725d72015-07-01 16:47:22 -070034#include <media/stagefright/VideoFrameScheduler.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090035#include <media/MediaCodecBuffer.h>
Wonsik Kimee8116b2019-07-19 15:55:44 -070036#include <utils/SystemClock.h>
Lajos Molnardc43dfa2014-05-07 15:33:04 -070037
Lajos Molnar09524832014-07-17 14:29:51 -070038#include <inttypes.h>
39
Andreas Huberf9334412010-12-15 15:17:42 -080040namespace android {
41
Andy Hunga0b39712015-05-31 22:40:49 -070042/*
43 * Example of common configuration settings in shell script form
44
45 #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
46 adb shell setprop audio.offload.disable 1
47
48 #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
49 adb shell setprop audio.offload.video 1
50
51 #Use audio callbacks for PCM data
52 adb shell setprop media.stagefright.audio.cbk 1
53
Andy Hung288da022015-05-31 22:55:59 -070054 #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
55 adb shell setprop media.stagefright.audio.deep 1
56
Andy Hung179652e2015-05-31 22:49:46 -070057 #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
58 adb shell setprop media.stagefright.audio.sink 1000
59
Andy Hunga0b39712015-05-31 22:40:49 -070060 * These configurations take effect for the next track played (not the current track).
61 */
62
63static inline bool getUseAudioCallbackSetting() {
64 return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
65}
66
Andy Hung179652e2015-05-31 22:49:46 -070067static inline int32_t getAudioSinkPcmMsSetting() {
68 return property_get_int32(
69 "media.stagefright.audio.sink", 500 /* default_value */);
70}
71
Ronghua Wuf5b1db12014-09-09 10:11:08 -070072// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
73// is closed to allow the audio DSP to power down.
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -080074static const int64_t kOffloadPauseMaxUs = 10000000LL;
Ronghua Wuf5b1db12014-09-09 10:11:08 -070075
Eric Laurent7fb51272022-07-01 16:42:48 +020076// Additional delay after teardown before releasing the wake lock to allow time for the audio path
77// to be completely released
78static const int64_t kWakelockReleaseDelayUs = 2000000LL;
79
Wei Jia12b62652016-02-09 17:49:31 -080080// Maximum allowed delay from AudioSink, 1.5 seconds.
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -080081static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000LL;
Wei Jia12b62652016-02-09 17:49:31 -080082
Andy Hung528c8402016-01-12 12:39:34 -080083static const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
84
Wei Jiacc951512019-04-03 16:10:42 -070085// Default video frame display duration when only video exists.
86// Used to set max media time in MediaClock.
87static const int64_t kDefaultVideoFrameIntervalUs = 100000LL;
88
Andreas Huber714aa7b2011-09-13 08:28:38 -070089// static
Andy Hungf0e83642014-12-19 17:55:56 -080090const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
91 AUDIO_CHANNEL_NONE,
92 AUDIO_OUTPUT_FLAG_NONE,
93 AUDIO_FORMAT_INVALID,
94 0, // mNumChannels
95 0 // mSampleRate
96};
97
98// static
Andreas Huber714aa7b2011-09-13 08:28:38 -070099const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
100
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -0700101static audio_format_t constexpr audioFormatFromEncoding(int32_t pcmEncoding) {
102 switch (pcmEncoding) {
103 case kAudioEncodingPcmFloat:
104 return AUDIO_FORMAT_PCM_FLOAT;
105 case kAudioEncodingPcm16bit:
106 return AUDIO_FORMAT_PCM_16_BIT;
107 case kAudioEncodingPcm8bit:
108 return AUDIO_FORMAT_PCM_8_BIT; // TODO: do we want to support this?
109 default:
110 ALOGE("%s: Invalid encoding: %d", __func__, pcmEncoding);
111 return AUDIO_FORMAT_INVALID;
112 }
113}
114
Andreas Huberf9334412010-12-15 15:17:42 -0800115NuPlayer::Renderer::Renderer(
116 const sp<MediaPlayerBase::AudioSink> &sink,
Wei Jia0a68f662017-08-30 18:01:26 -0700117 const sp<MediaClock> &mediaClock,
Andreas Huberd5e56232013-03-12 11:01:43 -0700118 const sp<AMessage> &notify,
119 uint32_t flags)
Andreas Huberf9334412010-12-15 15:17:42 -0800120 : mAudioSink(sink),
Wei Jiad2f35de2016-02-17 16:48:06 -0800121 mUseVirtualAudioSink(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800122 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -0700123 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -0800124 mNumFramesWritten(0),
125 mDrainAudioQueuePending(false),
126 mDrainVideoQueuePending(false),
127 mAudioQueueGeneration(0),
128 mVideoQueueGeneration(0),
Wei Jia7b15cb32015-02-03 17:46:06 -0800129 mAudioDrainGeneration(0),
130 mVideoDrainGeneration(0),
Wei Jia7c8d0e02015-08-27 17:40:21 -0700131 mAudioEOSGeneration(0),
Wei Jia0a68f662017-08-30 18:01:26 -0700132 mMediaClock(mediaClock),
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700133 mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
Ronghua Wua73d9e02014-10-08 15:13:29 -0700134 mAudioFirstAnchorTimeMediaUs(-1),
Ronghua Wueecb7802014-10-19 23:12:50 -0700135 mAnchorTimeMediaUs(-1),
Lajos Molnarf5926712014-10-21 09:36:43 -0700136 mAnchorNumFramesWritten(-1),
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800137 mVideoLateByUs(0LL),
Wei Jiadc293e32017-10-16 18:29:37 -0700138 mNextVideoTimeMediaUs(-1),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800139 mHasAudio(false),
140 mHasVideo(false),
Chong Zhang7137ec72014-11-12 16:41:05 -0800141 mNotifyCompleteAudio(false),
142 mNotifyCompleteVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800143 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -0700144 mPaused(false),
Andy Hungb03dcb32015-08-27 16:18:59 -0700145 mPauseDrainAudioAllowedUs(0),
Andy Hung09e0c362014-09-12 15:12:16 -0700146 mVideoSampleReceived(false),
James Dongf57b4ea2012-07-20 13:38:36 -0700147 mVideoRenderingStarted(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700148 mVideoRenderingStartGeneration(0),
149 mAudioRenderingStartGeneration(0),
Andy Hungb12ea0b2015-09-03 15:13:01 -0700150 mRenderingDataDelivered(false),
Andy Hung528c8402016-01-12 12:39:34 -0800151 mNextAudioClockUpdateTimeUs(-1),
Wei Jia2995dc72015-07-24 16:00:33 -0700152 mLastAudioMediaTimeUs(-1),
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700153 mAudioOffloadPauseTimeoutGeneration(0),
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700154 mAudioTornDown(false),
Lajos Molnard5923402014-10-20 17:47:54 -0700155 mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
Andy Hungf0e83642014-12-19 17:55:56 -0800156 mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
Lajos Molnard5923402014-10-20 17:47:54 -0700157 mTotalBuffersQueued(0),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800158 mLastAudioBufferDrained(0),
Andy Hunga0b39712015-05-31 22:40:49 -0700159 mUseAudioCallback(false),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800160 mWakeLock(new AWakeLock()) {
Wei Jia0a68f662017-08-30 18:01:26 -0700161 CHECK(mediaClock != NULL);
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700162 mPlaybackRate = mPlaybackSettings.mSpeed;
163 mMediaClock->setPlaybackRate(mPlaybackRate);
Wonsik Kimee8116b2019-07-19 15:55:44 -0700164 (void)mSyncFlag.test_and_set();
Andreas Huberf9334412010-12-15 15:17:42 -0800165}
166
167NuPlayer::Renderer::~Renderer() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700168 if (offloadingAudio()) {
169 mAudioSink->stop();
170 mAudioSink->flush();
171 mAudioSink->close();
172 }
Wei Jia4c74fde2016-08-26 16:00:52 -0700173
174 // Try to avoid racing condition in case callback is still on.
175 Mutex::Autolock autoLock(mLock);
Wei Jia9a3101b2016-11-08 14:34:24 -0800176 if (mUseAudioCallback) {
177 flushQueue(&mAudioQueue);
178 flushQueue(&mVideoQueue);
179 }
Wei Jia4c74fde2016-08-26 16:00:52 -0700180 mWakeLock.clear();
Wei Jia4c74fde2016-08-26 16:00:52 -0700181 mVideoScheduler.clear();
182 mNotify.clear();
183 mAudioSink.clear();
Andreas Huberf9334412010-12-15 15:17:42 -0800184}
185
186void NuPlayer::Renderer::queueBuffer(
187 bool audio,
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900188 const sp<MediaCodecBuffer> &buffer,
Andreas Huberf9334412010-12-15 15:17:42 -0800189 const sp<AMessage> &notifyConsumed) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800190 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800191 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800192 msg->setInt32("audio", static_cast<int32_t>(audio));
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900193 msg->setObject("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -0800194 msg->setMessage("notifyConsumed", notifyConsumed);
195 msg->post();
196}
197
198void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
199 CHECK_NE(finalResult, (status_t)OK);
200
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800201 sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800202 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800203 msg->setInt32("audio", static_cast<int32_t>(audio));
204 msg->setInt32("finalResult", finalResult);
205 msg->post();
206}
207
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700208status_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
209 sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
210 writeToAMessage(msg, rate);
211 sp<AMessage> response;
212 status_t err = msg->postAndAwaitResponse(&response);
213 if (err == OK && response != NULL) {
214 CHECK(response->findInt32("err", &err));
215 }
216 return err;
217}
218
219status_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
220 if (rate.mSpeed == 0.f) {
221 onPause();
222 // don't call audiosink's setPlaybackRate if pausing, as pitch does not
223 // have to correspond to the any non-0 speed (e.g old speed). Keep
224 // settings nonetheless, using the old speed, in case audiosink changes.
225 AudioPlaybackRate newRate = rate;
226 newRate.mSpeed = mPlaybackSettings.mSpeed;
227 mPlaybackSettings = newRate;
228 return OK;
229 }
230
Wei Jia27ea08e2015-05-12 14:50:35 -0700231 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700232 status_t err = mAudioSink->setPlaybackRate(rate);
233 if (err != OK) {
234 return err;
235 }
236 }
237 mPlaybackSettings = rate;
238 mPlaybackRate = rate.mSpeed;
239 mMediaClock->setPlaybackRate(mPlaybackRate);
240 return OK;
241}
242
243status_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
244 sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
245 sp<AMessage> response;
246 status_t err = msg->postAndAwaitResponse(&response);
247 if (err == OK && response != NULL) {
248 CHECK(response->findInt32("err", &err));
249 if (err == OK) {
250 readFromAMessage(response, rate);
251 }
252 }
253 return err;
254}
255
256status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
Wei Jia27ea08e2015-05-12 14:50:35 -0700257 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700258 status_t err = mAudioSink->getPlaybackRate(rate);
259 if (err == OK) {
260 if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
261 ALOGW("correcting mismatch in internal/external playback rate");
262 }
263 // get playback settings used by audiosink, as it may be
264 // slightly off due to audiosink not taking small changes.
265 mPlaybackSettings = *rate;
266 if (mPaused) {
267 rate->mSpeed = 0.f;
268 }
269 }
270 return err;
271 }
272 *rate = mPlaybackSettings;
273 return OK;
274}
275
276status_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
277 sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
278 writeToAMessage(msg, sync, videoFpsHint);
279 sp<AMessage> response;
280 status_t err = msg->postAndAwaitResponse(&response);
281 if (err == OK && response != NULL) {
282 CHECK(response->findInt32("err", &err));
283 }
284 return err;
285}
286
287status_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
288 if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
289 return BAD_VALUE;
290 }
291 // TODO: support sync sources
292 return INVALID_OPERATION;
293}
294
295status_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
296 sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
297 sp<AMessage> response;
298 status_t err = msg->postAndAwaitResponse(&response);
299 if (err == OK && response != NULL) {
300 CHECK(response->findInt32("err", &err));
301 if (err == OK) {
302 readFromAMessage(response, sync, videoFps);
303 }
304 }
305 return err;
306}
307
308status_t NuPlayer::Renderer::onGetSyncSettings(
309 AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
310 *sync = mSyncSettings;
311 *videoFps = -1.f;
312 return OK;
Wei Jia98160162015-02-04 17:01:11 -0800313}
314
Chong Zhang7137ec72014-11-12 16:41:05 -0800315void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800316 {
Wei Jia7b15cb32015-02-03 17:46:06 -0800317 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800318 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800319 mNotifyCompleteAudio |= notifyComplete;
Wei Jia3b0cd262015-07-13 11:28:10 -0700320 clearAudioFirstAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800321 ++mAudioQueueGeneration;
322 ++mAudioDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800323 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -0800324 mNotifyCompleteVideo |= notifyComplete;
Wei Jia7b15cb32015-02-03 17:46:06 -0800325 ++mVideoQueueGeneration;
326 ++mVideoDrainGeneration;
Wei Jiacc951512019-04-03 16:10:42 -0700327 mNextVideoTimeMediaUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -0800328 }
Wei Jia7b15cb32015-02-03 17:46:06 -0800329
Wei Jia9a3101b2016-11-08 14:34:24 -0800330 mMediaClock->clearAnchor();
Wei Jia7b15cb32015-02-03 17:46:06 -0800331 mVideoLateByUs = 0;
332 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800333 }
334
Wonsik Kimee8116b2019-07-19 15:55:44 -0700335 // Wait until the current job in the message queue is done, to make sure
336 // buffer processing from the old generation is finished. After the current
337 // job is finished, access to buffers are protected by generation.
338 Mutex::Autolock syncLock(mSyncLock);
339 int64_t syncCount = mSyncCount;
340 mSyncFlag.clear();
341
342 // Make sure message queue is not empty after mSyncFlag is cleared.
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800343 sp<AMessage> msg = new AMessage(kWhatFlush, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800344 msg->setInt32("audio", static_cast<int32_t>(audio));
345 msg->post();
Wonsik Kimee8116b2019-07-19 15:55:44 -0700346
347 int64_t uptimeMs = uptimeMillis();
348 while (mSyncCount == syncCount) {
349 (void)mSyncCondition.waitRelative(mSyncLock, ms2ns(1000));
350 if (uptimeMillis() - uptimeMs > 1000) {
351 ALOGW("flush(): no wake-up from sync point for 1s; stop waiting to "
352 "prevent being stuck indefinitely.");
353 break;
354 }
355 }
Andreas Huberf9334412010-12-15 15:17:42 -0800356}
357
358void NuPlayer::Renderer::signalTimeDiscontinuity() {
Wei Jia28a8a9f2014-08-18 11:29:50 -0700359}
360
361void NuPlayer::Renderer::signalDisableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800362 (new AMessage(kWhatDisableOffloadAudio, this))->post();
Wei Jia28a8a9f2014-08-18 11:29:50 -0700363}
364
Ronghua Wua10fd232014-11-06 16:15:20 -0800365void NuPlayer::Renderer::signalEnableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800366 (new AMessage(kWhatEnableOffloadAudio, this))->post();
Ronghua Wua10fd232014-11-06 16:15:20 -0800367}
368
Andreas Huberb4082222011-01-20 15:23:04 -0800369void NuPlayer::Renderer::pause() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800370 (new AMessage(kWhatPause, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800371}
372
373void NuPlayer::Renderer::resume() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800374 (new AMessage(kWhatResume, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800375}
376
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700377void NuPlayer::Renderer::setVideoFrameRate(float fps) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800378 sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700379 msg->setFloat("frame-rate", fps);
380 msg->post();
381}
382
Wei Jia4ecbea32015-10-20 18:09:57 -0700383// Called on any threads without mLock acquired.
Wei Jia7b15cb32015-02-03 17:46:06 -0800384status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
Wei Jia4ecbea32015-10-20 18:09:57 -0700385 status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
386 if (result == OK) {
387 return result;
388 }
389
390 // MediaClock has not started yet. Try to start it if possible.
391 {
392 Mutex::Autolock autoLock(mLock);
393 if (mAudioFirstAnchorTimeMediaUs == -1) {
394 return result;
395 }
396
397 AudioTimestamp ts;
398 status_t res = mAudioSink->getTimestamp(ts);
399 if (res != OK) {
400 return result;
401 }
402
403 // AudioSink has rendered some frames.
404 int64_t nowUs = ALooper::GetNowUs();
zengjingdb131352018-03-19 17:23:49 +0800405 int64_t playedOutDurationUs = mAudioSink->getPlayedOutDurationUs(nowUs);
406 if (playedOutDurationUs == 0) {
407 *mediaUs = mAudioFirstAnchorTimeMediaUs;
408 return OK;
409 }
410 int64_t nowMediaUs = playedOutDurationUs + mAudioFirstAnchorTimeMediaUs;
Wei Jia4ecbea32015-10-20 18:09:57 -0700411 mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
412 }
413
Wei Jia98160162015-02-04 17:01:11 -0800414 return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700415}
416
Wei Jia7b15cb32015-02-03 17:46:06 -0800417void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
418 mAudioFirstAnchorTimeMediaUs = -1;
419 mMediaClock->setStartingTimeMedia(-1);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700420}
421
Wei Jia7b15cb32015-02-03 17:46:06 -0800422void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700423 if (mAudioFirstAnchorTimeMediaUs == -1) {
424 mAudioFirstAnchorTimeMediaUs = mediaUs;
Wei Jia7b15cb32015-02-03 17:46:06 -0800425 mMediaClock->setStartingTimeMedia(mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700426 }
427}
428
Wei Jia9a3101b2016-11-08 14:34:24 -0800429// Called on renderer looper.
430void NuPlayer::Renderer::clearAnchorTime() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800431 mMediaClock->clearAnchor();
432 mAnchorTimeMediaUs = -1;
433 mAnchorNumFramesWritten = -1;
Ronghua Wua73d9e02014-10-08 15:13:29 -0700434}
435
436void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800437 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700438 mVideoLateByUs = lateUs;
439}
440
441int64_t NuPlayer::Renderer::getVideoLateByUs() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800442 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700443 return mVideoLateByUs;
444}
445
Andy Hung202bce12014-12-03 11:47:36 -0800446status_t NuPlayer::Renderer::openAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700447 const sp<AMessage> &format,
448 bool offloadOnly,
449 bool hasVideo,
Andy Hung202bce12014-12-03 11:47:36 -0800450 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530451 bool *isOffloaded,
452 bool isStreaming) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800453 sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700454 msg->setMessage("format", format);
455 msg->setInt32("offload-only", offloadOnly);
456 msg->setInt32("has-video", hasVideo);
457 msg->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530458 msg->setInt32("isStreaming", isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700459
460 sp<AMessage> response;
Leena Winterrowd66e4c4772015-09-10 15:41:08 -0700461 status_t postStatus = msg->postAndAwaitResponse(&response);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700462
Andy Hung202bce12014-12-03 11:47:36 -0800463 int32_t err;
Leena Winterrowd66e4c4772015-09-10 15:41:08 -0700464 if (postStatus != OK || response.get() == nullptr || !response->findInt32("err", &err)) {
Andy Hung202bce12014-12-03 11:47:36 -0800465 err = INVALID_OPERATION;
466 } else if (err == OK && isOffloaded != NULL) {
467 int32_t offload;
468 CHECK(response->findInt32("offload", &offload));
469 *isOffloaded = (offload != 0);
470 }
471 return err;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700472}
473
474void NuPlayer::Renderer::closeAudioSink() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800475 sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700476
477 sp<AMessage> response;
478 msg->postAndAwaitResponse(&response);
479}
480
Wei Jia9a3101b2016-11-08 14:34:24 -0800481void NuPlayer::Renderer::changeAudioFormat(
482 const sp<AMessage> &format,
483 bool offloadOnly,
484 bool hasVideo,
485 uint32_t flags,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530486 bool isStreaming,
Wei Jia9a3101b2016-11-08 14:34:24 -0800487 const sp<AMessage> &notify) {
488 sp<AMessage> meta = new AMessage;
489 meta->setMessage("format", format);
490 meta->setInt32("offload-only", offloadOnly);
491 meta->setInt32("has-video", hasVideo);
492 meta->setInt32("flags", flags);
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530493 meta->setInt32("isStreaming", isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -0800494
495 sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
496 msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
497 msg->setMessage("notify", notify);
498 msg->setMessage("meta", meta);
499 msg->post();
500}
501
Andreas Huberf9334412010-12-15 15:17:42 -0800502void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
503 switch (msg->what()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700504 case kWhatOpenAudioSink:
505 {
506 sp<AMessage> format;
507 CHECK(msg->findMessage("format", &format));
508
509 int32_t offloadOnly;
510 CHECK(msg->findInt32("offload-only", &offloadOnly));
511
512 int32_t hasVideo;
513 CHECK(msg->findInt32("has-video", &hasVideo));
514
515 uint32_t flags;
516 CHECK(msg->findInt32("flags", (int32_t *)&flags));
517
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +0530518 uint32_t isStreaming;
519 CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
520
521 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700522
523 sp<AMessage> response = new AMessage;
Andy Hung202bce12014-12-03 11:47:36 -0800524 response->setInt32("err", err);
525 response->setInt32("offload", offloadingAudio());
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700526
Lajos Molnar3f274362015-03-05 14:35:41 -0800527 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700528 CHECK(msg->senderAwaitsResponse(&replyID));
529 response->postReply(replyID);
530
531 break;
532 }
533
534 case kWhatCloseAudioSink:
535 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800536 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700537 CHECK(msg->senderAwaitsResponse(&replyID));
538
539 onCloseAudioSink();
540
541 sp<AMessage> response = new AMessage;
542 response->postReply(replyID);
543 break;
544 }
545
Wei Jiabc2fb722014-07-08 16:37:57 -0700546 case kWhatStopAudioSink:
547 {
548 mAudioSink->stop();
549 break;
550 }
551
Wei Jia9a3101b2016-11-08 14:34:24 -0800552 case kWhatChangeAudioFormat:
553 {
554 int32_t queueGeneration;
555 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
556
557 sp<AMessage> notify;
558 CHECK(msg->findMessage("notify", &notify));
559
560 if (offloadingAudio()) {
561 ALOGW("changeAudioFormat should NOT be called in offload mode");
562 notify->setInt32("err", INVALID_OPERATION);
563 notify->post();
564 break;
565 }
566
567 sp<AMessage> meta;
568 CHECK(msg->findMessage("meta", &meta));
569
570 if (queueGeneration != getQueueGeneration(true /* audio */)
571 || mAudioQueue.empty()) {
572 onChangeAudioFormat(meta, notify);
573 break;
574 }
575
576 QueueEntry entry;
577 entry.mNotifyConsumed = notify;
578 entry.mMeta = meta;
579
580 Mutex::Autolock autoLock(mLock);
581 mAudioQueue.push_back(entry);
582 postDrainAudioQueue_l();
583
584 break;
585 }
586
Andreas Huberf9334412010-12-15 15:17:42 -0800587 case kWhatDrainAudioQueue:
588 {
Wei Jia3ab25452015-06-10 09:37:47 -0700589 mDrainAudioQueuePending = false;
590
Andreas Huberf9334412010-12-15 15:17:42 -0800591 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800592 CHECK(msg->findInt32("drainGeneration", &generation));
593 if (generation != getDrainGeneration(true /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800594 break;
595 }
596
Andreas Huber078cfcf2011-09-15 12:25:04 -0700597 if (onDrainAudioQueue()) {
598 uint32_t numFramesPlayed;
599 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
600 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800601
Wei Jia1fb35b72017-09-25 16:08:13 -0700602 // Handle AudioTrack race when start is immediately called after flush.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700603 uint32_t numFramesPendingPlayout =
Wei Jia1fb35b72017-09-25 16:08:13 -0700604 (mNumFramesWritten > numFramesPlayed ?
605 mNumFramesWritten - numFramesPlayed : 0);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700606
607 // This is how long the audio sink will have data to
608 // play back.
609 int64_t delayUs =
610 mAudioSink->msecsPerFrame()
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800611 * numFramesPendingPlayout * 1000LL;
Wei Jiad9c2e9c2015-04-10 19:04:09 -0700612 if (mPlaybackRate > 1.0f) {
613 delayUs /= mPlaybackRate;
614 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700615
616 // Let's give it more data after about half that time
617 // has elapsed.
Andy Hungf2c87b32016-04-07 19:49:29 -0700618 delayUs /= 2;
619 // check the buffer size to estimate maximum delay permitted.
620 const int64_t maxDrainDelayUs = std::max(
621 mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
622 ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
623 (long long)delayUs, (long long)maxDrainDelayUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800624 Mutex::Autolock autoLock(mLock);
Andy Hungf2c87b32016-04-07 19:49:29 -0700625 postDrainAudioQueue_l(delayUs);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700626 }
Andreas Huberf9334412010-12-15 15:17:42 -0800627 break;
628 }
629
630 case kWhatDrainVideoQueue:
631 {
632 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800633 CHECK(msg->findInt32("drainGeneration", &generation));
634 if (generation != getDrainGeneration(false /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800635 break;
636 }
637
638 mDrainVideoQueuePending = false;
639
640 onDrainVideoQueue();
641
Wei Jia7b15cb32015-02-03 17:46:06 -0800642 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -0800643 break;
644 }
645
Lajos Molnard5923402014-10-20 17:47:54 -0700646 case kWhatPostDrainVideoQueue:
647 {
648 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800649 CHECK(msg->findInt32("drainGeneration", &generation));
650 if (generation != getDrainGeneration(false /* audio */)) {
Lajos Molnard5923402014-10-20 17:47:54 -0700651 break;
652 }
653
654 mDrainVideoQueuePending = false;
Wei Jia7b15cb32015-02-03 17:46:06 -0800655 postDrainVideoQueue();
Lajos Molnard5923402014-10-20 17:47:54 -0700656 break;
657 }
658
Andreas Huberf9334412010-12-15 15:17:42 -0800659 case kWhatQueueBuffer:
660 {
661 onQueueBuffer(msg);
662 break;
663 }
664
665 case kWhatQueueEOS:
666 {
667 onQueueEOS(msg);
668 break;
669 }
670
Wei Jia7c8d0e02015-08-27 17:40:21 -0700671 case kWhatEOS:
672 {
673 int32_t generation;
674 CHECK(msg->findInt32("audioEOSGeneration", &generation));
675 if (generation != mAudioEOSGeneration) {
676 break;
677 }
678 status_t finalResult;
679 CHECK(msg->findInt32("finalResult", &finalResult));
680 notifyEOS(true /* audio */, finalResult);
681 break;
682 }
683
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700684 case kWhatConfigPlayback:
Wei Jia98160162015-02-04 17:01:11 -0800685 {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700686 sp<AReplyToken> replyID;
687 CHECK(msg->senderAwaitsResponse(&replyID));
688 AudioPlaybackRate rate;
689 readFromAMessage(msg, &rate);
690 status_t err = onConfigPlayback(rate);
691 sp<AMessage> response = new AMessage;
692 response->setInt32("err", err);
693 response->postReply(replyID);
694 break;
695 }
696
697 case kWhatGetPlaybackSettings:
698 {
699 sp<AReplyToken> replyID;
700 CHECK(msg->senderAwaitsResponse(&replyID));
701 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
702 status_t err = onGetPlaybackSettings(&rate);
703 sp<AMessage> response = new AMessage;
704 if (err == OK) {
705 writeToAMessage(response, rate);
706 }
707 response->setInt32("err", err);
708 response->postReply(replyID);
709 break;
710 }
711
712 case kWhatConfigSync:
713 {
714 sp<AReplyToken> replyID;
715 CHECK(msg->senderAwaitsResponse(&replyID));
716 AVSyncSettings sync;
717 float videoFpsHint;
718 readFromAMessage(msg, &sync, &videoFpsHint);
719 status_t err = onConfigSync(sync, videoFpsHint);
720 sp<AMessage> response = new AMessage;
721 response->setInt32("err", err);
722 response->postReply(replyID);
723 break;
724 }
725
726 case kWhatGetSyncSettings:
727 {
728 sp<AReplyToken> replyID;
729 CHECK(msg->senderAwaitsResponse(&replyID));
730
731 ALOGV("kWhatGetSyncSettings");
732 AVSyncSettings sync;
733 float videoFps = -1.f;
734 status_t err = onGetSyncSettings(&sync, &videoFps);
735 sp<AMessage> response = new AMessage;
736 if (err == OK) {
737 writeToAMessage(response, sync, videoFps);
738 }
739 response->setInt32("err", err);
740 response->postReply(replyID);
Wei Jia98160162015-02-04 17:01:11 -0800741 break;
742 }
743
Andreas Huberf9334412010-12-15 15:17:42 -0800744 case kWhatFlush:
745 {
746 onFlush(msg);
747 break;
748 }
749
Wei Jiabc2fb722014-07-08 16:37:57 -0700750 case kWhatDisableOffloadAudio:
751 {
752 onDisableOffloadAudio();
753 break;
754 }
755
Ronghua Wua10fd232014-11-06 16:15:20 -0800756 case kWhatEnableOffloadAudio:
757 {
758 onEnableOffloadAudio();
759 break;
760 }
761
Andreas Huberb4082222011-01-20 15:23:04 -0800762 case kWhatPause:
763 {
764 onPause();
765 break;
766 }
767
768 case kWhatResume:
769 {
770 onResume();
771 break;
772 }
773
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700774 case kWhatSetVideoFrameRate:
775 {
776 float fps;
777 CHECK(msg->findFloat("frame-rate", &fps));
778 onSetVideoFrameRate(fps);
779 break;
780 }
781
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700782 case kWhatAudioTearDown:
Wei Jia3a2956d2014-07-22 16:01:33 -0700783 {
Wei Jiaa05f1e32016-03-25 16:31:22 -0700784 int32_t reason;
785 CHECK(msg->findInt32("reason", &reason));
786
787 onAudioTearDown((AudioTearDownReason)reason);
Wei Jia3a2956d2014-07-22 16:01:33 -0700788 break;
789 }
790
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700791 case kWhatAudioOffloadPauseTimeout:
792 {
793 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800794 CHECK(msg->findInt32("drainGeneration", &generation));
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700795 if (generation != mAudioOffloadPauseTimeoutGeneration) {
796 break;
797 }
Ronghua Wu08529172014-10-02 16:55:52 -0700798 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700799 onAudioTearDown(kDueToTimeout);
Eric Laurent7fb51272022-07-01 16:42:48 +0200800 sp<AMessage> newMsg = new AMessage(kWhatReleaseWakeLock, this);
801 newMsg->setInt32("drainGeneration", generation);
802 newMsg->post(kWakelockReleaseDelayUs);
803 break;
804 }
805
806 case kWhatReleaseWakeLock:
807 {
808 int32_t generation;
809 CHECK(msg->findInt32("drainGeneration", &generation));
810 if (generation != mAudioOffloadPauseTimeoutGeneration) {
811 break;
812 }
813 ALOGV("releasing audio offload pause wakelock.");
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800814 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700815 break;
816 }
817
Andreas Huberf9334412010-12-15 15:17:42 -0800818 default:
819 TRESPASS();
820 break;
821 }
Wonsik Kimee8116b2019-07-19 15:55:44 -0700822 if (!mSyncFlag.test_and_set()) {
823 Mutex::Autolock syncLock(mSyncLock);
824 ++mSyncCount;
825 mSyncCondition.broadcast();
826 }
Andreas Huberf9334412010-12-15 15:17:42 -0800827}
828
Wei Jiabc2fb722014-07-08 16:37:57 -0700829void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700830 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800831 return;
832 }
833
834 if (mAudioQueue.empty()) {
835 return;
836 }
837
Andy Hungb03dcb32015-08-27 16:18:59 -0700838 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
839 if (mPaused) {
840 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
841 if (diffUs > delayUs) {
842 delayUs = diffUs;
843 }
844 }
845
Andreas Huberf9334412010-12-15 15:17:42 -0800846 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800847 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800848 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700849 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800850}
851
Wei Jia7b15cb32015-02-03 17:46:06 -0800852void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
853 mAudioRenderingStartGeneration = mAudioDrainGeneration;
854 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700855 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700856}
857
Wei Jia7b15cb32015-02-03 17:46:06 -0800858void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
859 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
860 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700861 mRenderingDataDelivered = true;
862 if (mPaused) {
863 return;
864 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700865 mVideoRenderingStartGeneration = -1;
866 mAudioRenderingStartGeneration = -1;
867
868 sp<AMessage> notify = mNotify->dup();
869 notify->setInt32("what", kWhatMediaRenderingStart);
870 notify->post();
871 }
872}
873
Wei Jiabc2fb722014-07-08 16:37:57 -0700874// static
875size_t NuPlayer::Renderer::AudioSinkCallback(
876 MediaPlayerBase::AudioSink * /* audioSink */,
877 void *buffer,
878 size_t size,
879 void *cookie,
880 MediaPlayerBase::AudioSink::cb_event_t event) {
881 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
882
883 switch (event) {
884 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
885 {
886 return me->fillAudioBuffer(buffer, size);
887 break;
888 }
889
890 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
891 {
Andy Hunga0b39712015-05-31 22:40:49 -0700892 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jia4c74fde2016-08-26 16:00:52 -0700893 me->notifyEOSCallback();
Wei Jiabc2fb722014-07-08 16:37:57 -0700894 break;
895 }
896
897 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
898 {
Andy Hunga0b39712015-05-31 22:40:49 -0700899 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Wei Jiaa05f1e32016-03-25 16:31:22 -0700900 me->notifyAudioTearDown(kDueToError);
Wei Jiabc2fb722014-07-08 16:37:57 -0700901 break;
902 }
903 }
904
905 return 0;
906}
907
Wei Jia4c74fde2016-08-26 16:00:52 -0700908void NuPlayer::Renderer::notifyEOSCallback() {
909 Mutex::Autolock autoLock(mLock);
910
911 if (!mUseAudioCallback) {
912 return;
913 }
914
Wei Jiad214a562017-07-10 13:20:55 -0700915 notifyEOS_l(true /* audio */, ERROR_END_OF_STREAM);
Wei Jia4c74fde2016-08-26 16:00:52 -0700916}
917
Wei Jiabc2fb722014-07-08 16:37:57 -0700918size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
919 Mutex::Autolock autoLock(mLock);
920
Andy Hung85e48142015-05-31 23:04:15 -0700921 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700922 return 0;
923 }
924
925 bool hasEOS = false;
926
927 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700928 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700929 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700930 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700931 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700932
933 if (entry->mBuffer == NULL) { // EOS
934 hasEOS = true;
935 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700936 break;
937 }
938
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700939 if (firstEntry && entry->mOffset == 0) {
940 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700941 int64_t mediaTimeUs;
942 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Paras Nagda86dc6182020-10-27 13:01:47 +0530943 if (mediaTimeUs < 0) {
944 ALOGD("fillAudioBuffer: reset negative media time %.2f secs to zero",
945 mediaTimeUs / 1E6);
946 mediaTimeUs = 0;
947 }
Andy Hunga0b39712015-05-31 22:40:49 -0700948 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800949 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700950 }
951
952 size_t copy = entry->mBuffer->size() - entry->mOffset;
953 size_t sizeRemaining = size - sizeCopied;
954 if (copy > sizeRemaining) {
955 copy = sizeRemaining;
956 }
957
958 memcpy((char *)buffer + sizeCopied,
959 entry->mBuffer->data() + entry->mOffset,
960 copy);
961
962 entry->mOffset += copy;
963 if (entry->mOffset == entry->mBuffer->size()) {
964 entry->mNotifyConsumed->post();
965 mAudioQueue.erase(mAudioQueue.begin());
966 entry = NULL;
967 }
968 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -0800969
970 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -0700971 }
972
Lajos Molnarf5926712014-10-21 09:36:43 -0700973 if (mAudioFirstAnchorTimeMediaUs >= 0) {
974 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -0800975 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -0700976 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800977 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -0800978 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -0700979 }
980
Andy Hunga0b39712015-05-31 22:40:49 -0700981 // for non-offloaded audio, we need to compute the frames written because
982 // there is no EVENT_STREAM_END notification. The frames written gives
983 // an estimate on the pending played out duration.
984 if (!offloadingAudio()) {
985 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -0700986 }
987
Andy Hunga0b39712015-05-31 22:40:49 -0700988 if (hasEOS) {
989 (new AMessage(kWhatStopAudioSink, this))->post();
990 // As there is currently no EVENT_STREAM_END callback notification for
991 // non-offloaded audio tracks, we need to post the EOS ourselves.
992 if (!offloadingAudio()) {
993 int64_t postEOSDelayUs = 0;
994 if (mAudioSink->needsTrailingPadding()) {
995 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
996 }
Wei Jiad214a562017-07-10 13:20:55 -0700997 ALOGV("fillAudioBuffer: notifyEOS_l "
Andy Hunga0b39712015-05-31 22:40:49 -0700998 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
999 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001000 notifyEOS_l(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Andy Hunga0b39712015-05-31 22:40:49 -07001001 }
1002 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001003 return sizeCopied;
1004}
1005
Chong Zhang9da0ce42015-06-11 17:18:58 -07001006void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
1007 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
1008 bool foundEOS = false;
1009 while (it != mAudioQueue.end()) {
1010 int32_t eos;
1011 QueueEntry *entry = &*it++;
Wei Jia9a3101b2016-11-08 14:34:24 -08001012 if ((entry->mBuffer == nullptr && entry->mNotifyConsumed == nullptr)
Chong Zhang9da0ce42015-06-11 17:18:58 -07001013 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
1014 itEOS = it;
1015 foundEOS = true;
1016 }
1017 }
1018
1019 if (foundEOS) {
1020 // post all replies before EOS and drop the samples
1021 for (it = mAudioQueue.begin(); it != itEOS; it++) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001022 if (it->mBuffer == nullptr) {
1023 if (it->mNotifyConsumed == nullptr) {
1024 // delay doesn't matter as we don't even have an AudioTrack
1025 notifyEOS(true /* audio */, it->mFinalResult);
1026 } else {
1027 // TAG for re-opening audio sink.
1028 onChangeAudioFormat(it->mMeta, it->mNotifyConsumed);
1029 }
Chong Zhang9da0ce42015-06-11 17:18:58 -07001030 } else {
1031 it->mNotifyConsumed->post();
1032 }
1033 }
1034 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
1035 }
1036}
1037
Andreas Huber078cfcf2011-09-15 12:25:04 -07001038bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -07001039 // do not drain audio during teardown as queued buffers may be invalid.
1040 if (mAudioTornDown) {
1041 return false;
1042 }
Wei Jia230b1882015-03-19 15:13:51 -07001043 // TODO: This call to getPosition checks if AudioTrack has been created
1044 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
1045 // CHECKs on getPosition will fail.
1046 // We still need to figure out why AudioTrack is not created when
1047 // this function is called. One possible reason could be leftover
1048 // audio. Another possible place is to check whether decoder
1049 // has received INFO_FORMAT_CHANGED as the first buffer since
1050 // AudioSink is opened there, and possible interactions with flush
1051 // immediately after start. Investigate error message
1052 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -07001053 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -07001054 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -07001055 // When getPosition fails, renderer will not reschedule the draining
1056 // unless new samples are queued.
1057 // If we have pending EOS (or "eos" marker for discontinuities), we need
1058 // to post these now as NuPlayerDecoder might be waiting for it.
1059 drainAudioQueueUntilLastEOS();
1060
1061 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -07001062 return false;
1063 }
Andreas Huberc92fd242011-08-16 13:48:44 -07001064
Wei Jia230b1882015-03-19 15:13:51 -07001065#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -07001066 ssize_t numFramesAvailableToWrite =
1067 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
1068
Andreas Huber078cfcf2011-09-15 12:25:04 -07001069 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +00001070 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -07001071 } else {
Steve Block3856b092011-10-20 11:56:00 +01001072 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -07001073 mAudioSink->frameCount() - numFramesAvailableToWrite);
1074 }
1075#endif
1076
Andy Hung005e9d02015-05-31 23:16:07 -07001077 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -08001078 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -07001079 QueueEntry *entry = &*mAudioQueue.begin();
1080
1081 if (entry->mBuffer == NULL) {
Wei Jia9a3101b2016-11-08 14:34:24 -08001082 if (entry->mNotifyConsumed != nullptr) {
1083 // TAG for re-open audio sink.
1084 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
1085 mAudioQueue.erase(mAudioQueue.begin());
1086 continue;
1087 }
1088
Andreas Huberc92fd242011-08-16 13:48:44 -07001089 // EOS
Haynes Mathew George62d4e072016-06-13 11:23:22 -07001090 if (mPaused) {
1091 // Do not notify EOS when paused.
1092 // This is needed to avoid switch to next clip while in pause.
1093 ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
1094 return false;
1095 }
1096
Ronghua Wu5095d702014-08-27 12:05:48 -07001097 int64_t postEOSDelayUs = 0;
1098 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -07001099 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -07001100 }
1101 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001102 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -07001103
1104 mAudioQueue.erase(mAudioQueue.begin());
1105 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -08001106 if (mAudioSink->needsTrailingPadding()) {
1107 // If we're not in gapless playback (i.e. through setNextPlayer), we
1108 // need to stop the track here, because that will play out the last
1109 // little bit at the end of the file. Otherwise short files won't play.
1110 mAudioSink->stop();
1111 mNumFramesWritten = 0;
1112 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001113 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -07001114 }
1115
Wei Jia9a3101b2016-11-08 14:34:24 -08001116 mLastAudioBufferDrained = entry->mBufferOrdinal;
1117
Chong Zhang81636762015-04-21 09:33:47 -07001118 // ignore 0-sized buffer which could be EOS marker with no data
1119 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -08001120 int64_t mediaTimeUs;
1121 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -07001122 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
1123 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -07001124 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001125 }
1126
1127 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -08001128
Wei Jia7d3f4df2015-03-03 15:28:00 -08001129 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
1130 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -07001131 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -08001132 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001133 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -07001134 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001135 } else {
1136 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -07001137 // This can only happen when AudioSink was opened with doNotReconnect flag set to
1138 // true, in which case the NuPlayer will handle the reconnect.
Wei Jiaa05f1e32016-03-25 16:31:22 -07001139 notifyAudioTearDown(kDueToError);
Wei Jia7d3f4df2015-03-03 15:28:00 -08001140 }
Andy Hung202bce12014-12-03 11:47:36 -08001141 break;
Andy Hunga31335a2014-08-20 17:37:59 -07001142 }
Andreas Huberf9334412010-12-15 15:17:42 -08001143
Andy Hunga31335a2014-08-20 17:37:59 -07001144 entry->mOffset += written;
Wei Jia03cee242016-05-26 15:22:59 -07001145 size_t remainder = entry->mBuffer->size() - entry->mOffset;
1146 if ((ssize_t)remainder < mAudioSink->frameSize()) {
1147 if (remainder > 0) {
1148 ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
1149 remainder);
1150 entry->mOffset += remainder;
1151 copy -= remainder;
1152 }
1153
Andreas Huberf9334412010-12-15 15:17:42 -08001154 entry->mNotifyConsumed->post();
1155 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -07001156
Andreas Huberf9334412010-12-15 15:17:42 -08001157 entry = NULL;
1158 }
1159
Andy Hunga31335a2014-08-20 17:37:59 -07001160 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -07001161 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001162
Wei Jia7b15cb32015-02-03 17:46:06 -08001163 {
1164 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -07001165 int64_t maxTimeMedia;
1166 maxTimeMedia =
1167 mAnchorTimeMediaUs +
1168 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
1169 * 1000LL * mAudioSink->msecsPerFrame());
1170 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
1171
Wei Jia7b15cb32015-02-03 17:46:06 -08001172 notifyIfMediaRenderingStarted_l();
1173 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001174
Andy Hunga31335a2014-08-20 17:37:59 -07001175 if (written != (ssize_t)copy) {
1176 // A short count was received from AudioSink::write()
1177 //
Wei Jia7d3f4df2015-03-03 15:28:00 -08001178 // AudioSink write is called in non-blocking mode.
1179 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -07001180 //
Wei Jia03cee242016-05-26 15:22:59 -07001181 // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
1182 // discarded.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001183 // 2) The data to be copied exceeds the available buffer in AudioSink.
1184 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
1185 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -07001186
1187 // (Case 1)
1188 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
1189 // needs to fail, as we should not carry over fractional frames between calls.
Colin Cross0bdcf662017-04-27 16:15:51 -07001190 CHECK_EQ(copy % mAudioSink->frameSize(), 0u);
Andy Hunga31335a2014-08-20 17:37:59 -07001191
Wei Jia7d3f4df2015-03-03 15:28:00 -08001192 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -07001193 // Return early to the caller.
1194 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -08001195 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -07001196 break;
1197 }
1198 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001199
Andy Hung005e9d02015-05-31 23:16:07 -07001200 // calculate whether we need to reschedule another write.
1201 bool reschedule = !mAudioQueue.empty()
1202 && (!mPaused
1203 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1204 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1205 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1206 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001207}
1208
Wei Jia98160162015-02-04 17:01:11 -08001209int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1210 int32_t sampleRate = offloadingAudio() ?
1211 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001212 if (sampleRate == 0) {
1213 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1214 return 0;
1215 }
hyoungjun.byun2c2050c2019-01-31 12:11:38 +09001216
1217 return (int64_t)(numFrames * 1000000LL / sampleRate);
Wei Jia98160162015-02-04 17:01:11 -08001218}
1219
1220// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001221int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001222 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiad2f35de2016-02-17 16:48:06 -08001223 if (mUseVirtualAudioSink) {
1224 int64_t nowUs = ALooper::GetNowUs();
1225 int64_t mediaUs;
1226 if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001227 return 0LL;
Wei Jiad2f35de2016-02-17 16:48:06 -08001228 } else {
1229 return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1230 }
1231 }
Andy Hungffa36952017-08-17 10:41:51 -07001232
1233 const int64_t audioSinkPlayedUs = mAudioSink->getPlayedOutDurationUs(nowUs);
1234 int64_t pendingUs = writtenAudioDurationUs - audioSinkPlayedUs;
1235 if (pendingUs < 0) {
1236 // This shouldn't happen unless the timestamp is stale.
1237 ALOGW("%s: pendingUs %lld < 0, clamping to zero, potential resume after pause "
1238 "writtenAudioDurationUs: %lld, audioSinkPlayedUs: %lld",
1239 __func__, (long long)pendingUs,
1240 (long long)writtenAudioDurationUs, (long long)audioSinkPlayedUs);
1241 pendingUs = 0;
1242 }
1243 return pendingUs;
Ronghua Wu5095d702014-08-27 12:05:48 -07001244}
1245
Ronghua Wua73d9e02014-10-08 15:13:29 -07001246int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001247 int64_t realUs;
1248 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001249 // If failed to get current position, e.g. due to audio clock is
1250 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001251 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001252 }
Wei Jia98160162015-02-04 17:01:11 -08001253 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001254}
1255
Ronghua Wueecb7802014-10-19 23:12:50 -07001256void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001257 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001258 // TRICKY: vorbis decoder generates multiple frames with the same
1259 // timestamp, so only update on the first frame with a given timestamp
1260 if (mediaTimeUs == mAnchorTimeMediaUs) {
1261 return;
1262 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001263 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001264
Andy Hung528c8402016-01-12 12:39:34 -08001265 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1266 if (mNextAudioClockUpdateTimeUs == -1) {
1267 AudioTimestamp ts;
1268 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1269 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1270 }
1271 }
Wei Jia12b62652016-02-09 17:49:31 -08001272 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001273 if (mNextAudioClockUpdateTimeUs >= 0) {
1274 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1275 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1276 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001277 mUseVirtualAudioSink = false;
Andy Hung528c8402016-01-12 12:39:34 -08001278 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1279 }
Wei Jia12b62652016-02-09 17:49:31 -08001280 } else {
1281 int64_t unused;
1282 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1283 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1284 > kMaxAllowedAudioSinkDelayUs)) {
1285 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1286 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1287 // connected to audio out.
1288 // Switch to system clock. This essentially creates a virtual AudioSink with
1289 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1290 // This virtual AudioSink renders audio data starting from the very first sample
1291 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001292 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001293 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001294 mUseVirtualAudioSink = true;
Wei Jia12b62652016-02-09 17:49:31 -08001295 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001296 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001297 mAnchorNumFramesWritten = mNumFramesWritten;
Wei Jia7b15cb32015-02-03 17:46:06 -08001298 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001299}
1300
Wei Jia7b15cb32015-02-03 17:46:06 -08001301// Called without mLock acquired.
1302void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001303 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001304 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001305 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001306 return;
1307 }
1308
1309 if (mVideoQueue.empty()) {
1310 return;
1311 }
1312
1313 QueueEntry &entry = *mVideoQueue.begin();
1314
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001315 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001316 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001317
Andreas Huberf9334412010-12-15 15:17:42 -08001318 if (entry.mBuffer == NULL) {
1319 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001320 msg->post();
1321 mDrainVideoQueuePending = true;
1322 return;
1323 }
1324
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001325 int64_t nowUs = ALooper::GetNowUs();
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001326 if (mFlags & FLAG_REAL_TIME) {
Wei Jia17648f32017-09-19 13:16:30 -07001327 int64_t realTimeUs;
1328 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &realTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001329
Wei Jia17648f32017-09-19 13:16:30 -07001330 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Lajos Molnard5923402014-10-20 17:47:54 -07001331
Wei Jia17648f32017-09-19 13:16:30 -07001332 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
Robert Shih00541e22015-12-18 17:04:00 -08001333
Wei Jia17648f32017-09-19 13:16:30 -07001334 int64_t delayUs = realTimeUs - nowUs;
1335
1336 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %lld", (long long)delayUs);
1337 // post 2 display refreshes before rendering is due
1338 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1339
1340 mDrainVideoQueuePending = true;
1341 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001342 }
1343
Wei Jia17648f32017-09-19 13:16:30 -07001344 int64_t mediaTimeUs;
1345 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001346
Wei Jia17648f32017-09-19 13:16:30 -07001347 {
1348 Mutex::Autolock autoLock(mLock);
1349 if (mAnchorTimeMediaUs < 0) {
1350 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1351 mAnchorTimeMediaUs = mediaTimeUs;
1352 }
1353 }
Wei Jia1225b932019-01-04 12:44:38 -08001354 mNextVideoTimeMediaUs = mediaTimeUs;
Wei Jia17648f32017-09-19 13:16:30 -07001355 if (!mHasAudio) {
1356 // smooth out videos >= 10fps
Wei Jiacc951512019-04-03 16:10:42 -07001357 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia17648f32017-09-19 13:16:30 -07001358 }
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001359
Wei Jia17648f32017-09-19 13:16:30 -07001360 if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
1361 msg->post();
1362 } else {
1363 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1364
1365 // post 2 display refreshes before rendering is due
1366 mMediaClock->addTimer(msg, mediaTimeUs, -twoVsyncsUs);
1367 }
Andreas Huberf9334412010-12-15 15:17:42 -08001368
1369 mDrainVideoQueuePending = true;
1370}
1371
1372void NuPlayer::Renderer::onDrainVideoQueue() {
1373 if (mVideoQueue.empty()) {
1374 return;
1375 }
1376
1377 QueueEntry *entry = &*mVideoQueue.begin();
1378
1379 if (entry->mBuffer == NULL) {
1380 // EOS
1381
Andreas Huberc92fd242011-08-16 13:48:44 -07001382 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001383
1384 mVideoQueue.erase(mVideoQueue.begin());
1385 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001386
Ronghua Wua73d9e02014-10-08 15:13:29 -07001387 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001388 return;
1389 }
1390
Wei Jia25d696f2015-11-19 10:57:15 -08001391 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001392 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001393 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001394 if (mFlags & FLAG_REAL_TIME) {
1395 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1396 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001397 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001398
Ronghua Wua73d9e02014-10-08 15:13:29 -07001399 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001400 }
Wei Jia17648f32017-09-19 13:16:30 -07001401 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
Andreas Huberd5e56232013-03-12 11:01:43 -07001402
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001403 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001404
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001405 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001406 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001407 tooLate = (mVideoLateByUs > 40000);
1408
1409 if (tooLate) {
1410 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001411 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001412 } else {
Wei Jia98160162015-02-04 17:01:11 -08001413 int64_t mediaUs = 0;
1414 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001415 ALOGV("rendering video at media time %.2f secs",
1416 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001417 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001418
1419 if (!(mFlags & FLAG_REAL_TIME)
1420 && mLastAudioMediaTimeUs != -1
1421 && mediaTimeUs > mLastAudioMediaTimeUs) {
1422 // If audio ends before video, video continues to drive media clock.
1423 // Also smooth out videos >= 10fps.
Wei Jiacc951512019-04-03 16:10:42 -07001424 mMediaClock->updateMaxTimeMedia(mediaTimeUs + kDefaultVideoFrameIntervalUs);
Wei Jia2995dc72015-07-24 16:00:33 -07001425 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001426 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001427 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001428 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001429 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001430 // This will ensure that the first frame after a flush won't be used as anchor
1431 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia9a3101b2016-11-08 14:34:24 -08001432 clearAnchorTime();
Wei Jia49966ff2014-10-08 18:44:45 -07001433 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001434 }
Andreas Huberf9334412010-12-15 15:17:42 -08001435
Wei Jia25d696f2015-11-19 10:57:15 -08001436 // Always render the first video frame while keeping stats on A/V sync.
1437 if (!mVideoSampleReceived) {
1438 realTimeUs = nowUs;
1439 tooLate = false;
1440 }
1441
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001442 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000LL);
Glenn Kasten683525b2011-11-04 18:05:35 -07001443 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001444 entry->mNotifyConsumed->post();
1445 mVideoQueue.erase(mVideoQueue.begin());
1446 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001447
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001448 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001449
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001450 if (!mPaused) {
1451 if (!mVideoRenderingStarted) {
1452 mVideoRenderingStarted = true;
1453 notifyVideoRenderingStart();
1454 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001455 Mutex::Autolock autoLock(mLock);
1456 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001457 }
Andreas Huberf9334412010-12-15 15:17:42 -08001458}
1459
James Dongf57b4ea2012-07-20 13:38:36 -07001460void NuPlayer::Renderer::notifyVideoRenderingStart() {
1461 sp<AMessage> notify = mNotify->dup();
1462 notify->setInt32("what", kWhatVideoRenderingStart);
1463 notify->post();
1464}
1465
Ronghua Wu5095d702014-08-27 12:05:48 -07001466void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jiad214a562017-07-10 13:20:55 -07001467 Mutex::Autolock autoLock(mLock);
1468 notifyEOS_l(audio, finalResult, delayUs);
1469}
1470
1471void NuPlayer::Renderer::notifyEOS_l(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001472 if (audio && delayUs > 0) {
1473 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1474 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1475 msg->setInt32("finalResult", finalResult);
1476 msg->post(delayUs);
1477 return;
1478 }
Andreas Huberf9334412010-12-15 15:17:42 -08001479 sp<AMessage> notify = mNotify->dup();
1480 notify->setInt32("what", kWhatEOS);
1481 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001482 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001483 notify->post(delayUs);
Wei Jiad214a562017-07-10 13:20:55 -07001484
1485 if (audio) {
1486 // Video might outlive audio. Clear anchor to enable video only case.
1487 mAnchorTimeMediaUs = -1;
Wei Jiaaec8d822017-08-25 15:27:57 -07001488 mHasAudio = false;
Wei Jiadc293e32017-10-16 18:29:37 -07001489 if (mNextVideoTimeMediaUs >= 0) {
1490 int64_t mediaUs = 0;
Wei Jia1225b932019-01-04 12:44:38 -08001491 int64_t nowUs = ALooper::GetNowUs();
1492 status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
1493 if (result == OK) {
1494 if (mNextVideoTimeMediaUs > mediaUs) {
1495 mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
1496 }
1497 } else {
1498 mMediaClock->updateAnchor(
Wei Jiacc951512019-04-03 16:10:42 -07001499 mNextVideoTimeMediaUs, nowUs,
1500 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
Wei Jiadc293e32017-10-16 18:29:37 -07001501 }
1502 }
Wei Jiad214a562017-07-10 13:20:55 -07001503 }
Andreas Huberf9334412010-12-15 15:17:42 -08001504}
1505
Wei Jiaa05f1e32016-03-25 16:31:22 -07001506void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1507 sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1508 msg->setInt32("reason", reason);
1509 msg->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001510}
1511
Andreas Huberf9334412010-12-15 15:17:42 -08001512void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1513 int32_t audio;
1514 CHECK(msg->findInt32("audio", &audio));
1515
Wei Jia7b15cb32015-02-03 17:46:06 -08001516 if (dropBufferIfStale(audio, msg)) {
1517 return;
1518 }
1519
1520 if (audio) {
1521 mHasAudio = true;
1522 } else {
1523 mHasVideo = true;
1524 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001525
1526 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001527 if (mVideoScheduler == NULL) {
1528 mVideoScheduler = new VideoFrameScheduler();
1529 mVideoScheduler->init();
1530 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001531 }
1532
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001533 sp<RefBase> obj;
1534 CHECK(msg->findObject("buffer", &obj));
1535 sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
Andreas Huberf9334412010-12-15 15:17:42 -08001536
1537 sp<AMessage> notifyConsumed;
1538 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1539
1540 QueueEntry entry;
1541 entry.mBuffer = buffer;
1542 entry.mNotifyConsumed = notifyConsumed;
1543 entry.mOffset = 0;
1544 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001545 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001546
1547 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001548 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001549 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001550 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001551 } else {
1552 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001553 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001554 }
1555
Wei Jia7b15cb32015-02-03 17:46:06 -08001556 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001557 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1558 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001559 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001560
Wonsik Kim7e34bf52016-08-23 00:09:18 +09001561 sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1562 sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
Andreas Hubercb67cd12011-08-26 16:02:19 -07001563
1564 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1565 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001566 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001567 return;
1568 }
1569
1570 int64_t firstAudioTimeUs;
1571 int64_t firstVideoTimeUs;
1572 CHECK(firstAudioBuffer->meta()
1573 ->findInt64("timeUs", &firstAudioTimeUs));
1574 CHECK(firstVideoBuffer->meta()
1575 ->findInt64("timeUs", &firstVideoTimeUs));
1576
1577 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1578
Steve Block3856b092011-10-20 11:56:00 +01001579 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001580
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -08001581 if (diff > 100000LL) {
Andreas Hubercb67cd12011-08-26 16:02:19 -07001582 // Audio data starts More than 0.1 secs before video.
1583 // Drop some audio.
1584
1585 (*mAudioQueue.begin()).mNotifyConsumed->post();
1586 mAudioQueue.erase(mAudioQueue.begin());
1587 return;
1588 }
1589
Wei Jiabc2fb722014-07-08 16:37:57 -07001590 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001591}
1592
Wei Jiabc2fb722014-07-08 16:37:57 -07001593void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001594 if (!mSyncQueues) {
1595 return;
1596 }
1597
1598 mSyncQueues = false;
1599
1600 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001601 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001602 }
1603
1604 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001605 mLock.unlock();
1606 postDrainVideoQueue();
1607 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001608 }
1609}
1610
1611void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1612 int32_t audio;
1613 CHECK(msg->findInt32("audio", &audio));
1614
Wei Jia7b15cb32015-02-03 17:46:06 -08001615 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001616 return;
1617 }
1618
1619 int32_t finalResult;
1620 CHECK(msg->findInt32("finalResult", &finalResult));
1621
1622 QueueEntry entry;
1623 entry.mOffset = 0;
1624 entry.mFinalResult = finalResult;
1625
1626 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001627 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001628 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001629 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001630 }
Andreas Huberf9334412010-12-15 15:17:42 -08001631 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001632 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001633 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001634 if (mVideoQueue.empty() && getSyncQueues()) {
1635 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001636 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001637 }
Andreas Huberf9334412010-12-15 15:17:42 -08001638 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001639 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001640 }
1641}
1642
1643void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001644 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001645 CHECK(msg->findInt32("audio", &audio));
1646
Wei Jia28a8a9f2014-08-18 11:29:50 -07001647 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001648 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001649 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001650 notifyComplete = mNotifyCompleteAudio;
1651 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001652 mLastAudioMediaTimeUs = -1;
Wei Jiacc951512019-04-03 16:10:42 -07001653
1654 mHasAudio = false;
1655 if (mNextVideoTimeMediaUs >= 0) {
1656 int64_t nowUs = ALooper::GetNowUs();
1657 mMediaClock->updateAnchor(
1658 mNextVideoTimeMediaUs, nowUs,
1659 mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
1660 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001661 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001662 notifyComplete = mNotifyCompleteVideo;
1663 mNotifyCompleteVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001664 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001665
Wei Jia7b15cb32015-02-03 17:46:06 -08001666 // If we're currently syncing the queues, i.e. dropping audio while
1667 // aligning the first audio/video buffer times and only one of the
1668 // two queues has data, we may starve that queue by not requesting
1669 // more buffers from the decoder. If the other source then encounters
1670 // a discontinuity that leads to flushing, we'll never find the
1671 // corresponding discontinuity on the other queue.
1672 // Therefore we'll stop syncing the queues if at least one of them
1673 // is flushed.
1674 syncQueuesDone_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001675 }
Wei Jia9a3101b2016-11-08 14:34:24 -08001676 clearAnchorTime();
Andreas Huberf9334412010-12-15 15:17:42 -08001677
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001678 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001679 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001680 {
1681 Mutex::Autolock autoLock(mLock);
1682 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001683
Wei Jia7b15cb32015-02-03 17:46:06 -08001684 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001685 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001686 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001687
Andy Hunga0b39712015-05-31 22:40:49 -07001688 // the frame count will be reset after flush.
1689 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001690 }
Andreas Huberf9334412010-12-15 15:17:42 -08001691
Andreas Huberf9334412010-12-15 15:17:42 -08001692 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001693
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001694 mAudioSink->pause();
1695 mAudioSink->flush();
1696 if (!offloadingAudio()) {
Wei Jia9e7ed332015-05-01 16:35:43 -07001697 // Call stop() to signal to the AudioSink to completely fill the
1698 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001699 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001700 mAudioSink->stop();
Wei Jia9e7ed332015-05-01 16:35:43 -07001701 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001702 }
Santiago Seifertd0ba1bb2021-08-27 16:22:16 +00001703 if (!mPaused) {
1704 mAudioSink->start();
1705 }
Andy Hung528c8402016-01-12 12:39:34 -08001706 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001707 } else {
1708 flushQueue(&mVideoQueue);
1709
Andreas Huberf9334412010-12-15 15:17:42 -08001710 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001711
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001712 if (mVideoScheduler != NULL) {
1713 mVideoScheduler->restart();
1714 }
1715
Wei Jia7b15cb32015-02-03 17:46:06 -08001716 Mutex::Autolock autoLock(mLock);
1717 ++mVideoDrainGeneration;
1718 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001719 }
1720
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001721 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001722
1723 if (notifyComplete) {
1724 notifyFlushComplete(audio);
1725 }
Andreas Huberf9334412010-12-15 15:17:42 -08001726}
1727
1728void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1729 while (!queue->empty()) {
1730 QueueEntry *entry = &*queue->begin();
1731
1732 if (entry->mBuffer != NULL) {
1733 entry->mNotifyConsumed->post();
Wei Jia9a3101b2016-11-08 14:34:24 -08001734 } else if (entry->mNotifyConsumed != nullptr) {
1735 // Is it needed to open audio sink now?
1736 onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
Andreas Huberf9334412010-12-15 15:17:42 -08001737 }
1738
1739 queue->erase(queue->begin());
1740 entry = NULL;
1741 }
1742}
1743
1744void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1745 sp<AMessage> notify = mNotify->dup();
1746 notify->setInt32("what", kWhatFlushComplete);
1747 notify->setInt32("audio", static_cast<int32_t>(audio));
1748 notify->post();
1749}
1750
Wei Jia7b15cb32015-02-03 17:46:06 -08001751bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001752 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001753 int32_t queueGeneration;
1754 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001755
Wei Jia7b15cb32015-02-03 17:46:06 -08001756 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001757 return false;
1758 }
1759
1760 sp<AMessage> notifyConsumed;
1761 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1762 notifyConsumed->post();
1763 }
1764
1765 return true;
1766}
1767
Andreas Huber3831a062010-12-21 10:22:33 -08001768void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001769 if (offloadingAudio()) {
1770 return;
1771 }
Andreas Huber3831a062010-12-21 10:22:33 -08001772 CHECK(!mDrainAudioQueuePending);
1773 mNumFramesWritten = 0;
Wei Jia9a3101b2016-11-08 14:34:24 -08001774 mAnchorNumFramesWritten = -1;
Marco Nelissen4110c102012-03-29 09:31:28 -07001775 uint32_t written;
1776 if (mAudioSink->getFramesWritten(&written) == OK) {
1777 mNumFramesWritten = written;
1778 }
Andreas Huber3831a062010-12-21 10:22:33 -08001779}
1780
Wei Jiabc2fb722014-07-08 16:37:57 -07001781void NuPlayer::Renderer::onDisableOffloadAudio() {
1782 Mutex::Autolock autoLock(mLock);
1783 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001784 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001785 if (mAudioRenderingStartGeneration != -1) {
1786 prepareForMediaRenderingStart_l();
andysu36177952018-04-20 15:17:13 +08001787 // PauseTimeout is applied to offload mode only. Cancel pending timer.
1788 cancelAudioOffloadPauseTimeout();
Robert Shihe1d70192015-07-23 17:54:13 -07001789 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001790}
1791
Ronghua Wua10fd232014-11-06 16:15:20 -08001792void NuPlayer::Renderer::onEnableOffloadAudio() {
1793 Mutex::Autolock autoLock(mLock);
1794 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001795 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001796 if (mAudioRenderingStartGeneration != -1) {
1797 prepareForMediaRenderingStart_l();
1798 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001799}
1800
Andreas Huberb4082222011-01-20 15:23:04 -08001801void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001802 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001803 return;
1804 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001805
Eric Laurent7fb51272022-07-01 16:42:48 +02001806 startAudioOffloadPauseTimeout();
1807
Wei Jia28a8a9f2014-08-18 11:29:50 -07001808 {
1809 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001810 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001811 ++mVideoDrainGeneration;
1812 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001813 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001814 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001815 }
1816
Andreas Huberb4082222011-01-20 15:23:04 -08001817 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001818 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001819
Andy Hung84200732015-12-03 14:41:06 -08001820 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1821 mAudioSink->pause();
Andreas Huberb4082222011-01-20 15:23:04 -08001822
Lajos Molnar6d339f12015-04-17 16:15:53 -07001823 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001824 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001825}
1826
1827void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001828 if (!mPaused) {
1829 return;
1830 }
Andreas Huberb4082222011-01-20 15:23:04 -08001831
Andy Hung84200732015-12-03 14:41:06 -08001832 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1833 cancelAudioOffloadPauseTimeout();
1834 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001835 status_t err = mAudioSink->start();
1836 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001837 ALOGE("cannot start AudioSink err %d", err);
Wei Jiaa05f1e32016-03-25 16:31:22 -07001838 notifyAudioTearDown(kDueToError);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001839 }
Andreas Huberb4082222011-01-20 15:23:04 -08001840 }
1841
Wei Jia7b15cb32015-02-03 17:46:06 -08001842 {
1843 Mutex::Autolock autoLock(mLock);
1844 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001845 // rendering started message may have been delayed if we were paused.
1846 if (mRenderingDataDelivered) {
1847 notifyIfMediaRenderingStarted_l();
1848 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001849 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001850 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001851 mAudioSink->setPlaybackRate(mPlaybackSettings);
1852 }
1853
Wei Jia98160162015-02-04 17:01:11 -08001854 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001855
Wei Jia7b15cb32015-02-03 17:46:06 -08001856 if (!mAudioQueue.empty()) {
1857 postDrainAudioQueue_l();
1858 }
Andreas Huberb4082222011-01-20 15:23:04 -08001859 }
1860
1861 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001862 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001863 }
1864}
1865
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001866void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1867 if (mVideoScheduler == NULL) {
1868 mVideoScheduler = new VideoFrameScheduler();
1869 }
1870 mVideoScheduler->init(fps);
1871}
1872
Wei Jia7b15cb32015-02-03 17:46:06 -08001873int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1874 Mutex::Autolock autoLock(mLock);
1875 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1876}
1877
1878int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1879 Mutex::Autolock autoLock(mLock);
1880 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1881}
1882
1883bool NuPlayer::Renderer::getSyncQueues() {
1884 Mutex::Autolock autoLock(mLock);
1885 return mSyncQueues;
1886}
1887
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001888void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1889 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001890 return;
1891 }
andysu36177952018-04-20 15:17:13 +08001892
1893 // TimeoutWhenPaused is only for offload mode.
1894 if (reason == kDueToTimeout && !offloadingAudio()) {
1895 return;
1896 }
1897
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001898 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001899
Ronghua Wua73d9e02014-10-08 15:13:29 -07001900 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001901 sp<AMessage> notify = mNotify->dup();
1902 if (getCurrentPosition(&currentPositionUs) == OK) {
1903 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001904 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001905
Wei Jia3a2956d2014-07-22 16:01:33 -07001906 mAudioSink->stop();
1907 mAudioSink->flush();
1908
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001909 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001910 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001911 notify->post();
1912}
1913
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001914void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1915 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001916 mWakeLock->acquire();
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001917 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001918 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001919 msg->post(kOffloadPauseMaxUs);
1920 }
1921}
1922
1923void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
Andy Hung21afe802016-04-21 14:52:05 -07001924 // We may have called startAudioOffloadPauseTimeout() without
1925 // the AudioSink open and with offloadingAudio enabled.
1926 //
1927 // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
1928 // we always release the wakelock and increment the pause timeout generation.
1929 //
1930 // Note: The acquired wakelock prevents the device from suspending
1931 // immediately after offload pause (in case a resume happens shortly thereafter).
1932 mWakeLock->release(true);
1933 ++mAudioOffloadPauseTimeoutGeneration;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001934}
1935
Andy Hung202bce12014-12-03 11:47:36 -08001936status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001937 const sp<AMessage> &format,
1938 bool offloadOnly,
1939 bool hasVideo,
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05301940 uint32_t flags,
1941 bool isStreaming) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001942 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1943 offloadOnly, offloadingAudio());
1944 bool audioSinkChanged = false;
1945
1946 int32_t numChannels;
1947 CHECK(format->findInt32("channel-count", &numChannels));
1948
Mikhail Naganov55773032020-10-01 15:08:13 -07001949 int32_t rawChannelMask;
1950 audio_channel_mask_t channelMask =
1951 format->findInt32("channel-mask", &rawChannelMask) ?
1952 static_cast<audio_channel_mask_t>(rawChannelMask)
1953 // signal to the AudioSink to derive the mask from count.
1954 : CHANNEL_MASK_USE_CHANNEL_ORDER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001955
1956 int32_t sampleRate;
1957 CHECK(format->findInt32("sample-rate", &sampleRate));
1958
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07001959 // read pcm encoding from MediaCodec output format, if available
1960 int32_t pcmEncoding;
1961 audio_format_t audioFormat =
1962 format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
1963 audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
1964
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001965 if (offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001966 AString mime;
1967 CHECK(format->findString("mime", &mime));
1968 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
1969
1970 if (err != OK) {
1971 ALOGE("Couldn't map mime \"%s\" to a valid "
1972 "audio_format", mime.c_str());
1973 onDisableOffloadAudio();
1974 } else {
1975 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
1976 mime.c_str(), audioFormat);
1977
Ajender Reddy55a85792021-02-25 21:01:35 +05301978 int avgBitRate = 0;
Lajos Molnar46f80162016-05-19 15:35:47 -07001979 format->findInt32("bitrate", &avgBitRate);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001980
1981 int32_t aacProfile = -1;
1982 if (audioFormat == AUDIO_FORMAT_AAC
1983 && format->findInt32("aac-profile", &aacProfile)) {
1984 // Redefine AAC format as per aac profile
1985 mapAACProfileToAudioFormat(
1986 audioFormat,
1987 aacProfile);
1988 }
1989
1990 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
1991 offloadInfo.duration_us = -1;
1992 format->findInt64(
1993 "durationUs", &offloadInfo.duration_us);
1994 offloadInfo.sample_rate = sampleRate;
1995 offloadInfo.channel_mask = channelMask;
1996 offloadInfo.format = audioFormat;
1997 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
1998 offloadInfo.bit_rate = avgBitRate;
1999 offloadInfo.has_video = hasVideo;
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302000 offloadInfo.is_streaming = isStreaming;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002001
2002 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
2003 ALOGV("openAudioSink: no change in offload mode");
2004 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08002005 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002006 }
Andy Hungf0e83642014-12-19 17:55:56 -08002007 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
2008
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002009 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002010 uint32_t offloadFlags = flags;
2011 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
2012 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002013 audioSinkChanged = true;
2014 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07002015
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002016 err = mAudioSink->open(
2017 sampleRate,
2018 numChannels,
2019 (audio_channel_mask_t)channelMask,
2020 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002021 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002022 &NuPlayer::Renderer::AudioSinkCallback,
2023 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002024 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002025 &offloadInfo);
2026
2027 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07002028 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
2029 }
2030
2031 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002032 // If the playback is offloaded to h/w, we pass
2033 // the HAL some metadata information.
2034 // We don't want to do this for PCM because it
2035 // will be going through the AudioFlinger mixer
2036 // before reaching the hardware.
2037 // TODO
2038 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07002039 if (!mPaused) { // for preview mode, don't start if paused
2040 err = mAudioSink->start();
2041 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002042 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
2043 }
2044 if (err != OK) {
2045 // Clean up, fall back to non offload mode.
2046 mAudioSink->close();
2047 onDisableOffloadAudio();
2048 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
2049 ALOGV("openAudioSink: offload failed");
Wei Jiaa05f1e32016-03-25 16:31:22 -07002050 if (offloadOnly) {
2051 notifyAudioTearDown(kForceNonOffload);
2052 }
Wei Jia3ab25452015-06-10 09:37:47 -07002053 } else {
2054 mUseAudioCallback = true; // offload mode transfers data through callback
2055 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002056 }
2057 }
2058 }
2059 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002060 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07002061 uint32_t pcmFlags = flags;
2062 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08002063
2064 const PcmInfo info = {
2065 (audio_channel_mask_t)channelMask,
2066 (audio_output_flags_t)pcmFlags,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002067 audioFormat,
Andy Hungf0e83642014-12-19 17:55:56 -08002068 numChannels,
2069 sampleRate
2070 };
2071 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
2072 ALOGV("openAudioSink: no change in pcm mode");
2073 // no change from previous configuration, everything ok.
2074 return OK;
2075 }
2076
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002077 audioSinkChanged = true;
2078 mAudioSink->close();
2079 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07002080 // Note: It is possible to set up the callback, but not use it to send audio data.
2081 // This requires a fix in AudioSink to explicitly specify the transfer mode.
2082 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07002083 if (mUseAudioCallback) {
2084 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
2085 }
Andy Hung179652e2015-05-31 22:49:46 -07002086
2087 // Compute the desired buffer size.
2088 // For callback mode, the amount of time before wakeup is about half the buffer size.
2089 const uint32_t frameCount =
2090 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
2091
Ronghua Wu7665f582015-09-02 10:15:30 -07002092 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
2093 // AudioSink. We don't want this when there's video because it will cause a video seek to
2094 // the previous I frame. But we do want this when there's only audio because it will give
2095 // NuPlayer a chance to switch from non-offload mode to offload mode.
2096 // So we only set doNotReconnect when there's no video.
2097 const bool doNotReconnect = !hasVideo;
Andy Hungff874dc2016-04-11 16:49:09 -07002098
2099 // We should always be able to set our playback settings if the sink is closed.
2100 LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
2101 "onOpenAudioSink: can't set playback rate on closed sink");
Andy Hung202bce12014-12-03 11:47:36 -08002102 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002103 sampleRate,
2104 numChannels,
2105 (audio_channel_mask_t)channelMask,
Ari Hausman-Cohen2b674bb2018-06-22 14:53:20 -07002106 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07002107 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07002108 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
2109 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002110 (audio_output_flags_t)pcmFlags,
2111 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07002112 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07002113 frameCount);
Andy Hung202bce12014-12-03 11:47:36 -08002114 if (err != OK) {
2115 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07002116 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08002117 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08002118 return err;
2119 }
Andy Hungf0e83642014-12-19 17:55:56 -08002120 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07002121 if (!mPaused) { // for preview mode, don't start if paused
2122 mAudioSink->start();
2123 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002124 }
2125 if (audioSinkChanged) {
2126 onAudioSinkChanged();
2127 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07002128 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08002129 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002130}
2131
2132void NuPlayer::Renderer::onCloseAudioSink() {
2133 mAudioSink->close();
2134 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08002135 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07002136}
2137
Wei Jia9a3101b2016-11-08 14:34:24 -08002138void NuPlayer::Renderer::onChangeAudioFormat(
2139 const sp<AMessage> &meta, const sp<AMessage> &notify) {
2140 sp<AMessage> format;
2141 CHECK(meta->findMessage("format", &format));
2142
2143 int32_t offloadOnly;
2144 CHECK(meta->findInt32("offload-only", &offloadOnly));
2145
2146 int32_t hasVideo;
2147 CHECK(meta->findInt32("has-video", &hasVideo));
2148
2149 uint32_t flags;
2150 CHECK(meta->findInt32("flags", (int32_t *)&flags));
2151
Dhananjay Kumarc387f2b2015-08-06 10:43:16 +05302152 uint32_t isStreaming;
2153 CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
2154
2155 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
Wei Jia9a3101b2016-11-08 14:34:24 -08002156
2157 if (err != OK) {
2158 notify->setInt32("err", err);
2159 }
2160 notify->post();
2161}
2162
Andreas Huberf9334412010-12-15 15:17:42 -08002163} // namespace android