blob: 5f36fc1c260effc497e2d7768a7091a2df183a35 [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
21#include "NuPlayerRenderer.h"
Andy Hunga0b39712015-05-31 22:40:49 -070022#include <cutils/properties.h>
Andreas Huberf9334412010-12-15 15:17:42 -080023#include <media/stagefright/foundation/ABuffer.h>
24#include <media/stagefright/foundation/ADebug.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080025#include <media/stagefright/foundation/AMessage.h>
Ronghua Wua73d9e02014-10-08 15:13:29 -070026#include <media/stagefright/foundation/AUtils.h>
Weiyin Jiang35d5af12015-01-28 16:14:02 +080027#include <media/stagefright/foundation/AWakeLock.h>
Wei Jia5833b6a2015-03-09 17:01:47 -070028#include <media/stagefright/MediaClock.h>
Wei Jiabc2fb722014-07-08 16:37:57 -070029#include <media/stagefright/MediaErrors.h>
30#include <media/stagefright/MetaData.h>
Chong Zhang3b9eb1f2014-10-15 17:05:08 -070031#include <media/stagefright/Utils.h>
Lajos Molnara3725d72015-07-01 16:47:22 -070032#include <media/stagefright/VideoFrameScheduler.h>
Lajos Molnardc43dfa2014-05-07 15:33:04 -070033
Lajos Molnar09524832014-07-17 14:29:51 -070034#include <inttypes.h>
35
Andreas Huberf9334412010-12-15 15:17:42 -080036namespace android {
37
Andy Hunga0b39712015-05-31 22:40:49 -070038/*
39 * Example of common configuration settings in shell script form
40
41 #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
42 adb shell setprop audio.offload.disable 1
43
44 #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
45 adb shell setprop audio.offload.video 1
46
47 #Use audio callbacks for PCM data
48 adb shell setprop media.stagefright.audio.cbk 1
49
Andy Hung288da022015-05-31 22:55:59 -070050 #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
51 adb shell setprop media.stagefright.audio.deep 1
52
Andy Hung179652e2015-05-31 22:49:46 -070053 #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
54 adb shell setprop media.stagefright.audio.sink 1000
55
Andy Hunga0b39712015-05-31 22:40:49 -070056 * These configurations take effect for the next track played (not the current track).
57 */
58
59static inline bool getUseAudioCallbackSetting() {
60 return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
61}
62
Andy Hung179652e2015-05-31 22:49:46 -070063static inline int32_t getAudioSinkPcmMsSetting() {
64 return property_get_int32(
65 "media.stagefright.audio.sink", 500 /* default_value */);
66}
67
Ronghua Wuf5b1db12014-09-09 10:11:08 -070068// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
69// is closed to allow the audio DSP to power down.
Eric Laurenta5d316f2014-10-29 15:32:17 -070070static const int64_t kOffloadPauseMaxUs = 10000000ll;
Ronghua Wuf5b1db12014-09-09 10:11:08 -070071
Wei Jia12b62652016-02-09 17:49:31 -080072// Maximum allowed delay from AudioSink, 1.5 seconds.
73static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000ll;
74
Andy Hung528c8402016-01-12 12:39:34 -080075static const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
76
Andreas Huber714aa7b2011-09-13 08:28:38 -070077// static
Andy Hungf0e83642014-12-19 17:55:56 -080078const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
79 AUDIO_CHANNEL_NONE,
80 AUDIO_OUTPUT_FLAG_NONE,
81 AUDIO_FORMAT_INVALID,
82 0, // mNumChannels
83 0 // mSampleRate
84};
85
86// static
Andreas Huber714aa7b2011-09-13 08:28:38 -070087const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
88
Andreas Huberf9334412010-12-15 15:17:42 -080089NuPlayer::Renderer::Renderer(
90 const sp<MediaPlayerBase::AudioSink> &sink,
Andreas Huberd5e56232013-03-12 11:01:43 -070091 const sp<AMessage> &notify,
92 uint32_t flags)
Andreas Huberf9334412010-12-15 15:17:42 -080093 : mAudioSink(sink),
Wei Jiad2f35de2016-02-17 16:48:06 -080094 mUseVirtualAudioSink(false),
Andreas Huberf9334412010-12-15 15:17:42 -080095 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -070096 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -080097 mNumFramesWritten(0),
98 mDrainAudioQueuePending(false),
99 mDrainVideoQueuePending(false),
100 mAudioQueueGeneration(0),
101 mVideoQueueGeneration(0),
Wei Jia7b15cb32015-02-03 17:46:06 -0800102 mAudioDrainGeneration(0),
103 mVideoDrainGeneration(0),
Wei Jia7c8d0e02015-08-27 17:40:21 -0700104 mAudioEOSGeneration(0),
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700105 mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
Ronghua Wua73d9e02014-10-08 15:13:29 -0700106 mAudioFirstAnchorTimeMediaUs(-1),
Ronghua Wueecb7802014-10-19 23:12:50 -0700107 mAnchorTimeMediaUs(-1),
Lajos Molnarf5926712014-10-21 09:36:43 -0700108 mAnchorNumFramesWritten(-1),
Ronghua Wua73d9e02014-10-08 15:13:29 -0700109 mVideoLateByUs(0ll),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800110 mHasAudio(false),
111 mHasVideo(false),
Chong Zhang7137ec72014-11-12 16:41:05 -0800112 mNotifyCompleteAudio(false),
113 mNotifyCompleteVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800114 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -0700115 mPaused(false),
Andy Hungb03dcb32015-08-27 16:18:59 -0700116 mPauseDrainAudioAllowedUs(0),
Andy Hung09e0c362014-09-12 15:12:16 -0700117 mVideoSampleReceived(false),
James Dongf57b4ea2012-07-20 13:38:36 -0700118 mVideoRenderingStarted(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700119 mVideoRenderingStartGeneration(0),
120 mAudioRenderingStartGeneration(0),
Andy Hungb12ea0b2015-09-03 15:13:01 -0700121 mRenderingDataDelivered(false),
Andy Hung528c8402016-01-12 12:39:34 -0800122 mNextAudioClockUpdateTimeUs(-1),
Wei Jia2995dc72015-07-24 16:00:33 -0700123 mLastAudioMediaTimeUs(-1),
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700124 mAudioOffloadPauseTimeoutGeneration(0),
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700125 mAudioTornDown(false),
Lajos Molnard5923402014-10-20 17:47:54 -0700126 mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
Andy Hungf0e83642014-12-19 17:55:56 -0800127 mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
Lajos Molnard5923402014-10-20 17:47:54 -0700128 mTotalBuffersQueued(0),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800129 mLastAudioBufferDrained(0),
Andy Hunga0b39712015-05-31 22:40:49 -0700130 mUseAudioCallback(false),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800131 mWakeLock(new AWakeLock()) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800132 mMediaClock = new MediaClock;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700133 mPlaybackRate = mPlaybackSettings.mSpeed;
134 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberf9334412010-12-15 15:17:42 -0800135}
136
137NuPlayer::Renderer::~Renderer() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700138 if (offloadingAudio()) {
139 mAudioSink->stop();
140 mAudioSink->flush();
141 mAudioSink->close();
142 }
Andreas Huberf9334412010-12-15 15:17:42 -0800143}
144
145void NuPlayer::Renderer::queueBuffer(
146 bool audio,
147 const sp<ABuffer> &buffer,
148 const sp<AMessage> &notifyConsumed) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800149 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800150 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800151 msg->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800152 msg->setBuffer("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -0800153 msg->setMessage("notifyConsumed", notifyConsumed);
154 msg->post();
155}
156
157void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
158 CHECK_NE(finalResult, (status_t)OK);
159
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800160 sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800161 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800162 msg->setInt32("audio", static_cast<int32_t>(audio));
163 msg->setInt32("finalResult", finalResult);
164 msg->post();
165}
166
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700167status_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
168 sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
169 writeToAMessage(msg, rate);
170 sp<AMessage> response;
171 status_t err = msg->postAndAwaitResponse(&response);
172 if (err == OK && response != NULL) {
173 CHECK(response->findInt32("err", &err));
174 }
175 return err;
176}
177
178status_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
179 if (rate.mSpeed == 0.f) {
180 onPause();
181 // don't call audiosink's setPlaybackRate if pausing, as pitch does not
182 // have to correspond to the any non-0 speed (e.g old speed). Keep
183 // settings nonetheless, using the old speed, in case audiosink changes.
184 AudioPlaybackRate newRate = rate;
185 newRate.mSpeed = mPlaybackSettings.mSpeed;
186 mPlaybackSettings = newRate;
187 return OK;
188 }
189
Wei Jia27ea08e2015-05-12 14:50:35 -0700190 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700191 status_t err = mAudioSink->setPlaybackRate(rate);
192 if (err != OK) {
193 return err;
194 }
195 }
196 mPlaybackSettings = rate;
197 mPlaybackRate = rate.mSpeed;
198 mMediaClock->setPlaybackRate(mPlaybackRate);
199 return OK;
200}
201
202status_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
203 sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
204 sp<AMessage> response;
205 status_t err = msg->postAndAwaitResponse(&response);
206 if (err == OK && response != NULL) {
207 CHECK(response->findInt32("err", &err));
208 if (err == OK) {
209 readFromAMessage(response, rate);
210 }
211 }
212 return err;
213}
214
215status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
Wei Jia27ea08e2015-05-12 14:50:35 -0700216 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700217 status_t err = mAudioSink->getPlaybackRate(rate);
218 if (err == OK) {
219 if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
220 ALOGW("correcting mismatch in internal/external playback rate");
221 }
222 // get playback settings used by audiosink, as it may be
223 // slightly off due to audiosink not taking small changes.
224 mPlaybackSettings = *rate;
225 if (mPaused) {
226 rate->mSpeed = 0.f;
227 }
228 }
229 return err;
230 }
231 *rate = mPlaybackSettings;
232 return OK;
233}
234
235status_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
236 sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
237 writeToAMessage(msg, sync, videoFpsHint);
238 sp<AMessage> response;
239 status_t err = msg->postAndAwaitResponse(&response);
240 if (err == OK && response != NULL) {
241 CHECK(response->findInt32("err", &err));
242 }
243 return err;
244}
245
246status_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
247 if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
248 return BAD_VALUE;
249 }
250 // TODO: support sync sources
251 return INVALID_OPERATION;
252}
253
254status_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
255 sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
256 sp<AMessage> response;
257 status_t err = msg->postAndAwaitResponse(&response);
258 if (err == OK && response != NULL) {
259 CHECK(response->findInt32("err", &err));
260 if (err == OK) {
261 readFromAMessage(response, sync, videoFps);
262 }
263 }
264 return err;
265}
266
267status_t NuPlayer::Renderer::onGetSyncSettings(
268 AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
269 *sync = mSyncSettings;
270 *videoFps = -1.f;
271 return OK;
Wei Jia98160162015-02-04 17:01:11 -0800272}
273
Chong Zhang7137ec72014-11-12 16:41:05 -0800274void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800275 {
Wei Jia7b15cb32015-02-03 17:46:06 -0800276 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800277 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800278 mNotifyCompleteAudio |= notifyComplete;
Wei Jia3b0cd262015-07-13 11:28:10 -0700279 clearAudioFirstAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800280 ++mAudioQueueGeneration;
281 ++mAudioDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800282 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -0800283 mNotifyCompleteVideo |= notifyComplete;
Wei Jia7b15cb32015-02-03 17:46:06 -0800284 ++mVideoQueueGeneration;
285 ++mVideoDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800286 }
Wei Jia7b15cb32015-02-03 17:46:06 -0800287
288 clearAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800289 mVideoLateByUs = 0;
290 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800291 }
292
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800293 sp<AMessage> msg = new AMessage(kWhatFlush, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800294 msg->setInt32("audio", static_cast<int32_t>(audio));
295 msg->post();
296}
297
298void NuPlayer::Renderer::signalTimeDiscontinuity() {
Wei Jia28a8a9f2014-08-18 11:29:50 -0700299}
300
301void NuPlayer::Renderer::signalDisableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800302 (new AMessage(kWhatDisableOffloadAudio, this))->post();
Wei Jia28a8a9f2014-08-18 11:29:50 -0700303}
304
Ronghua Wua10fd232014-11-06 16:15:20 -0800305void NuPlayer::Renderer::signalEnableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800306 (new AMessage(kWhatEnableOffloadAudio, this))->post();
Ronghua Wua10fd232014-11-06 16:15:20 -0800307}
308
Andreas Huberb4082222011-01-20 15:23:04 -0800309void NuPlayer::Renderer::pause() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800310 (new AMessage(kWhatPause, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800311}
312
313void NuPlayer::Renderer::resume() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800314 (new AMessage(kWhatResume, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800315}
316
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700317void NuPlayer::Renderer::setVideoFrameRate(float fps) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800318 sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700319 msg->setFloat("frame-rate", fps);
320 msg->post();
321}
322
Wei Jia4ecbea32015-10-20 18:09:57 -0700323// Called on any threads without mLock acquired.
Wei Jia7b15cb32015-02-03 17:46:06 -0800324status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
Wei Jia4ecbea32015-10-20 18:09:57 -0700325 status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
326 if (result == OK) {
327 return result;
328 }
329
330 // MediaClock has not started yet. Try to start it if possible.
331 {
332 Mutex::Autolock autoLock(mLock);
333 if (mAudioFirstAnchorTimeMediaUs == -1) {
334 return result;
335 }
336
337 AudioTimestamp ts;
338 status_t res = mAudioSink->getTimestamp(ts);
339 if (res != OK) {
340 return result;
341 }
342
343 // AudioSink has rendered some frames.
344 int64_t nowUs = ALooper::GetNowUs();
Wei Jiad855a732015-10-21 13:31:15 -0700345 int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
Wei Jia4ecbea32015-10-20 18:09:57 -0700346 + mAudioFirstAnchorTimeMediaUs;
347 mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
348 }
349
Wei Jia98160162015-02-04 17:01:11 -0800350 return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700351}
352
Wei Jia7b15cb32015-02-03 17:46:06 -0800353void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
354 mAudioFirstAnchorTimeMediaUs = -1;
355 mMediaClock->setStartingTimeMedia(-1);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700356}
357
Wei Jia7b15cb32015-02-03 17:46:06 -0800358void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700359 if (mAudioFirstAnchorTimeMediaUs == -1) {
360 mAudioFirstAnchorTimeMediaUs = mediaUs;
Wei Jia7b15cb32015-02-03 17:46:06 -0800361 mMediaClock->setStartingTimeMedia(mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700362 }
363}
364
Wei Jia7b15cb32015-02-03 17:46:06 -0800365void NuPlayer::Renderer::clearAnchorTime_l() {
366 mMediaClock->clearAnchor();
367 mAnchorTimeMediaUs = -1;
368 mAnchorNumFramesWritten = -1;
Ronghua Wua73d9e02014-10-08 15:13:29 -0700369}
370
371void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800372 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700373 mVideoLateByUs = lateUs;
374}
375
376int64_t NuPlayer::Renderer::getVideoLateByUs() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800377 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700378 return mVideoLateByUs;
379}
380
Andy Hung202bce12014-12-03 11:47:36 -0800381status_t NuPlayer::Renderer::openAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700382 const sp<AMessage> &format,
383 bool offloadOnly,
384 bool hasVideo,
Andy Hung202bce12014-12-03 11:47:36 -0800385 uint32_t flags,
386 bool *isOffloaded) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800387 sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700388 msg->setMessage("format", format);
389 msg->setInt32("offload-only", offloadOnly);
390 msg->setInt32("has-video", hasVideo);
391 msg->setInt32("flags", flags);
392
393 sp<AMessage> response;
394 msg->postAndAwaitResponse(&response);
395
Andy Hung202bce12014-12-03 11:47:36 -0800396 int32_t err;
397 if (!response->findInt32("err", &err)) {
398 err = INVALID_OPERATION;
399 } else if (err == OK && isOffloaded != NULL) {
400 int32_t offload;
401 CHECK(response->findInt32("offload", &offload));
402 *isOffloaded = (offload != 0);
403 }
404 return err;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700405}
406
407void NuPlayer::Renderer::closeAudioSink() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800408 sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700409
410 sp<AMessage> response;
411 msg->postAndAwaitResponse(&response);
412}
413
Andreas Huberf9334412010-12-15 15:17:42 -0800414void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
415 switch (msg->what()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700416 case kWhatOpenAudioSink:
417 {
418 sp<AMessage> format;
419 CHECK(msg->findMessage("format", &format));
420
421 int32_t offloadOnly;
422 CHECK(msg->findInt32("offload-only", &offloadOnly));
423
424 int32_t hasVideo;
425 CHECK(msg->findInt32("has-video", &hasVideo));
426
427 uint32_t flags;
428 CHECK(msg->findInt32("flags", (int32_t *)&flags));
429
Andy Hung202bce12014-12-03 11:47:36 -0800430 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700431
432 sp<AMessage> response = new AMessage;
Andy Hung202bce12014-12-03 11:47:36 -0800433 response->setInt32("err", err);
434 response->setInt32("offload", offloadingAudio());
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700435
Lajos Molnar3f274362015-03-05 14:35:41 -0800436 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700437 CHECK(msg->senderAwaitsResponse(&replyID));
438 response->postReply(replyID);
439
440 break;
441 }
442
443 case kWhatCloseAudioSink:
444 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800445 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700446 CHECK(msg->senderAwaitsResponse(&replyID));
447
448 onCloseAudioSink();
449
450 sp<AMessage> response = new AMessage;
451 response->postReply(replyID);
452 break;
453 }
454
Wei Jiabc2fb722014-07-08 16:37:57 -0700455 case kWhatStopAudioSink:
456 {
457 mAudioSink->stop();
458 break;
459 }
460
Andreas Huberf9334412010-12-15 15:17:42 -0800461 case kWhatDrainAudioQueue:
462 {
Wei Jia3ab25452015-06-10 09:37:47 -0700463 mDrainAudioQueuePending = false;
464
Andreas Huberf9334412010-12-15 15:17:42 -0800465 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800466 CHECK(msg->findInt32("drainGeneration", &generation));
467 if (generation != getDrainGeneration(true /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800468 break;
469 }
470
Andreas Huber078cfcf2011-09-15 12:25:04 -0700471 if (onDrainAudioQueue()) {
472 uint32_t numFramesPlayed;
473 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
474 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800475
Andreas Huber078cfcf2011-09-15 12:25:04 -0700476 uint32_t numFramesPendingPlayout =
477 mNumFramesWritten - numFramesPlayed;
478
479 // This is how long the audio sink will have data to
480 // play back.
481 int64_t delayUs =
482 mAudioSink->msecsPerFrame()
483 * numFramesPendingPlayout * 1000ll;
Wei Jiad9c2e9c2015-04-10 19:04:09 -0700484 if (mPlaybackRate > 1.0f) {
485 delayUs /= mPlaybackRate;
486 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700487
488 // Let's give it more data after about half that time
489 // has elapsed.
Wei Jia7b15cb32015-02-03 17:46:06 -0800490 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -0700491 postDrainAudioQueue_l(delayUs / 2);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700492 }
Andreas Huberf9334412010-12-15 15:17:42 -0800493 break;
494 }
495
496 case kWhatDrainVideoQueue:
497 {
498 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800499 CHECK(msg->findInt32("drainGeneration", &generation));
500 if (generation != getDrainGeneration(false /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800501 break;
502 }
503
504 mDrainVideoQueuePending = false;
505
506 onDrainVideoQueue();
507
Wei Jia7b15cb32015-02-03 17:46:06 -0800508 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -0800509 break;
510 }
511
Lajos Molnard5923402014-10-20 17:47:54 -0700512 case kWhatPostDrainVideoQueue:
513 {
514 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800515 CHECK(msg->findInt32("drainGeneration", &generation));
516 if (generation != getDrainGeneration(false /* audio */)) {
Lajos Molnard5923402014-10-20 17:47:54 -0700517 break;
518 }
519
520 mDrainVideoQueuePending = false;
Wei Jia7b15cb32015-02-03 17:46:06 -0800521 postDrainVideoQueue();
Lajos Molnard5923402014-10-20 17:47:54 -0700522 break;
523 }
524
Andreas Huberf9334412010-12-15 15:17:42 -0800525 case kWhatQueueBuffer:
526 {
527 onQueueBuffer(msg);
528 break;
529 }
530
531 case kWhatQueueEOS:
532 {
533 onQueueEOS(msg);
534 break;
535 }
536
Wei Jia7c8d0e02015-08-27 17:40:21 -0700537 case kWhatEOS:
538 {
539 int32_t generation;
540 CHECK(msg->findInt32("audioEOSGeneration", &generation));
541 if (generation != mAudioEOSGeneration) {
542 break;
543 }
544 status_t finalResult;
545 CHECK(msg->findInt32("finalResult", &finalResult));
546 notifyEOS(true /* audio */, finalResult);
547 break;
548 }
549
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700550 case kWhatConfigPlayback:
Wei Jia98160162015-02-04 17:01:11 -0800551 {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700552 sp<AReplyToken> replyID;
553 CHECK(msg->senderAwaitsResponse(&replyID));
554 AudioPlaybackRate rate;
555 readFromAMessage(msg, &rate);
556 status_t err = onConfigPlayback(rate);
557 sp<AMessage> response = new AMessage;
558 response->setInt32("err", err);
559 response->postReply(replyID);
560 break;
561 }
562
563 case kWhatGetPlaybackSettings:
564 {
565 sp<AReplyToken> replyID;
566 CHECK(msg->senderAwaitsResponse(&replyID));
567 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
568 status_t err = onGetPlaybackSettings(&rate);
569 sp<AMessage> response = new AMessage;
570 if (err == OK) {
571 writeToAMessage(response, rate);
572 }
573 response->setInt32("err", err);
574 response->postReply(replyID);
575 break;
576 }
577
578 case kWhatConfigSync:
579 {
580 sp<AReplyToken> replyID;
581 CHECK(msg->senderAwaitsResponse(&replyID));
582 AVSyncSettings sync;
583 float videoFpsHint;
584 readFromAMessage(msg, &sync, &videoFpsHint);
585 status_t err = onConfigSync(sync, videoFpsHint);
586 sp<AMessage> response = new AMessage;
587 response->setInt32("err", err);
588 response->postReply(replyID);
589 break;
590 }
591
592 case kWhatGetSyncSettings:
593 {
594 sp<AReplyToken> replyID;
595 CHECK(msg->senderAwaitsResponse(&replyID));
596
597 ALOGV("kWhatGetSyncSettings");
598 AVSyncSettings sync;
599 float videoFps = -1.f;
600 status_t err = onGetSyncSettings(&sync, &videoFps);
601 sp<AMessage> response = new AMessage;
602 if (err == OK) {
603 writeToAMessage(response, sync, videoFps);
604 }
605 response->setInt32("err", err);
606 response->postReply(replyID);
Wei Jia98160162015-02-04 17:01:11 -0800607 break;
608 }
609
Andreas Huberf9334412010-12-15 15:17:42 -0800610 case kWhatFlush:
611 {
612 onFlush(msg);
613 break;
614 }
615
Wei Jiabc2fb722014-07-08 16:37:57 -0700616 case kWhatDisableOffloadAudio:
617 {
618 onDisableOffloadAudio();
619 break;
620 }
621
Ronghua Wua10fd232014-11-06 16:15:20 -0800622 case kWhatEnableOffloadAudio:
623 {
624 onEnableOffloadAudio();
625 break;
626 }
627
Andreas Huberb4082222011-01-20 15:23:04 -0800628 case kWhatPause:
629 {
630 onPause();
631 break;
632 }
633
634 case kWhatResume:
635 {
636 onResume();
637 break;
638 }
639
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700640 case kWhatSetVideoFrameRate:
641 {
642 float fps;
643 CHECK(msg->findFloat("frame-rate", &fps));
644 onSetVideoFrameRate(fps);
645 break;
646 }
647
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700648 case kWhatAudioTearDown:
Wei Jia3a2956d2014-07-22 16:01:33 -0700649 {
Wei Jiaa05f1e32016-03-25 16:31:22 -0700650 int32_t reason;
651 CHECK(msg->findInt32("reason", &reason));
652
653 onAudioTearDown((AudioTearDownReason)reason);
Wei Jia3a2956d2014-07-22 16:01:33 -0700654 break;
655 }
656
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700657 case kWhatAudioOffloadPauseTimeout:
658 {
659 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800660 CHECK(msg->findInt32("drainGeneration", &generation));
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700661 if (generation != mAudioOffloadPauseTimeoutGeneration) {
662 break;
663 }
Ronghua Wu08529172014-10-02 16:55:52 -0700664 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700665 onAudioTearDown(kDueToTimeout);
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800666 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700667 break;
668 }
669
Andreas Huberf9334412010-12-15 15:17:42 -0800670 default:
671 TRESPASS();
672 break;
673 }
674}
675
Wei Jiabc2fb722014-07-08 16:37:57 -0700676void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700677 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800678 return;
679 }
680
681 if (mAudioQueue.empty()) {
682 return;
683 }
684
Andy Hungb03dcb32015-08-27 16:18:59 -0700685 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
686 if (mPaused) {
687 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
688 if (diffUs > delayUs) {
689 delayUs = diffUs;
690 }
691 }
692
Andreas Huberf9334412010-12-15 15:17:42 -0800693 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800694 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800695 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700696 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800697}
698
Wei Jia7b15cb32015-02-03 17:46:06 -0800699void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
700 mAudioRenderingStartGeneration = mAudioDrainGeneration;
701 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700702 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700703}
704
Wei Jia7b15cb32015-02-03 17:46:06 -0800705void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
706 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
707 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700708 mRenderingDataDelivered = true;
709 if (mPaused) {
710 return;
711 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700712 mVideoRenderingStartGeneration = -1;
713 mAudioRenderingStartGeneration = -1;
714
715 sp<AMessage> notify = mNotify->dup();
716 notify->setInt32("what", kWhatMediaRenderingStart);
717 notify->post();
718 }
719}
720
Wei Jiabc2fb722014-07-08 16:37:57 -0700721// static
722size_t NuPlayer::Renderer::AudioSinkCallback(
723 MediaPlayerBase::AudioSink * /* audioSink */,
724 void *buffer,
725 size_t size,
726 void *cookie,
727 MediaPlayerBase::AudioSink::cb_event_t event) {
728 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
729
730 switch (event) {
731 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
732 {
733 return me->fillAudioBuffer(buffer, size);
734 break;
735 }
736
737 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
738 {
Andy Hunga0b39712015-05-31 22:40:49 -0700739 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jiabc2fb722014-07-08 16:37:57 -0700740 me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
741 break;
742 }
743
744 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
745 {
Andy Hunga0b39712015-05-31 22:40:49 -0700746 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Wei Jiaa05f1e32016-03-25 16:31:22 -0700747 me->notifyAudioTearDown(kDueToError);
Wei Jiabc2fb722014-07-08 16:37:57 -0700748 break;
749 }
750 }
751
752 return 0;
753}
754
755size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
756 Mutex::Autolock autoLock(mLock);
757
Andy Hung85e48142015-05-31 23:04:15 -0700758 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700759 return 0;
760 }
761
762 bool hasEOS = false;
763
764 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700765 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700766 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700767 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700768 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700769
770 if (entry->mBuffer == NULL) { // EOS
771 hasEOS = true;
772 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700773 break;
774 }
775
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700776 if (firstEntry && entry->mOffset == 0) {
777 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700778 int64_t mediaTimeUs;
779 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -0700780 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800781 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700782 }
783
784 size_t copy = entry->mBuffer->size() - entry->mOffset;
785 size_t sizeRemaining = size - sizeCopied;
786 if (copy > sizeRemaining) {
787 copy = sizeRemaining;
788 }
789
790 memcpy((char *)buffer + sizeCopied,
791 entry->mBuffer->data() + entry->mOffset,
792 copy);
793
794 entry->mOffset += copy;
795 if (entry->mOffset == entry->mBuffer->size()) {
796 entry->mNotifyConsumed->post();
797 mAudioQueue.erase(mAudioQueue.begin());
798 entry = NULL;
799 }
800 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -0800801
802 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -0700803 }
804
Lajos Molnarf5926712014-10-21 09:36:43 -0700805 if (mAudioFirstAnchorTimeMediaUs >= 0) {
806 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -0800807 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -0700808 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800809 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -0800810 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -0700811 }
812
Andy Hunga0b39712015-05-31 22:40:49 -0700813 // for non-offloaded audio, we need to compute the frames written because
814 // there is no EVENT_STREAM_END notification. The frames written gives
815 // an estimate on the pending played out duration.
816 if (!offloadingAudio()) {
817 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -0700818 }
819
Andy Hunga0b39712015-05-31 22:40:49 -0700820 if (hasEOS) {
821 (new AMessage(kWhatStopAudioSink, this))->post();
822 // As there is currently no EVENT_STREAM_END callback notification for
823 // non-offloaded audio tracks, we need to post the EOS ourselves.
824 if (!offloadingAudio()) {
825 int64_t postEOSDelayUs = 0;
826 if (mAudioSink->needsTrailingPadding()) {
827 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
828 }
829 ALOGV("fillAudioBuffer: notifyEOS "
830 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
831 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
832 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
833 }
834 }
Wei Jiabc2fb722014-07-08 16:37:57 -0700835 return sizeCopied;
836}
837
Chong Zhang9da0ce42015-06-11 17:18:58 -0700838void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
839 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
840 bool foundEOS = false;
841 while (it != mAudioQueue.end()) {
842 int32_t eos;
843 QueueEntry *entry = &*it++;
844 if (entry->mBuffer == NULL
845 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
846 itEOS = it;
847 foundEOS = true;
848 }
849 }
850
851 if (foundEOS) {
852 // post all replies before EOS and drop the samples
853 for (it = mAudioQueue.begin(); it != itEOS; it++) {
854 if (it->mBuffer == NULL) {
855 // delay doesn't matter as we don't even have an AudioTrack
856 notifyEOS(true /* audio */, it->mFinalResult);
857 } else {
858 it->mNotifyConsumed->post();
859 }
860 }
861 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
862 }
863}
864
Andreas Huber078cfcf2011-09-15 12:25:04 -0700865bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -0700866 // do not drain audio during teardown as queued buffers may be invalid.
867 if (mAudioTornDown) {
868 return false;
869 }
Wei Jia230b1882015-03-19 15:13:51 -0700870 // TODO: This call to getPosition checks if AudioTrack has been created
871 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
872 // CHECKs on getPosition will fail.
873 // We still need to figure out why AudioTrack is not created when
874 // this function is called. One possible reason could be leftover
875 // audio. Another possible place is to check whether decoder
876 // has received INFO_FORMAT_CHANGED as the first buffer since
877 // AudioSink is opened there, and possible interactions with flush
878 // immediately after start. Investigate error message
879 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700880 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700881 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -0700882 // When getPosition fails, renderer will not reschedule the draining
883 // unless new samples are queued.
884 // If we have pending EOS (or "eos" marker for discontinuities), we need
885 // to post these now as NuPlayerDecoder might be waiting for it.
886 drainAudioQueueUntilLastEOS();
887
888 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700889 return false;
890 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700891
Wei Jia230b1882015-03-19 15:13:51 -0700892#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -0700893 ssize_t numFramesAvailableToWrite =
894 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
895
Andreas Huber078cfcf2011-09-15 12:25:04 -0700896 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000897 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700898 } else {
Steve Block3856b092011-10-20 11:56:00 +0100899 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700900 mAudioSink->frameCount() - numFramesAvailableToWrite);
901 }
902#endif
903
Andy Hung005e9d02015-05-31 23:16:07 -0700904 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -0800905 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700906 QueueEntry *entry = &*mAudioQueue.begin();
907
Lajos Molnard5923402014-10-20 17:47:54 -0700908 mLastAudioBufferDrained = entry->mBufferOrdinal;
909
Andreas Huberc92fd242011-08-16 13:48:44 -0700910 if (entry->mBuffer == NULL) {
911 // EOS
Ronghua Wu5095d702014-08-27 12:05:48 -0700912 int64_t postEOSDelayUs = 0;
913 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -0700914 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -0700915 }
916 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -0700917 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -0700918
919 mAudioQueue.erase(mAudioQueue.begin());
920 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -0800921 if (mAudioSink->needsTrailingPadding()) {
922 // If we're not in gapless playback (i.e. through setNextPlayer), we
923 // need to stop the track here, because that will play out the last
924 // little bit at the end of the file. Otherwise short files won't play.
925 mAudioSink->stop();
926 mNumFramesWritten = 0;
927 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700928 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700929 }
930
Chong Zhang81636762015-04-21 09:33:47 -0700931 // ignore 0-sized buffer which could be EOS marker with no data
932 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -0800933 int64_t mediaTimeUs;
934 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -0700935 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
936 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -0700937 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800938 }
939
940 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -0800941
Wei Jia7d3f4df2015-03-03 15:28:00 -0800942 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
943 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -0700944 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -0800945 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800946 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -0700947 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -0800948 } else {
949 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -0700950 // This can only happen when AudioSink was opened with doNotReconnect flag set to
951 // true, in which case the NuPlayer will handle the reconnect.
Wei Jiaa05f1e32016-03-25 16:31:22 -0700952 notifyAudioTearDown(kDueToError);
Wei Jia7d3f4df2015-03-03 15:28:00 -0800953 }
Andy Hung202bce12014-12-03 11:47:36 -0800954 break;
Andy Hunga31335a2014-08-20 17:37:59 -0700955 }
Andreas Huberf9334412010-12-15 15:17:42 -0800956
Andy Hunga31335a2014-08-20 17:37:59 -0700957 entry->mOffset += written;
Andreas Huberf9334412010-12-15 15:17:42 -0800958 if (entry->mOffset == entry->mBuffer->size()) {
959 entry->mNotifyConsumed->post();
960 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700961
Andreas Huberf9334412010-12-15 15:17:42 -0800962 entry = NULL;
963 }
964
Andy Hunga31335a2014-08-20 17:37:59 -0700965 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700966 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700967
Wei Jia7b15cb32015-02-03 17:46:06 -0800968 {
969 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -0700970 int64_t maxTimeMedia;
971 maxTimeMedia =
972 mAnchorTimeMediaUs +
973 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
974 * 1000LL * mAudioSink->msecsPerFrame());
975 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
976
Wei Jia7b15cb32015-02-03 17:46:06 -0800977 notifyIfMediaRenderingStarted_l();
978 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800979
Andy Hunga31335a2014-08-20 17:37:59 -0700980 if (written != (ssize_t)copy) {
981 // A short count was received from AudioSink::write()
982 //
Wei Jia7d3f4df2015-03-03 15:28:00 -0800983 // AudioSink write is called in non-blocking mode.
984 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -0700985 //
986 // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800987 // 2) The data to be copied exceeds the available buffer in AudioSink.
988 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
989 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -0700990
991 // (Case 1)
992 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
993 // needs to fail, as we should not carry over fractional frames between calls.
994 CHECK_EQ(copy % mAudioSink->frameSize(), 0);
995
Wei Jia7d3f4df2015-03-03 15:28:00 -0800996 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -0700997 // Return early to the caller.
998 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800999 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -07001000 break;
1001 }
1002 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001003
Andy Hung005e9d02015-05-31 23:16:07 -07001004 // calculate whether we need to reschedule another write.
1005 bool reschedule = !mAudioQueue.empty()
1006 && (!mPaused
1007 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1008 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1009 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1010 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001011}
1012
Wei Jia98160162015-02-04 17:01:11 -08001013int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1014 int32_t sampleRate = offloadingAudio() ?
1015 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001016 if (sampleRate == 0) {
1017 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1018 return 0;
1019 }
Wei Jia98160162015-02-04 17:01:11 -08001020 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1021 return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
1022}
1023
1024// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001025int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001026 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiad2f35de2016-02-17 16:48:06 -08001027 if (mUseVirtualAudioSink) {
1028 int64_t nowUs = ALooper::GetNowUs();
1029 int64_t mediaUs;
1030 if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
1031 return 0ll;
1032 } else {
1033 return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1034 }
1035 }
Wei Jiac4ac8172015-10-21 10:35:48 -07001036 return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
Ronghua Wu5095d702014-08-27 12:05:48 -07001037}
1038
Ronghua Wua73d9e02014-10-08 15:13:29 -07001039int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001040 int64_t realUs;
1041 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001042 // If failed to get current position, e.g. due to audio clock is
1043 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001044 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001045 }
Wei Jia98160162015-02-04 17:01:11 -08001046 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001047}
1048
Ronghua Wueecb7802014-10-19 23:12:50 -07001049void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001050 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001051 // TRICKY: vorbis decoder generates multiple frames with the same
1052 // timestamp, so only update on the first frame with a given timestamp
1053 if (mediaTimeUs == mAnchorTimeMediaUs) {
1054 return;
1055 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001056 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001057
Andy Hung528c8402016-01-12 12:39:34 -08001058 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1059 if (mNextAudioClockUpdateTimeUs == -1) {
1060 AudioTimestamp ts;
1061 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1062 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1063 }
1064 }
Wei Jia12b62652016-02-09 17:49:31 -08001065 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001066 if (mNextAudioClockUpdateTimeUs >= 0) {
1067 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1068 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1069 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001070 mUseVirtualAudioSink = false;
Andy Hung528c8402016-01-12 12:39:34 -08001071 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1072 }
Wei Jia12b62652016-02-09 17:49:31 -08001073 } else {
1074 int64_t unused;
1075 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1076 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1077 > kMaxAllowedAudioSinkDelayUs)) {
1078 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1079 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1080 // connected to audio out.
1081 // Switch to system clock. This essentially creates a virtual AudioSink with
1082 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1083 // This virtual AudioSink renders audio data starting from the very first sample
1084 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001085 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001086 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001087 mUseVirtualAudioSink = true;
Wei Jia12b62652016-02-09 17:49:31 -08001088 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001089 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001090 mAnchorNumFramesWritten = mNumFramesWritten;
Wei Jia7b15cb32015-02-03 17:46:06 -08001091 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001092}
1093
Wei Jia7b15cb32015-02-03 17:46:06 -08001094// Called without mLock acquired.
1095void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001096 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001097 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001098 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001099 return;
1100 }
1101
1102 if (mVideoQueue.empty()) {
1103 return;
1104 }
1105
1106 QueueEntry &entry = *mVideoQueue.begin();
1107
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001108 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001109 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001110
Andreas Huberf9334412010-12-15 15:17:42 -08001111 if (entry.mBuffer == NULL) {
1112 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001113 msg->post();
1114 mDrainVideoQueuePending = true;
1115 return;
1116 }
1117
Robert Shih00541e22015-12-18 17:04:00 -08001118 bool needRepostDrainVideoQueue = false;
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001119 int64_t delayUs;
1120 int64_t nowUs = ALooper::GetNowUs();
1121 int64_t realTimeUs;
1122 if (mFlags & FLAG_REAL_TIME) {
Andreas Huberd5e56232013-03-12 11:01:43 -07001123 int64_t mediaTimeUs;
1124 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001125 realTimeUs = mediaTimeUs;
Andreas Huberf9334412010-12-15 15:17:42 -08001126 } else {
1127 int64_t mediaTimeUs;
1128 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1129
Wei Jia7b15cb32015-02-03 17:46:06 -08001130 {
1131 Mutex::Autolock autoLock(mLock);
1132 if (mAnchorTimeMediaUs < 0) {
1133 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1134 mAnchorTimeMediaUs = mediaTimeUs;
1135 realTimeUs = nowUs;
Wei Jia25d696f2015-11-19 10:57:15 -08001136 } else if (!mVideoSampleReceived) {
1137 // Always render the first video frame.
1138 realTimeUs = nowUs;
Robert Shih00541e22015-12-18 17:04:00 -08001139 } else if (mAudioFirstAnchorTimeMediaUs < 0
1140 || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001141 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Robert Shih00541e22015-12-18 17:04:00 -08001142 } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
1143 needRepostDrainVideoQueue = true;
1144 realTimeUs = nowUs;
1145 } else {
1146 realTimeUs = nowUs;
Wei Jia7b15cb32015-02-03 17:46:06 -08001147 }
Andreas Huberf9334412010-12-15 15:17:42 -08001148 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001149 if (!mHasAudio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001150 // smooth out videos >= 10fps
1151 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
Lajos Molnarf5926712014-10-21 09:36:43 -07001152 }
Lajos Molnard5923402014-10-20 17:47:54 -07001153
1154 // Heuristics to handle situation when media time changed without a
1155 // discontinuity. If we have not drained an audio buffer that was
1156 // received after this buffer, repost in 10 msec. Otherwise repost
1157 // in 500 msec.
1158 delayUs = realTimeUs - nowUs;
Robert Shih00541e22015-12-18 17:04:00 -08001159 int64_t postDelayUs = -1;
Lajos Molnard5923402014-10-20 17:47:54 -07001160 if (delayUs > 500000) {
Robert Shih00541e22015-12-18 17:04:00 -08001161 postDelayUs = 500000;
Lajos Molnard5923402014-10-20 17:47:54 -07001162 if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1163 postDelayUs = 10000;
1164 }
Robert Shih00541e22015-12-18 17:04:00 -08001165 } else if (needRepostDrainVideoQueue) {
1166 // CHECK(mPlaybackRate > 0);
1167 // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
1168 // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
1169 postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
1170 postDelayUs /= mPlaybackRate;
1171 }
1172
1173 if (postDelayUs >= 0) {
Lajos Molnard5923402014-10-20 17:47:54 -07001174 msg->setWhat(kWhatPostDrainVideoQueue);
1175 msg->post(postDelayUs);
1176 mVideoScheduler->restart();
Robert Shih00541e22015-12-18 17:04:00 -08001177 ALOGI("possible video time jump of %dms or uninitialized media clock, retrying in %dms",
Lajos Molnard5923402014-10-20 17:47:54 -07001178 (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1179 mDrainVideoQueuePending = true;
1180 return;
1181 }
Andreas Huberf9334412010-12-15 15:17:42 -08001182 }
1183
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001184 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1185 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1186
1187 delayUs = realTimeUs - nowUs;
1188
Lajos Molnar09524832014-07-17 14:29:51 -07001189 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001190 // post 2 display refreshes before rendering is due
1191 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
Andreas Huberf9334412010-12-15 15:17:42 -08001192
1193 mDrainVideoQueuePending = true;
1194}
1195
1196void NuPlayer::Renderer::onDrainVideoQueue() {
1197 if (mVideoQueue.empty()) {
1198 return;
1199 }
1200
1201 QueueEntry *entry = &*mVideoQueue.begin();
1202
1203 if (entry->mBuffer == NULL) {
1204 // EOS
1205
Andreas Huberc92fd242011-08-16 13:48:44 -07001206 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001207
1208 mVideoQueue.erase(mVideoQueue.begin());
1209 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001210
Ronghua Wua73d9e02014-10-08 15:13:29 -07001211 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001212 return;
1213 }
1214
Wei Jia25d696f2015-11-19 10:57:15 -08001215 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001216 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001217 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001218 if (mFlags & FLAG_REAL_TIME) {
1219 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1220 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001221 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001222
Ronghua Wua73d9e02014-10-08 15:13:29 -07001223 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001224 }
1225
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001226 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001227
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001228 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001229 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001230 tooLate = (mVideoLateByUs > 40000);
1231
1232 if (tooLate) {
1233 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001234 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001235 } else {
Wei Jia98160162015-02-04 17:01:11 -08001236 int64_t mediaUs = 0;
1237 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001238 ALOGV("rendering video at media time %.2f secs",
1239 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001240 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001241
1242 if (!(mFlags & FLAG_REAL_TIME)
1243 && mLastAudioMediaTimeUs != -1
1244 && mediaTimeUs > mLastAudioMediaTimeUs) {
1245 // If audio ends before video, video continues to drive media clock.
1246 // Also smooth out videos >= 10fps.
1247 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1248 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001249 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001250 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001251 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001252 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001253 // This will ensure that the first frame after a flush won't be used as anchor
1254 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia7b15cb32015-02-03 17:46:06 -08001255 Mutex::Autolock autoLock(mLock);
1256 clearAnchorTime_l();
Wei Jia49966ff2014-10-08 18:44:45 -07001257 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001258 }
Andreas Huberf9334412010-12-15 15:17:42 -08001259
Wei Jia25d696f2015-11-19 10:57:15 -08001260 // Always render the first video frame while keeping stats on A/V sync.
1261 if (!mVideoSampleReceived) {
1262 realTimeUs = nowUs;
1263 tooLate = false;
1264 }
1265
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001266 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
Glenn Kasten683525b2011-11-04 18:05:35 -07001267 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001268 entry->mNotifyConsumed->post();
1269 mVideoQueue.erase(mVideoQueue.begin());
1270 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001271
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001272 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001273
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001274 if (!mPaused) {
1275 if (!mVideoRenderingStarted) {
1276 mVideoRenderingStarted = true;
1277 notifyVideoRenderingStart();
1278 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001279 Mutex::Autolock autoLock(mLock);
1280 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001281 }
Andreas Huberf9334412010-12-15 15:17:42 -08001282}
1283
James Dongf57b4ea2012-07-20 13:38:36 -07001284void NuPlayer::Renderer::notifyVideoRenderingStart() {
1285 sp<AMessage> notify = mNotify->dup();
1286 notify->setInt32("what", kWhatVideoRenderingStart);
1287 notify->post();
1288}
1289
Ronghua Wu5095d702014-08-27 12:05:48 -07001290void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001291 if (audio && delayUs > 0) {
1292 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1293 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1294 msg->setInt32("finalResult", finalResult);
1295 msg->post(delayUs);
1296 return;
1297 }
Andreas Huberf9334412010-12-15 15:17:42 -08001298 sp<AMessage> notify = mNotify->dup();
1299 notify->setInt32("what", kWhatEOS);
1300 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001301 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001302 notify->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001303}
1304
Wei Jiaa05f1e32016-03-25 16:31:22 -07001305void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1306 sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1307 msg->setInt32("reason", reason);
1308 msg->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001309}
1310
Andreas Huberf9334412010-12-15 15:17:42 -08001311void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1312 int32_t audio;
1313 CHECK(msg->findInt32("audio", &audio));
1314
Wei Jia7b15cb32015-02-03 17:46:06 -08001315 if (dropBufferIfStale(audio, msg)) {
1316 return;
1317 }
1318
1319 if (audio) {
1320 mHasAudio = true;
1321 } else {
1322 mHasVideo = true;
1323 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001324
1325 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001326 if (mVideoScheduler == NULL) {
1327 mVideoScheduler = new VideoFrameScheduler();
1328 mVideoScheduler->init();
1329 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001330 }
1331
Andreas Huber2d8bedd2012-02-21 14:38:23 -08001332 sp<ABuffer> buffer;
1333 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -08001334
1335 sp<AMessage> notifyConsumed;
1336 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1337
1338 QueueEntry entry;
1339 entry.mBuffer = buffer;
1340 entry.mNotifyConsumed = notifyConsumed;
1341 entry.mOffset = 0;
1342 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001343 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001344
1345 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001346 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001347 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001348 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001349 } else {
1350 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001351 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001352 }
1353
Wei Jia7b15cb32015-02-03 17:46:06 -08001354 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001355 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1356 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001357 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001358
1359 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1360 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1361
1362 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1363 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001364 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001365 return;
1366 }
1367
1368 int64_t firstAudioTimeUs;
1369 int64_t firstVideoTimeUs;
1370 CHECK(firstAudioBuffer->meta()
1371 ->findInt64("timeUs", &firstAudioTimeUs));
1372 CHECK(firstVideoBuffer->meta()
1373 ->findInt64("timeUs", &firstVideoTimeUs));
1374
1375 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1376
Steve Block3856b092011-10-20 11:56:00 +01001377 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001378
1379 if (diff > 100000ll) {
1380 // Audio data starts More than 0.1 secs before video.
1381 // Drop some audio.
1382
1383 (*mAudioQueue.begin()).mNotifyConsumed->post();
1384 mAudioQueue.erase(mAudioQueue.begin());
1385 return;
1386 }
1387
Wei Jiabc2fb722014-07-08 16:37:57 -07001388 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001389}
1390
Wei Jiabc2fb722014-07-08 16:37:57 -07001391void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001392 if (!mSyncQueues) {
1393 return;
1394 }
1395
1396 mSyncQueues = false;
1397
1398 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001399 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001400 }
1401
1402 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001403 mLock.unlock();
1404 postDrainVideoQueue();
1405 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001406 }
1407}
1408
1409void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1410 int32_t audio;
1411 CHECK(msg->findInt32("audio", &audio));
1412
Wei Jia7b15cb32015-02-03 17:46:06 -08001413 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001414 return;
1415 }
1416
1417 int32_t finalResult;
1418 CHECK(msg->findInt32("finalResult", &finalResult));
1419
1420 QueueEntry entry;
1421 entry.mOffset = 0;
1422 entry.mFinalResult = finalResult;
1423
1424 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001425 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001426 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001427 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001428 }
Andreas Huberf9334412010-12-15 15:17:42 -08001429 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001430 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001431 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001432 if (mVideoQueue.empty() && getSyncQueues()) {
1433 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001434 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001435 }
Andreas Huberf9334412010-12-15 15:17:42 -08001436 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001437 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001438 }
1439}
1440
1441void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001442 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001443 CHECK(msg->findInt32("audio", &audio));
1444
Wei Jia28a8a9f2014-08-18 11:29:50 -07001445 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001446 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001447 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001448 notifyComplete = mNotifyCompleteAudio;
1449 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001450 mLastAudioMediaTimeUs = -1;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001451 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001452 notifyComplete = mNotifyCompleteVideo;
1453 mNotifyCompleteVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001454 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001455
Wei Jia7b15cb32015-02-03 17:46:06 -08001456 // If we're currently syncing the queues, i.e. dropping audio while
1457 // aligning the first audio/video buffer times and only one of the
1458 // two queues has data, we may starve that queue by not requesting
1459 // more buffers from the decoder. If the other source then encounters
1460 // a discontinuity that leads to flushing, we'll never find the
1461 // corresponding discontinuity on the other queue.
1462 // Therefore we'll stop syncing the queues if at least one of them
1463 // is flushed.
1464 syncQueuesDone_l();
1465 clearAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001466 }
Andreas Huberf9334412010-12-15 15:17:42 -08001467
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001468 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001469 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001470 {
1471 Mutex::Autolock autoLock(mLock);
1472 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001473
Wei Jia7b15cb32015-02-03 17:46:06 -08001474 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001475 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001476 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001477
Andy Hunga0b39712015-05-31 22:40:49 -07001478 // the frame count will be reset after flush.
1479 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001480 }
Andreas Huberf9334412010-12-15 15:17:42 -08001481
Andreas Huberf9334412010-12-15 15:17:42 -08001482 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001483
Wei Jiabc2fb722014-07-08 16:37:57 -07001484 if (offloadingAudio()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001485 mAudioSink->pause();
1486 mAudioSink->flush();
Andy Hung85e48142015-05-31 23:04:15 -07001487 if (!mPaused) {
1488 mAudioSink->start();
1489 }
Wei Jia9e7ed332015-05-01 16:35:43 -07001490 } else {
1491 mAudioSink->pause();
1492 mAudioSink->flush();
1493 // Call stop() to signal to the AudioSink to completely fill the
1494 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001495 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001496 mAudioSink->stop();
Andy Hungb03dcb32015-08-27 16:18:59 -07001497 if (mPaused) {
1498 // Race condition: if renderer is paused and audio sink is stopped,
1499 // we need to make sure that the audio track buffer fully drains
1500 // before delivering data.
1501 // FIXME: remove this if we can detect if stop() is complete.
1502 const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1503 mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1504 } else {
Wei Jia9e7ed332015-05-01 16:35:43 -07001505 mAudioSink->start();
1506 }
1507 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001508 }
Andy Hung528c8402016-01-12 12:39:34 -08001509 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001510 } else {
1511 flushQueue(&mVideoQueue);
1512
Andreas Huberf9334412010-12-15 15:17:42 -08001513 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001514
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001515 if (mVideoScheduler != NULL) {
1516 mVideoScheduler->restart();
1517 }
1518
Wei Jia7b15cb32015-02-03 17:46:06 -08001519 Mutex::Autolock autoLock(mLock);
1520 ++mVideoDrainGeneration;
1521 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001522 }
1523
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001524 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001525
1526 if (notifyComplete) {
1527 notifyFlushComplete(audio);
1528 }
Andreas Huberf9334412010-12-15 15:17:42 -08001529}
1530
1531void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1532 while (!queue->empty()) {
1533 QueueEntry *entry = &*queue->begin();
1534
1535 if (entry->mBuffer != NULL) {
1536 entry->mNotifyConsumed->post();
1537 }
1538
1539 queue->erase(queue->begin());
1540 entry = NULL;
1541 }
1542}
1543
1544void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1545 sp<AMessage> notify = mNotify->dup();
1546 notify->setInt32("what", kWhatFlushComplete);
1547 notify->setInt32("audio", static_cast<int32_t>(audio));
1548 notify->post();
1549}
1550
Wei Jia7b15cb32015-02-03 17:46:06 -08001551bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001552 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001553 int32_t queueGeneration;
1554 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001555
Wei Jia7b15cb32015-02-03 17:46:06 -08001556 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001557 return false;
1558 }
1559
1560 sp<AMessage> notifyConsumed;
1561 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1562 notifyConsumed->post();
1563 }
1564
1565 return true;
1566}
1567
Andreas Huber3831a062010-12-21 10:22:33 -08001568void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001569 if (offloadingAudio()) {
1570 return;
1571 }
Andreas Huber3831a062010-12-21 10:22:33 -08001572 CHECK(!mDrainAudioQueuePending);
1573 mNumFramesWritten = 0;
Wei Jia7b15cb32015-02-03 17:46:06 -08001574 {
1575 Mutex::Autolock autoLock(mLock);
1576 mAnchorNumFramesWritten = -1;
1577 }
Marco Nelissen4110c102012-03-29 09:31:28 -07001578 uint32_t written;
1579 if (mAudioSink->getFramesWritten(&written) == OK) {
1580 mNumFramesWritten = written;
1581 }
Andreas Huber3831a062010-12-21 10:22:33 -08001582}
1583
Wei Jiabc2fb722014-07-08 16:37:57 -07001584void NuPlayer::Renderer::onDisableOffloadAudio() {
1585 Mutex::Autolock autoLock(mLock);
1586 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001587 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001588 if (mAudioRenderingStartGeneration != -1) {
1589 prepareForMediaRenderingStart_l();
1590 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001591}
1592
Ronghua Wua10fd232014-11-06 16:15:20 -08001593void NuPlayer::Renderer::onEnableOffloadAudio() {
1594 Mutex::Autolock autoLock(mLock);
1595 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001596 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001597 if (mAudioRenderingStartGeneration != -1) {
1598 prepareForMediaRenderingStart_l();
1599 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001600}
1601
Andreas Huberb4082222011-01-20 15:23:04 -08001602void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001603 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001604 return;
1605 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001606
Wei Jia28a8a9f2014-08-18 11:29:50 -07001607 {
1608 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001609 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001610 ++mVideoDrainGeneration;
1611 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001612 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001613 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001614 }
1615
Andreas Huberb4082222011-01-20 15:23:04 -08001616 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001617 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001618
Andy Hung84200732015-12-03 14:41:06 -08001619 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1620 mAudioSink->pause();
1621 startAudioOffloadPauseTimeout();
Andreas Huberb4082222011-01-20 15:23:04 -08001622
Lajos Molnar6d339f12015-04-17 16:15:53 -07001623 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001624 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001625}
1626
1627void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001628 if (!mPaused) {
1629 return;
1630 }
Andreas Huberb4082222011-01-20 15:23:04 -08001631
Andy Hung84200732015-12-03 14:41:06 -08001632 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1633 cancelAudioOffloadPauseTimeout();
1634 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001635 status_t err = mAudioSink->start();
1636 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001637 ALOGE("cannot start AudioSink err %d", err);
Wei Jiaa05f1e32016-03-25 16:31:22 -07001638 notifyAudioTearDown(kDueToError);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001639 }
Andreas Huberb4082222011-01-20 15:23:04 -08001640 }
1641
Wei Jia7b15cb32015-02-03 17:46:06 -08001642 {
1643 Mutex::Autolock autoLock(mLock);
1644 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001645 // rendering started message may have been delayed if we were paused.
1646 if (mRenderingDataDelivered) {
1647 notifyIfMediaRenderingStarted_l();
1648 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001649 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001650 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001651 mAudioSink->setPlaybackRate(mPlaybackSettings);
1652 }
1653
Wei Jia98160162015-02-04 17:01:11 -08001654 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001655
Wei Jia7b15cb32015-02-03 17:46:06 -08001656 if (!mAudioQueue.empty()) {
1657 postDrainAudioQueue_l();
1658 }
Andreas Huberb4082222011-01-20 15:23:04 -08001659 }
1660
1661 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001662 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001663 }
1664}
1665
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001666void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1667 if (mVideoScheduler == NULL) {
1668 mVideoScheduler = new VideoFrameScheduler();
1669 }
1670 mVideoScheduler->init(fps);
1671}
1672
Wei Jia7b15cb32015-02-03 17:46:06 -08001673int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1674 Mutex::Autolock autoLock(mLock);
1675 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1676}
1677
1678int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1679 Mutex::Autolock autoLock(mLock);
1680 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1681}
1682
1683bool NuPlayer::Renderer::getSyncQueues() {
1684 Mutex::Autolock autoLock(mLock);
1685 return mSyncQueues;
1686}
1687
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001688void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1689 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001690 return;
1691 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001692 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001693
Ronghua Wua73d9e02014-10-08 15:13:29 -07001694 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001695 sp<AMessage> notify = mNotify->dup();
1696 if (getCurrentPosition(&currentPositionUs) == OK) {
1697 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001698 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001699
Wei Jia3a2956d2014-07-22 16:01:33 -07001700 mAudioSink->stop();
1701 mAudioSink->flush();
1702
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001703 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001704 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001705 notify->post();
1706}
1707
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001708void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1709 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001710 mWakeLock->acquire();
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001711 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001712 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001713 msg->post(kOffloadPauseMaxUs);
1714 }
1715}
1716
1717void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1718 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001719 mWakeLock->release(true);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001720 ++mAudioOffloadPauseTimeoutGeneration;
1721 }
1722}
1723
Andy Hung202bce12014-12-03 11:47:36 -08001724status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001725 const sp<AMessage> &format,
1726 bool offloadOnly,
1727 bool hasVideo,
1728 uint32_t flags) {
1729 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1730 offloadOnly, offloadingAudio());
1731 bool audioSinkChanged = false;
1732
1733 int32_t numChannels;
1734 CHECK(format->findInt32("channel-count", &numChannels));
1735
1736 int32_t channelMask;
1737 if (!format->findInt32("channel-mask", &channelMask)) {
1738 // signal to the AudioSink to derive the mask from count.
1739 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
1740 }
1741
1742 int32_t sampleRate;
1743 CHECK(format->findInt32("sample-rate", &sampleRate));
1744
1745 if (offloadingAudio()) {
1746 audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
1747 AString mime;
1748 CHECK(format->findString("mime", &mime));
1749 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
1750
1751 if (err != OK) {
1752 ALOGE("Couldn't map mime \"%s\" to a valid "
1753 "audio_format", mime.c_str());
1754 onDisableOffloadAudio();
1755 } else {
1756 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
1757 mime.c_str(), audioFormat);
1758
1759 int avgBitRate = -1;
1760 format->findInt32("bit-rate", &avgBitRate);
1761
1762 int32_t aacProfile = -1;
1763 if (audioFormat == AUDIO_FORMAT_AAC
1764 && format->findInt32("aac-profile", &aacProfile)) {
1765 // Redefine AAC format as per aac profile
1766 mapAACProfileToAudioFormat(
1767 audioFormat,
1768 aacProfile);
1769 }
1770
1771 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
1772 offloadInfo.duration_us = -1;
1773 format->findInt64(
1774 "durationUs", &offloadInfo.duration_us);
1775 offloadInfo.sample_rate = sampleRate;
1776 offloadInfo.channel_mask = channelMask;
1777 offloadInfo.format = audioFormat;
1778 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
1779 offloadInfo.bit_rate = avgBitRate;
1780 offloadInfo.has_video = hasVideo;
1781 offloadInfo.is_streaming = true;
1782
1783 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
1784 ALOGV("openAudioSink: no change in offload mode");
1785 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08001786 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001787 }
Andy Hungf0e83642014-12-19 17:55:56 -08001788 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1789
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001790 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001791 uint32_t offloadFlags = flags;
1792 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1793 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001794 audioSinkChanged = true;
1795 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07001796
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001797 err = mAudioSink->open(
1798 sampleRate,
1799 numChannels,
1800 (audio_channel_mask_t)channelMask,
1801 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07001802 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001803 &NuPlayer::Renderer::AudioSinkCallback,
1804 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001805 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001806 &offloadInfo);
1807
1808 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001809 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
1810 }
1811
1812 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001813 // If the playback is offloaded to h/w, we pass
1814 // the HAL some metadata information.
1815 // We don't want to do this for PCM because it
1816 // will be going through the AudioFlinger mixer
1817 // before reaching the hardware.
1818 // TODO
1819 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07001820 if (!mPaused) { // for preview mode, don't start if paused
1821 err = mAudioSink->start();
1822 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001823 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
1824 }
1825 if (err != OK) {
1826 // Clean up, fall back to non offload mode.
1827 mAudioSink->close();
1828 onDisableOffloadAudio();
1829 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1830 ALOGV("openAudioSink: offload failed");
Wei Jiaa05f1e32016-03-25 16:31:22 -07001831 if (offloadOnly) {
1832 notifyAudioTearDown(kForceNonOffload);
1833 }
Wei Jia3ab25452015-06-10 09:37:47 -07001834 } else {
1835 mUseAudioCallback = true; // offload mode transfers data through callback
1836 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001837 }
1838 }
1839 }
1840 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001841 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001842 uint32_t pcmFlags = flags;
1843 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08001844
1845 const PcmInfo info = {
1846 (audio_channel_mask_t)channelMask,
1847 (audio_output_flags_t)pcmFlags,
1848 AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1849 numChannels,
1850 sampleRate
1851 };
1852 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1853 ALOGV("openAudioSink: no change in pcm mode");
1854 // no change from previous configuration, everything ok.
1855 return OK;
1856 }
1857
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001858 audioSinkChanged = true;
1859 mAudioSink->close();
1860 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07001861 // Note: It is possible to set up the callback, but not use it to send audio data.
1862 // This requires a fix in AudioSink to explicitly specify the transfer mode.
1863 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07001864 if (mUseAudioCallback) {
1865 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
1866 }
Andy Hung179652e2015-05-31 22:49:46 -07001867
1868 // Compute the desired buffer size.
1869 // For callback mode, the amount of time before wakeup is about half the buffer size.
1870 const uint32_t frameCount =
1871 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1872
Ronghua Wu7665f582015-09-02 10:15:30 -07001873 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
1874 // AudioSink. We don't want this when there's video because it will cause a video seek to
1875 // the previous I frame. But we do want this when there's only audio because it will give
1876 // NuPlayer a chance to switch from non-offload mode to offload mode.
1877 // So we only set doNotReconnect when there's no video.
1878 const bool doNotReconnect = !hasVideo;
Andy Hungff874dc2016-04-11 16:49:09 -07001879
1880 // We should always be able to set our playback settings if the sink is closed.
1881 LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
1882 "onOpenAudioSink: can't set playback rate on closed sink");
Andy Hung202bce12014-12-03 11:47:36 -08001883 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001884 sampleRate,
1885 numChannels,
1886 (audio_channel_mask_t)channelMask,
1887 AUDIO_FORMAT_PCM_16_BIT,
Andy Hung179652e2015-05-31 22:49:46 -07001888 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07001889 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1890 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001891 (audio_output_flags_t)pcmFlags,
1892 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07001893 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07001894 frameCount);
Andy Hung202bce12014-12-03 11:47:36 -08001895 if (err != OK) {
1896 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07001897 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08001898 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08001899 return err;
1900 }
Andy Hungf0e83642014-12-19 17:55:56 -08001901 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07001902 if (!mPaused) { // for preview mode, don't start if paused
1903 mAudioSink->start();
1904 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001905 }
1906 if (audioSinkChanged) {
1907 onAudioSinkChanged();
1908 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001909 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08001910 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001911}
1912
1913void NuPlayer::Renderer::onCloseAudioSink() {
1914 mAudioSink->close();
1915 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08001916 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001917}
1918
Andreas Huberf9334412010-12-15 15:17:42 -08001919} // namespace android
1920