blob: 0e6a6e6d15428c57fada83fa151f34cac4015332 [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 {
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700650 onAudioTearDown(kDueToError);
Wei Jia3a2956d2014-07-22 16:01:33 -0700651 break;
652 }
653
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700654 case kWhatAudioOffloadPauseTimeout:
655 {
656 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800657 CHECK(msg->findInt32("drainGeneration", &generation));
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700658 if (generation != mAudioOffloadPauseTimeoutGeneration) {
659 break;
660 }
Ronghua Wu08529172014-10-02 16:55:52 -0700661 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700662 onAudioTearDown(kDueToTimeout);
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800663 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700664 break;
665 }
666
Andreas Huberf9334412010-12-15 15:17:42 -0800667 default:
668 TRESPASS();
669 break;
670 }
671}
672
Wei Jiabc2fb722014-07-08 16:37:57 -0700673void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700674 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800675 return;
676 }
677
678 if (mAudioQueue.empty()) {
679 return;
680 }
681
Andy Hungb03dcb32015-08-27 16:18:59 -0700682 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
683 if (mPaused) {
684 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
685 if (diffUs > delayUs) {
686 delayUs = diffUs;
687 }
688 }
689
Andreas Huberf9334412010-12-15 15:17:42 -0800690 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800691 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800692 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700693 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800694}
695
Wei Jia7b15cb32015-02-03 17:46:06 -0800696void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
697 mAudioRenderingStartGeneration = mAudioDrainGeneration;
698 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700699 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700700}
701
Wei Jia7b15cb32015-02-03 17:46:06 -0800702void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
703 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
704 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700705 mRenderingDataDelivered = true;
706 if (mPaused) {
707 return;
708 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700709 mVideoRenderingStartGeneration = -1;
710 mAudioRenderingStartGeneration = -1;
711
712 sp<AMessage> notify = mNotify->dup();
713 notify->setInt32("what", kWhatMediaRenderingStart);
714 notify->post();
715 }
716}
717
Wei Jiabc2fb722014-07-08 16:37:57 -0700718// static
719size_t NuPlayer::Renderer::AudioSinkCallback(
720 MediaPlayerBase::AudioSink * /* audioSink */,
721 void *buffer,
722 size_t size,
723 void *cookie,
724 MediaPlayerBase::AudioSink::cb_event_t event) {
725 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
726
727 switch (event) {
728 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
729 {
730 return me->fillAudioBuffer(buffer, size);
731 break;
732 }
733
734 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
735 {
Andy Hunga0b39712015-05-31 22:40:49 -0700736 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jiabc2fb722014-07-08 16:37:57 -0700737 me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
738 break;
739 }
740
741 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
742 {
Andy Hunga0b39712015-05-31 22:40:49 -0700743 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700744 me->notifyAudioTearDown();
Wei Jiabc2fb722014-07-08 16:37:57 -0700745 break;
746 }
747 }
748
749 return 0;
750}
751
752size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
753 Mutex::Autolock autoLock(mLock);
754
Andy Hung85e48142015-05-31 23:04:15 -0700755 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700756 return 0;
757 }
758
759 bool hasEOS = false;
760
761 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700762 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700763 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700764 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700765 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700766
767 if (entry->mBuffer == NULL) { // EOS
768 hasEOS = true;
769 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700770 break;
771 }
772
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700773 if (firstEntry && entry->mOffset == 0) {
774 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700775 int64_t mediaTimeUs;
776 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -0700777 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800778 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700779 }
780
781 size_t copy = entry->mBuffer->size() - entry->mOffset;
782 size_t sizeRemaining = size - sizeCopied;
783 if (copy > sizeRemaining) {
784 copy = sizeRemaining;
785 }
786
787 memcpy((char *)buffer + sizeCopied,
788 entry->mBuffer->data() + entry->mOffset,
789 copy);
790
791 entry->mOffset += copy;
792 if (entry->mOffset == entry->mBuffer->size()) {
793 entry->mNotifyConsumed->post();
794 mAudioQueue.erase(mAudioQueue.begin());
795 entry = NULL;
796 }
797 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -0800798
799 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -0700800 }
801
Lajos Molnarf5926712014-10-21 09:36:43 -0700802 if (mAudioFirstAnchorTimeMediaUs >= 0) {
803 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -0800804 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -0700805 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800806 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -0800807 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -0700808 }
809
Andy Hunga0b39712015-05-31 22:40:49 -0700810 // for non-offloaded audio, we need to compute the frames written because
811 // there is no EVENT_STREAM_END notification. The frames written gives
812 // an estimate on the pending played out duration.
813 if (!offloadingAudio()) {
814 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -0700815 }
816
Andy Hunga0b39712015-05-31 22:40:49 -0700817 if (hasEOS) {
818 (new AMessage(kWhatStopAudioSink, this))->post();
819 // As there is currently no EVENT_STREAM_END callback notification for
820 // non-offloaded audio tracks, we need to post the EOS ourselves.
821 if (!offloadingAudio()) {
822 int64_t postEOSDelayUs = 0;
823 if (mAudioSink->needsTrailingPadding()) {
824 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
825 }
826 ALOGV("fillAudioBuffer: notifyEOS "
827 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
828 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
829 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
830 }
831 }
Wei Jiabc2fb722014-07-08 16:37:57 -0700832 return sizeCopied;
833}
834
Chong Zhang9da0ce42015-06-11 17:18:58 -0700835void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
836 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
837 bool foundEOS = false;
838 while (it != mAudioQueue.end()) {
839 int32_t eos;
840 QueueEntry *entry = &*it++;
841 if (entry->mBuffer == NULL
842 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
843 itEOS = it;
844 foundEOS = true;
845 }
846 }
847
848 if (foundEOS) {
849 // post all replies before EOS and drop the samples
850 for (it = mAudioQueue.begin(); it != itEOS; it++) {
851 if (it->mBuffer == NULL) {
852 // delay doesn't matter as we don't even have an AudioTrack
853 notifyEOS(true /* audio */, it->mFinalResult);
854 } else {
855 it->mNotifyConsumed->post();
856 }
857 }
858 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
859 }
860}
861
Andreas Huber078cfcf2011-09-15 12:25:04 -0700862bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -0700863 // do not drain audio during teardown as queued buffers may be invalid.
864 if (mAudioTornDown) {
865 return false;
866 }
Wei Jia230b1882015-03-19 15:13:51 -0700867 // TODO: This call to getPosition checks if AudioTrack has been created
868 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
869 // CHECKs on getPosition will fail.
870 // We still need to figure out why AudioTrack is not created when
871 // this function is called. One possible reason could be leftover
872 // audio. Another possible place is to check whether decoder
873 // has received INFO_FORMAT_CHANGED as the first buffer since
874 // AudioSink is opened there, and possible interactions with flush
875 // immediately after start. Investigate error message
876 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700877 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700878 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -0700879 // When getPosition fails, renderer will not reschedule the draining
880 // unless new samples are queued.
881 // If we have pending EOS (or "eos" marker for discontinuities), we need
882 // to post these now as NuPlayerDecoder might be waiting for it.
883 drainAudioQueueUntilLastEOS();
884
885 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700886 return false;
887 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700888
Wei Jia230b1882015-03-19 15:13:51 -0700889#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -0700890 ssize_t numFramesAvailableToWrite =
891 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
892
Andreas Huber078cfcf2011-09-15 12:25:04 -0700893 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000894 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700895 } else {
Steve Block3856b092011-10-20 11:56:00 +0100896 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700897 mAudioSink->frameCount() - numFramesAvailableToWrite);
898 }
899#endif
900
Andy Hung005e9d02015-05-31 23:16:07 -0700901 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -0800902 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700903 QueueEntry *entry = &*mAudioQueue.begin();
904
Lajos Molnard5923402014-10-20 17:47:54 -0700905 mLastAudioBufferDrained = entry->mBufferOrdinal;
906
Andreas Huberc92fd242011-08-16 13:48:44 -0700907 if (entry->mBuffer == NULL) {
908 // EOS
Ronghua Wu5095d702014-08-27 12:05:48 -0700909 int64_t postEOSDelayUs = 0;
910 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -0700911 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -0700912 }
913 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -0700914 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -0700915
916 mAudioQueue.erase(mAudioQueue.begin());
917 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -0800918 if (mAudioSink->needsTrailingPadding()) {
919 // If we're not in gapless playback (i.e. through setNextPlayer), we
920 // need to stop the track here, because that will play out the last
921 // little bit at the end of the file. Otherwise short files won't play.
922 mAudioSink->stop();
923 mNumFramesWritten = 0;
924 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700925 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700926 }
927
Chong Zhang81636762015-04-21 09:33:47 -0700928 // ignore 0-sized buffer which could be EOS marker with no data
929 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -0800930 int64_t mediaTimeUs;
931 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -0700932 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
933 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -0700934 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800935 }
936
937 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -0800938
Wei Jia7d3f4df2015-03-03 15:28:00 -0800939 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
940 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -0700941 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -0800942 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800943 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -0700944 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -0800945 } else {
946 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -0700947 // This can only happen when AudioSink was opened with doNotReconnect flag set to
948 // true, in which case the NuPlayer will handle the reconnect.
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700949 notifyAudioTearDown();
Wei Jia7d3f4df2015-03-03 15:28:00 -0800950 }
Andy Hung202bce12014-12-03 11:47:36 -0800951 break;
Andy Hunga31335a2014-08-20 17:37:59 -0700952 }
Andreas Huberf9334412010-12-15 15:17:42 -0800953
Andy Hunga31335a2014-08-20 17:37:59 -0700954 entry->mOffset += written;
Andreas Huberf9334412010-12-15 15:17:42 -0800955 if (entry->mOffset == entry->mBuffer->size()) {
956 entry->mNotifyConsumed->post();
957 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700958
Andreas Huberf9334412010-12-15 15:17:42 -0800959 entry = NULL;
960 }
961
Andy Hunga31335a2014-08-20 17:37:59 -0700962 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700963 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700964
Wei Jia7b15cb32015-02-03 17:46:06 -0800965 {
966 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -0700967 int64_t maxTimeMedia;
968 maxTimeMedia =
969 mAnchorTimeMediaUs +
970 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
971 * 1000LL * mAudioSink->msecsPerFrame());
972 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
973
Wei Jia7b15cb32015-02-03 17:46:06 -0800974 notifyIfMediaRenderingStarted_l();
975 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800976
Andy Hunga31335a2014-08-20 17:37:59 -0700977 if (written != (ssize_t)copy) {
978 // A short count was received from AudioSink::write()
979 //
Wei Jia7d3f4df2015-03-03 15:28:00 -0800980 // AudioSink write is called in non-blocking mode.
981 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -0700982 //
983 // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800984 // 2) The data to be copied exceeds the available buffer in AudioSink.
985 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
986 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -0700987
988 // (Case 1)
989 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
990 // needs to fail, as we should not carry over fractional frames between calls.
991 CHECK_EQ(copy % mAudioSink->frameSize(), 0);
992
Wei Jia7d3f4df2015-03-03 15:28:00 -0800993 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -0700994 // Return early to the caller.
995 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800996 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -0700997 break;
998 }
999 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001000
Andy Hung005e9d02015-05-31 23:16:07 -07001001 // calculate whether we need to reschedule another write.
1002 bool reschedule = !mAudioQueue.empty()
1003 && (!mPaused
1004 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1005 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1006 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1007 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001008}
1009
Wei Jia98160162015-02-04 17:01:11 -08001010int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1011 int32_t sampleRate = offloadingAudio() ?
1012 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001013 if (sampleRate == 0) {
1014 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1015 return 0;
1016 }
Wei Jia98160162015-02-04 17:01:11 -08001017 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1018 return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
1019}
1020
1021// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001022int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001023 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiad2f35de2016-02-17 16:48:06 -08001024 if (mUseVirtualAudioSink) {
1025 int64_t nowUs = ALooper::GetNowUs();
1026 int64_t mediaUs;
1027 if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
1028 return 0ll;
1029 } else {
1030 return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1031 }
1032 }
Wei Jiac4ac8172015-10-21 10:35:48 -07001033 return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
Ronghua Wu5095d702014-08-27 12:05:48 -07001034}
1035
Ronghua Wua73d9e02014-10-08 15:13:29 -07001036int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001037 int64_t realUs;
1038 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001039 // If failed to get current position, e.g. due to audio clock is
1040 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001041 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001042 }
Wei Jia98160162015-02-04 17:01:11 -08001043 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001044}
1045
Ronghua Wueecb7802014-10-19 23:12:50 -07001046void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001047 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001048 // TRICKY: vorbis decoder generates multiple frames with the same
1049 // timestamp, so only update on the first frame with a given timestamp
1050 if (mediaTimeUs == mAnchorTimeMediaUs) {
1051 return;
1052 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001053 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001054
Andy Hung528c8402016-01-12 12:39:34 -08001055 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1056 if (mNextAudioClockUpdateTimeUs == -1) {
1057 AudioTimestamp ts;
1058 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1059 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1060 }
1061 }
Wei Jia12b62652016-02-09 17:49:31 -08001062 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001063 if (mNextAudioClockUpdateTimeUs >= 0) {
1064 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1065 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1066 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001067 mUseVirtualAudioSink = false;
Andy Hung528c8402016-01-12 12:39:34 -08001068 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1069 }
Wei Jia12b62652016-02-09 17:49:31 -08001070 } else {
1071 int64_t unused;
1072 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1073 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1074 > kMaxAllowedAudioSinkDelayUs)) {
1075 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1076 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1077 // connected to audio out.
1078 // Switch to system clock. This essentially creates a virtual AudioSink with
1079 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1080 // This virtual AudioSink renders audio data starting from the very first sample
1081 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001082 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001083 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
Wei Jiad2f35de2016-02-17 16:48:06 -08001084 mUseVirtualAudioSink = true;
Wei Jia12b62652016-02-09 17:49:31 -08001085 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001086 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001087 mAnchorNumFramesWritten = mNumFramesWritten;
Wei Jia7b15cb32015-02-03 17:46:06 -08001088 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001089}
1090
Wei Jia7b15cb32015-02-03 17:46:06 -08001091// Called without mLock acquired.
1092void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001093 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001094 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001095 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001096 return;
1097 }
1098
1099 if (mVideoQueue.empty()) {
1100 return;
1101 }
1102
1103 QueueEntry &entry = *mVideoQueue.begin();
1104
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001105 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001106 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001107
Andreas Huberf9334412010-12-15 15:17:42 -08001108 if (entry.mBuffer == NULL) {
1109 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001110 msg->post();
1111 mDrainVideoQueuePending = true;
1112 return;
1113 }
1114
Robert Shih00541e22015-12-18 17:04:00 -08001115 bool needRepostDrainVideoQueue = false;
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001116 int64_t delayUs;
1117 int64_t nowUs = ALooper::GetNowUs();
1118 int64_t realTimeUs;
1119 if (mFlags & FLAG_REAL_TIME) {
Andreas Huberd5e56232013-03-12 11:01:43 -07001120 int64_t mediaTimeUs;
1121 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001122 realTimeUs = mediaTimeUs;
Andreas Huberf9334412010-12-15 15:17:42 -08001123 } else {
1124 int64_t mediaTimeUs;
1125 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1126
Wei Jia7b15cb32015-02-03 17:46:06 -08001127 {
1128 Mutex::Autolock autoLock(mLock);
1129 if (mAnchorTimeMediaUs < 0) {
1130 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1131 mAnchorTimeMediaUs = mediaTimeUs;
1132 realTimeUs = nowUs;
Wei Jia25d696f2015-11-19 10:57:15 -08001133 } else if (!mVideoSampleReceived) {
1134 // Always render the first video frame.
1135 realTimeUs = nowUs;
Robert Shih00541e22015-12-18 17:04:00 -08001136 } else if (mAudioFirstAnchorTimeMediaUs < 0
1137 || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001138 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Robert Shih00541e22015-12-18 17:04:00 -08001139 } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
1140 needRepostDrainVideoQueue = true;
1141 realTimeUs = nowUs;
1142 } else {
1143 realTimeUs = nowUs;
Wei Jia7b15cb32015-02-03 17:46:06 -08001144 }
Andreas Huberf9334412010-12-15 15:17:42 -08001145 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001146 if (!mHasAudio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001147 // smooth out videos >= 10fps
1148 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
Lajos Molnarf5926712014-10-21 09:36:43 -07001149 }
Lajos Molnard5923402014-10-20 17:47:54 -07001150
1151 // Heuristics to handle situation when media time changed without a
1152 // discontinuity. If we have not drained an audio buffer that was
1153 // received after this buffer, repost in 10 msec. Otherwise repost
1154 // in 500 msec.
1155 delayUs = realTimeUs - nowUs;
Robert Shih00541e22015-12-18 17:04:00 -08001156 int64_t postDelayUs = -1;
Lajos Molnard5923402014-10-20 17:47:54 -07001157 if (delayUs > 500000) {
Robert Shih00541e22015-12-18 17:04:00 -08001158 postDelayUs = 500000;
Lajos Molnard5923402014-10-20 17:47:54 -07001159 if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1160 postDelayUs = 10000;
1161 }
Robert Shih00541e22015-12-18 17:04:00 -08001162 } else if (needRepostDrainVideoQueue) {
1163 // CHECK(mPlaybackRate > 0);
1164 // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
1165 // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
1166 postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
1167 postDelayUs /= mPlaybackRate;
1168 }
1169
1170 if (postDelayUs >= 0) {
Lajos Molnard5923402014-10-20 17:47:54 -07001171 msg->setWhat(kWhatPostDrainVideoQueue);
1172 msg->post(postDelayUs);
1173 mVideoScheduler->restart();
Robert Shih00541e22015-12-18 17:04:00 -08001174 ALOGI("possible video time jump of %dms or uninitialized media clock, retrying in %dms",
Lajos Molnard5923402014-10-20 17:47:54 -07001175 (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1176 mDrainVideoQueuePending = true;
1177 return;
1178 }
Andreas Huberf9334412010-12-15 15:17:42 -08001179 }
1180
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001181 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1182 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1183
1184 delayUs = realTimeUs - nowUs;
1185
Lajos Molnar09524832014-07-17 14:29:51 -07001186 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001187 // post 2 display refreshes before rendering is due
1188 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
Andreas Huberf9334412010-12-15 15:17:42 -08001189
1190 mDrainVideoQueuePending = true;
1191}
1192
1193void NuPlayer::Renderer::onDrainVideoQueue() {
1194 if (mVideoQueue.empty()) {
1195 return;
1196 }
1197
1198 QueueEntry *entry = &*mVideoQueue.begin();
1199
1200 if (entry->mBuffer == NULL) {
1201 // EOS
1202
Andreas Huberc92fd242011-08-16 13:48:44 -07001203 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001204
1205 mVideoQueue.erase(mVideoQueue.begin());
1206 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001207
Ronghua Wua73d9e02014-10-08 15:13:29 -07001208 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001209 return;
1210 }
1211
Wei Jia25d696f2015-11-19 10:57:15 -08001212 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001213 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001214 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001215 if (mFlags & FLAG_REAL_TIME) {
1216 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1217 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001218 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001219
Ronghua Wua73d9e02014-10-08 15:13:29 -07001220 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001221 }
1222
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001223 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001224
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001225 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001226 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001227 tooLate = (mVideoLateByUs > 40000);
1228
1229 if (tooLate) {
1230 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001231 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001232 } else {
Wei Jia98160162015-02-04 17:01:11 -08001233 int64_t mediaUs = 0;
1234 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001235 ALOGV("rendering video at media time %.2f secs",
1236 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001237 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001238
1239 if (!(mFlags & FLAG_REAL_TIME)
1240 && mLastAudioMediaTimeUs != -1
1241 && mediaTimeUs > mLastAudioMediaTimeUs) {
1242 // If audio ends before video, video continues to drive media clock.
1243 // Also smooth out videos >= 10fps.
1244 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1245 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001246 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001247 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001248 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001249 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001250 // This will ensure that the first frame after a flush won't be used as anchor
1251 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia7b15cb32015-02-03 17:46:06 -08001252 Mutex::Autolock autoLock(mLock);
1253 clearAnchorTime_l();
Wei Jia49966ff2014-10-08 18:44:45 -07001254 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001255 }
Andreas Huberf9334412010-12-15 15:17:42 -08001256
Wei Jia25d696f2015-11-19 10:57:15 -08001257 // Always render the first video frame while keeping stats on A/V sync.
1258 if (!mVideoSampleReceived) {
1259 realTimeUs = nowUs;
1260 tooLate = false;
1261 }
1262
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001263 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
Glenn Kasten683525b2011-11-04 18:05:35 -07001264 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001265 entry->mNotifyConsumed->post();
1266 mVideoQueue.erase(mVideoQueue.begin());
1267 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001268
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001269 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001270
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001271 if (!mPaused) {
1272 if (!mVideoRenderingStarted) {
1273 mVideoRenderingStarted = true;
1274 notifyVideoRenderingStart();
1275 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001276 Mutex::Autolock autoLock(mLock);
1277 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001278 }
Andreas Huberf9334412010-12-15 15:17:42 -08001279}
1280
James Dongf57b4ea2012-07-20 13:38:36 -07001281void NuPlayer::Renderer::notifyVideoRenderingStart() {
1282 sp<AMessage> notify = mNotify->dup();
1283 notify->setInt32("what", kWhatVideoRenderingStart);
1284 notify->post();
1285}
1286
Ronghua Wu5095d702014-08-27 12:05:48 -07001287void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001288 if (audio && delayUs > 0) {
1289 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1290 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1291 msg->setInt32("finalResult", finalResult);
1292 msg->post(delayUs);
1293 return;
1294 }
Andreas Huberf9334412010-12-15 15:17:42 -08001295 sp<AMessage> notify = mNotify->dup();
1296 notify->setInt32("what", kWhatEOS);
1297 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001298 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001299 notify->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001300}
1301
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001302void NuPlayer::Renderer::notifyAudioTearDown() {
1303 (new AMessage(kWhatAudioTearDown, this))->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001304}
1305
Andreas Huberf9334412010-12-15 15:17:42 -08001306void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1307 int32_t audio;
1308 CHECK(msg->findInt32("audio", &audio));
1309
Wei Jia7b15cb32015-02-03 17:46:06 -08001310 if (dropBufferIfStale(audio, msg)) {
1311 return;
1312 }
1313
1314 if (audio) {
1315 mHasAudio = true;
1316 } else {
1317 mHasVideo = true;
1318 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001319
1320 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001321 if (mVideoScheduler == NULL) {
1322 mVideoScheduler = new VideoFrameScheduler();
1323 mVideoScheduler->init();
1324 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001325 }
1326
Andreas Huber2d8bedd2012-02-21 14:38:23 -08001327 sp<ABuffer> buffer;
1328 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -08001329
1330 sp<AMessage> notifyConsumed;
1331 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1332
1333 QueueEntry entry;
1334 entry.mBuffer = buffer;
1335 entry.mNotifyConsumed = notifyConsumed;
1336 entry.mOffset = 0;
1337 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001338 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001339
1340 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001341 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001342 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001343 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001344 } else {
1345 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001346 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001347 }
1348
Wei Jia7b15cb32015-02-03 17:46:06 -08001349 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001350 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1351 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001352 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001353
1354 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1355 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1356
1357 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1358 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001359 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001360 return;
1361 }
1362
1363 int64_t firstAudioTimeUs;
1364 int64_t firstVideoTimeUs;
1365 CHECK(firstAudioBuffer->meta()
1366 ->findInt64("timeUs", &firstAudioTimeUs));
1367 CHECK(firstVideoBuffer->meta()
1368 ->findInt64("timeUs", &firstVideoTimeUs));
1369
1370 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1371
Steve Block3856b092011-10-20 11:56:00 +01001372 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001373
1374 if (diff > 100000ll) {
1375 // Audio data starts More than 0.1 secs before video.
1376 // Drop some audio.
1377
1378 (*mAudioQueue.begin()).mNotifyConsumed->post();
1379 mAudioQueue.erase(mAudioQueue.begin());
1380 return;
1381 }
1382
Wei Jiabc2fb722014-07-08 16:37:57 -07001383 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001384}
1385
Wei Jiabc2fb722014-07-08 16:37:57 -07001386void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001387 if (!mSyncQueues) {
1388 return;
1389 }
1390
1391 mSyncQueues = false;
1392
1393 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001394 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001395 }
1396
1397 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001398 mLock.unlock();
1399 postDrainVideoQueue();
1400 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001401 }
1402}
1403
1404void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1405 int32_t audio;
1406 CHECK(msg->findInt32("audio", &audio));
1407
Wei Jia7b15cb32015-02-03 17:46:06 -08001408 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001409 return;
1410 }
1411
1412 int32_t finalResult;
1413 CHECK(msg->findInt32("finalResult", &finalResult));
1414
1415 QueueEntry entry;
1416 entry.mOffset = 0;
1417 entry.mFinalResult = finalResult;
1418
1419 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001420 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001421 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001422 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001423 }
Andreas Huberf9334412010-12-15 15:17:42 -08001424 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001425 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001426 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001427 if (mVideoQueue.empty() && getSyncQueues()) {
1428 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001429 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001430 }
Andreas Huberf9334412010-12-15 15:17:42 -08001431 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001432 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001433 }
1434}
1435
1436void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001437 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001438 CHECK(msg->findInt32("audio", &audio));
1439
Wei Jia28a8a9f2014-08-18 11:29:50 -07001440 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001441 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001442 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001443 notifyComplete = mNotifyCompleteAudio;
1444 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001445 mLastAudioMediaTimeUs = -1;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001446 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001447 notifyComplete = mNotifyCompleteVideo;
1448 mNotifyCompleteVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001449 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001450
Wei Jia7b15cb32015-02-03 17:46:06 -08001451 // If we're currently syncing the queues, i.e. dropping audio while
1452 // aligning the first audio/video buffer times and only one of the
1453 // two queues has data, we may starve that queue by not requesting
1454 // more buffers from the decoder. If the other source then encounters
1455 // a discontinuity that leads to flushing, we'll never find the
1456 // corresponding discontinuity on the other queue.
1457 // Therefore we'll stop syncing the queues if at least one of them
1458 // is flushed.
1459 syncQueuesDone_l();
1460 clearAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001461 }
Andreas Huberf9334412010-12-15 15:17:42 -08001462
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001463 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001464 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001465 {
1466 Mutex::Autolock autoLock(mLock);
1467 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001468
Wei Jia7b15cb32015-02-03 17:46:06 -08001469 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001470 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001471 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001472
Andy Hunga0b39712015-05-31 22:40:49 -07001473 // the frame count will be reset after flush.
1474 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001475 }
Andreas Huberf9334412010-12-15 15:17:42 -08001476
Andreas Huberf9334412010-12-15 15:17:42 -08001477 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001478
Wei Jiabc2fb722014-07-08 16:37:57 -07001479 if (offloadingAudio()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001480 mAudioSink->pause();
1481 mAudioSink->flush();
Andy Hung85e48142015-05-31 23:04:15 -07001482 if (!mPaused) {
1483 mAudioSink->start();
1484 }
Wei Jia9e7ed332015-05-01 16:35:43 -07001485 } else {
1486 mAudioSink->pause();
1487 mAudioSink->flush();
1488 // Call stop() to signal to the AudioSink to completely fill the
1489 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001490 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001491 mAudioSink->stop();
Andy Hungb03dcb32015-08-27 16:18:59 -07001492 if (mPaused) {
1493 // Race condition: if renderer is paused and audio sink is stopped,
1494 // we need to make sure that the audio track buffer fully drains
1495 // before delivering data.
1496 // FIXME: remove this if we can detect if stop() is complete.
1497 const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1498 mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1499 } else {
Wei Jia9e7ed332015-05-01 16:35:43 -07001500 mAudioSink->start();
1501 }
1502 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001503 }
Andy Hung528c8402016-01-12 12:39:34 -08001504 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001505 } else {
1506 flushQueue(&mVideoQueue);
1507
Andreas Huberf9334412010-12-15 15:17:42 -08001508 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001509
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001510 if (mVideoScheduler != NULL) {
1511 mVideoScheduler->restart();
1512 }
1513
Wei Jia7b15cb32015-02-03 17:46:06 -08001514 Mutex::Autolock autoLock(mLock);
1515 ++mVideoDrainGeneration;
1516 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001517 }
1518
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001519 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001520
1521 if (notifyComplete) {
1522 notifyFlushComplete(audio);
1523 }
Andreas Huberf9334412010-12-15 15:17:42 -08001524}
1525
1526void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1527 while (!queue->empty()) {
1528 QueueEntry *entry = &*queue->begin();
1529
1530 if (entry->mBuffer != NULL) {
1531 entry->mNotifyConsumed->post();
1532 }
1533
1534 queue->erase(queue->begin());
1535 entry = NULL;
1536 }
1537}
1538
1539void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1540 sp<AMessage> notify = mNotify->dup();
1541 notify->setInt32("what", kWhatFlushComplete);
1542 notify->setInt32("audio", static_cast<int32_t>(audio));
1543 notify->post();
1544}
1545
Wei Jia7b15cb32015-02-03 17:46:06 -08001546bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001547 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001548 int32_t queueGeneration;
1549 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001550
Wei Jia7b15cb32015-02-03 17:46:06 -08001551 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001552 return false;
1553 }
1554
1555 sp<AMessage> notifyConsumed;
1556 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1557 notifyConsumed->post();
1558 }
1559
1560 return true;
1561}
1562
Andreas Huber3831a062010-12-21 10:22:33 -08001563void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001564 if (offloadingAudio()) {
1565 return;
1566 }
Andreas Huber3831a062010-12-21 10:22:33 -08001567 CHECK(!mDrainAudioQueuePending);
1568 mNumFramesWritten = 0;
Wei Jia7b15cb32015-02-03 17:46:06 -08001569 {
1570 Mutex::Autolock autoLock(mLock);
1571 mAnchorNumFramesWritten = -1;
1572 }
Marco Nelissen4110c102012-03-29 09:31:28 -07001573 uint32_t written;
1574 if (mAudioSink->getFramesWritten(&written) == OK) {
1575 mNumFramesWritten = written;
1576 }
Andreas Huber3831a062010-12-21 10:22:33 -08001577}
1578
Wei Jiabc2fb722014-07-08 16:37:57 -07001579void NuPlayer::Renderer::onDisableOffloadAudio() {
1580 Mutex::Autolock autoLock(mLock);
1581 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001582 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001583 if (mAudioRenderingStartGeneration != -1) {
1584 prepareForMediaRenderingStart_l();
1585 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001586}
1587
Ronghua Wua10fd232014-11-06 16:15:20 -08001588void NuPlayer::Renderer::onEnableOffloadAudio() {
1589 Mutex::Autolock autoLock(mLock);
1590 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001591 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001592 if (mAudioRenderingStartGeneration != -1) {
1593 prepareForMediaRenderingStart_l();
1594 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001595}
1596
Andreas Huberb4082222011-01-20 15:23:04 -08001597void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001598 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001599 return;
1600 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001601
Wei Jia28a8a9f2014-08-18 11:29:50 -07001602 {
1603 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001604 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001605 ++mVideoDrainGeneration;
1606 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001607 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001608 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001609 }
1610
Andreas Huberb4082222011-01-20 15:23:04 -08001611 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001612 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001613
Andy Hung84200732015-12-03 14:41:06 -08001614 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1615 mAudioSink->pause();
1616 startAudioOffloadPauseTimeout();
Andreas Huberb4082222011-01-20 15:23:04 -08001617
Lajos Molnar6d339f12015-04-17 16:15:53 -07001618 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001619 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001620}
1621
1622void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001623 if (!mPaused) {
1624 return;
1625 }
Andreas Huberb4082222011-01-20 15:23:04 -08001626
Andy Hung84200732015-12-03 14:41:06 -08001627 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1628 cancelAudioOffloadPauseTimeout();
1629 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001630 status_t err = mAudioSink->start();
1631 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001632 ALOGE("cannot start AudioSink err %d", err);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001633 notifyAudioTearDown();
1634 }
Andreas Huberb4082222011-01-20 15:23:04 -08001635 }
1636
Wei Jia7b15cb32015-02-03 17:46:06 -08001637 {
1638 Mutex::Autolock autoLock(mLock);
1639 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001640 // rendering started message may have been delayed if we were paused.
1641 if (mRenderingDataDelivered) {
1642 notifyIfMediaRenderingStarted_l();
1643 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001644 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001645 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001646 mAudioSink->setPlaybackRate(mPlaybackSettings);
1647 }
1648
Wei Jia98160162015-02-04 17:01:11 -08001649 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001650
Wei Jia7b15cb32015-02-03 17:46:06 -08001651 if (!mAudioQueue.empty()) {
1652 postDrainAudioQueue_l();
1653 }
Andreas Huberb4082222011-01-20 15:23:04 -08001654 }
1655
1656 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001657 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001658 }
1659}
1660
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001661void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1662 if (mVideoScheduler == NULL) {
1663 mVideoScheduler = new VideoFrameScheduler();
1664 }
1665 mVideoScheduler->init(fps);
1666}
1667
Wei Jia7b15cb32015-02-03 17:46:06 -08001668int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1669 Mutex::Autolock autoLock(mLock);
1670 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1671}
1672
1673int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1674 Mutex::Autolock autoLock(mLock);
1675 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1676}
1677
1678bool NuPlayer::Renderer::getSyncQueues() {
1679 Mutex::Autolock autoLock(mLock);
1680 return mSyncQueues;
1681}
1682
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001683void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1684 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001685 return;
1686 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001687 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001688
Ronghua Wua73d9e02014-10-08 15:13:29 -07001689 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001690 sp<AMessage> notify = mNotify->dup();
1691 if (getCurrentPosition(&currentPositionUs) == OK) {
1692 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001693 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001694
Wei Jia3a2956d2014-07-22 16:01:33 -07001695 mAudioSink->stop();
1696 mAudioSink->flush();
1697
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001698 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001699 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001700 notify->post();
1701}
1702
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001703void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1704 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001705 mWakeLock->acquire();
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001706 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001707 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001708 msg->post(kOffloadPauseMaxUs);
1709 }
1710}
1711
1712void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1713 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001714 mWakeLock->release(true);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001715 ++mAudioOffloadPauseTimeoutGeneration;
1716 }
1717}
1718
Andy Hung202bce12014-12-03 11:47:36 -08001719status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001720 const sp<AMessage> &format,
1721 bool offloadOnly,
1722 bool hasVideo,
1723 uint32_t flags) {
1724 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1725 offloadOnly, offloadingAudio());
1726 bool audioSinkChanged = false;
1727
1728 int32_t numChannels;
1729 CHECK(format->findInt32("channel-count", &numChannels));
1730
1731 int32_t channelMask;
1732 if (!format->findInt32("channel-mask", &channelMask)) {
1733 // signal to the AudioSink to derive the mask from count.
1734 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
1735 }
1736
1737 int32_t sampleRate;
1738 CHECK(format->findInt32("sample-rate", &sampleRate));
1739
1740 if (offloadingAudio()) {
1741 audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
1742 AString mime;
1743 CHECK(format->findString("mime", &mime));
1744 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
1745
1746 if (err != OK) {
1747 ALOGE("Couldn't map mime \"%s\" to a valid "
1748 "audio_format", mime.c_str());
1749 onDisableOffloadAudio();
1750 } else {
1751 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
1752 mime.c_str(), audioFormat);
1753
1754 int avgBitRate = -1;
1755 format->findInt32("bit-rate", &avgBitRate);
1756
1757 int32_t aacProfile = -1;
1758 if (audioFormat == AUDIO_FORMAT_AAC
1759 && format->findInt32("aac-profile", &aacProfile)) {
1760 // Redefine AAC format as per aac profile
1761 mapAACProfileToAudioFormat(
1762 audioFormat,
1763 aacProfile);
1764 }
1765
1766 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
1767 offloadInfo.duration_us = -1;
1768 format->findInt64(
1769 "durationUs", &offloadInfo.duration_us);
1770 offloadInfo.sample_rate = sampleRate;
1771 offloadInfo.channel_mask = channelMask;
1772 offloadInfo.format = audioFormat;
1773 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
1774 offloadInfo.bit_rate = avgBitRate;
1775 offloadInfo.has_video = hasVideo;
1776 offloadInfo.is_streaming = true;
1777
1778 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
1779 ALOGV("openAudioSink: no change in offload mode");
1780 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08001781 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001782 }
Andy Hungf0e83642014-12-19 17:55:56 -08001783 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1784
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001785 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001786 uint32_t offloadFlags = flags;
1787 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1788 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001789 audioSinkChanged = true;
1790 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07001791
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001792 err = mAudioSink->open(
1793 sampleRate,
1794 numChannels,
1795 (audio_channel_mask_t)channelMask,
1796 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07001797 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001798 &NuPlayer::Renderer::AudioSinkCallback,
1799 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001800 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001801 &offloadInfo);
1802
1803 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001804 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
1805 }
1806
1807 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001808 // If the playback is offloaded to h/w, we pass
1809 // the HAL some metadata information.
1810 // We don't want to do this for PCM because it
1811 // will be going through the AudioFlinger mixer
1812 // before reaching the hardware.
1813 // TODO
1814 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07001815 if (!mPaused) { // for preview mode, don't start if paused
1816 err = mAudioSink->start();
1817 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001818 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
1819 }
1820 if (err != OK) {
1821 // Clean up, fall back to non offload mode.
1822 mAudioSink->close();
1823 onDisableOffloadAudio();
1824 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1825 ALOGV("openAudioSink: offload failed");
Wei Jia3ab25452015-06-10 09:37:47 -07001826 } else {
1827 mUseAudioCallback = true; // offload mode transfers data through callback
1828 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001829 }
1830 }
1831 }
1832 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001833 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001834 uint32_t pcmFlags = flags;
1835 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08001836
1837 const PcmInfo info = {
1838 (audio_channel_mask_t)channelMask,
1839 (audio_output_flags_t)pcmFlags,
1840 AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1841 numChannels,
1842 sampleRate
1843 };
1844 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1845 ALOGV("openAudioSink: no change in pcm mode");
1846 // no change from previous configuration, everything ok.
1847 return OK;
1848 }
1849
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001850 audioSinkChanged = true;
1851 mAudioSink->close();
1852 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07001853 // Note: It is possible to set up the callback, but not use it to send audio data.
1854 // This requires a fix in AudioSink to explicitly specify the transfer mode.
1855 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07001856 if (mUseAudioCallback) {
1857 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
1858 }
Andy Hung179652e2015-05-31 22:49:46 -07001859
1860 // Compute the desired buffer size.
1861 // For callback mode, the amount of time before wakeup is about half the buffer size.
1862 const uint32_t frameCount =
1863 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1864
Ronghua Wu7665f582015-09-02 10:15:30 -07001865 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
1866 // AudioSink. We don't want this when there's video because it will cause a video seek to
1867 // the previous I frame. But we do want this when there's only audio because it will give
1868 // NuPlayer a chance to switch from non-offload mode to offload mode.
1869 // So we only set doNotReconnect when there's no video.
1870 const bool doNotReconnect = !hasVideo;
Andy Hung202bce12014-12-03 11:47:36 -08001871 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001872 sampleRate,
1873 numChannels,
1874 (audio_channel_mask_t)channelMask,
1875 AUDIO_FORMAT_PCM_16_BIT,
Andy Hung179652e2015-05-31 22:49:46 -07001876 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07001877 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1878 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001879 (audio_output_flags_t)pcmFlags,
1880 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07001881 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07001882 frameCount);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001883 if (err == OK) {
1884 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
1885 }
Andy Hung202bce12014-12-03 11:47:36 -08001886 if (err != OK) {
1887 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07001888 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08001889 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08001890 return err;
1891 }
Andy Hungf0e83642014-12-19 17:55:56 -08001892 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07001893 if (!mPaused) { // for preview mode, don't start if paused
1894 mAudioSink->start();
1895 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001896 }
1897 if (audioSinkChanged) {
1898 onAudioSinkChanged();
1899 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001900 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08001901 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001902}
1903
1904void NuPlayer::Renderer::onCloseAudioSink() {
1905 mAudioSink->close();
1906 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08001907 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001908}
1909
Andreas Huberf9334412010-12-15 15:17:42 -08001910} // namespace android
1911