• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
22 #include <algorithm>
23 #include <cutils/properties.h>
24 #include <media/stagefright/foundation/ABuffer.h>
25 #include <media/stagefright/foundation/ADebug.h>
26 #include <media/stagefright/foundation/AMessage.h>
27 #include <media/stagefright/foundation/AUtils.h>
28 #include <media/stagefright/foundation/AWakeLock.h>
29 #include <media/stagefright/MediaClock.h>
30 #include <media/stagefright/MediaErrors.h>
31 #include <media/stagefright/MetaData.h>
32 #include <media/stagefright/Utils.h>
33 #include <media/stagefright/VideoFrameScheduler.h>
34 
35 #include <inttypes.h>
36 
37 namespace android {
38 
39 /*
40  * Example of common configuration settings in shell script form
41 
42    #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
43    adb shell setprop audio.offload.disable 1
44 
45    #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
46    adb shell setprop audio.offload.video 1
47 
48    #Use audio callbacks for PCM data
49    adb shell setprop media.stagefright.audio.cbk 1
50 
51    #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
52    adb shell setprop media.stagefright.audio.deep 1
53 
54    #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
55    adb shell setprop media.stagefright.audio.sink 1000
56 
57  * These configurations take effect for the next track played (not the current track).
58  */
59 
getUseAudioCallbackSetting()60 static inline bool getUseAudioCallbackSetting() {
61     return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
62 }
63 
getAudioSinkPcmMsSetting()64 static inline int32_t getAudioSinkPcmMsSetting() {
65     return property_get_int32(
66             "media.stagefright.audio.sink", 500 /* default_value */);
67 }
68 
69 // Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
70 // is closed to allow the audio DSP to power down.
71 static const int64_t kOffloadPauseMaxUs = 10000000ll;
72 
73 // Maximum allowed delay from AudioSink, 1.5 seconds.
74 static const int64_t kMaxAllowedAudioSinkDelayUs = 1500000ll;
75 
76 static const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
77 
78 // static
79 const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
80         AUDIO_CHANNEL_NONE,
81         AUDIO_OUTPUT_FLAG_NONE,
82         AUDIO_FORMAT_INVALID,
83         0, // mNumChannels
84         0 // mSampleRate
85 };
86 
87 // static
88 const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
89 
Renderer(const sp<MediaPlayerBase::AudioSink> & sink,const sp<AMessage> & notify,uint32_t flags)90 NuPlayer::Renderer::Renderer(
91         const sp<MediaPlayerBase::AudioSink> &sink,
92         const sp<AMessage> &notify,
93         uint32_t flags)
94     : mAudioSink(sink),
95       mUseVirtualAudioSink(false),
96       mNotify(notify),
97       mFlags(flags),
98       mNumFramesWritten(0),
99       mDrainAudioQueuePending(false),
100       mDrainVideoQueuePending(false),
101       mAudioQueueGeneration(0),
102       mVideoQueueGeneration(0),
103       mAudioDrainGeneration(0),
104       mVideoDrainGeneration(0),
105       mAudioEOSGeneration(0),
106       mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
107       mAudioFirstAnchorTimeMediaUs(-1),
108       mAnchorTimeMediaUs(-1),
109       mAnchorNumFramesWritten(-1),
110       mVideoLateByUs(0ll),
111       mHasAudio(false),
112       mHasVideo(false),
113       mNotifyCompleteAudio(false),
114       mNotifyCompleteVideo(false),
115       mSyncQueues(false),
116       mPaused(false),
117       mPauseDrainAudioAllowedUs(0),
118       mVideoSampleReceived(false),
119       mVideoRenderingStarted(false),
120       mVideoRenderingStartGeneration(0),
121       mAudioRenderingStartGeneration(0),
122       mRenderingDataDelivered(false),
123       mNextAudioClockUpdateTimeUs(-1),
124       mLastAudioMediaTimeUs(-1),
125       mAudioOffloadPauseTimeoutGeneration(0),
126       mAudioTornDown(false),
127       mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
128       mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
129       mTotalBuffersQueued(0),
130       mLastAudioBufferDrained(0),
131       mUseAudioCallback(false),
132       mWakeLock(new AWakeLock()) {
133     mMediaClock = new MediaClock;
134     mPlaybackRate = mPlaybackSettings.mSpeed;
135     mMediaClock->setPlaybackRate(mPlaybackRate);
136 }
137 
~Renderer()138 NuPlayer::Renderer::~Renderer() {
139     if (offloadingAudio()) {
140         mAudioSink->stop();
141         mAudioSink->flush();
142         mAudioSink->close();
143     }
144 }
145 
queueBuffer(bool audio,const sp<ABuffer> & buffer,const sp<AMessage> & notifyConsumed)146 void NuPlayer::Renderer::queueBuffer(
147         bool audio,
148         const sp<ABuffer> &buffer,
149         const sp<AMessage> &notifyConsumed) {
150     sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
151     msg->setInt32("queueGeneration", getQueueGeneration(audio));
152     msg->setInt32("audio", static_cast<int32_t>(audio));
153     msg->setBuffer("buffer", buffer);
154     msg->setMessage("notifyConsumed", notifyConsumed);
155     msg->post();
156 }
157 
queueEOS(bool audio,status_t finalResult)158 void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
159     CHECK_NE(finalResult, (status_t)OK);
160 
161     sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
162     msg->setInt32("queueGeneration", getQueueGeneration(audio));
163     msg->setInt32("audio", static_cast<int32_t>(audio));
164     msg->setInt32("finalResult", finalResult);
165     msg->post();
166 }
167 
setPlaybackSettings(const AudioPlaybackRate & rate)168 status_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
169     sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
170     writeToAMessage(msg, rate);
171     sp<AMessage> response;
172     status_t err = msg->postAndAwaitResponse(&response);
173     if (err == OK && response != NULL) {
174         CHECK(response->findInt32("err", &err));
175     }
176     return err;
177 }
178 
onConfigPlayback(const AudioPlaybackRate & rate)179 status_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
180     if (rate.mSpeed == 0.f) {
181         onPause();
182         // don't call audiosink's setPlaybackRate if pausing, as pitch does not
183         // have to correspond to the any non-0 speed (e.g old speed). Keep
184         // settings nonetheless, using the old speed, in case audiosink changes.
185         AudioPlaybackRate newRate = rate;
186         newRate.mSpeed = mPlaybackSettings.mSpeed;
187         mPlaybackSettings = newRate;
188         return OK;
189     }
190 
191     if (mAudioSink != NULL && mAudioSink->ready()) {
192         status_t err = mAudioSink->setPlaybackRate(rate);
193         if (err != OK) {
194             return err;
195         }
196     }
197     mPlaybackSettings = rate;
198     mPlaybackRate = rate.mSpeed;
199     mMediaClock->setPlaybackRate(mPlaybackRate);
200     return OK;
201 }
202 
getPlaybackSettings(AudioPlaybackRate * rate)203 status_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
204     sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
205     sp<AMessage> response;
206     status_t err = msg->postAndAwaitResponse(&response);
207     if (err == OK && response != NULL) {
208         CHECK(response->findInt32("err", &err));
209         if (err == OK) {
210             readFromAMessage(response, rate);
211         }
212     }
213     return err;
214 }
215 
onGetPlaybackSettings(AudioPlaybackRate * rate)216 status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
217     if (mAudioSink != NULL && mAudioSink->ready()) {
218         status_t err = mAudioSink->getPlaybackRate(rate);
219         if (err == OK) {
220             if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
221                 ALOGW("correcting mismatch in internal/external playback rate");
222             }
223             // get playback settings used by audiosink, as it may be
224             // slightly off due to audiosink not taking small changes.
225             mPlaybackSettings = *rate;
226             if (mPaused) {
227                 rate->mSpeed = 0.f;
228             }
229         }
230         return err;
231     }
232     *rate = mPlaybackSettings;
233     return OK;
234 }
235 
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)236 status_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
237     sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
238     writeToAMessage(msg, sync, videoFpsHint);
239     sp<AMessage> response;
240     status_t err = msg->postAndAwaitResponse(&response);
241     if (err == OK && response != NULL) {
242         CHECK(response->findInt32("err", &err));
243     }
244     return err;
245 }
246 
onConfigSync(const AVSyncSettings & sync,float videoFpsHint __unused)247 status_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
248     if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
249         return BAD_VALUE;
250     }
251     // TODO: support sync sources
252     return INVALID_OPERATION;
253 }
254 
getSyncSettings(AVSyncSettings * sync,float * videoFps)255 status_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
256     sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
257     sp<AMessage> response;
258     status_t err = msg->postAndAwaitResponse(&response);
259     if (err == OK && response != NULL) {
260         CHECK(response->findInt32("err", &err));
261         if (err == OK) {
262             readFromAMessage(response, sync, videoFps);
263         }
264     }
265     return err;
266 }
267 
onGetSyncSettings(AVSyncSettings * sync,float * videoFps)268 status_t NuPlayer::Renderer::onGetSyncSettings(
269         AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
270     *sync = mSyncSettings;
271     *videoFps = -1.f;
272     return OK;
273 }
274 
flush(bool audio,bool notifyComplete)275 void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
276     {
277         Mutex::Autolock autoLock(mLock);
278         if (audio) {
279             mNotifyCompleteAudio |= notifyComplete;
280             clearAudioFirstAnchorTime_l();
281             ++mAudioQueueGeneration;
282             ++mAudioDrainGeneration;
283         } else {
284             mNotifyCompleteVideo |= notifyComplete;
285             ++mVideoQueueGeneration;
286             ++mVideoDrainGeneration;
287         }
288 
289         clearAnchorTime_l();
290         mVideoLateByUs = 0;
291         mSyncQueues = false;
292     }
293 
294     sp<AMessage> msg = new AMessage(kWhatFlush, this);
295     msg->setInt32("audio", static_cast<int32_t>(audio));
296     msg->post();
297 }
298 
signalTimeDiscontinuity()299 void NuPlayer::Renderer::signalTimeDiscontinuity() {
300 }
301 
signalDisableOffloadAudio()302 void NuPlayer::Renderer::signalDisableOffloadAudio() {
303     (new AMessage(kWhatDisableOffloadAudio, this))->post();
304 }
305 
signalEnableOffloadAudio()306 void NuPlayer::Renderer::signalEnableOffloadAudio() {
307     (new AMessage(kWhatEnableOffloadAudio, this))->post();
308 }
309 
pause()310 void NuPlayer::Renderer::pause() {
311     (new AMessage(kWhatPause, this))->post();
312 }
313 
resume()314 void NuPlayer::Renderer::resume() {
315     (new AMessage(kWhatResume, this))->post();
316 }
317 
setVideoFrameRate(float fps)318 void NuPlayer::Renderer::setVideoFrameRate(float fps) {
319     sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
320     msg->setFloat("frame-rate", fps);
321     msg->post();
322 }
323 
324 // Called on any threads without mLock acquired.
getCurrentPosition(int64_t * mediaUs)325 status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
326     status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
327     if (result == OK) {
328         return result;
329     }
330 
331     // MediaClock has not started yet. Try to start it if possible.
332     {
333         Mutex::Autolock autoLock(mLock);
334         if (mAudioFirstAnchorTimeMediaUs == -1) {
335             return result;
336         }
337 
338         AudioTimestamp ts;
339         status_t res = mAudioSink->getTimestamp(ts);
340         if (res != OK) {
341             return result;
342         }
343 
344         // AudioSink has rendered some frames.
345         int64_t nowUs = ALooper::GetNowUs();
346         int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
347                 + mAudioFirstAnchorTimeMediaUs;
348         mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
349     }
350 
351     return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
352 }
353 
clearAudioFirstAnchorTime_l()354 void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
355     mAudioFirstAnchorTimeMediaUs = -1;
356     mMediaClock->setStartingTimeMedia(-1);
357 }
358 
setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs)359 void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
360     if (mAudioFirstAnchorTimeMediaUs == -1) {
361         mAudioFirstAnchorTimeMediaUs = mediaUs;
362         mMediaClock->setStartingTimeMedia(mediaUs);
363     }
364 }
365 
clearAnchorTime_l()366 void NuPlayer::Renderer::clearAnchorTime_l() {
367     mMediaClock->clearAnchor();
368     mAnchorTimeMediaUs = -1;
369     mAnchorNumFramesWritten = -1;
370 }
371 
setVideoLateByUs(int64_t lateUs)372 void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
373     Mutex::Autolock autoLock(mLock);
374     mVideoLateByUs = lateUs;
375 }
376 
getVideoLateByUs()377 int64_t NuPlayer::Renderer::getVideoLateByUs() {
378     Mutex::Autolock autoLock(mLock);
379     return mVideoLateByUs;
380 }
381 
openAudioSink(const sp<AMessage> & format,bool offloadOnly,bool hasVideo,uint32_t flags,bool * isOffloaded)382 status_t NuPlayer::Renderer::openAudioSink(
383         const sp<AMessage> &format,
384         bool offloadOnly,
385         bool hasVideo,
386         uint32_t flags,
387         bool *isOffloaded) {
388     sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
389     msg->setMessage("format", format);
390     msg->setInt32("offload-only", offloadOnly);
391     msg->setInt32("has-video", hasVideo);
392     msg->setInt32("flags", flags);
393 
394     sp<AMessage> response;
395     msg->postAndAwaitResponse(&response);
396 
397     int32_t err;
398     if (!response->findInt32("err", &err)) {
399         err = INVALID_OPERATION;
400     } else if (err == OK && isOffloaded != NULL) {
401         int32_t offload;
402         CHECK(response->findInt32("offload", &offload));
403         *isOffloaded = (offload != 0);
404     }
405     return err;
406 }
407 
closeAudioSink()408 void NuPlayer::Renderer::closeAudioSink() {
409     sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
410 
411     sp<AMessage> response;
412     msg->postAndAwaitResponse(&response);
413 }
414 
onMessageReceived(const sp<AMessage> & msg)415 void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
416     switch (msg->what()) {
417         case kWhatOpenAudioSink:
418         {
419             sp<AMessage> format;
420             CHECK(msg->findMessage("format", &format));
421 
422             int32_t offloadOnly;
423             CHECK(msg->findInt32("offload-only", &offloadOnly));
424 
425             int32_t hasVideo;
426             CHECK(msg->findInt32("has-video", &hasVideo));
427 
428             uint32_t flags;
429             CHECK(msg->findInt32("flags", (int32_t *)&flags));
430 
431             status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
432 
433             sp<AMessage> response = new AMessage;
434             response->setInt32("err", err);
435             response->setInt32("offload", offloadingAudio());
436 
437             sp<AReplyToken> replyID;
438             CHECK(msg->senderAwaitsResponse(&replyID));
439             response->postReply(replyID);
440 
441             break;
442         }
443 
444         case kWhatCloseAudioSink:
445         {
446             sp<AReplyToken> replyID;
447             CHECK(msg->senderAwaitsResponse(&replyID));
448 
449             onCloseAudioSink();
450 
451             sp<AMessage> response = new AMessage;
452             response->postReply(replyID);
453             break;
454         }
455 
456         case kWhatStopAudioSink:
457         {
458             mAudioSink->stop();
459             break;
460         }
461 
462         case kWhatDrainAudioQueue:
463         {
464             mDrainAudioQueuePending = false;
465 
466             int32_t generation;
467             CHECK(msg->findInt32("drainGeneration", &generation));
468             if (generation != getDrainGeneration(true /* audio */)) {
469                 break;
470             }
471 
472             if (onDrainAudioQueue()) {
473                 uint32_t numFramesPlayed;
474                 CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
475                          (status_t)OK);
476 
477                 uint32_t numFramesPendingPlayout =
478                     mNumFramesWritten - numFramesPlayed;
479 
480                 // This is how long the audio sink will have data to
481                 // play back.
482                 int64_t delayUs =
483                     mAudioSink->msecsPerFrame()
484                         * numFramesPendingPlayout * 1000ll;
485                 if (mPlaybackRate > 1.0f) {
486                     delayUs /= mPlaybackRate;
487                 }
488 
489                 // Let's give it more data after about half that time
490                 // has elapsed.
491                 delayUs /= 2;
492                 // check the buffer size to estimate maximum delay permitted.
493                 const int64_t maxDrainDelayUs = std::max(
494                         mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
495                 ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
496                         (long long)delayUs, (long long)maxDrainDelayUs);
497                 Mutex::Autolock autoLock(mLock);
498                 postDrainAudioQueue_l(delayUs);
499             }
500             break;
501         }
502 
503         case kWhatDrainVideoQueue:
504         {
505             int32_t generation;
506             CHECK(msg->findInt32("drainGeneration", &generation));
507             if (generation != getDrainGeneration(false /* audio */)) {
508                 break;
509             }
510 
511             mDrainVideoQueuePending = false;
512 
513             onDrainVideoQueue();
514 
515             postDrainVideoQueue();
516             break;
517         }
518 
519         case kWhatPostDrainVideoQueue:
520         {
521             int32_t generation;
522             CHECK(msg->findInt32("drainGeneration", &generation));
523             if (generation != getDrainGeneration(false /* audio */)) {
524                 break;
525             }
526 
527             mDrainVideoQueuePending = false;
528             postDrainVideoQueue();
529             break;
530         }
531 
532         case kWhatQueueBuffer:
533         {
534             onQueueBuffer(msg);
535             break;
536         }
537 
538         case kWhatQueueEOS:
539         {
540             onQueueEOS(msg);
541             break;
542         }
543 
544         case kWhatEOS:
545         {
546             int32_t generation;
547             CHECK(msg->findInt32("audioEOSGeneration", &generation));
548             if (generation != mAudioEOSGeneration) {
549                 break;
550             }
551             status_t finalResult;
552             CHECK(msg->findInt32("finalResult", &finalResult));
553             notifyEOS(true /* audio */, finalResult);
554             break;
555         }
556 
557         case kWhatConfigPlayback:
558         {
559             sp<AReplyToken> replyID;
560             CHECK(msg->senderAwaitsResponse(&replyID));
561             AudioPlaybackRate rate;
562             readFromAMessage(msg, &rate);
563             status_t err = onConfigPlayback(rate);
564             sp<AMessage> response = new AMessage;
565             response->setInt32("err", err);
566             response->postReply(replyID);
567             break;
568         }
569 
570         case kWhatGetPlaybackSettings:
571         {
572             sp<AReplyToken> replyID;
573             CHECK(msg->senderAwaitsResponse(&replyID));
574             AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
575             status_t err = onGetPlaybackSettings(&rate);
576             sp<AMessage> response = new AMessage;
577             if (err == OK) {
578                 writeToAMessage(response, rate);
579             }
580             response->setInt32("err", err);
581             response->postReply(replyID);
582             break;
583         }
584 
585         case kWhatConfigSync:
586         {
587             sp<AReplyToken> replyID;
588             CHECK(msg->senderAwaitsResponse(&replyID));
589             AVSyncSettings sync;
590             float videoFpsHint;
591             readFromAMessage(msg, &sync, &videoFpsHint);
592             status_t err = onConfigSync(sync, videoFpsHint);
593             sp<AMessage> response = new AMessage;
594             response->setInt32("err", err);
595             response->postReply(replyID);
596             break;
597         }
598 
599         case kWhatGetSyncSettings:
600         {
601             sp<AReplyToken> replyID;
602             CHECK(msg->senderAwaitsResponse(&replyID));
603 
604             ALOGV("kWhatGetSyncSettings");
605             AVSyncSettings sync;
606             float videoFps = -1.f;
607             status_t err = onGetSyncSettings(&sync, &videoFps);
608             sp<AMessage> response = new AMessage;
609             if (err == OK) {
610                 writeToAMessage(response, sync, videoFps);
611             }
612             response->setInt32("err", err);
613             response->postReply(replyID);
614             break;
615         }
616 
617         case kWhatFlush:
618         {
619             onFlush(msg);
620             break;
621         }
622 
623         case kWhatDisableOffloadAudio:
624         {
625             onDisableOffloadAudio();
626             break;
627         }
628 
629         case kWhatEnableOffloadAudio:
630         {
631             onEnableOffloadAudio();
632             break;
633         }
634 
635         case kWhatPause:
636         {
637             onPause();
638             break;
639         }
640 
641         case kWhatResume:
642         {
643             onResume();
644             break;
645         }
646 
647         case kWhatSetVideoFrameRate:
648         {
649             float fps;
650             CHECK(msg->findFloat("frame-rate", &fps));
651             onSetVideoFrameRate(fps);
652             break;
653         }
654 
655         case kWhatAudioTearDown:
656         {
657             int32_t reason;
658             CHECK(msg->findInt32("reason", &reason));
659 
660             onAudioTearDown((AudioTearDownReason)reason);
661             break;
662         }
663 
664         case kWhatAudioOffloadPauseTimeout:
665         {
666             int32_t generation;
667             CHECK(msg->findInt32("drainGeneration", &generation));
668             if (generation != mAudioOffloadPauseTimeoutGeneration) {
669                 break;
670             }
671             ALOGV("Audio Offload tear down due to pause timeout.");
672             onAudioTearDown(kDueToTimeout);
673             mWakeLock->release();
674             break;
675         }
676 
677         default:
678             TRESPASS();
679             break;
680     }
681 }
682 
postDrainAudioQueue_l(int64_t delayUs)683 void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
684     if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
685         return;
686     }
687 
688     if (mAudioQueue.empty()) {
689         return;
690     }
691 
692     // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
693     if (mPaused) {
694         const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
695         if (diffUs > delayUs) {
696             delayUs = diffUs;
697         }
698     }
699 
700     mDrainAudioQueuePending = true;
701     sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
702     msg->setInt32("drainGeneration", mAudioDrainGeneration);
703     msg->post(delayUs);
704 }
705 
prepareForMediaRenderingStart_l()706 void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
707     mAudioRenderingStartGeneration = mAudioDrainGeneration;
708     mVideoRenderingStartGeneration = mVideoDrainGeneration;
709     mRenderingDataDelivered = false;
710 }
711 
notifyIfMediaRenderingStarted_l()712 void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
713     if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
714         mAudioRenderingStartGeneration == mAudioDrainGeneration) {
715         mRenderingDataDelivered = true;
716         if (mPaused) {
717             return;
718         }
719         mVideoRenderingStartGeneration = -1;
720         mAudioRenderingStartGeneration = -1;
721 
722         sp<AMessage> notify = mNotify->dup();
723         notify->setInt32("what", kWhatMediaRenderingStart);
724         notify->post();
725     }
726 }
727 
728 // static
AudioSinkCallback(MediaPlayerBase::AudioSink *,void * buffer,size_t size,void * cookie,MediaPlayerBase::AudioSink::cb_event_t event)729 size_t NuPlayer::Renderer::AudioSinkCallback(
730         MediaPlayerBase::AudioSink * /* audioSink */,
731         void *buffer,
732         size_t size,
733         void *cookie,
734         MediaPlayerBase::AudioSink::cb_event_t event) {
735     NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
736 
737     switch (event) {
738         case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
739         {
740             return me->fillAudioBuffer(buffer, size);
741             break;
742         }
743 
744         case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
745         {
746             ALOGV("AudioSink::CB_EVENT_STREAM_END");
747             me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
748             break;
749         }
750 
751         case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
752         {
753             ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
754             me->notifyAudioTearDown(kDueToError);
755             break;
756         }
757     }
758 
759     return 0;
760 }
761 
fillAudioBuffer(void * buffer,size_t size)762 size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
763     Mutex::Autolock autoLock(mLock);
764 
765     if (!mUseAudioCallback) {
766         return 0;
767     }
768 
769     bool hasEOS = false;
770 
771     size_t sizeCopied = 0;
772     bool firstEntry = true;
773     QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
774     while (sizeCopied < size && !mAudioQueue.empty()) {
775         entry = &*mAudioQueue.begin();
776 
777         if (entry->mBuffer == NULL) { // EOS
778             hasEOS = true;
779             mAudioQueue.erase(mAudioQueue.begin());
780             break;
781         }
782 
783         if (firstEntry && entry->mOffset == 0) {
784             firstEntry = false;
785             int64_t mediaTimeUs;
786             CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
787             ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
788             setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
789         }
790 
791         size_t copy = entry->mBuffer->size() - entry->mOffset;
792         size_t sizeRemaining = size - sizeCopied;
793         if (copy > sizeRemaining) {
794             copy = sizeRemaining;
795         }
796 
797         memcpy((char *)buffer + sizeCopied,
798                entry->mBuffer->data() + entry->mOffset,
799                copy);
800 
801         entry->mOffset += copy;
802         if (entry->mOffset == entry->mBuffer->size()) {
803             entry->mNotifyConsumed->post();
804             mAudioQueue.erase(mAudioQueue.begin());
805             entry = NULL;
806         }
807         sizeCopied += copy;
808 
809         notifyIfMediaRenderingStarted_l();
810     }
811 
812     if (mAudioFirstAnchorTimeMediaUs >= 0) {
813         int64_t nowUs = ALooper::GetNowUs();
814         int64_t nowMediaUs =
815             mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
816         // we don't know how much data we are queueing for offloaded tracks.
817         mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
818     }
819 
820     // for non-offloaded audio, we need to compute the frames written because
821     // there is no EVENT_STREAM_END notification. The frames written gives
822     // an estimate on the pending played out duration.
823     if (!offloadingAudio()) {
824         mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
825     }
826 
827     if (hasEOS) {
828         (new AMessage(kWhatStopAudioSink, this))->post();
829         // As there is currently no EVENT_STREAM_END callback notification for
830         // non-offloaded audio tracks, we need to post the EOS ourselves.
831         if (!offloadingAudio()) {
832             int64_t postEOSDelayUs = 0;
833             if (mAudioSink->needsTrailingPadding()) {
834                 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
835             }
836             ALOGV("fillAudioBuffer: notifyEOS "
837                     "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
838                     mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
839             notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
840         }
841     }
842     return sizeCopied;
843 }
844 
drainAudioQueueUntilLastEOS()845 void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
846     List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
847     bool foundEOS = false;
848     while (it != mAudioQueue.end()) {
849         int32_t eos;
850         QueueEntry *entry = &*it++;
851         if (entry->mBuffer == NULL
852                 || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
853             itEOS = it;
854             foundEOS = true;
855         }
856     }
857 
858     if (foundEOS) {
859         // post all replies before EOS and drop the samples
860         for (it = mAudioQueue.begin(); it != itEOS; it++) {
861             if (it->mBuffer == NULL) {
862                 // delay doesn't matter as we don't even have an AudioTrack
863                 notifyEOS(true /* audio */, it->mFinalResult);
864             } else {
865                 it->mNotifyConsumed->post();
866             }
867         }
868         mAudioQueue.erase(mAudioQueue.begin(), itEOS);
869     }
870 }
871 
onDrainAudioQueue()872 bool NuPlayer::Renderer::onDrainAudioQueue() {
873     // do not drain audio during teardown as queued buffers may be invalid.
874     if (mAudioTornDown) {
875         return false;
876     }
877     // TODO: This call to getPosition checks if AudioTrack has been created
878     // in AudioSink before draining audio. If AudioTrack doesn't exist, then
879     // CHECKs on getPosition will fail.
880     // We still need to figure out why AudioTrack is not created when
881     // this function is called. One possible reason could be leftover
882     // audio. Another possible place is to check whether decoder
883     // has received INFO_FORMAT_CHANGED as the first buffer since
884     // AudioSink is opened there, and possible interactions with flush
885     // immediately after start. Investigate error message
886     // "vorbis_dsp_synthesis returned -135", along with RTSP.
887     uint32_t numFramesPlayed;
888     if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
889         // When getPosition fails, renderer will not reschedule the draining
890         // unless new samples are queued.
891         // If we have pending EOS (or "eos" marker for discontinuities), we need
892         // to post these now as NuPlayerDecoder might be waiting for it.
893         drainAudioQueueUntilLastEOS();
894 
895         ALOGW("onDrainAudioQueue(): audio sink is not ready");
896         return false;
897     }
898 
899 #if 0
900     ssize_t numFramesAvailableToWrite =
901         mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
902 
903     if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
904         ALOGI("audio sink underrun");
905     } else {
906         ALOGV("audio queue has %d frames left to play",
907              mAudioSink->frameCount() - numFramesAvailableToWrite);
908     }
909 #endif
910 
911     uint32_t prevFramesWritten = mNumFramesWritten;
912     while (!mAudioQueue.empty()) {
913         QueueEntry *entry = &*mAudioQueue.begin();
914 
915         mLastAudioBufferDrained = entry->mBufferOrdinal;
916 
917         if (entry->mBuffer == NULL) {
918             // EOS
919             int64_t postEOSDelayUs = 0;
920             if (mAudioSink->needsTrailingPadding()) {
921                 postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
922             }
923             notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
924             mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
925 
926             mAudioQueue.erase(mAudioQueue.begin());
927             entry = NULL;
928             if (mAudioSink->needsTrailingPadding()) {
929                 // If we're not in gapless playback (i.e. through setNextPlayer), we
930                 // need to stop the track here, because that will play out the last
931                 // little bit at the end of the file. Otherwise short files won't play.
932                 mAudioSink->stop();
933                 mNumFramesWritten = 0;
934             }
935             return false;
936         }
937 
938         // ignore 0-sized buffer which could be EOS marker with no data
939         if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
940             int64_t mediaTimeUs;
941             CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
942             ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
943                     mediaTimeUs / 1E6);
944             onNewAudioMediaTime(mediaTimeUs);
945         }
946 
947         size_t copy = entry->mBuffer->size() - entry->mOffset;
948 
949         ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
950                                             copy, false /* blocking */);
951         if (written < 0) {
952             // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
953             if (written == WOULD_BLOCK) {
954                 ALOGV("AudioSink write would block when writing %zu bytes", copy);
955             } else {
956                 ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
957                 // This can only happen when AudioSink was opened with doNotReconnect flag set to
958                 // true, in which case the NuPlayer will handle the reconnect.
959                 notifyAudioTearDown(kDueToError);
960             }
961             break;
962         }
963 
964         entry->mOffset += written;
965         size_t remainder = entry->mBuffer->size() - entry->mOffset;
966         if ((ssize_t)remainder < mAudioSink->frameSize()) {
967             if (remainder > 0) {
968                 ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
969                         remainder);
970                 entry->mOffset += remainder;
971                 copy -= remainder;
972             }
973 
974             entry->mNotifyConsumed->post();
975             mAudioQueue.erase(mAudioQueue.begin());
976 
977             entry = NULL;
978         }
979 
980         size_t copiedFrames = written / mAudioSink->frameSize();
981         mNumFramesWritten += copiedFrames;
982 
983         {
984             Mutex::Autolock autoLock(mLock);
985             int64_t maxTimeMedia;
986             maxTimeMedia =
987                 mAnchorTimeMediaUs +
988                         (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
989                                 * 1000LL * mAudioSink->msecsPerFrame());
990             mMediaClock->updateMaxTimeMedia(maxTimeMedia);
991 
992             notifyIfMediaRenderingStarted_l();
993         }
994 
995         if (written != (ssize_t)copy) {
996             // A short count was received from AudioSink::write()
997             //
998             // AudioSink write is called in non-blocking mode.
999             // It may return with a short count when:
1000             //
1001             // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
1002             //    discarded.
1003             // 2) The data to be copied exceeds the available buffer in AudioSink.
1004             // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
1005             // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
1006 
1007             // (Case 1)
1008             // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
1009             // needs to fail, as we should not carry over fractional frames between calls.
1010             CHECK_EQ(copy % mAudioSink->frameSize(), 0);
1011 
1012             // (Case 2, 3, 4)
1013             // Return early to the caller.
1014             // Beware of calling immediately again as this may busy-loop if you are not careful.
1015             ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
1016             break;
1017         }
1018     }
1019 
1020     // calculate whether we need to reschedule another write.
1021     bool reschedule = !mAudioQueue.empty()
1022             && (!mPaused
1023                 || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1024     //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
1025     //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1026     return reschedule;
1027 }
1028 
getDurationUsIfPlayedAtSampleRate(uint32_t numFrames)1029 int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
1030     int32_t sampleRate = offloadingAudio() ?
1031             mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
1032     if (sampleRate == 0) {
1033         ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
1034         return 0;
1035     }
1036     // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
1037     return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
1038 }
1039 
1040 // Calculate duration of pending samples if played at normal rate (i.e., 1.0).
getPendingAudioPlayoutDurationUs(int64_t nowUs)1041 int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
1042     int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1043     if (mUseVirtualAudioSink) {
1044         int64_t nowUs = ALooper::GetNowUs();
1045         int64_t mediaUs;
1046         if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
1047             return 0ll;
1048         } else {
1049             return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1050         }
1051     }
1052     return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
1053 }
1054 
getRealTimeUs(int64_t mediaTimeUs,int64_t nowUs)1055 int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
1056     int64_t realUs;
1057     if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
1058         // If failed to get current position, e.g. due to audio clock is
1059         // not ready, then just play out video immediately without delay.
1060         return nowUs;
1061     }
1062     return realUs;
1063 }
1064 
onNewAudioMediaTime(int64_t mediaTimeUs)1065 void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
1066     Mutex::Autolock autoLock(mLock);
1067     // TRICKY: vorbis decoder generates multiple frames with the same
1068     // timestamp, so only update on the first frame with a given timestamp
1069     if (mediaTimeUs == mAnchorTimeMediaUs) {
1070         return;
1071     }
1072     setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
1073 
1074     // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1075     if (mNextAudioClockUpdateTimeUs == -1) {
1076         AudioTimestamp ts;
1077         if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1078             mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1079         }
1080     }
1081     int64_t nowUs = ALooper::GetNowUs();
1082     if (mNextAudioClockUpdateTimeUs >= 0) {
1083         if (nowUs >= mNextAudioClockUpdateTimeUs) {
1084             int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1085             mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
1086             mUseVirtualAudioSink = false;
1087             mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1088         }
1089     } else {
1090         int64_t unused;
1091         if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
1092                 && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
1093                         > kMaxAllowedAudioSinkDelayUs)) {
1094             // Enough data has been sent to AudioSink, but AudioSink has not rendered
1095             // any data yet. Something is wrong with AudioSink, e.g., the device is not
1096             // connected to audio out.
1097             // Switch to system clock. This essentially creates a virtual AudioSink with
1098             // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
1099             // This virtual AudioSink renders audio data starting from the very first sample
1100             // and it's paced by system clock.
1101             ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
1102             mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
1103             mUseVirtualAudioSink = true;
1104         }
1105     }
1106     mAnchorNumFramesWritten = mNumFramesWritten;
1107     mAnchorTimeMediaUs = mediaTimeUs;
1108 }
1109 
1110 // Called without mLock acquired.
postDrainVideoQueue()1111 void NuPlayer::Renderer::postDrainVideoQueue() {
1112     if (mDrainVideoQueuePending
1113             || getSyncQueues()
1114             || (mPaused && mVideoSampleReceived)) {
1115         return;
1116     }
1117 
1118     if (mVideoQueue.empty()) {
1119         return;
1120     }
1121 
1122     QueueEntry &entry = *mVideoQueue.begin();
1123 
1124     sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
1125     msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
1126 
1127     if (entry.mBuffer == NULL) {
1128         // EOS doesn't carry a timestamp.
1129         msg->post();
1130         mDrainVideoQueuePending = true;
1131         return;
1132     }
1133 
1134     bool needRepostDrainVideoQueue = false;
1135     int64_t delayUs;
1136     int64_t nowUs = ALooper::GetNowUs();
1137     int64_t realTimeUs;
1138     if (mFlags & FLAG_REAL_TIME) {
1139         int64_t mediaTimeUs;
1140         CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1141         realTimeUs = mediaTimeUs;
1142     } else {
1143         int64_t mediaTimeUs;
1144         CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1145 
1146         {
1147             Mutex::Autolock autoLock(mLock);
1148             if (mAnchorTimeMediaUs < 0) {
1149                 mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
1150                 mAnchorTimeMediaUs = mediaTimeUs;
1151                 realTimeUs = nowUs;
1152             } else if (!mVideoSampleReceived) {
1153                 // Always render the first video frame.
1154                 realTimeUs = nowUs;
1155             } else if (mAudioFirstAnchorTimeMediaUs < 0
1156                 || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
1157                 realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1158             } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
1159                 needRepostDrainVideoQueue = true;
1160                 realTimeUs = nowUs;
1161             } else {
1162                 realTimeUs = nowUs;
1163             }
1164         }
1165         if (!mHasAudio) {
1166             // smooth out videos >= 10fps
1167             mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1168         }
1169 
1170         // Heuristics to handle situation when media time changed without a
1171         // discontinuity. If we have not drained an audio buffer that was
1172         // received after this buffer, repost in 10 msec. Otherwise repost
1173         // in 500 msec.
1174         delayUs = realTimeUs - nowUs;
1175         int64_t postDelayUs = -1;
1176         if (delayUs > 500000) {
1177             postDelayUs = 500000;
1178             if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1179                 postDelayUs = 10000;
1180             }
1181         } else if (needRepostDrainVideoQueue) {
1182             // CHECK(mPlaybackRate > 0);
1183             // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
1184             // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
1185             postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
1186             postDelayUs /= mPlaybackRate;
1187         }
1188 
1189         if (postDelayUs >= 0) {
1190             msg->setWhat(kWhatPostDrainVideoQueue);
1191             msg->post(postDelayUs);
1192             mVideoScheduler->restart();
1193             ALOGI("possible video time jump of %dms or uninitialized media clock, retrying in %dms",
1194                     (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1195             mDrainVideoQueuePending = true;
1196             return;
1197         }
1198     }
1199 
1200     realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1201     int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1202 
1203     delayUs = realTimeUs - nowUs;
1204 
1205     ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
1206     // post 2 display refreshes before rendering is due
1207     msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1208 
1209     mDrainVideoQueuePending = true;
1210 }
1211 
onDrainVideoQueue()1212 void NuPlayer::Renderer::onDrainVideoQueue() {
1213     if (mVideoQueue.empty()) {
1214         return;
1215     }
1216 
1217     QueueEntry *entry = &*mVideoQueue.begin();
1218 
1219     if (entry->mBuffer == NULL) {
1220         // EOS
1221 
1222         notifyEOS(false /* audio */, entry->mFinalResult);
1223 
1224         mVideoQueue.erase(mVideoQueue.begin());
1225         entry = NULL;
1226 
1227         setVideoLateByUs(0);
1228         return;
1229     }
1230 
1231     int64_t nowUs = ALooper::GetNowUs();
1232     int64_t realTimeUs;
1233     int64_t mediaTimeUs = -1;
1234     if (mFlags & FLAG_REAL_TIME) {
1235         CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1236     } else {
1237         CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1238 
1239         realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1240     }
1241 
1242     bool tooLate = false;
1243 
1244     if (!mPaused) {
1245         setVideoLateByUs(nowUs - realTimeUs);
1246         tooLate = (mVideoLateByUs > 40000);
1247 
1248         if (tooLate) {
1249             ALOGV("video late by %lld us (%.2f secs)",
1250                  (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
1251         } else {
1252             int64_t mediaUs = 0;
1253             mMediaClock->getMediaTime(realTimeUs, &mediaUs);
1254             ALOGV("rendering video at media time %.2f secs",
1255                     (mFlags & FLAG_REAL_TIME ? realTimeUs :
1256                     mediaUs) / 1E6);
1257 
1258             if (!(mFlags & FLAG_REAL_TIME)
1259                     && mLastAudioMediaTimeUs != -1
1260                     && mediaTimeUs > mLastAudioMediaTimeUs) {
1261                 // If audio ends before video, video continues to drive media clock.
1262                 // Also smooth out videos >= 10fps.
1263                 mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1264             }
1265         }
1266     } else {
1267         setVideoLateByUs(0);
1268         if (!mVideoSampleReceived && !mHasAudio) {
1269             // This will ensure that the first frame after a flush won't be used as anchor
1270             // when renderer is in paused state, because resume can happen any time after seek.
1271             Mutex::Autolock autoLock(mLock);
1272             clearAnchorTime_l();
1273         }
1274     }
1275 
1276     // Always render the first video frame while keeping stats on A/V sync.
1277     if (!mVideoSampleReceived) {
1278         realTimeUs = nowUs;
1279         tooLate = false;
1280     }
1281 
1282     entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
1283     entry->mNotifyConsumed->setInt32("render", !tooLate);
1284     entry->mNotifyConsumed->post();
1285     mVideoQueue.erase(mVideoQueue.begin());
1286     entry = NULL;
1287 
1288     mVideoSampleReceived = true;
1289 
1290     if (!mPaused) {
1291         if (!mVideoRenderingStarted) {
1292             mVideoRenderingStarted = true;
1293             notifyVideoRenderingStart();
1294         }
1295         Mutex::Autolock autoLock(mLock);
1296         notifyIfMediaRenderingStarted_l();
1297     }
1298 }
1299 
notifyVideoRenderingStart()1300 void NuPlayer::Renderer::notifyVideoRenderingStart() {
1301     sp<AMessage> notify = mNotify->dup();
1302     notify->setInt32("what", kWhatVideoRenderingStart);
1303     notify->post();
1304 }
1305 
notifyEOS(bool audio,status_t finalResult,int64_t delayUs)1306 void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
1307     if (audio && delayUs > 0) {
1308         sp<AMessage> msg = new AMessage(kWhatEOS, this);
1309         msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
1310         msg->setInt32("finalResult", finalResult);
1311         msg->post(delayUs);
1312         return;
1313     }
1314     sp<AMessage> notify = mNotify->dup();
1315     notify->setInt32("what", kWhatEOS);
1316     notify->setInt32("audio", static_cast<int32_t>(audio));
1317     notify->setInt32("finalResult", finalResult);
1318     notify->post(delayUs);
1319 }
1320 
notifyAudioTearDown(AudioTearDownReason reason)1321 void NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1322     sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1323     msg->setInt32("reason", reason);
1324     msg->post();
1325 }
1326 
onQueueBuffer(const sp<AMessage> & msg)1327 void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1328     int32_t audio;
1329     CHECK(msg->findInt32("audio", &audio));
1330 
1331     if (dropBufferIfStale(audio, msg)) {
1332         return;
1333     }
1334 
1335     if (audio) {
1336         mHasAudio = true;
1337     } else {
1338         mHasVideo = true;
1339     }
1340 
1341     if (mHasVideo) {
1342         if (mVideoScheduler == NULL) {
1343             mVideoScheduler = new VideoFrameScheduler();
1344             mVideoScheduler->init();
1345         }
1346     }
1347 
1348     sp<ABuffer> buffer;
1349     CHECK(msg->findBuffer("buffer", &buffer));
1350 
1351     sp<AMessage> notifyConsumed;
1352     CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1353 
1354     QueueEntry entry;
1355     entry.mBuffer = buffer;
1356     entry.mNotifyConsumed = notifyConsumed;
1357     entry.mOffset = 0;
1358     entry.mFinalResult = OK;
1359     entry.mBufferOrdinal = ++mTotalBuffersQueued;
1360 
1361     if (audio) {
1362         Mutex::Autolock autoLock(mLock);
1363         mAudioQueue.push_back(entry);
1364         postDrainAudioQueue_l();
1365     } else {
1366         mVideoQueue.push_back(entry);
1367         postDrainVideoQueue();
1368     }
1369 
1370     Mutex::Autolock autoLock(mLock);
1371     if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1372         return;
1373     }
1374 
1375     sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1376     sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1377 
1378     if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1379         // EOS signalled on either queue.
1380         syncQueuesDone_l();
1381         return;
1382     }
1383 
1384     int64_t firstAudioTimeUs;
1385     int64_t firstVideoTimeUs;
1386     CHECK(firstAudioBuffer->meta()
1387             ->findInt64("timeUs", &firstAudioTimeUs));
1388     CHECK(firstVideoBuffer->meta()
1389             ->findInt64("timeUs", &firstVideoTimeUs));
1390 
1391     int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1392 
1393     ALOGV("queueDiff = %.2f secs", diff / 1E6);
1394 
1395     if (diff > 100000ll) {
1396         // Audio data starts More than 0.1 secs before video.
1397         // Drop some audio.
1398 
1399         (*mAudioQueue.begin()).mNotifyConsumed->post();
1400         mAudioQueue.erase(mAudioQueue.begin());
1401         return;
1402     }
1403 
1404     syncQueuesDone_l();
1405 }
1406 
syncQueuesDone_l()1407 void NuPlayer::Renderer::syncQueuesDone_l() {
1408     if (!mSyncQueues) {
1409         return;
1410     }
1411 
1412     mSyncQueues = false;
1413 
1414     if (!mAudioQueue.empty()) {
1415         postDrainAudioQueue_l();
1416     }
1417 
1418     if (!mVideoQueue.empty()) {
1419         mLock.unlock();
1420         postDrainVideoQueue();
1421         mLock.lock();
1422     }
1423 }
1424 
onQueueEOS(const sp<AMessage> & msg)1425 void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1426     int32_t audio;
1427     CHECK(msg->findInt32("audio", &audio));
1428 
1429     if (dropBufferIfStale(audio, msg)) {
1430         return;
1431     }
1432 
1433     int32_t finalResult;
1434     CHECK(msg->findInt32("finalResult", &finalResult));
1435 
1436     QueueEntry entry;
1437     entry.mOffset = 0;
1438     entry.mFinalResult = finalResult;
1439 
1440     if (audio) {
1441         Mutex::Autolock autoLock(mLock);
1442         if (mAudioQueue.empty() && mSyncQueues) {
1443             syncQueuesDone_l();
1444         }
1445         mAudioQueue.push_back(entry);
1446         postDrainAudioQueue_l();
1447     } else {
1448         if (mVideoQueue.empty() && getSyncQueues()) {
1449             Mutex::Autolock autoLock(mLock);
1450             syncQueuesDone_l();
1451         }
1452         mVideoQueue.push_back(entry);
1453         postDrainVideoQueue();
1454     }
1455 }
1456 
onFlush(const sp<AMessage> & msg)1457 void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
1458     int32_t audio, notifyComplete;
1459     CHECK(msg->findInt32("audio", &audio));
1460 
1461     {
1462         Mutex::Autolock autoLock(mLock);
1463         if (audio) {
1464             notifyComplete = mNotifyCompleteAudio;
1465             mNotifyCompleteAudio = false;
1466             mLastAudioMediaTimeUs = -1;
1467         } else {
1468             notifyComplete = mNotifyCompleteVideo;
1469             mNotifyCompleteVideo = false;
1470         }
1471 
1472         // If we're currently syncing the queues, i.e. dropping audio while
1473         // aligning the first audio/video buffer times and only one of the
1474         // two queues has data, we may starve that queue by not requesting
1475         // more buffers from the decoder. If the other source then encounters
1476         // a discontinuity that leads to flushing, we'll never find the
1477         // corresponding discontinuity on the other queue.
1478         // Therefore we'll stop syncing the queues if at least one of them
1479         // is flushed.
1480         syncQueuesDone_l();
1481         clearAnchorTime_l();
1482     }
1483 
1484     ALOGV("flushing %s", audio ? "audio" : "video");
1485     if (audio) {
1486         {
1487             Mutex::Autolock autoLock(mLock);
1488             flushQueue(&mAudioQueue);
1489 
1490             ++mAudioDrainGeneration;
1491             ++mAudioEOSGeneration;
1492             prepareForMediaRenderingStart_l();
1493 
1494             // the frame count will be reset after flush.
1495             clearAudioFirstAnchorTime_l();
1496         }
1497 
1498         mDrainAudioQueuePending = false;
1499 
1500         if (offloadingAudio()) {
1501             mAudioSink->pause();
1502             mAudioSink->flush();
1503             if (!mPaused) {
1504                 mAudioSink->start();
1505             }
1506         } else {
1507             mAudioSink->pause();
1508             mAudioSink->flush();
1509             // Call stop() to signal to the AudioSink to completely fill the
1510             // internal buffer before resuming playback.
1511             // FIXME: this is ignored after flush().
1512             mAudioSink->stop();
1513             if (mPaused) {
1514                 // Race condition: if renderer is paused and audio sink is stopped,
1515                 // we need to make sure that the audio track buffer fully drains
1516                 // before delivering data.
1517                 // FIXME: remove this if we can detect if stop() is complete.
1518                 const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1519                 mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1520             } else {
1521                 mAudioSink->start();
1522             }
1523             mNumFramesWritten = 0;
1524         }
1525         mNextAudioClockUpdateTimeUs = -1;
1526     } else {
1527         flushQueue(&mVideoQueue);
1528 
1529         mDrainVideoQueuePending = false;
1530 
1531         if (mVideoScheduler != NULL) {
1532             mVideoScheduler->restart();
1533         }
1534 
1535         Mutex::Autolock autoLock(mLock);
1536         ++mVideoDrainGeneration;
1537         prepareForMediaRenderingStart_l();
1538     }
1539 
1540     mVideoSampleReceived = false;
1541 
1542     if (notifyComplete) {
1543         notifyFlushComplete(audio);
1544     }
1545 }
1546 
flushQueue(List<QueueEntry> * queue)1547 void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1548     while (!queue->empty()) {
1549         QueueEntry *entry = &*queue->begin();
1550 
1551         if (entry->mBuffer != NULL) {
1552             entry->mNotifyConsumed->post();
1553         }
1554 
1555         queue->erase(queue->begin());
1556         entry = NULL;
1557     }
1558 }
1559 
notifyFlushComplete(bool audio)1560 void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1561     sp<AMessage> notify = mNotify->dup();
1562     notify->setInt32("what", kWhatFlushComplete);
1563     notify->setInt32("audio", static_cast<int32_t>(audio));
1564     notify->post();
1565 }
1566 
dropBufferIfStale(bool audio,const sp<AMessage> & msg)1567 bool NuPlayer::Renderer::dropBufferIfStale(
1568         bool audio, const sp<AMessage> &msg) {
1569     int32_t queueGeneration;
1570     CHECK(msg->findInt32("queueGeneration", &queueGeneration));
1571 
1572     if (queueGeneration == getQueueGeneration(audio)) {
1573         return false;
1574     }
1575 
1576     sp<AMessage> notifyConsumed;
1577     if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1578         notifyConsumed->post();
1579     }
1580 
1581     return true;
1582 }
1583 
onAudioSinkChanged()1584 void NuPlayer::Renderer::onAudioSinkChanged() {
1585     if (offloadingAudio()) {
1586         return;
1587     }
1588     CHECK(!mDrainAudioQueuePending);
1589     mNumFramesWritten = 0;
1590     {
1591         Mutex::Autolock autoLock(mLock);
1592         mAnchorNumFramesWritten = -1;
1593     }
1594     uint32_t written;
1595     if (mAudioSink->getFramesWritten(&written) == OK) {
1596         mNumFramesWritten = written;
1597     }
1598 }
1599 
onDisableOffloadAudio()1600 void NuPlayer::Renderer::onDisableOffloadAudio() {
1601     Mutex::Autolock autoLock(mLock);
1602     mFlags &= ~FLAG_OFFLOAD_AUDIO;
1603     ++mAudioDrainGeneration;
1604     if (mAudioRenderingStartGeneration != -1) {
1605         prepareForMediaRenderingStart_l();
1606     }
1607 }
1608 
onEnableOffloadAudio()1609 void NuPlayer::Renderer::onEnableOffloadAudio() {
1610     Mutex::Autolock autoLock(mLock);
1611     mFlags |= FLAG_OFFLOAD_AUDIO;
1612     ++mAudioDrainGeneration;
1613     if (mAudioRenderingStartGeneration != -1) {
1614         prepareForMediaRenderingStart_l();
1615     }
1616 }
1617 
onPause()1618 void NuPlayer::Renderer::onPause() {
1619     if (mPaused) {
1620         return;
1621     }
1622 
1623     {
1624         Mutex::Autolock autoLock(mLock);
1625         // we do not increment audio drain generation so that we fill audio buffer during pause.
1626         ++mVideoDrainGeneration;
1627         prepareForMediaRenderingStart_l();
1628         mPaused = true;
1629         mMediaClock->setPlaybackRate(0.0);
1630     }
1631 
1632     mDrainAudioQueuePending = false;
1633     mDrainVideoQueuePending = false;
1634 
1635     // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1636     mAudioSink->pause();
1637     startAudioOffloadPauseTimeout();
1638 
1639     ALOGV("now paused audio queue has %zu entries, video has %zu entries",
1640           mAudioQueue.size(), mVideoQueue.size());
1641 }
1642 
onResume()1643 void NuPlayer::Renderer::onResume() {
1644     if (!mPaused) {
1645         return;
1646     }
1647 
1648     // Note: audio data may not have been decoded, and the AudioSink may not be opened.
1649     cancelAudioOffloadPauseTimeout();
1650     if (mAudioSink->ready()) {
1651         status_t err = mAudioSink->start();
1652         if (err != OK) {
1653             ALOGE("cannot start AudioSink err %d", err);
1654             notifyAudioTearDown(kDueToError);
1655         }
1656     }
1657 
1658     {
1659         Mutex::Autolock autoLock(mLock);
1660         mPaused = false;
1661         // rendering started message may have been delayed if we were paused.
1662         if (mRenderingDataDelivered) {
1663             notifyIfMediaRenderingStarted_l();
1664         }
1665         // configure audiosink as we did not do it when pausing
1666         if (mAudioSink != NULL && mAudioSink->ready()) {
1667             mAudioSink->setPlaybackRate(mPlaybackSettings);
1668         }
1669 
1670         mMediaClock->setPlaybackRate(mPlaybackRate);
1671 
1672         if (!mAudioQueue.empty()) {
1673             postDrainAudioQueue_l();
1674         }
1675     }
1676 
1677     if (!mVideoQueue.empty()) {
1678         postDrainVideoQueue();
1679     }
1680 }
1681 
onSetVideoFrameRate(float fps)1682 void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1683     if (mVideoScheduler == NULL) {
1684         mVideoScheduler = new VideoFrameScheduler();
1685     }
1686     mVideoScheduler->init(fps);
1687 }
1688 
getQueueGeneration(bool audio)1689 int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
1690     Mutex::Autolock autoLock(mLock);
1691     return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
1692 }
1693 
getDrainGeneration(bool audio)1694 int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
1695     Mutex::Autolock autoLock(mLock);
1696     return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
1697 }
1698 
getSyncQueues()1699 bool NuPlayer::Renderer::getSyncQueues() {
1700     Mutex::Autolock autoLock(mLock);
1701     return mSyncQueues;
1702 }
1703 
onAudioTearDown(AudioTearDownReason reason)1704 void NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1705     if (mAudioTornDown) {
1706         return;
1707     }
1708     mAudioTornDown = true;
1709 
1710     int64_t currentPositionUs;
1711     sp<AMessage> notify = mNotify->dup();
1712     if (getCurrentPosition(&currentPositionUs) == OK) {
1713         notify->setInt64("positionUs", currentPositionUs);
1714     }
1715 
1716     mAudioSink->stop();
1717     mAudioSink->flush();
1718 
1719     notify->setInt32("what", kWhatAudioTearDown);
1720     notify->setInt32("reason", reason);
1721     notify->post();
1722 }
1723 
startAudioOffloadPauseTimeout()1724 void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1725     if (offloadingAudio()) {
1726         mWakeLock->acquire();
1727         sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
1728         msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
1729         msg->post(kOffloadPauseMaxUs);
1730     }
1731 }
1732 
cancelAudioOffloadPauseTimeout()1733 void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1734     // We may have called startAudioOffloadPauseTimeout() without
1735     // the AudioSink open and with offloadingAudio enabled.
1736     //
1737     // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
1738     // we always release the wakelock and increment the pause timeout generation.
1739     //
1740     // Note: The acquired wakelock prevents the device from suspending
1741     // immediately after offload pause (in case a resume happens shortly thereafter).
1742     mWakeLock->release(true);
1743     ++mAudioOffloadPauseTimeoutGeneration;
1744 }
1745 
onOpenAudioSink(const sp<AMessage> & format,bool offloadOnly,bool hasVideo,uint32_t flags)1746 status_t NuPlayer::Renderer::onOpenAudioSink(
1747         const sp<AMessage> &format,
1748         bool offloadOnly,
1749         bool hasVideo,
1750         uint32_t flags) {
1751     ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
1752             offloadOnly, offloadingAudio());
1753     bool audioSinkChanged = false;
1754 
1755     int32_t numChannels;
1756     CHECK(format->findInt32("channel-count", &numChannels));
1757 
1758     int32_t channelMask;
1759     if (!format->findInt32("channel-mask", &channelMask)) {
1760         // signal to the AudioSink to derive the mask from count.
1761         channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
1762     }
1763 
1764     int32_t sampleRate;
1765     CHECK(format->findInt32("sample-rate", &sampleRate));
1766 
1767     if (offloadingAudio()) {
1768         audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
1769         AString mime;
1770         CHECK(format->findString("mime", &mime));
1771         status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
1772 
1773         if (err != OK) {
1774             ALOGE("Couldn't map mime \"%s\" to a valid "
1775                     "audio_format", mime.c_str());
1776             onDisableOffloadAudio();
1777         } else {
1778             ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
1779                     mime.c_str(), audioFormat);
1780 
1781             int avgBitRate = -1;
1782             format->findInt32("bitrate", &avgBitRate);
1783 
1784             int32_t aacProfile = -1;
1785             if (audioFormat == AUDIO_FORMAT_AAC
1786                     && format->findInt32("aac-profile", &aacProfile)) {
1787                 // Redefine AAC format as per aac profile
1788                 mapAACProfileToAudioFormat(
1789                         audioFormat,
1790                         aacProfile);
1791             }
1792 
1793             audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
1794             offloadInfo.duration_us = -1;
1795             format->findInt64(
1796                     "durationUs", &offloadInfo.duration_us);
1797             offloadInfo.sample_rate = sampleRate;
1798             offloadInfo.channel_mask = channelMask;
1799             offloadInfo.format = audioFormat;
1800             offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
1801             offloadInfo.bit_rate = avgBitRate;
1802             offloadInfo.has_video = hasVideo;
1803             offloadInfo.is_streaming = true;
1804 
1805             if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
1806                 ALOGV("openAudioSink: no change in offload mode");
1807                 // no change from previous configuration, everything ok.
1808                 return OK;
1809             }
1810             mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1811 
1812             ALOGV("openAudioSink: try to open AudioSink in offload mode");
1813             uint32_t offloadFlags = flags;
1814             offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1815             offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
1816             audioSinkChanged = true;
1817             mAudioSink->close();
1818 
1819             err = mAudioSink->open(
1820                     sampleRate,
1821                     numChannels,
1822                     (audio_channel_mask_t)channelMask,
1823                     audioFormat,
1824                     0 /* bufferCount - unused */,
1825                     &NuPlayer::Renderer::AudioSinkCallback,
1826                     this,
1827                     (audio_output_flags_t)offloadFlags,
1828                     &offloadInfo);
1829 
1830             if (err == OK) {
1831                 err = mAudioSink->setPlaybackRate(mPlaybackSettings);
1832             }
1833 
1834             if (err == OK) {
1835                 // If the playback is offloaded to h/w, we pass
1836                 // the HAL some metadata information.
1837                 // We don't want to do this for PCM because it
1838                 // will be going through the AudioFlinger mixer
1839                 // before reaching the hardware.
1840                 // TODO
1841                 mCurrentOffloadInfo = offloadInfo;
1842                 if (!mPaused) { // for preview mode, don't start if paused
1843                     err = mAudioSink->start();
1844                 }
1845                 ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
1846             }
1847             if (err != OK) {
1848                 // Clean up, fall back to non offload mode.
1849                 mAudioSink->close();
1850                 onDisableOffloadAudio();
1851                 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1852                 ALOGV("openAudioSink: offload failed");
1853                 if (offloadOnly) {
1854                     notifyAudioTearDown(kForceNonOffload);
1855                 }
1856             } else {
1857                 mUseAudioCallback = true;  // offload mode transfers data through callback
1858                 ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
1859             }
1860         }
1861     }
1862     if (!offloadOnly && !offloadingAudio()) {
1863         ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1864         uint32_t pcmFlags = flags;
1865         pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1866 
1867         const PcmInfo info = {
1868                 (audio_channel_mask_t)channelMask,
1869                 (audio_output_flags_t)pcmFlags,
1870                 AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1871                 numChannels,
1872                 sampleRate
1873         };
1874         if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1875             ALOGV("openAudioSink: no change in pcm mode");
1876             // no change from previous configuration, everything ok.
1877             return OK;
1878         }
1879 
1880         audioSinkChanged = true;
1881         mAudioSink->close();
1882         mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1883         // Note: It is possible to set up the callback, but not use it to send audio data.
1884         // This requires a fix in AudioSink to explicitly specify the transfer mode.
1885         mUseAudioCallback = getUseAudioCallbackSetting();
1886         if (mUseAudioCallback) {
1887             ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
1888         }
1889 
1890         // Compute the desired buffer size.
1891         // For callback mode, the amount of time before wakeup is about half the buffer size.
1892         const uint32_t frameCount =
1893                 (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1894 
1895         // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
1896         // AudioSink. We don't want this when there's video because it will cause a video seek to
1897         // the previous I frame. But we do want this when there's only audio because it will give
1898         // NuPlayer a chance to switch from non-offload mode to offload mode.
1899         // So we only set doNotReconnect when there's no video.
1900         const bool doNotReconnect = !hasVideo;
1901 
1902         // We should always be able to set our playback settings if the sink is closed.
1903         LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
1904                 "onOpenAudioSink: can't set playback rate on closed sink");
1905         status_t err = mAudioSink->open(
1906                     sampleRate,
1907                     numChannels,
1908                     (audio_channel_mask_t)channelMask,
1909                     AUDIO_FORMAT_PCM_16_BIT,
1910                     0 /* bufferCount - unused */,
1911                     mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1912                     mUseAudioCallback ? this : NULL,
1913                     (audio_output_flags_t)pcmFlags,
1914                     NULL,
1915                     doNotReconnect,
1916                     frameCount);
1917         if (err != OK) {
1918             ALOGW("openAudioSink: non offloaded open failed status: %d", err);
1919             mAudioSink->close();
1920             mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1921             return err;
1922         }
1923         mCurrentPcmInfo = info;
1924         if (!mPaused) { // for preview mode, don't start if paused
1925             mAudioSink->start();
1926         }
1927     }
1928     if (audioSinkChanged) {
1929         onAudioSinkChanged();
1930     }
1931     mAudioTornDown = false;
1932     return OK;
1933 }
1934 
onCloseAudioSink()1935 void NuPlayer::Renderer::onCloseAudioSink() {
1936     mAudioSink->close();
1937     mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1938     mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1939 }
1940 
1941 }  // namespace android
1942 
1943