blob: a049a30077204bb5f9ef419d12f3a6d2c582d735 [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),
94 mNotify(notify),
Andreas Huberd5e56232013-03-12 11:01:43 -070095 mFlags(flags),
Andreas Huberf9334412010-12-15 15:17:42 -080096 mNumFramesWritten(0),
97 mDrainAudioQueuePending(false),
98 mDrainVideoQueuePending(false),
99 mAudioQueueGeneration(0),
100 mVideoQueueGeneration(0),
Wei Jia7b15cb32015-02-03 17:46:06 -0800101 mAudioDrainGeneration(0),
102 mVideoDrainGeneration(0),
Wei Jia7c8d0e02015-08-27 17:40:21 -0700103 mAudioEOSGeneration(0),
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700104 mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
Ronghua Wua73d9e02014-10-08 15:13:29 -0700105 mAudioFirstAnchorTimeMediaUs(-1),
Ronghua Wueecb7802014-10-19 23:12:50 -0700106 mAnchorTimeMediaUs(-1),
Lajos Molnarf5926712014-10-21 09:36:43 -0700107 mAnchorNumFramesWritten(-1),
Ronghua Wua73d9e02014-10-08 15:13:29 -0700108 mVideoLateByUs(0ll),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800109 mHasAudio(false),
110 mHasVideo(false),
Chong Zhang7137ec72014-11-12 16:41:05 -0800111 mNotifyCompleteAudio(false),
112 mNotifyCompleteVideo(false),
Andreas Huberbc7f5b22011-01-21 10:15:23 -0800113 mSyncQueues(false),
Andreas Huber714aa7b2011-09-13 08:28:38 -0700114 mPaused(false),
Andy Hungb03dcb32015-08-27 16:18:59 -0700115 mPauseDrainAudioAllowedUs(0),
Andy Hung09e0c362014-09-12 15:12:16 -0700116 mVideoSampleReceived(false),
James Dongf57b4ea2012-07-20 13:38:36 -0700117 mVideoRenderingStarted(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700118 mVideoRenderingStartGeneration(0),
119 mAudioRenderingStartGeneration(0),
Andy Hungb12ea0b2015-09-03 15:13:01 -0700120 mRenderingDataDelivered(false),
Andy Hung528c8402016-01-12 12:39:34 -0800121 mNextAudioClockUpdateTimeUs(-1),
Wei Jia2995dc72015-07-24 16:00:33 -0700122 mLastAudioMediaTimeUs(-1),
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700123 mAudioOffloadPauseTimeoutGeneration(0),
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700124 mAudioTornDown(false),
Lajos Molnard5923402014-10-20 17:47:54 -0700125 mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
Andy Hungf0e83642014-12-19 17:55:56 -0800126 mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
Lajos Molnard5923402014-10-20 17:47:54 -0700127 mTotalBuffersQueued(0),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800128 mLastAudioBufferDrained(0),
Andy Hunga0b39712015-05-31 22:40:49 -0700129 mUseAudioCallback(false),
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800130 mWakeLock(new AWakeLock()) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800131 mMediaClock = new MediaClock;
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700132 mPlaybackRate = mPlaybackSettings.mSpeed;
133 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberf9334412010-12-15 15:17:42 -0800134}
135
136NuPlayer::Renderer::~Renderer() {
Wei Jiabc2fb722014-07-08 16:37:57 -0700137 if (offloadingAudio()) {
138 mAudioSink->stop();
139 mAudioSink->flush();
140 mAudioSink->close();
141 }
Andreas Huberf9334412010-12-15 15:17:42 -0800142}
143
144void NuPlayer::Renderer::queueBuffer(
145 bool audio,
146 const sp<ABuffer> &buffer,
147 const sp<AMessage> &notifyConsumed) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800148 sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800149 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800150 msg->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800151 msg->setBuffer("buffer", buffer);
Andreas Huberf9334412010-12-15 15:17:42 -0800152 msg->setMessage("notifyConsumed", notifyConsumed);
153 msg->post();
154}
155
156void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
157 CHECK_NE(finalResult, (status_t)OK);
158
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800159 sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800160 msg->setInt32("queueGeneration", getQueueGeneration(audio));
Andreas Huberf9334412010-12-15 15:17:42 -0800161 msg->setInt32("audio", static_cast<int32_t>(audio));
162 msg->setInt32("finalResult", finalResult);
163 msg->post();
164}
165
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700166status_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
167 sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
168 writeToAMessage(msg, rate);
169 sp<AMessage> response;
170 status_t err = msg->postAndAwaitResponse(&response);
171 if (err == OK && response != NULL) {
172 CHECK(response->findInt32("err", &err));
173 }
174 return err;
175}
176
177status_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
178 if (rate.mSpeed == 0.f) {
179 onPause();
180 // don't call audiosink's setPlaybackRate if pausing, as pitch does not
181 // have to correspond to the any non-0 speed (e.g old speed). Keep
182 // settings nonetheless, using the old speed, in case audiosink changes.
183 AudioPlaybackRate newRate = rate;
184 newRate.mSpeed = mPlaybackSettings.mSpeed;
185 mPlaybackSettings = newRate;
186 return OK;
187 }
188
Wei Jia27ea08e2015-05-12 14:50:35 -0700189 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700190 status_t err = mAudioSink->setPlaybackRate(rate);
191 if (err != OK) {
192 return err;
193 }
194 }
195 mPlaybackSettings = rate;
196 mPlaybackRate = rate.mSpeed;
197 mMediaClock->setPlaybackRate(mPlaybackRate);
198 return OK;
199}
200
201status_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
202 sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
203 sp<AMessage> response;
204 status_t err = msg->postAndAwaitResponse(&response);
205 if (err == OK && response != NULL) {
206 CHECK(response->findInt32("err", &err));
207 if (err == OK) {
208 readFromAMessage(response, rate);
209 }
210 }
211 return err;
212}
213
214status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
Wei Jia27ea08e2015-05-12 14:50:35 -0700215 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700216 status_t err = mAudioSink->getPlaybackRate(rate);
217 if (err == OK) {
218 if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
219 ALOGW("correcting mismatch in internal/external playback rate");
220 }
221 // get playback settings used by audiosink, as it may be
222 // slightly off due to audiosink not taking small changes.
223 mPlaybackSettings = *rate;
224 if (mPaused) {
225 rate->mSpeed = 0.f;
226 }
227 }
228 return err;
229 }
230 *rate = mPlaybackSettings;
231 return OK;
232}
233
234status_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
235 sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
236 writeToAMessage(msg, sync, videoFpsHint);
237 sp<AMessage> response;
238 status_t err = msg->postAndAwaitResponse(&response);
239 if (err == OK && response != NULL) {
240 CHECK(response->findInt32("err", &err));
241 }
242 return err;
243}
244
245status_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
246 if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
247 return BAD_VALUE;
248 }
249 // TODO: support sync sources
250 return INVALID_OPERATION;
251}
252
253status_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
254 sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
255 sp<AMessage> response;
256 status_t err = msg->postAndAwaitResponse(&response);
257 if (err == OK && response != NULL) {
258 CHECK(response->findInt32("err", &err));
259 if (err == OK) {
260 readFromAMessage(response, sync, videoFps);
261 }
262 }
263 return err;
264}
265
266status_t NuPlayer::Renderer::onGetSyncSettings(
267 AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
268 *sync = mSyncSettings;
269 *videoFps = -1.f;
270 return OK;
Wei Jia98160162015-02-04 17:01:11 -0800271}
272
Chong Zhang7137ec72014-11-12 16:41:05 -0800273void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800274 {
Wei Jia7b15cb32015-02-03 17:46:06 -0800275 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -0800276 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800277 mNotifyCompleteAudio |= notifyComplete;
Wei Jia3b0cd262015-07-13 11:28:10 -0700278 clearAudioFirstAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800279 ++mAudioQueueGeneration;
280 ++mAudioDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800281 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -0800282 mNotifyCompleteVideo |= notifyComplete;
Wei Jia7b15cb32015-02-03 17:46:06 -0800283 ++mVideoQueueGeneration;
284 ++mVideoDrainGeneration;
Andreas Huberf9334412010-12-15 15:17:42 -0800285 }
Wei Jia7b15cb32015-02-03 17:46:06 -0800286
287 clearAnchorTime_l();
Wei Jia7b15cb32015-02-03 17:46:06 -0800288 mVideoLateByUs = 0;
289 mSyncQueues = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800290 }
291
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800292 sp<AMessage> msg = new AMessage(kWhatFlush, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800293 msg->setInt32("audio", static_cast<int32_t>(audio));
294 msg->post();
295}
296
297void NuPlayer::Renderer::signalTimeDiscontinuity() {
Wei Jia28a8a9f2014-08-18 11:29:50 -0700298}
299
300void NuPlayer::Renderer::signalDisableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800301 (new AMessage(kWhatDisableOffloadAudio, this))->post();
Wei Jia28a8a9f2014-08-18 11:29:50 -0700302}
303
Ronghua Wua10fd232014-11-06 16:15:20 -0800304void NuPlayer::Renderer::signalEnableOffloadAudio() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800305 (new AMessage(kWhatEnableOffloadAudio, this))->post();
Ronghua Wua10fd232014-11-06 16:15:20 -0800306}
307
Andreas Huberb4082222011-01-20 15:23:04 -0800308void NuPlayer::Renderer::pause() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800309 (new AMessage(kWhatPause, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800310}
311
312void NuPlayer::Renderer::resume() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800313 (new AMessage(kWhatResume, this))->post();
Andreas Huberb4082222011-01-20 15:23:04 -0800314}
315
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700316void NuPlayer::Renderer::setVideoFrameRate(float fps) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800317 sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700318 msg->setFloat("frame-rate", fps);
319 msg->post();
320}
321
Wei Jia4ecbea32015-10-20 18:09:57 -0700322// Called on any threads without mLock acquired.
Wei Jia7b15cb32015-02-03 17:46:06 -0800323status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
Wei Jia4ecbea32015-10-20 18:09:57 -0700324 status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
325 if (result == OK) {
326 return result;
327 }
328
329 // MediaClock has not started yet. Try to start it if possible.
330 {
331 Mutex::Autolock autoLock(mLock);
332 if (mAudioFirstAnchorTimeMediaUs == -1) {
333 return result;
334 }
335
336 AudioTimestamp ts;
337 status_t res = mAudioSink->getTimestamp(ts);
338 if (res != OK) {
339 return result;
340 }
341
342 // AudioSink has rendered some frames.
343 int64_t nowUs = ALooper::GetNowUs();
Wei Jiad855a732015-10-21 13:31:15 -0700344 int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
Wei Jia4ecbea32015-10-20 18:09:57 -0700345 + mAudioFirstAnchorTimeMediaUs;
346 mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
347 }
348
Wei Jia98160162015-02-04 17:01:11 -0800349 return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700350}
351
Wei Jia7b15cb32015-02-03 17:46:06 -0800352void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
353 mAudioFirstAnchorTimeMediaUs = -1;
354 mMediaClock->setStartingTimeMedia(-1);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700355}
356
Wei Jia7b15cb32015-02-03 17:46:06 -0800357void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
Ronghua Wua73d9e02014-10-08 15:13:29 -0700358 if (mAudioFirstAnchorTimeMediaUs == -1) {
359 mAudioFirstAnchorTimeMediaUs = mediaUs;
Wei Jia7b15cb32015-02-03 17:46:06 -0800360 mMediaClock->setStartingTimeMedia(mediaUs);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700361 }
362}
363
Wei Jia7b15cb32015-02-03 17:46:06 -0800364void NuPlayer::Renderer::clearAnchorTime_l() {
365 mMediaClock->clearAnchor();
366 mAnchorTimeMediaUs = -1;
367 mAnchorNumFramesWritten = -1;
Ronghua Wua73d9e02014-10-08 15:13:29 -0700368}
369
370void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -0800371 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700372 mVideoLateByUs = lateUs;
373}
374
375int64_t NuPlayer::Renderer::getVideoLateByUs() {
Wei Jia7b15cb32015-02-03 17:46:06 -0800376 Mutex::Autolock autoLock(mLock);
Ronghua Wua73d9e02014-10-08 15:13:29 -0700377 return mVideoLateByUs;
378}
379
Andy Hung202bce12014-12-03 11:47:36 -0800380status_t NuPlayer::Renderer::openAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700381 const sp<AMessage> &format,
382 bool offloadOnly,
383 bool hasVideo,
Andy Hung202bce12014-12-03 11:47:36 -0800384 uint32_t flags,
385 bool *isOffloaded) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800386 sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700387 msg->setMessage("format", format);
388 msg->setInt32("offload-only", offloadOnly);
389 msg->setInt32("has-video", hasVideo);
390 msg->setInt32("flags", flags);
391
392 sp<AMessage> response;
393 msg->postAndAwaitResponse(&response);
394
Andy Hung202bce12014-12-03 11:47:36 -0800395 int32_t err;
396 if (!response->findInt32("err", &err)) {
397 err = INVALID_OPERATION;
398 } else if (err == OK && isOffloaded != NULL) {
399 int32_t offload;
400 CHECK(response->findInt32("offload", &offload));
401 *isOffloaded = (offload != 0);
402 }
403 return err;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700404}
405
406void NuPlayer::Renderer::closeAudioSink() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800407 sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700408
409 sp<AMessage> response;
410 msg->postAndAwaitResponse(&response);
411}
412
Andreas Huberf9334412010-12-15 15:17:42 -0800413void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
414 switch (msg->what()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700415 case kWhatOpenAudioSink:
416 {
417 sp<AMessage> format;
418 CHECK(msg->findMessage("format", &format));
419
420 int32_t offloadOnly;
421 CHECK(msg->findInt32("offload-only", &offloadOnly));
422
423 int32_t hasVideo;
424 CHECK(msg->findInt32("has-video", &hasVideo));
425
426 uint32_t flags;
427 CHECK(msg->findInt32("flags", (int32_t *)&flags));
428
Andy Hung202bce12014-12-03 11:47:36 -0800429 status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700430
431 sp<AMessage> response = new AMessage;
Andy Hung202bce12014-12-03 11:47:36 -0800432 response->setInt32("err", err);
433 response->setInt32("offload", offloadingAudio());
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700434
Lajos Molnar3f274362015-03-05 14:35:41 -0800435 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700436 CHECK(msg->senderAwaitsResponse(&replyID));
437 response->postReply(replyID);
438
439 break;
440 }
441
442 case kWhatCloseAudioSink:
443 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800444 sp<AReplyToken> replyID;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -0700445 CHECK(msg->senderAwaitsResponse(&replyID));
446
447 onCloseAudioSink();
448
449 sp<AMessage> response = new AMessage;
450 response->postReply(replyID);
451 break;
452 }
453
Wei Jiabc2fb722014-07-08 16:37:57 -0700454 case kWhatStopAudioSink:
455 {
456 mAudioSink->stop();
457 break;
458 }
459
Andreas Huberf9334412010-12-15 15:17:42 -0800460 case kWhatDrainAudioQueue:
461 {
Wei Jia3ab25452015-06-10 09:37:47 -0700462 mDrainAudioQueuePending = false;
463
Andreas Huberf9334412010-12-15 15:17:42 -0800464 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800465 CHECK(msg->findInt32("drainGeneration", &generation));
466 if (generation != getDrainGeneration(true /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800467 break;
468 }
469
Andreas Huber078cfcf2011-09-15 12:25:04 -0700470 if (onDrainAudioQueue()) {
471 uint32_t numFramesPlayed;
472 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
473 (status_t)OK);
Andreas Huberf9334412010-12-15 15:17:42 -0800474
Andreas Huber078cfcf2011-09-15 12:25:04 -0700475 uint32_t numFramesPendingPlayout =
476 mNumFramesWritten - numFramesPlayed;
477
478 // This is how long the audio sink will have data to
479 // play back.
480 int64_t delayUs =
481 mAudioSink->msecsPerFrame()
482 * numFramesPendingPlayout * 1000ll;
Wei Jiad9c2e9c2015-04-10 19:04:09 -0700483 if (mPlaybackRate > 1.0f) {
484 delayUs /= mPlaybackRate;
485 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700486
487 // Let's give it more data after about half that time
488 // has elapsed.
Wei Jia7b15cb32015-02-03 17:46:06 -0800489 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -0700490 postDrainAudioQueue_l(delayUs / 2);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700491 }
Andreas Huberf9334412010-12-15 15:17:42 -0800492 break;
493 }
494
495 case kWhatDrainVideoQueue:
496 {
497 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800498 CHECK(msg->findInt32("drainGeneration", &generation));
499 if (generation != getDrainGeneration(false /* audio */)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800500 break;
501 }
502
503 mDrainVideoQueuePending = false;
504
505 onDrainVideoQueue();
506
Wei Jia7b15cb32015-02-03 17:46:06 -0800507 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -0800508 break;
509 }
510
Lajos Molnard5923402014-10-20 17:47:54 -0700511 case kWhatPostDrainVideoQueue:
512 {
513 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800514 CHECK(msg->findInt32("drainGeneration", &generation));
515 if (generation != getDrainGeneration(false /* audio */)) {
Lajos Molnard5923402014-10-20 17:47:54 -0700516 break;
517 }
518
519 mDrainVideoQueuePending = false;
Wei Jia7b15cb32015-02-03 17:46:06 -0800520 postDrainVideoQueue();
Lajos Molnard5923402014-10-20 17:47:54 -0700521 break;
522 }
523
Andreas Huberf9334412010-12-15 15:17:42 -0800524 case kWhatQueueBuffer:
525 {
526 onQueueBuffer(msg);
527 break;
528 }
529
530 case kWhatQueueEOS:
531 {
532 onQueueEOS(msg);
533 break;
534 }
535
Wei Jia7c8d0e02015-08-27 17:40:21 -0700536 case kWhatEOS:
537 {
538 int32_t generation;
539 CHECK(msg->findInt32("audioEOSGeneration", &generation));
540 if (generation != mAudioEOSGeneration) {
541 break;
542 }
543 status_t finalResult;
544 CHECK(msg->findInt32("finalResult", &finalResult));
545 notifyEOS(true /* audio */, finalResult);
546 break;
547 }
548
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700549 case kWhatConfigPlayback:
Wei Jia98160162015-02-04 17:01:11 -0800550 {
Lajos Molnar3a474aa2015-04-24 17:10:07 -0700551 sp<AReplyToken> replyID;
552 CHECK(msg->senderAwaitsResponse(&replyID));
553 AudioPlaybackRate rate;
554 readFromAMessage(msg, &rate);
555 status_t err = onConfigPlayback(rate);
556 sp<AMessage> response = new AMessage;
557 response->setInt32("err", err);
558 response->postReply(replyID);
559 break;
560 }
561
562 case kWhatGetPlaybackSettings:
563 {
564 sp<AReplyToken> replyID;
565 CHECK(msg->senderAwaitsResponse(&replyID));
566 AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
567 status_t err = onGetPlaybackSettings(&rate);
568 sp<AMessage> response = new AMessage;
569 if (err == OK) {
570 writeToAMessage(response, rate);
571 }
572 response->setInt32("err", err);
573 response->postReply(replyID);
574 break;
575 }
576
577 case kWhatConfigSync:
578 {
579 sp<AReplyToken> replyID;
580 CHECK(msg->senderAwaitsResponse(&replyID));
581 AVSyncSettings sync;
582 float videoFpsHint;
583 readFromAMessage(msg, &sync, &videoFpsHint);
584 status_t err = onConfigSync(sync, videoFpsHint);
585 sp<AMessage> response = new AMessage;
586 response->setInt32("err", err);
587 response->postReply(replyID);
588 break;
589 }
590
591 case kWhatGetSyncSettings:
592 {
593 sp<AReplyToken> replyID;
594 CHECK(msg->senderAwaitsResponse(&replyID));
595
596 ALOGV("kWhatGetSyncSettings");
597 AVSyncSettings sync;
598 float videoFps = -1.f;
599 status_t err = onGetSyncSettings(&sync, &videoFps);
600 sp<AMessage> response = new AMessage;
601 if (err == OK) {
602 writeToAMessage(response, sync, videoFps);
603 }
604 response->setInt32("err", err);
605 response->postReply(replyID);
Wei Jia98160162015-02-04 17:01:11 -0800606 break;
607 }
608
Andreas Huberf9334412010-12-15 15:17:42 -0800609 case kWhatFlush:
610 {
611 onFlush(msg);
612 break;
613 }
614
Wei Jiabc2fb722014-07-08 16:37:57 -0700615 case kWhatDisableOffloadAudio:
616 {
617 onDisableOffloadAudio();
618 break;
619 }
620
Ronghua Wua10fd232014-11-06 16:15:20 -0800621 case kWhatEnableOffloadAudio:
622 {
623 onEnableOffloadAudio();
624 break;
625 }
626
Andreas Huberb4082222011-01-20 15:23:04 -0800627 case kWhatPause:
628 {
629 onPause();
630 break;
631 }
632
633 case kWhatResume:
634 {
635 onResume();
636 break;
637 }
638
Lajos Molnarc851b5d2014-09-18 14:14:29 -0700639 case kWhatSetVideoFrameRate:
640 {
641 float fps;
642 CHECK(msg->findFloat("frame-rate", &fps));
643 onSetVideoFrameRate(fps);
644 break;
645 }
646
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700647 case kWhatAudioTearDown:
Wei Jia3a2956d2014-07-22 16:01:33 -0700648 {
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700649 onAudioTearDown(kDueToError);
Wei Jia3a2956d2014-07-22 16:01:33 -0700650 break;
651 }
652
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700653 case kWhatAudioOffloadPauseTimeout:
654 {
655 int32_t generation;
Wei Jia7b15cb32015-02-03 17:46:06 -0800656 CHECK(msg->findInt32("drainGeneration", &generation));
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700657 if (generation != mAudioOffloadPauseTimeoutGeneration) {
658 break;
659 }
Ronghua Wu08529172014-10-02 16:55:52 -0700660 ALOGV("Audio Offload tear down due to pause timeout.");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700661 onAudioTearDown(kDueToTimeout);
Weiyin Jiang35d5af12015-01-28 16:14:02 +0800662 mWakeLock->release();
Ronghua Wuf5b1db12014-09-09 10:11:08 -0700663 break;
664 }
665
Andreas Huberf9334412010-12-15 15:17:42 -0800666 default:
667 TRESPASS();
668 break;
669 }
670}
671
Wei Jiabc2fb722014-07-08 16:37:57 -0700672void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
Andy Hung005e9d02015-05-31 23:16:07 -0700673 if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
Andreas Huberf9334412010-12-15 15:17:42 -0800674 return;
675 }
676
677 if (mAudioQueue.empty()) {
678 return;
679 }
680
Andy Hungb03dcb32015-08-27 16:18:59 -0700681 // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
682 if (mPaused) {
683 const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
684 if (diffUs > delayUs) {
685 delayUs = diffUs;
686 }
687 }
688
Andreas Huberf9334412010-12-15 15:17:42 -0800689 mDrainAudioQueuePending = true;
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800690 sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -0800691 msg->setInt32("drainGeneration", mAudioDrainGeneration);
Andreas Huber078cfcf2011-09-15 12:25:04 -0700692 msg->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800693}
694
Wei Jia7b15cb32015-02-03 17:46:06 -0800695void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
696 mAudioRenderingStartGeneration = mAudioDrainGeneration;
697 mVideoRenderingStartGeneration = mVideoDrainGeneration;
Andy Hungb12ea0b2015-09-03 15:13:01 -0700698 mRenderingDataDelivered = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700699}
700
Wei Jia7b15cb32015-02-03 17:46:06 -0800701void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
702 if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
703 mAudioRenderingStartGeneration == mAudioDrainGeneration) {
Andy Hungb12ea0b2015-09-03 15:13:01 -0700704 mRenderingDataDelivered = true;
705 if (mPaused) {
706 return;
707 }
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700708 mVideoRenderingStartGeneration = -1;
709 mAudioRenderingStartGeneration = -1;
710
711 sp<AMessage> notify = mNotify->dup();
712 notify->setInt32("what", kWhatMediaRenderingStart);
713 notify->post();
714 }
715}
716
Wei Jiabc2fb722014-07-08 16:37:57 -0700717// static
718size_t NuPlayer::Renderer::AudioSinkCallback(
719 MediaPlayerBase::AudioSink * /* audioSink */,
720 void *buffer,
721 size_t size,
722 void *cookie,
723 MediaPlayerBase::AudioSink::cb_event_t event) {
724 NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
725
726 switch (event) {
727 case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
728 {
729 return me->fillAudioBuffer(buffer, size);
730 break;
731 }
732
733 case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
734 {
Andy Hunga0b39712015-05-31 22:40:49 -0700735 ALOGV("AudioSink::CB_EVENT_STREAM_END");
Wei Jiabc2fb722014-07-08 16:37:57 -0700736 me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
737 break;
738 }
739
740 case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
741 {
Andy Hunga0b39712015-05-31 22:40:49 -0700742 ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700743 me->notifyAudioTearDown();
Wei Jiabc2fb722014-07-08 16:37:57 -0700744 break;
745 }
746 }
747
748 return 0;
749}
750
751size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
752 Mutex::Autolock autoLock(mLock);
753
Andy Hung85e48142015-05-31 23:04:15 -0700754 if (!mUseAudioCallback) {
Wei Jiabc2fb722014-07-08 16:37:57 -0700755 return 0;
756 }
757
758 bool hasEOS = false;
759
760 size_t sizeCopied = 0;
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700761 bool firstEntry = true;
Andy Hunga0b39712015-05-31 22:40:49 -0700762 QueueEntry *entry; // will be valid after while loop if hasEOS is set.
Wei Jiabc2fb722014-07-08 16:37:57 -0700763 while (sizeCopied < size && !mAudioQueue.empty()) {
Andy Hunga0b39712015-05-31 22:40:49 -0700764 entry = &*mAudioQueue.begin();
Wei Jiabc2fb722014-07-08 16:37:57 -0700765
766 if (entry->mBuffer == NULL) { // EOS
767 hasEOS = true;
768 mAudioQueue.erase(mAudioQueue.begin());
Wei Jiabc2fb722014-07-08 16:37:57 -0700769 break;
770 }
771
Ronghua Wu3e5efb32014-08-18 16:27:08 -0700772 if (firstEntry && entry->mOffset == 0) {
773 firstEntry = false;
Wei Jiabc2fb722014-07-08 16:37:57 -0700774 int64_t mediaTimeUs;
775 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -0700776 ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
Wei Jia7b15cb32015-02-03 17:46:06 -0800777 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jiabc2fb722014-07-08 16:37:57 -0700778 }
779
780 size_t copy = entry->mBuffer->size() - entry->mOffset;
781 size_t sizeRemaining = size - sizeCopied;
782 if (copy > sizeRemaining) {
783 copy = sizeRemaining;
784 }
785
786 memcpy((char *)buffer + sizeCopied,
787 entry->mBuffer->data() + entry->mOffset,
788 copy);
789
790 entry->mOffset += copy;
791 if (entry->mOffset == entry->mBuffer->size()) {
792 entry->mNotifyConsumed->post();
793 mAudioQueue.erase(mAudioQueue.begin());
794 entry = NULL;
795 }
796 sizeCopied += copy;
Wei Jia7b15cb32015-02-03 17:46:06 -0800797
798 notifyIfMediaRenderingStarted_l();
Wei Jiabc2fb722014-07-08 16:37:57 -0700799 }
800
Lajos Molnarf5926712014-10-21 09:36:43 -0700801 if (mAudioFirstAnchorTimeMediaUs >= 0) {
802 int64_t nowUs = ALooper::GetNowUs();
Wei Jia98160162015-02-04 17:01:11 -0800803 int64_t nowMediaUs =
Wei Jiac4ac8172015-10-21 10:35:48 -0700804 mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
Wei Jia7b15cb32015-02-03 17:46:06 -0800805 // we don't know how much data we are queueing for offloaded tracks.
Wei Jia98160162015-02-04 17:01:11 -0800806 mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
Lajos Molnarf5926712014-10-21 09:36:43 -0700807 }
808
Andy Hunga0b39712015-05-31 22:40:49 -0700809 // for non-offloaded audio, we need to compute the frames written because
810 // there is no EVENT_STREAM_END notification. The frames written gives
811 // an estimate on the pending played out duration.
812 if (!offloadingAudio()) {
813 mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
Wei Jiabc2fb722014-07-08 16:37:57 -0700814 }
815
Andy Hunga0b39712015-05-31 22:40:49 -0700816 if (hasEOS) {
817 (new AMessage(kWhatStopAudioSink, this))->post();
818 // As there is currently no EVENT_STREAM_END callback notification for
819 // non-offloaded audio tracks, we need to post the EOS ourselves.
820 if (!offloadingAudio()) {
821 int64_t postEOSDelayUs = 0;
822 if (mAudioSink->needsTrailingPadding()) {
823 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
824 }
825 ALOGV("fillAudioBuffer: notifyEOS "
826 "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld",
827 mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
828 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
829 }
830 }
Wei Jiabc2fb722014-07-08 16:37:57 -0700831 return sizeCopied;
832}
833
Chong Zhang9da0ce42015-06-11 17:18:58 -0700834void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
835 List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
836 bool foundEOS = false;
837 while (it != mAudioQueue.end()) {
838 int32_t eos;
839 QueueEntry *entry = &*it++;
840 if (entry->mBuffer == NULL
841 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
842 itEOS = it;
843 foundEOS = true;
844 }
845 }
846
847 if (foundEOS) {
848 // post all replies before EOS and drop the samples
849 for (it = mAudioQueue.begin(); it != itEOS; it++) {
850 if (it->mBuffer == NULL) {
851 // delay doesn't matter as we don't even have an AudioTrack
852 notifyEOS(true /* audio */, it->mFinalResult);
853 } else {
854 it->mNotifyConsumed->post();
855 }
856 }
857 mAudioQueue.erase(mAudioQueue.begin(), itEOS);
858 }
859}
860
Andreas Huber078cfcf2011-09-15 12:25:04 -0700861bool NuPlayer::Renderer::onDrainAudioQueue() {
Andy Hung58d315c2015-09-11 18:44:56 -0700862 // do not drain audio during teardown as queued buffers may be invalid.
863 if (mAudioTornDown) {
864 return false;
865 }
Wei Jia230b1882015-03-19 15:13:51 -0700866 // TODO: This call to getPosition checks if AudioTrack has been created
867 // in AudioSink before draining audio. If AudioTrack doesn't exist, then
868 // CHECKs on getPosition will fail.
869 // We still need to figure out why AudioTrack is not created when
870 // this function is called. One possible reason could be leftover
871 // audio. Another possible place is to check whether decoder
872 // has received INFO_FORMAT_CHANGED as the first buffer since
873 // AudioSink is opened there, and possible interactions with flush
874 // immediately after start. Investigate error message
875 // "vorbis_dsp_synthesis returned -135", along with RTSP.
Andreas Huber078cfcf2011-09-15 12:25:04 -0700876 uint32_t numFramesPlayed;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700877 if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
Chong Zhang9da0ce42015-06-11 17:18:58 -0700878 // When getPosition fails, renderer will not reschedule the draining
879 // unless new samples are queued.
880 // If we have pending EOS (or "eos" marker for discontinuities), we need
881 // to post these now as NuPlayerDecoder might be waiting for it.
882 drainAudioQueueUntilLastEOS();
883
884 ALOGW("onDrainAudioQueue(): audio sink is not ready");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700885 return false;
886 }
Andreas Huberc92fd242011-08-16 13:48:44 -0700887
Wei Jia230b1882015-03-19 15:13:51 -0700888#if 0
Andreas Huber078cfcf2011-09-15 12:25:04 -0700889 ssize_t numFramesAvailableToWrite =
890 mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
891
Andreas Huber078cfcf2011-09-15 12:25:04 -0700892 if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
Steve Blockdf64d152012-01-04 20:05:49 +0000893 ALOGI("audio sink underrun");
Andreas Huber078cfcf2011-09-15 12:25:04 -0700894 } else {
Steve Block3856b092011-10-20 11:56:00 +0100895 ALOGV("audio queue has %d frames left to play",
Andreas Huber078cfcf2011-09-15 12:25:04 -0700896 mAudioSink->frameCount() - numFramesAvailableToWrite);
897 }
898#endif
899
Andy Hung005e9d02015-05-31 23:16:07 -0700900 uint32_t prevFramesWritten = mNumFramesWritten;
Wei Jia7d3f4df2015-03-03 15:28:00 -0800901 while (!mAudioQueue.empty()) {
Andreas Huberc92fd242011-08-16 13:48:44 -0700902 QueueEntry *entry = &*mAudioQueue.begin();
903
Lajos Molnard5923402014-10-20 17:47:54 -0700904 mLastAudioBufferDrained = entry->mBufferOrdinal;
905
Andreas Huberc92fd242011-08-16 13:48:44 -0700906 if (entry->mBuffer == NULL) {
907 // EOS
Ronghua Wu5095d702014-08-27 12:05:48 -0700908 int64_t postEOSDelayUs = 0;
909 if (mAudioSink->needsTrailingPadding()) {
Lajos Molnar06ad1522014-08-28 07:27:44 -0700910 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
Ronghua Wu5095d702014-08-27 12:05:48 -0700911 }
912 notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
Wei Jia2995dc72015-07-24 16:00:33 -0700913 mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Andreas Huberc92fd242011-08-16 13:48:44 -0700914
915 mAudioQueue.erase(mAudioQueue.begin());
916 entry = NULL;
Andy Hung34912322014-12-18 18:48:39 -0800917 if (mAudioSink->needsTrailingPadding()) {
918 // If we're not in gapless playback (i.e. through setNextPlayer), we
919 // need to stop the track here, because that will play out the last
920 // little bit at the end of the file. Otherwise short files won't play.
921 mAudioSink->stop();
922 mNumFramesWritten = 0;
923 }
Andreas Huber078cfcf2011-09-15 12:25:04 -0700924 return false;
Eric Laurent9b7d9502011-03-21 11:49:00 -0700925 }
926
Chong Zhang81636762015-04-21 09:33:47 -0700927 // ignore 0-sized buffer which could be EOS marker with no data
928 if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
Andreas Huberf9334412010-12-15 15:17:42 -0800929 int64_t mediaTimeUs;
930 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andy Hunga0b39712015-05-31 22:40:49 -0700931 ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
932 mediaTimeUs / 1E6);
Ronghua Wueecb7802014-10-19 23:12:50 -0700933 onNewAudioMediaTime(mediaTimeUs);
Andreas Huberf9334412010-12-15 15:17:42 -0800934 }
935
936 size_t copy = entry->mBuffer->size() - entry->mOffset;
Andreas Huberf9334412010-12-15 15:17:42 -0800937
Wei Jia7d3f4df2015-03-03 15:28:00 -0800938 ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
939 copy, false /* blocking */);
Andy Hunga31335a2014-08-20 17:37:59 -0700940 if (written < 0) {
Andy Hung202bce12014-12-03 11:47:36 -0800941 // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800942 if (written == WOULD_BLOCK) {
Wei Jiadf809472015-06-09 11:21:13 -0700943 ALOGV("AudioSink write would block when writing %zu bytes", copy);
Wei Jia7d3f4df2015-03-03 15:28:00 -0800944 } else {
945 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
Ronghua Wu7665f582015-09-02 10:15:30 -0700946 // This can only happen when AudioSink was opened with doNotReconnect flag set to
947 // true, in which case the NuPlayer will handle the reconnect.
Ronghua Wufaeb0f22015-05-21 12:20:21 -0700948 notifyAudioTearDown();
Wei Jia7d3f4df2015-03-03 15:28:00 -0800949 }
Andy Hung202bce12014-12-03 11:47:36 -0800950 break;
Andy Hunga31335a2014-08-20 17:37:59 -0700951 }
Andreas Huberf9334412010-12-15 15:17:42 -0800952
Andy Hunga31335a2014-08-20 17:37:59 -0700953 entry->mOffset += written;
Andreas Huberf9334412010-12-15 15:17:42 -0800954 if (entry->mOffset == entry->mBuffer->size()) {
955 entry->mNotifyConsumed->post();
956 mAudioQueue.erase(mAudioQueue.begin());
Eric Laurent9b7d9502011-03-21 11:49:00 -0700957
Andreas Huberf9334412010-12-15 15:17:42 -0800958 entry = NULL;
959 }
960
Andy Hunga31335a2014-08-20 17:37:59 -0700961 size_t copiedFrames = written / mAudioSink->frameSize();
Andreas Huber078cfcf2011-09-15 12:25:04 -0700962 mNumFramesWritten += copiedFrames;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700963
Wei Jia7b15cb32015-02-03 17:46:06 -0800964 {
965 Mutex::Autolock autoLock(mLock);
Wei Jiad005c5d2015-10-13 10:58:07 -0700966 int64_t maxTimeMedia;
967 maxTimeMedia =
968 mAnchorTimeMediaUs +
969 (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
970 * 1000LL * mAudioSink->msecsPerFrame());
971 mMediaClock->updateMaxTimeMedia(maxTimeMedia);
972
Wei Jia7b15cb32015-02-03 17:46:06 -0800973 notifyIfMediaRenderingStarted_l();
974 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800975
Andy Hunga31335a2014-08-20 17:37:59 -0700976 if (written != (ssize_t)copy) {
977 // A short count was received from AudioSink::write()
978 //
Wei Jia7d3f4df2015-03-03 15:28:00 -0800979 // AudioSink write is called in non-blocking mode.
980 // It may return with a short count when:
Andy Hunga31335a2014-08-20 17:37:59 -0700981 //
982 // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800983 // 2) The data to be copied exceeds the available buffer in AudioSink.
984 // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
985 // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
Andy Hunga31335a2014-08-20 17:37:59 -0700986
987 // (Case 1)
988 // Must be a multiple of the frame size. If it is not a multiple of a frame size, it
989 // needs to fail, as we should not carry over fractional frames between calls.
990 CHECK_EQ(copy % mAudioSink->frameSize(), 0);
991
Wei Jia7d3f4df2015-03-03 15:28:00 -0800992 // (Case 2, 3, 4)
Andy Hunga31335a2014-08-20 17:37:59 -0700993 // Return early to the caller.
994 // Beware of calling immediately again as this may busy-loop if you are not careful.
Wei Jia7d3f4df2015-03-03 15:28:00 -0800995 ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
Andy Hunga31335a2014-08-20 17:37:59 -0700996 break;
997 }
998 }
Lajos Molnarf5926712014-10-21 09:36:43 -0700999
Andy Hung005e9d02015-05-31 23:16:07 -07001000 // calculate whether we need to reschedule another write.
1001 bool reschedule = !mAudioQueue.empty()
1002 && (!mPaused
1003 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1004 //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u",
1005 // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1006 return reschedule;
Andreas Huberf9334412010-12-15 15:17:42 -08001007}
1008
Wei Jia98160162015-02-04 17:01:11 -08001009int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1010 int32_t sampleRate = offloadingAudio() ?
1011 mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
Wei Jia4d7ac852015-08-31 18:33:14 -07001012 if (sampleRate == 0) {
1013 ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1014 return 0;
1015 }
Wei Jia98160162015-02-04 17:01:11 -08001016 // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1017 return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
1018}
1019
1020// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
Lajos Molnar06ad1522014-08-28 07:27:44 -07001021int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001022 int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
Wei Jiac4ac8172015-10-21 10:35:48 -07001023 return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
Ronghua Wu5095d702014-08-27 12:05:48 -07001024}
1025
Ronghua Wua73d9e02014-10-08 15:13:29 -07001026int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
Wei Jia98160162015-02-04 17:01:11 -08001027 int64_t realUs;
1028 if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001029 // If failed to get current position, e.g. due to audio clock is
1030 // not ready, then just play out video immediately without delay.
Ronghua Wueecb7802014-10-19 23:12:50 -07001031 return nowUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001032 }
Wei Jia98160162015-02-04 17:01:11 -08001033 return realUs;
Ronghua Wua73d9e02014-10-08 15:13:29 -07001034}
1035
Ronghua Wueecb7802014-10-19 23:12:50 -07001036void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001037 Mutex::Autolock autoLock(mLock);
Ronghua Wueecb7802014-10-19 23:12:50 -07001038 // TRICKY: vorbis decoder generates multiple frames with the same
1039 // timestamp, so only update on the first frame with a given timestamp
1040 if (mediaTimeUs == mAnchorTimeMediaUs) {
1041 return;
1042 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001043 setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
Wei Jia4ecbea32015-10-20 18:09:57 -07001044
Andy Hung528c8402016-01-12 12:39:34 -08001045 // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1046 if (mNextAudioClockUpdateTimeUs == -1) {
1047 AudioTimestamp ts;
1048 if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1049 mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1050 }
1051 }
Wei Jia12b62652016-02-09 17:49:31 -08001052 int64_t nowUs = ALooper::GetNowUs();
Andy Hung528c8402016-01-12 12:39:34 -08001053 if (mNextAudioClockUpdateTimeUs >= 0) {
1054 if (nowUs >= mNextAudioClockUpdateTimeUs) {
1055 int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1056 mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
1057 mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1058 }
Wei Jia12b62652016-02-09 17:49:31 -08001059 } else {
1060 int64_t unused;
1061 if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1062 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1063 > kMaxAllowedAudioSinkDelayUs)) {
1064 // Enough data has been sent to AudioSink, but AudioSink has not rendered
1065 // any data yet. Something is wrong with AudioSink, e.g., the device is not
1066 // connected to audio out.
1067 // Switch to system clock. This essentially creates a virtual AudioSink with
1068 // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1069 // This virtual AudioSink renders audio data starting from the very first sample
1070 // and it's paced by system clock.
Wei Jia07af6512016-02-10 10:45:47 -08001071 ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
Wei Jia12b62652016-02-09 17:49:31 -08001072 mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
1073 }
Wei Jia4ecbea32015-10-20 18:09:57 -07001074 }
Wei Jia8edb3f82015-03-11 11:07:45 -07001075 mAnchorNumFramesWritten = mNumFramesWritten;
Wei Jia7b15cb32015-02-03 17:46:06 -08001076 mAnchorTimeMediaUs = mediaTimeUs;
Ronghua Wueecb7802014-10-19 23:12:50 -07001077}
1078
Wei Jia7b15cb32015-02-03 17:46:06 -08001079// Called without mLock acquired.
1080void NuPlayer::Renderer::postDrainVideoQueue() {
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001081 if (mDrainVideoQueuePending
Wei Jia7b15cb32015-02-03 17:46:06 -08001082 || getSyncQueues()
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001083 || (mPaused && mVideoSampleReceived)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001084 return;
1085 }
1086
1087 if (mVideoQueue.empty()) {
1088 return;
1089 }
1090
1091 QueueEntry &entry = *mVideoQueue.begin();
1092
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001093 sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001094 msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
Andreas Huberf9334412010-12-15 15:17:42 -08001095
Andreas Huberf9334412010-12-15 15:17:42 -08001096 if (entry.mBuffer == NULL) {
1097 // EOS doesn't carry a timestamp.
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001098 msg->post();
1099 mDrainVideoQueuePending = true;
1100 return;
1101 }
1102
Robert Shih00541e22015-12-18 17:04:00 -08001103 bool needRepostDrainVideoQueue = false;
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001104 int64_t delayUs;
1105 int64_t nowUs = ALooper::GetNowUs();
1106 int64_t realTimeUs;
1107 if (mFlags & FLAG_REAL_TIME) {
Andreas Huberd5e56232013-03-12 11:01:43 -07001108 int64_t mediaTimeUs;
1109 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001110 realTimeUs = mediaTimeUs;
Andreas Huberf9334412010-12-15 15:17:42 -08001111 } else {
1112 int64_t mediaTimeUs;
1113 CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1114
Wei Jia7b15cb32015-02-03 17:46:06 -08001115 {
1116 Mutex::Autolock autoLock(mLock);
1117 if (mAnchorTimeMediaUs < 0) {
1118 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1119 mAnchorTimeMediaUs = mediaTimeUs;
1120 realTimeUs = nowUs;
Wei Jia25d696f2015-11-19 10:57:15 -08001121 } else if (!mVideoSampleReceived) {
1122 // Always render the first video frame.
1123 realTimeUs = nowUs;
Robert Shih00541e22015-12-18 17:04:00 -08001124 } else if (mAudioFirstAnchorTimeMediaUs < 0
1125 || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001126 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Robert Shih00541e22015-12-18 17:04:00 -08001127 } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
1128 needRepostDrainVideoQueue = true;
1129 realTimeUs = nowUs;
1130 } else {
1131 realTimeUs = nowUs;
Wei Jia7b15cb32015-02-03 17:46:06 -08001132 }
Andreas Huberf9334412010-12-15 15:17:42 -08001133 }
Lajos Molnarf5926712014-10-21 09:36:43 -07001134 if (!mHasAudio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001135 // smooth out videos >= 10fps
1136 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
Lajos Molnarf5926712014-10-21 09:36:43 -07001137 }
Lajos Molnard5923402014-10-20 17:47:54 -07001138
1139 // Heuristics to handle situation when media time changed without a
1140 // discontinuity. If we have not drained an audio buffer that was
1141 // received after this buffer, repost in 10 msec. Otherwise repost
1142 // in 500 msec.
1143 delayUs = realTimeUs - nowUs;
Robert Shih00541e22015-12-18 17:04:00 -08001144 int64_t postDelayUs = -1;
Lajos Molnard5923402014-10-20 17:47:54 -07001145 if (delayUs > 500000) {
Robert Shih00541e22015-12-18 17:04:00 -08001146 postDelayUs = 500000;
Lajos Molnard5923402014-10-20 17:47:54 -07001147 if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1148 postDelayUs = 10000;
1149 }
Robert Shih00541e22015-12-18 17:04:00 -08001150 } else if (needRepostDrainVideoQueue) {
1151 // CHECK(mPlaybackRate > 0);
1152 // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
1153 // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
1154 postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
1155 postDelayUs /= mPlaybackRate;
1156 }
1157
1158 if (postDelayUs >= 0) {
Lajos Molnard5923402014-10-20 17:47:54 -07001159 msg->setWhat(kWhatPostDrainVideoQueue);
1160 msg->post(postDelayUs);
1161 mVideoScheduler->restart();
Robert Shih00541e22015-12-18 17:04:00 -08001162 ALOGI("possible video time jump of %dms or uninitialized media clock, retrying in %dms",
Lajos Molnard5923402014-10-20 17:47:54 -07001163 (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1164 mDrainVideoQueuePending = true;
1165 return;
1166 }
Andreas Huberf9334412010-12-15 15:17:42 -08001167 }
1168
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001169 realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1170 int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1171
1172 delayUs = realTimeUs - nowUs;
1173
Lajos Molnar09524832014-07-17 14:29:51 -07001174 ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001175 // post 2 display refreshes before rendering is due
1176 msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
Andreas Huberf9334412010-12-15 15:17:42 -08001177
1178 mDrainVideoQueuePending = true;
1179}
1180
1181void NuPlayer::Renderer::onDrainVideoQueue() {
1182 if (mVideoQueue.empty()) {
1183 return;
1184 }
1185
1186 QueueEntry *entry = &*mVideoQueue.begin();
1187
1188 if (entry->mBuffer == NULL) {
1189 // EOS
1190
Andreas Huberc92fd242011-08-16 13:48:44 -07001191 notifyEOS(false /* audio */, entry->mFinalResult);
Andreas Huberf9334412010-12-15 15:17:42 -08001192
1193 mVideoQueue.erase(mVideoQueue.begin());
1194 entry = NULL;
Andreas Huber3fe62152011-09-16 15:09:22 -07001195
Ronghua Wua73d9e02014-10-08 15:13:29 -07001196 setVideoLateByUs(0);
Andreas Huberf9334412010-12-15 15:17:42 -08001197 return;
1198 }
1199
Wei Jia25d696f2015-11-19 10:57:15 -08001200 int64_t nowUs = ALooper::GetNowUs();
Andreas Huberd5e56232013-03-12 11:01:43 -07001201 int64_t realTimeUs;
Wei Jia2995dc72015-07-24 16:00:33 -07001202 int64_t mediaTimeUs = -1;
Andreas Huberd5e56232013-03-12 11:01:43 -07001203 if (mFlags & FLAG_REAL_TIME) {
1204 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1205 } else {
Andreas Huberd5e56232013-03-12 11:01:43 -07001206 CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
Andreas Huberf9334412010-12-15 15:17:42 -08001207
Ronghua Wua73d9e02014-10-08 15:13:29 -07001208 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
Andreas Huberd5e56232013-03-12 11:01:43 -07001209 }
1210
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001211 bool tooLate = false;
Andreas Huber3fe62152011-09-16 15:09:22 -07001212
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001213 if (!mPaused) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001214 setVideoLateByUs(nowUs - realTimeUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001215 tooLate = (mVideoLateByUs > 40000);
1216
1217 if (tooLate) {
1218 ALOGV("video late by %lld us (%.2f secs)",
Lajos Molnar6d339f12015-04-17 16:15:53 -07001219 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001220 } else {
Wei Jia98160162015-02-04 17:01:11 -08001221 int64_t mediaUs = 0;
1222 mMediaClock->getMediaTime(realTimeUs, &mediaUs);
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001223 ALOGV("rendering video at media time %.2f secs",
1224 (mFlags & FLAG_REAL_TIME ? realTimeUs :
Wei Jia98160162015-02-04 17:01:11 -08001225 mediaUs) / 1E6);
Wei Jia2995dc72015-07-24 16:00:33 -07001226
1227 if (!(mFlags & FLAG_REAL_TIME)
1228 && mLastAudioMediaTimeUs != -1
1229 && mediaTimeUs > mLastAudioMediaTimeUs) {
1230 // If audio ends before video, video continues to drive media clock.
1231 // Also smooth out videos >= 10fps.
1232 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1233 }
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001234 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001235 } else {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001236 setVideoLateByUs(0);
Ronghua Wueecb7802014-10-19 23:12:50 -07001237 if (!mVideoSampleReceived && !mHasAudio) {
Ronghua Wua73d9e02014-10-08 15:13:29 -07001238 // This will ensure that the first frame after a flush won't be used as anchor
1239 // when renderer is in paused state, because resume can happen any time after seek.
Wei Jia7b15cb32015-02-03 17:46:06 -08001240 Mutex::Autolock autoLock(mLock);
1241 clearAnchorTime_l();
Wei Jia49966ff2014-10-08 18:44:45 -07001242 }
Andreas Huber078cfcf2011-09-15 12:25:04 -07001243 }
Andreas Huberf9334412010-12-15 15:17:42 -08001244
Wei Jia25d696f2015-11-19 10:57:15 -08001245 // Always render the first video frame while keeping stats on A/V sync.
1246 if (!mVideoSampleReceived) {
1247 realTimeUs = nowUs;
1248 tooLate = false;
1249 }
1250
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001251 entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
Glenn Kasten683525b2011-11-04 18:05:35 -07001252 entry->mNotifyConsumed->setInt32("render", !tooLate);
Andreas Huberf9334412010-12-15 15:17:42 -08001253 entry->mNotifyConsumed->post();
1254 mVideoQueue.erase(mVideoQueue.begin());
1255 entry = NULL;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001256
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001257 mVideoSampleReceived = true;
James Dongf57b4ea2012-07-20 13:38:36 -07001258
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001259 if (!mPaused) {
1260 if (!mVideoRenderingStarted) {
1261 mVideoRenderingStarted = true;
1262 notifyVideoRenderingStart();
1263 }
Wei Jia7b15cb32015-02-03 17:46:06 -08001264 Mutex::Autolock autoLock(mLock);
1265 notifyIfMediaRenderingStarted_l();
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001266 }
Andreas Huberf9334412010-12-15 15:17:42 -08001267}
1268
James Dongf57b4ea2012-07-20 13:38:36 -07001269void NuPlayer::Renderer::notifyVideoRenderingStart() {
1270 sp<AMessage> notify = mNotify->dup();
1271 notify->setInt32("what", kWhatVideoRenderingStart);
1272 notify->post();
1273}
1274
Ronghua Wu5095d702014-08-27 12:05:48 -07001275void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
Wei Jia7c8d0e02015-08-27 17:40:21 -07001276 if (audio && delayUs > 0) {
1277 sp<AMessage> msg = new AMessage(kWhatEOS, this);
1278 msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1279 msg->setInt32("finalResult", finalResult);
1280 msg->post(delayUs);
1281 return;
1282 }
Andreas Huberf9334412010-12-15 15:17:42 -08001283 sp<AMessage> notify = mNotify->dup();
1284 notify->setInt32("what", kWhatEOS);
1285 notify->setInt32("audio", static_cast<int32_t>(audio));
Andreas Huberc92fd242011-08-16 13:48:44 -07001286 notify->setInt32("finalResult", finalResult);
Ronghua Wu5095d702014-08-27 12:05:48 -07001287 notify->post(delayUs);
Andreas Huberf9334412010-12-15 15:17:42 -08001288}
1289
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001290void NuPlayer::Renderer::notifyAudioTearDown() {
1291 (new AMessage(kWhatAudioTearDown, this))->post();
Wei Jia3a2956d2014-07-22 16:01:33 -07001292}
1293
Andreas Huberf9334412010-12-15 15:17:42 -08001294void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1295 int32_t audio;
1296 CHECK(msg->findInt32("audio", &audio));
1297
Wei Jia7b15cb32015-02-03 17:46:06 -08001298 if (dropBufferIfStale(audio, msg)) {
1299 return;
1300 }
1301
1302 if (audio) {
1303 mHasAudio = true;
1304 } else {
1305 mHasVideo = true;
1306 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001307
1308 if (mHasVideo) {
Lajos Molnardc43dfa2014-05-07 15:33:04 -07001309 if (mVideoScheduler == NULL) {
1310 mVideoScheduler = new VideoFrameScheduler();
1311 mVideoScheduler->init();
1312 }
Andreas Huberbc7f5b22011-01-21 10:15:23 -08001313 }
1314
Andreas Huber2d8bedd2012-02-21 14:38:23 -08001315 sp<ABuffer> buffer;
1316 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -08001317
1318 sp<AMessage> notifyConsumed;
1319 CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1320
1321 QueueEntry entry;
1322 entry.mBuffer = buffer;
1323 entry.mNotifyConsumed = notifyConsumed;
1324 entry.mOffset = 0;
1325 entry.mFinalResult = OK;
Lajos Molnard5923402014-10-20 17:47:54 -07001326 entry.mBufferOrdinal = ++mTotalBuffersQueued;
Andreas Huberf9334412010-12-15 15:17:42 -08001327
1328 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001329 Mutex::Autolock autoLock(mLock);
Andreas Huberf9334412010-12-15 15:17:42 -08001330 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001331 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001332 } else {
1333 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001334 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001335 }
1336
Wei Jia7b15cb32015-02-03 17:46:06 -08001337 Mutex::Autolock autoLock(mLock);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001338 if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1339 return;
Andreas Huberf9334412010-12-15 15:17:42 -08001340 }
Andreas Hubercb67cd12011-08-26 16:02:19 -07001341
1342 sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1343 sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1344
1345 if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1346 // EOS signalled on either queue.
Wei Jiabc2fb722014-07-08 16:37:57 -07001347 syncQueuesDone_l();
Andreas Hubercb67cd12011-08-26 16:02:19 -07001348 return;
1349 }
1350
1351 int64_t firstAudioTimeUs;
1352 int64_t firstVideoTimeUs;
1353 CHECK(firstAudioBuffer->meta()
1354 ->findInt64("timeUs", &firstAudioTimeUs));
1355 CHECK(firstVideoBuffer->meta()
1356 ->findInt64("timeUs", &firstVideoTimeUs));
1357
1358 int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1359
Steve Block3856b092011-10-20 11:56:00 +01001360 ALOGV("queueDiff = %.2f secs", diff / 1E6);
Andreas Hubercb67cd12011-08-26 16:02:19 -07001361
1362 if (diff > 100000ll) {
1363 // Audio data starts More than 0.1 secs before video.
1364 // Drop some audio.
1365
1366 (*mAudioQueue.begin()).mNotifyConsumed->post();
1367 mAudioQueue.erase(mAudioQueue.begin());
1368 return;
1369 }
1370
Wei Jiabc2fb722014-07-08 16:37:57 -07001371 syncQueuesDone_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001372}
1373
Wei Jiabc2fb722014-07-08 16:37:57 -07001374void NuPlayer::Renderer::syncQueuesDone_l() {
Andreas Huberf9334412010-12-15 15:17:42 -08001375 if (!mSyncQueues) {
1376 return;
1377 }
1378
1379 mSyncQueues = false;
1380
1381 if (!mAudioQueue.empty()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001382 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001383 }
1384
1385 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001386 mLock.unlock();
1387 postDrainVideoQueue();
1388 mLock.lock();
Andreas Huberf9334412010-12-15 15:17:42 -08001389 }
1390}
1391
1392void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1393 int32_t audio;
1394 CHECK(msg->findInt32("audio", &audio));
1395
Wei Jia7b15cb32015-02-03 17:46:06 -08001396 if (dropBufferIfStale(audio, msg)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001397 return;
1398 }
1399
1400 int32_t finalResult;
1401 CHECK(msg->findInt32("finalResult", &finalResult));
1402
1403 QueueEntry entry;
1404 entry.mOffset = 0;
1405 entry.mFinalResult = finalResult;
1406
1407 if (audio) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001408 Mutex::Autolock autoLock(mLock);
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001409 if (mAudioQueue.empty() && mSyncQueues) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001410 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001411 }
Andreas Huberf9334412010-12-15 15:17:42 -08001412 mAudioQueue.push_back(entry);
Wei Jiabc2fb722014-07-08 16:37:57 -07001413 postDrainAudioQueue_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001414 } else {
Wei Jia7b15cb32015-02-03 17:46:06 -08001415 if (mVideoQueue.empty() && getSyncQueues()) {
1416 Mutex::Autolock autoLock(mLock);
Wei Jiabc2fb722014-07-08 16:37:57 -07001417 syncQueuesDone_l();
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001418 }
Andreas Huberf9334412010-12-15 15:17:42 -08001419 mVideoQueue.push_back(entry);
Wei Jia7b15cb32015-02-03 17:46:06 -08001420 postDrainVideoQueue();
Andreas Huberf9334412010-12-15 15:17:42 -08001421 }
1422}
1423
1424void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001425 int32_t audio, notifyComplete;
Andreas Huberf9334412010-12-15 15:17:42 -08001426 CHECK(msg->findInt32("audio", &audio));
1427
Wei Jia28a8a9f2014-08-18 11:29:50 -07001428 {
Wei Jia7b15cb32015-02-03 17:46:06 -08001429 Mutex::Autolock autoLock(mLock);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001430 if (audio) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001431 notifyComplete = mNotifyCompleteAudio;
1432 mNotifyCompleteAudio = false;
Wei Jia2995dc72015-07-24 16:00:33 -07001433 mLastAudioMediaTimeUs = -1;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001434 } else {
Chong Zhang7137ec72014-11-12 16:41:05 -08001435 notifyComplete = mNotifyCompleteVideo;
1436 mNotifyCompleteVideo = false;
Wei Jia28a8a9f2014-08-18 11:29:50 -07001437 }
Wei Jia28a8a9f2014-08-18 11:29:50 -07001438
Wei Jia7b15cb32015-02-03 17:46:06 -08001439 // If we're currently syncing the queues, i.e. dropping audio while
1440 // aligning the first audio/video buffer times and only one of the
1441 // two queues has data, we may starve that queue by not requesting
1442 // more buffers from the decoder. If the other source then encounters
1443 // a discontinuity that leads to flushing, we'll never find the
1444 // corresponding discontinuity on the other queue.
1445 // Therefore we'll stop syncing the queues if at least one of them
1446 // is flushed.
1447 syncQueuesDone_l();
1448 clearAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001449 }
Andreas Huberf9334412010-12-15 15:17:42 -08001450
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001451 ALOGV("flushing %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -08001452 if (audio) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001453 {
1454 Mutex::Autolock autoLock(mLock);
1455 flushQueue(&mAudioQueue);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001456
Wei Jia7b15cb32015-02-03 17:46:06 -08001457 ++mAudioDrainGeneration;
Wei Jia7c8d0e02015-08-27 17:40:21 -07001458 ++mAudioEOSGeneration;
Wei Jia7b15cb32015-02-03 17:46:06 -08001459 prepareForMediaRenderingStart_l();
Wei Jia28a8a9f2014-08-18 11:29:50 -07001460
Andy Hunga0b39712015-05-31 22:40:49 -07001461 // the frame count will be reset after flush.
1462 clearAudioFirstAnchorTime_l();
Wei Jiabc2fb722014-07-08 16:37:57 -07001463 }
Andreas Huberf9334412010-12-15 15:17:42 -08001464
Andreas Huberf9334412010-12-15 15:17:42 -08001465 mDrainAudioQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001466
Wei Jiabc2fb722014-07-08 16:37:57 -07001467 if (offloadingAudio()) {
Wei Jiabc2fb722014-07-08 16:37:57 -07001468 mAudioSink->pause();
1469 mAudioSink->flush();
Andy Hung85e48142015-05-31 23:04:15 -07001470 if (!mPaused) {
1471 mAudioSink->start();
1472 }
Wei Jia9e7ed332015-05-01 16:35:43 -07001473 } else {
1474 mAudioSink->pause();
1475 mAudioSink->flush();
1476 // Call stop() to signal to the AudioSink to completely fill the
1477 // internal buffer before resuming playback.
Andy Hungb03dcb32015-08-27 16:18:59 -07001478 // FIXME: this is ignored after flush().
Wei Jia9e7ed332015-05-01 16:35:43 -07001479 mAudioSink->stop();
Andy Hungb03dcb32015-08-27 16:18:59 -07001480 if (mPaused) {
1481 // Race condition: if renderer is paused and audio sink is stopped,
1482 // we need to make sure that the audio track buffer fully drains
1483 // before delivering data.
1484 // FIXME: remove this if we can detect if stop() is complete.
1485 const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1486 mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1487 } else {
Wei Jia9e7ed332015-05-01 16:35:43 -07001488 mAudioSink->start();
1489 }
1490 mNumFramesWritten = 0;
Wei Jiabc2fb722014-07-08 16:37:57 -07001491 }
Andy Hung528c8402016-01-12 12:39:34 -08001492 mNextAudioClockUpdateTimeUs = -1;
Andreas Huberf9334412010-12-15 15:17:42 -08001493 } else {
1494 flushQueue(&mVideoQueue);
1495
Andreas Huberf9334412010-12-15 15:17:42 -08001496 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001497
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001498 if (mVideoScheduler != NULL) {
1499 mVideoScheduler->restart();
1500 }
1501
Wei Jia7b15cb32015-02-03 17:46:06 -08001502 Mutex::Autolock autoLock(mLock);
1503 ++mVideoDrainGeneration;
1504 prepareForMediaRenderingStart_l();
Andreas Huberf9334412010-12-15 15:17:42 -08001505 }
1506
Chong Zhangfbe8bef2014-08-29 18:34:17 -07001507 mVideoSampleReceived = false;
Chong Zhang7137ec72014-11-12 16:41:05 -08001508
1509 if (notifyComplete) {
1510 notifyFlushComplete(audio);
1511 }
Andreas Huberf9334412010-12-15 15:17:42 -08001512}
1513
1514void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1515 while (!queue->empty()) {
1516 QueueEntry *entry = &*queue->begin();
1517
1518 if (entry->mBuffer != NULL) {
1519 entry->mNotifyConsumed->post();
1520 }
1521
1522 queue->erase(queue->begin());
1523 entry = NULL;
1524 }
1525}
1526
1527void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1528 sp<AMessage> notify = mNotify->dup();
1529 notify->setInt32("what", kWhatFlushComplete);
1530 notify->setInt32("audio", static_cast<int32_t>(audio));
1531 notify->post();
1532}
1533
Wei Jia7b15cb32015-02-03 17:46:06 -08001534bool NuPlayer::Renderer::dropBufferIfStale(
Andreas Huberf9334412010-12-15 15:17:42 -08001535 bool audio, const sp<AMessage> &msg) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001536 int32_t queueGeneration;
1537 CHECK(msg->findInt32("queueGeneration", &queueGeneration));
Andreas Huberf9334412010-12-15 15:17:42 -08001538
Wei Jia7b15cb32015-02-03 17:46:06 -08001539 if (queueGeneration == getQueueGeneration(audio)) {
Andreas Huberf9334412010-12-15 15:17:42 -08001540 return false;
1541 }
1542
1543 sp<AMessage> notifyConsumed;
1544 if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1545 notifyConsumed->post();
1546 }
1547
1548 return true;
1549}
1550
Andreas Huber3831a062010-12-21 10:22:33 -08001551void NuPlayer::Renderer::onAudioSinkChanged() {
Wei Jiabc2fb722014-07-08 16:37:57 -07001552 if (offloadingAudio()) {
1553 return;
1554 }
Andreas Huber3831a062010-12-21 10:22:33 -08001555 CHECK(!mDrainAudioQueuePending);
1556 mNumFramesWritten = 0;
Wei Jia7b15cb32015-02-03 17:46:06 -08001557 {
1558 Mutex::Autolock autoLock(mLock);
1559 mAnchorNumFramesWritten = -1;
1560 }
Marco Nelissen4110c102012-03-29 09:31:28 -07001561 uint32_t written;
1562 if (mAudioSink->getFramesWritten(&written) == OK) {
1563 mNumFramesWritten = written;
1564 }
Andreas Huber3831a062010-12-21 10:22:33 -08001565}
1566
Wei Jiabc2fb722014-07-08 16:37:57 -07001567void NuPlayer::Renderer::onDisableOffloadAudio() {
1568 Mutex::Autolock autoLock(mLock);
1569 mFlags &= ~FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001570 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001571 if (mAudioRenderingStartGeneration != -1) {
1572 prepareForMediaRenderingStart_l();
1573 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001574}
1575
Ronghua Wua10fd232014-11-06 16:15:20 -08001576void NuPlayer::Renderer::onEnableOffloadAudio() {
1577 Mutex::Autolock autoLock(mLock);
1578 mFlags |= FLAG_OFFLOAD_AUDIO;
Wei Jia7b15cb32015-02-03 17:46:06 -08001579 ++mAudioDrainGeneration;
Robert Shihe1d70192015-07-23 17:54:13 -07001580 if (mAudioRenderingStartGeneration != -1) {
1581 prepareForMediaRenderingStart_l();
1582 }
Ronghua Wua10fd232014-11-06 16:15:20 -08001583}
1584
Andreas Huberb4082222011-01-20 15:23:04 -08001585void NuPlayer::Renderer::onPause() {
Rachad8592dbb2014-09-09 13:10:28 -07001586 if (mPaused) {
Rachad8592dbb2014-09-09 13:10:28 -07001587 return;
1588 }
Lajos Molnar6d339f12015-04-17 16:15:53 -07001589
Wei Jia28a8a9f2014-08-18 11:29:50 -07001590 {
1591 Mutex::Autolock autoLock(mLock);
Andy Hung005e9d02015-05-31 23:16:07 -07001592 // we do not increment audio drain generation so that we fill audio buffer during pause.
Wei Jia7b15cb32015-02-03 17:46:06 -08001593 ++mVideoDrainGeneration;
1594 prepareForMediaRenderingStart_l();
Wei Jia73ddd212014-08-29 16:33:49 -07001595 mPaused = true;
Wei Jia98160162015-02-04 17:01:11 -08001596 mMediaClock->setPlaybackRate(0.0);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001597 }
1598
Andreas Huberb4082222011-01-20 15:23:04 -08001599 mDrainAudioQueuePending = false;
Andreas Huberb4082222011-01-20 15:23:04 -08001600 mDrainVideoQueuePending = false;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001601
Andy Hung84200732015-12-03 14:41:06 -08001602 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1603 mAudioSink->pause();
1604 startAudioOffloadPauseTimeout();
Andreas Huberb4082222011-01-20 15:23:04 -08001605
Lajos Molnar6d339f12015-04-17 16:15:53 -07001606 ALOGV("now paused audio queue has %zu entries, video has %zu entries",
Andreas Huberea9d51b2011-11-30 09:53:40 -08001607 mAudioQueue.size(), mVideoQueue.size());
Andreas Huberb4082222011-01-20 15:23:04 -08001608}
1609
1610void NuPlayer::Renderer::onResume() {
Andreas Huberb58ce9f2011-11-28 16:27:35 -08001611 if (!mPaused) {
1612 return;
1613 }
Andreas Huberb4082222011-01-20 15:23:04 -08001614
Andy Hung84200732015-12-03 14:41:06 -08001615 // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1616 cancelAudioOffloadPauseTimeout();
1617 if (mAudioSink->ready()) {
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001618 status_t err = mAudioSink->start();
1619 if (err != OK) {
Andy Hung58d315c2015-09-11 18:44:56 -07001620 ALOGE("cannot start AudioSink err %d", err);
Eric Laurent97c9f4f2015-08-11 18:04:14 -07001621 notifyAudioTearDown();
1622 }
Andreas Huberb4082222011-01-20 15:23:04 -08001623 }
1624
Wei Jia7b15cb32015-02-03 17:46:06 -08001625 {
1626 Mutex::Autolock autoLock(mLock);
1627 mPaused = false;
Andy Hungb12ea0b2015-09-03 15:13:01 -07001628 // rendering started message may have been delayed if we were paused.
1629 if (mRenderingDataDelivered) {
1630 notifyIfMediaRenderingStarted_l();
1631 }
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001632 // configure audiosink as we did not do it when pausing
Wei Jia27ea08e2015-05-12 14:50:35 -07001633 if (mAudioSink != NULL && mAudioSink->ready()) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001634 mAudioSink->setPlaybackRate(mPlaybackSettings);
1635 }
1636
Wei Jia98160162015-02-04 17:01:11 -08001637 mMediaClock->setPlaybackRate(mPlaybackRate);
Andreas Huberb4082222011-01-20 15:23:04 -08001638
Wei Jia7b15cb32015-02-03 17:46:06 -08001639 if (!mAudioQueue.empty()) {
1640 postDrainAudioQueue_l();
1641 }
Andreas Huberb4082222011-01-20 15:23:04 -08001642 }
1643
1644 if (!mVideoQueue.empty()) {
Wei Jia7b15cb32015-02-03 17:46:06 -08001645 postDrainVideoQueue();
Andreas Huberb4082222011-01-20 15:23:04 -08001646 }
1647}
1648
Lajos Molnarc851b5d2014-09-18 14:14:29 -07001649void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1650 if (mVideoScheduler == NULL) {
1651 mVideoScheduler = new VideoFrameScheduler();
1652 }
1653 mVideoScheduler->init(fps);
1654}
1655
Wei Jia7b15cb32015-02-03 17:46:06 -08001656int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1657 Mutex::Autolock autoLock(mLock);
1658 return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1659}
1660
1661int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1662 Mutex::Autolock autoLock(mLock);
1663 return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1664}
1665
1666bool NuPlayer::Renderer::getSyncQueues() {
1667 Mutex::Autolock autoLock(mLock);
1668 return mSyncQueues;
1669}
1670
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001671void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1672 if (mAudioTornDown) {
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001673 return;
1674 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001675 mAudioTornDown = true;
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001676
Ronghua Wua73d9e02014-10-08 15:13:29 -07001677 int64_t currentPositionUs;
Robert Shih1a5c8592015-08-04 18:07:44 -07001678 sp<AMessage> notify = mNotify->dup();
1679 if (getCurrentPosition(&currentPositionUs) == OK) {
1680 notify->setInt64("positionUs", currentPositionUs);
Wei Jia28a8a9f2014-08-18 11:29:50 -07001681 }
Lajos Molnar06ad1522014-08-28 07:27:44 -07001682
Wei Jia3a2956d2014-07-22 16:01:33 -07001683 mAudioSink->stop();
1684 mAudioSink->flush();
1685
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001686 notify->setInt32("what", kWhatAudioTearDown);
Ronghua Wu08529172014-10-02 16:55:52 -07001687 notify->setInt32("reason", reason);
Wei Jia3a2956d2014-07-22 16:01:33 -07001688 notify->post();
1689}
1690
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001691void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1692 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001693 mWakeLock->acquire();
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001694 sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
Wei Jia7b15cb32015-02-03 17:46:06 -08001695 msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001696 msg->post(kOffloadPauseMaxUs);
1697 }
1698}
1699
1700void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1701 if (offloadingAudio()) {
Weiyin Jiang35d5af12015-01-28 16:14:02 +08001702 mWakeLock->release(true);
Ronghua Wuf5b1db12014-09-09 10:11:08 -07001703 ++mAudioOffloadPauseTimeoutGeneration;
1704 }
1705}
1706
Andy Hung202bce12014-12-03 11:47:36 -08001707status_t NuPlayer::Renderer::onOpenAudioSink(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001708 const sp<AMessage> &format,
1709 bool offloadOnly,
1710 bool hasVideo,
1711 uint32_t flags) {
1712 ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1713 offloadOnly, offloadingAudio());
1714 bool audioSinkChanged = false;
1715
1716 int32_t numChannels;
1717 CHECK(format->findInt32("channel-count", &numChannels));
1718
1719 int32_t channelMask;
1720 if (!format->findInt32("channel-mask", &channelMask)) {
1721 // signal to the AudioSink to derive the mask from count.
1722 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
1723 }
1724
1725 int32_t sampleRate;
1726 CHECK(format->findInt32("sample-rate", &sampleRate));
1727
1728 if (offloadingAudio()) {
1729 audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
1730 AString mime;
1731 CHECK(format->findString("mime", &mime));
1732 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
1733
1734 if (err != OK) {
1735 ALOGE("Couldn't map mime \"%s\" to a valid "
1736 "audio_format", mime.c_str());
1737 onDisableOffloadAudio();
1738 } else {
1739 ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
1740 mime.c_str(), audioFormat);
1741
1742 int avgBitRate = -1;
1743 format->findInt32("bit-rate", &avgBitRate);
1744
1745 int32_t aacProfile = -1;
1746 if (audioFormat == AUDIO_FORMAT_AAC
1747 && format->findInt32("aac-profile", &aacProfile)) {
1748 // Redefine AAC format as per aac profile
1749 mapAACProfileToAudioFormat(
1750 audioFormat,
1751 aacProfile);
1752 }
1753
1754 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
1755 offloadInfo.duration_us = -1;
1756 format->findInt64(
1757 "durationUs", &offloadInfo.duration_us);
1758 offloadInfo.sample_rate = sampleRate;
1759 offloadInfo.channel_mask = channelMask;
1760 offloadInfo.format = audioFormat;
1761 offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
1762 offloadInfo.bit_rate = avgBitRate;
1763 offloadInfo.has_video = hasVideo;
1764 offloadInfo.is_streaming = true;
1765
1766 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
1767 ALOGV("openAudioSink: no change in offload mode");
1768 // no change from previous configuration, everything ok.
Andy Hung202bce12014-12-03 11:47:36 -08001769 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001770 }
Andy Hungf0e83642014-12-19 17:55:56 -08001771 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1772
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001773 ALOGV("openAudioSink: try to open AudioSink in offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001774 uint32_t offloadFlags = flags;
1775 offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1776 offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001777 audioSinkChanged = true;
1778 mAudioSink->close();
Andy Hunga0b39712015-05-31 22:40:49 -07001779
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001780 err = mAudioSink->open(
1781 sampleRate,
1782 numChannels,
1783 (audio_channel_mask_t)channelMask,
1784 audioFormat,
Andy Hung179652e2015-05-31 22:49:46 -07001785 0 /* bufferCount - unused */,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001786 &NuPlayer::Renderer::AudioSinkCallback,
1787 this,
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001788 (audio_output_flags_t)offloadFlags,
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001789 &offloadInfo);
1790
1791 if (err == OK) {
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001792 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
1793 }
1794
1795 if (err == OK) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001796 // If the playback is offloaded to h/w, we pass
1797 // the HAL some metadata information.
1798 // We don't want to do this for PCM because it
1799 // will be going through the AudioFlinger mixer
1800 // before reaching the hardware.
1801 // TODO
1802 mCurrentOffloadInfo = offloadInfo;
Andy Hung85e48142015-05-31 23:04:15 -07001803 if (!mPaused) { // for preview mode, don't start if paused
1804 err = mAudioSink->start();
1805 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001806 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
1807 }
1808 if (err != OK) {
1809 // Clean up, fall back to non offload mode.
1810 mAudioSink->close();
1811 onDisableOffloadAudio();
1812 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1813 ALOGV("openAudioSink: offload failed");
Wei Jia3ab25452015-06-10 09:37:47 -07001814 } else {
1815 mUseAudioCallback = true; // offload mode transfers data through callback
1816 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001817 }
1818 }
1819 }
1820 if (!offloadOnly && !offloadingAudio()) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001821 ALOGV("openAudioSink: open AudioSink in NON-offload mode");
Eric Laurentd88c3ca2014-10-28 10:52:11 -07001822 uint32_t pcmFlags = flags;
1823 pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
Andy Hungf0e83642014-12-19 17:55:56 -08001824
1825 const PcmInfo info = {
1826 (audio_channel_mask_t)channelMask,
1827 (audio_output_flags_t)pcmFlags,
1828 AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1829 numChannels,
1830 sampleRate
1831 };
1832 if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1833 ALOGV("openAudioSink: no change in pcm mode");
1834 // no change from previous configuration, everything ok.
1835 return OK;
1836 }
1837
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001838 audioSinkChanged = true;
1839 mAudioSink->close();
1840 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hunga0b39712015-05-31 22:40:49 -07001841 // Note: It is possible to set up the callback, but not use it to send audio data.
1842 // This requires a fix in AudioSink to explicitly specify the transfer mode.
1843 mUseAudioCallback = getUseAudioCallbackSetting();
Wei Jia3ab25452015-06-10 09:37:47 -07001844 if (mUseAudioCallback) {
1845 ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message.
1846 }
Andy Hung179652e2015-05-31 22:49:46 -07001847
1848 // Compute the desired buffer size.
1849 // For callback mode, the amount of time before wakeup is about half the buffer size.
1850 const uint32_t frameCount =
1851 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1852
Ronghua Wu7665f582015-09-02 10:15:30 -07001853 // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
1854 // AudioSink. We don't want this when there's video because it will cause a video seek to
1855 // the previous I frame. But we do want this when there's only audio because it will give
1856 // NuPlayer a chance to switch from non-offload mode to offload mode.
1857 // So we only set doNotReconnect when there's no video.
1858 const bool doNotReconnect = !hasVideo;
Andy Hung202bce12014-12-03 11:47:36 -08001859 status_t err = mAudioSink->open(
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001860 sampleRate,
1861 numChannels,
1862 (audio_channel_mask_t)channelMask,
1863 AUDIO_FORMAT_PCM_16_BIT,
Andy Hung179652e2015-05-31 22:49:46 -07001864 0 /* bufferCount - unused */,
Andy Hunga0b39712015-05-31 22:40:49 -07001865 mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1866 mUseAudioCallback ? this : NULL,
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001867 (audio_output_flags_t)pcmFlags,
1868 NULL,
Ronghua Wu7665f582015-09-02 10:15:30 -07001869 doNotReconnect,
Andy Hung179652e2015-05-31 22:49:46 -07001870 frameCount);
Lajos Molnar3a474aa2015-04-24 17:10:07 -07001871 if (err == OK) {
1872 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
1873 }
Andy Hung202bce12014-12-03 11:47:36 -08001874 if (err != OK) {
1875 ALOGW("openAudioSink: non offloaded open failed status: %d", err);
Wei Jia4d7ac852015-08-31 18:33:14 -07001876 mAudioSink->close();
Andy Hungf0e83642014-12-19 17:55:56 -08001877 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Andy Hung202bce12014-12-03 11:47:36 -08001878 return err;
1879 }
Andy Hungf0e83642014-12-19 17:55:56 -08001880 mCurrentPcmInfo = info;
Andy Hung005e9d02015-05-31 23:16:07 -07001881 if (!mPaused) { // for preview mode, don't start if paused
1882 mAudioSink->start();
1883 }
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001884 }
1885 if (audioSinkChanged) {
1886 onAudioSinkChanged();
1887 }
Ronghua Wufaeb0f22015-05-21 12:20:21 -07001888 mAudioTornDown = false;
Andy Hung202bce12014-12-03 11:47:36 -08001889 return OK;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001890}
1891
1892void NuPlayer::Renderer::onCloseAudioSink() {
1893 mAudioSink->close();
1894 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
Andy Hungf0e83642014-12-19 17:55:56 -08001895 mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001896}
1897
Andreas Huberf9334412010-12-15 15:17:42 -08001898} // namespace android
1899