1f933441648ef6a71dee783d733aac17b9508b452Andreas Huber/*
2f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
4f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * you may not use this file except in compliance with the License.
6f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * You may obtain a copy of the License at
7f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
8f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9f933441648ef6a71dee783d733aac17b9508b452Andreas Huber *
10f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Unless required by applicable law or agreed to in writing, software
11f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * See the License for the specific language governing permissions and
14f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * limitations under the License.
15f933441648ef6a71dee783d733aac17b9508b452Andreas Huber */
16f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
17f933441648ef6a71dee783d733aac17b9508b452Andreas Huber//#define LOG_NDEBUG 0
18f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#define LOG_TAG "NuPlayerRenderer"
19f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <utils/Log.h>
20f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
21f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include "NuPlayerRenderer.h"
22f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
23f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
24f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ADebug.h>
255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h>
26a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu#include <media/stagefright/foundation/AUtils.h>
2735d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang#include <media/stagefright/foundation/AWakeLock.h>
28bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MediaErrors.h>
29bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MetaData.h>
303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang#include <media/stagefright/Utils.h>
31f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
32dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <VideoFrameScheduler.h>
33dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
34095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar#include <inttypes.h>
35095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar
36f933441648ef6a71dee783d733aac17b9508b452Andreas Hubernamespace android {
37f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
38f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
39f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// is closed to allow the audio DSP to power down.
40a5d316fd802cfc92954527f27e6f32206a896113Eric Laurentstatic const int64_t kOffloadPauseMaxUs = 10000000ll;
41f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
42714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber// static
43f0e83644637bd05852c244df481f21a0d435ff66Andy Hungconst NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
44f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_CHANNEL_NONE,
45f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_OUTPUT_FLAG_NONE,
46f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_FORMAT_INVALID,
47f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0, // mNumChannels
48f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0 // mSampleRate
49f0e83644637bd05852c244df481f21a0d435ff66Andy Hung};
50f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
51f0e83644637bd05852c244df481f21a0d435ff66Andy Hung// static
52714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huberconst int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
53714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber
54f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::Renderer(
55f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<MediaPlayerBase::AudioSink> &sink,
56d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        const sp<AMessage> &notify,
57d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        uint32_t flags)
58f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    : mAudioSink(sink),
59f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNotify(notify),
60d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber      mFlags(flags),
61f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNumFramesWritten(0),
62f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainAudioQueuePending(false),
63f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainVideoQueuePending(false),
64f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mAudioQueueGeneration(0),
65f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mVideoQueueGeneration(0),
66a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mAudioFirstAnchorTimeMediaUs(-1),
67eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeMediaUs(-1),
68eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeRealUs(-1),
69f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorNumFramesWritten(-1),
70f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorMaxMediaUs(-1),
71a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mVideoLateByUs(0ll),
72bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasAudio(false),
73bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasVideo(false),
74a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mPauseStartedTimeRealUs(-1),
75a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mFlushingAudio(false),
76a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mFlushingVideo(false),
777137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteAudio(false),
787137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteVideo(false),
79bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mSyncQueues(false),
80714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber      mPaused(false),
81cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang      mPausePositionMediaTimeUs(-1),
8209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung      mVideoSampleReceived(false),
83f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong      mVideoRenderingStarted(false),
84cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mVideoRenderingStartGeneration(0),
85cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mAudioRenderingStartGeneration(0),
86f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu      mAudioOffloadPauseTimeoutGeneration(0),
873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang      mAudioOffloadTornDown(false),
88d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
89f0e83644637bd05852c244df481f21a0d435ff66Andy Hung      mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
90d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mTotalBuffersQueued(0),
9135d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mLastAudioBufferDrained(0),
9235d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mWakeLock(new AWakeLock()) {
9335d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
95f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
96f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::~Renderer() {
97bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
98bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->stop();
99bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->flush();
100bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->close();
101bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
102f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
103f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
104f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
105f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
106f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<ABuffer> &buffer,
107f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
108f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
109f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
1102d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
111f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
112f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
113f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
114f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
115f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
116f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
117f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
118f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
120f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
121f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
122f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
123f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1247137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
125f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
126f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        Mutex::Autolock autoLock(mFlushLock);
127f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
1287137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
12928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            if (mFlushingAudio) {
13028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia                return;
13128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            }
132f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mFlushingAudio = true;
133f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
1347137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
13528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            if (mFlushingVideo) {
13628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia                return;
13728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            }
138f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mFlushingVideo = true;
139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFlush, id());
143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
146f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
147f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
148bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
14914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // CHECK(mAudioQueue.empty());
15014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // CHECK(mVideoQueue.empty());
151a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    setAudioFirstAnchorTime(-1);
152eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    setAnchorTime(-1, -1);
153a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    setVideoLateByUs(0);
15414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mSyncQueues = false;
155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalAudioSinkChanged() {
15828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    (new AMessage(kWhatAudioSinkChanged, id()))->post();
15928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
16028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
16128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
16228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
16328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
16428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
165a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
166a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    (new AMessage(kWhatEnableOffloadAudio, id()))->post();
167a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
168a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
169b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
170b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    (new AMessage(kWhatPause, id()))->post();
171b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
172b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
173b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
174b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    (new AMessage(kWhatResume, id()))->post();
175b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
176b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
177c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
178c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, id());
179c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
180c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
181c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
182c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
183d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// Called on any threads, except renderer's thread.
184a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wustatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
185d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    {
186d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        Mutex::Autolock autoLock(mLock);
187d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        int64_t currentPositionUs;
188d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        if (getCurrentPositionIfPaused_l(&currentPositionUs)) {
189d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia            *mediaUs = currentPositionUs;
190d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia            return OK;
191d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        }
192d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    }
193d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    return getCurrentPositionFromAnchor(mediaUs, ALooper::GetNowUs());
194d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia}
195d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia
196d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// Called on only renderer's thread.
197d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jiastatus_t NuPlayer::Renderer::getCurrentPositionOnLooper(int64_t *mediaUs) {
198d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    return getCurrentPositionOnLooper(mediaUs, ALooper::GetNowUs());
199a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
200a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
201d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// Called on only renderer's thread.
202d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// Since mPaused and mPausePositionMediaTimeUs are changed only on renderer's
203d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// thread, no need to acquire mLock.
204d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jiastatus_t NuPlayer::Renderer::getCurrentPositionOnLooper(
205d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
206d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    int64_t currentPositionUs;
207d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    if (getCurrentPositionIfPaused_l(&currentPositionUs)) {
208d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        *mediaUs = currentPositionUs;
209d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        return OK;
210d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    }
211d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    return getCurrentPositionFromAnchor(mediaUs, nowUs, allowPastQueuedVideo);
212d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia}
213d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia
214d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// Called either with mLock acquired or on renderer's thread.
215d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jiabool NuPlayer::Renderer::getCurrentPositionIfPaused_l(int64_t *mediaUs) {
216cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang    if (!mPaused || mPausePositionMediaTimeUs < 0ll) {
217d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia        return false;
218d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    }
219d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    *mediaUs = mPausePositionMediaTimeUs;
220d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    return true;
221d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia}
222d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia
223d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia// Called on any threads.
224d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jiastatus_t NuPlayer::Renderer::getCurrentPositionFromAnchor(
225f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
226a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
227a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (!mHasAudio && !mHasVideo) {
228a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        return NO_INIT;
229a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
230a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
231eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mAnchorTimeMediaUs < 0) {
232eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return NO_INIT;
233eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
234f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
235eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
236a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
237eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mPauseStartedTimeRealUs != -1) {
238eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        positionUs -= (nowUs - mPauseStartedTimeRealUs);
239eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
240eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
241f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    // limit position to the last queued media time (for video only stream
242f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    // position will be discrete as we don't know how long each frame lasts)
243f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAnchorMaxMediaUs >= 0 && !allowPastQueuedVideo) {
244f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (positionUs > mAnchorMaxMediaUs) {
245f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            positionUs = mAnchorMaxMediaUs;
246f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
247f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
248f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
249eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (positionUs < mAudioFirstAnchorTimeMediaUs) {
250eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        positionUs = mAudioFirstAnchorTimeMediaUs;
251a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
252eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
253a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    *mediaUs = (positionUs <= 0) ? 0 : positionUs;
254a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return OK;
255a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
256a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
257a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setHasMedia(bool audio) {
258a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
259a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (audio) {
260a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mHasAudio = true;
261a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    } else {
262a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mHasVideo = true;
263a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
264a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
265a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
266a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) {
267a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
268a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mAudioFirstAnchorTimeMediaUs = mediaUs;
269a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
270a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
271a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) {
272a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
273a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
274a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
275a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
276a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
277a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
278f592671336be0a061799033e47ceeacb648ed3bfLajos Molnarvoid NuPlayer::Renderer::setAnchorTime(
279f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t mediaUs, int64_t realUs, int64_t numFramesWritten, bool resume) {
280a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
281eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    mAnchorTimeMediaUs = mediaUs;
282eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    mAnchorTimeRealUs = realUs;
283f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorNumFramesWritten = numFramesWritten;
284eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (resume) {
285eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        mPauseStartedTimeRealUs = -1;
286eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
287a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
288a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
289a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
290a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
291a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
292a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
293a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
294a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
295a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
296a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
297a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
298a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
299a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) {
300a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
301a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mPauseStartedTimeRealUs = realUs;
302a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
303a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
304202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
3053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
3063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
3073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
308202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
309202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        bool *isOffloaded) {
3103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, id());
3113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
3123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
3133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
3143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
3153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
3173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
3183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
319202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
320202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    if (!response->findInt32("err", &err)) {
321202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
322202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
323202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
324202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
325202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
326202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
327202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
3283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
3293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
3313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, id());
3323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
3343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
3353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
3363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
337f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
338f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
3393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
3403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
3413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
3423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
3433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
3453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
3463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
3483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
3493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
3513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
3523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
353202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
3543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
356202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
357202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
3583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t replyID;
3603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
3613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
3623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
3643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
3653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
3673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
3683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t replyID;
3693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
3703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
3723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
3743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
3753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
3763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
3773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
378bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
379bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
380bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
381bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
382bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
383bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
384f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
385f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
386f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
387f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(msg->findInt32("generation", &generation));
388f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            if (generation != mAudioQueueGeneration) {
389f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
390f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
391f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
392f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainAudioQueuePending = false;
393f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
394078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
395078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
396078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
397078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
398078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
399078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
400078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
401078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
402078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
403078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
404078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
405078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
406078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
407078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
408078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
409078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
410bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                // kWhatDrainAudioQueue is used for non-offloading mode,
411bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                // and mLock is used only for offloading mode. Therefore,
412bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                // no need to acquire mLock here.
413bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                postDrainAudioQueue_l(delayUs / 2);
414078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
415f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
416f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
417f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
418f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
419f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
420f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
421f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(msg->findInt32("generation", &generation));
422f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            if (generation != mVideoQueueGeneration) {
423f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
424f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
425f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
426f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
427f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
428f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
429f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
430231406d597cca1c9c009f870fbb62e46b8475186Wei Jia            Mutex::Autolock autoLock(mLock);
431231406d597cca1c9c009f870fbb62e46b8475186Wei Jia            postDrainVideoQueue_l();
432f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
433f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
434f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
435d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
436d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
437d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
438d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            CHECK(msg->findInt32("generation", &generation));
439d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (generation != mVideoQueueGeneration) {
440d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
441d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
442d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
443d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
444231406d597cca1c9c009f870fbb62e46b8475186Wei Jia            Mutex::Autolock autoLock(mLock);
445231406d597cca1c9c009f870fbb62e46b8475186Wei Jia            postDrainVideoQueue_l();
446d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
447d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
448d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
449f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
450f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
451f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
452f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
453f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
455f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
456f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
457f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
459f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
464f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
465f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
466f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
4673831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        case kWhatAudioSinkChanged:
4683831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        {
4693831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber            onAudioSinkChanged();
4703831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber            break;
4713831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        }
4723831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
473bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
474bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
475bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
476bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
477bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
478bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
479a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
480a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
481a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
482a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
483a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
484a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
485b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
486b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
487b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
488b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
489b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
490b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
491b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
492b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
493b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
494b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
495b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
496b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
497c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
498c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
499c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
500c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
501c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
502c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
503c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
504c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
5053a2956d148d81194e297408179e84a47a309ef48Wei Jia        case kWhatAudioOffloadTearDown:
5063a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
5070852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            onAudioOffloadTearDown(kDueToError);
5083a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
5093a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
5103a2956d148d81194e297408179e84a47a309ef48Wei Jia
511f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
512f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
513f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
514f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            CHECK(msg->findInt32("generation", &generation));
515f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
516f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
517f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
5180852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
5190852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            onAudioOffloadTearDown(kDueToTimeout);
52035d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang            mWakeLock->release();
521f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
522f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
523f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
524f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
525f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
526f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
530bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
531bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (mDrainAudioQueuePending || mSyncQueues || mPaused
532bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            || offloadingAudio()) {
533f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
534f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
535f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
536f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
537f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
538f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
539f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
540f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
541f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
542f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("generation", mAudioQueueGeneration);
543078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
544f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
545f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
546cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnarvoid NuPlayer::Renderer::prepareForMediaRenderingStart() {
547cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    mAudioRenderingStartGeneration = mAudioQueueGeneration;
548cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    mVideoRenderingStartGeneration = mVideoQueueGeneration;
549cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
550cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
551cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnarvoid NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
552cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
553cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration == mAudioQueueGeneration) {
554cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
555cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
556cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
557cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
558cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
559cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
560cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
561cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
562cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
563bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
564bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
565bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
566bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
567bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
568bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
569bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
570bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
571bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
572bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
573bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
574bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
575bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
576bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
577bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
578bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
579bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
580bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
581bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
582bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
583bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
584bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
585bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
586bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
5873a2956d148d81194e297408179e84a47a309ef48Wei Jia            me->notifyAudioOffloadTearDown();
588bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
589bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
590bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
591bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
592bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
593bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
594bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
595bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
596bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
597bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
59873ddd210ea572375198cac1d4960df793745fb4bWei Jia    if (!offloadingAudio() || mPaused) {
599bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
600bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
601bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
602bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
603bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
604bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
6053e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
606bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
607bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        QueueEntry *entry = &*mAudioQueue.begin();
608bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
609bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
610bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
611bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
612bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
613bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
614bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
615bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
6163e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
6173e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
618bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
619bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
620bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
621f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
622bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
623bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
624bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
625bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
626bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
627bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
628bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
629bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
630bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
631bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
632bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
633bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
634bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
635bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
636bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
637bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
638bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
639bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
640bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
641bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        notifyIfMediaRenderingStarted();
642bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
643bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
644f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
645f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
646f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        setAnchorTime(mAudioFirstAnchorTimeMediaUs, nowUs - getPlayedOutAudioDurationUs(nowUs));
647f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
648f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
649f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    // we don't know how much data we are queueing for offloaded tracks
650f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorMaxMediaUs = -1;
651f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
652bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
653bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        (new AMessage(kWhatStopAudioSink, id()))->post();
654bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
655bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
656bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
657bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
658bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
659078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
660078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
6612bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
6622bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
6632bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
664078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
665078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
666078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
667078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
668078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#if 0
669078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
670df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
671078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
6723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
673078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
674078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
675078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
676f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
677078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    size_t numBytesAvailableToWrite =
678078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        numFramesAvailableToWrite * mAudioSink->frameSize();
679078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
680078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
681f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
682f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
683d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        mLastAudioBufferDrained = entry->mBufferOrdinal;
684d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
685f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
686f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
6875095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
6885095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
68906ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
6905095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
6915095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
692f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
693f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
694f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
6953491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
6963491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
6973491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
6983491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
6993491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
7003491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
7013491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
702078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
703c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
704c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
705f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mOffset == 0) {
706f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
707f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
7083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
709eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
710f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
711f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
712f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
713f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (copy > numBytesAvailableToWrite) {
714f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            copy = numBytesAvailableToWrite;
715f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
716f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
717a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset, copy);
718a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
719202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
720202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
721202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
722a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
723f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
724a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
725f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mOffset == entry->mBuffer->size()) {
726f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
727f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
7289b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
729f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
730f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
731f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
732a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        numBytesAvailableToWrite -= written;
733a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
734078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
735cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
736cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notifyIfMediaRenderingStarted();
73743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
738a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
739a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
740a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
741a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // AudioSink write should block until exactly the number of bytes are delivered.
742a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // But it may return with a short count (without an error) when:
743a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
744a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
745a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // 2) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
746a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
747a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
748a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
749a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
750a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
751a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
752a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 2)
753a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
754a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
755a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            ALOGW("AudioSink write short frame count %zd < %zu", written, copy);
756a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
757a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
758a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
759f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorMaxMediaUs =
760f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        mAnchorTimeMediaUs +
761f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar                (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
762f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar                        * 1000LL * mAudioSink->msecsPerFrame());
763f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
764078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    return !mAudioQueue.empty();
765f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
766f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
76706ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
76806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    int64_t writtenAudioDurationUs =
76906ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        mNumFramesWritten * 1000LL * mAudioSink->msecsPerFrame();
77006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs);
7715095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
7725095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
773a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
774a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
775231406d597cca1c9c009f870fbb62e46b8475186Wei Jia    if (mPaused || getCurrentPositionOnLooper(
776d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia            &currentPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
777eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        // If failed to get current position, e.g. due to audio clock is not ready, then just
778eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        // play out video immediately without delay.
779eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
780a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
781a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return (mediaTimeUs - currentPositionUs) + nowUs;
782a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
783a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
784eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
785eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
786eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
787eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
788eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
789eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
790eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
791eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    int64_t nowUs = ALooper::GetNowUs();
792f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    setAnchorTime(
793f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs), mNumFramesWritten);
794eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
795eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
796231406d597cca1c9c009f870fbb62e46b8475186Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue_l() {
797fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
798fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || mSyncQueues
799fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
800f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
801f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
802f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
803f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
804f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
805f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
806f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
807f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
808f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
809f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
810f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("generation", mVideoQueueGeneration);
811f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
812f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
813f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
814dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
815dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
816dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
817dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
818dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
819dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
820dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
821dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
822dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
823d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
824d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
825dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
826f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
827f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
828f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
829f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
830eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (mAnchorTimeMediaUs < 0) {
831eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            setAnchorTime(mediaTimeUs, nowUs);
832231406d597cca1c9c009f870fbb62e46b8475186Wei Jia            mPausePositionMediaTimeUs = mediaTimeUs;
833474d7c778b63aa33dcf25a92e23a52c1c47f0ac1Wei Jia            mAnchorMaxMediaUs = mediaTimeUs;
834dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            realTimeUs = nowUs;
835f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
836a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
837f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
838f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
839f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            mAnchorMaxMediaUs = mediaTimeUs + 100000; // smooth out videos >= 10fps
840f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
841d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
842d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
843d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
844d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
845d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
846d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
847d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
848d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int64_t postDelayUs = 500000;
849d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
850d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
851d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
852d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
853d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
854d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
855d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            ALOGI("possible video time jump of %dms, retrying in %dms",
856d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                    (int)(delayUs / 1000), (int)(postDelayUs / 1000));
857d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
858d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
859d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
860f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
861f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
862dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
863dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
864dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
865dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
866dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
867095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
868dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
869dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
870f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
871f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
872f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
873f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
874f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
875f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
876f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
877f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
878f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
879f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
880f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
881f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
882f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
883f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
884c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
885f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
886f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
887f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
8883fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
889a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
890f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
891f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
892f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
893a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t nowUs = -1;
894d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
895d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
896d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
897d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
898d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
899d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
900d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
901a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        nowUs = ALooper::GetNowUs();
902a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
903d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
904f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
905fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
9063fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
907fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
908a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        if (nowUs == -1) {
909a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            nowUs = ALooper::GetNowUs();
910a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        }
911a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
912fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
913fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
914fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
915fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
916fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                 mVideoLateByUs, mVideoLateByUs / 1E6);
917fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
918fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
919fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
920eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu                    (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
921fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
922078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
923a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
924eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
925a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
926a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
927eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            setAnchorTime(-1, -1);
92849966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
929078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
930f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
931dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
932683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
933f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
934f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
935f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
93643c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
937fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
938f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
939fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
940fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
941fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
942fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
943fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
944fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        notifyIfMediaRenderingStarted();
945fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
946f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
947f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
948f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
949f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
950f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
951f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
952f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
953f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
9545095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
955f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
956f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
957f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
958c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
9595095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
960f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
961f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9623a2956d148d81194e297408179e84a47a309ef48Wei Jiavoid NuPlayer::Renderer::notifyAudioOffloadTearDown() {
9633a2956d148d81194e297408179e84a47a309ef48Wei Jia    (new AMessage(kWhatAudioOffloadTearDown, id()))->post();
9643a2956d148d81194e297408179e84a47a309ef48Wei Jia}
9653a2956d148d81194e297408179e84a47a309ef48Wei Jia
966f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
967f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
968f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
969f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
970a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    setHasMedia(audio);
971a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
972a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
973dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
974dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
975dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
976dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
977bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
978bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
979f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (dropBufferWhileFlushing(audio, msg)) {
980f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
981f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
982f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9832d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
9842d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
985f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
986f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
987f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
988f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
989f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
990f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
991f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
992f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
993f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
994d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
995f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
996231406d597cca1c9c009f870fbb62e46b8475186Wei Jia    Mutex::Autolock autoLock(mLock);
997f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
998f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
999bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1000f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1001f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
1002231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        postDrainVideoQueue_l();
1003f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1004f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1005cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1006cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1007cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1008f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1009cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1010cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1011f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1012cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1013cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
1014bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
1015cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1016cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1017f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1018cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
1019cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
1020cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
1021cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
1022cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
1023cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
1024f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1025cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1026f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
1028cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1029cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
1030cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
1031cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
1032cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1033cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
1034cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
1035cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1036f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1037cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1038bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
1039f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1040f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1041bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
1042f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
1043f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1044f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1045f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1046f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
1047f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1048f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
1049bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1050f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1051f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1052f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
1053231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        postDrainVideoQueue_l();
1054f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1055f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1056f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1057f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1058f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1059f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1060f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1061f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (dropBufferWhileFlushing(audio, msg)) {
1062f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1063f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1064f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1065f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1066f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1067f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1068f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1069f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1070f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1071f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1072231406d597cca1c9c009f870fbb62e46b8475186Wei Jia    Mutex::Autolock autoLock(mLock);
1073f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1074b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1075bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1076b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1077f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1078bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1079f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1080b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mVideoQueue.empty() && mSyncQueues) {
1081bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1082b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1083f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
1084231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        postDrainVideoQueue_l();
1085f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1086f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1087f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1088f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
10897137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1090f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1091f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
109228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
109328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mFlushLock);
109428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
109528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            mFlushingAudio = false;
10967137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
10977137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
109828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
109928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            mFlushingVideo = false;
11007137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
11017137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
110228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
110328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
110428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1105f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // If we're currently syncing the queues, i.e. dropping audio while
1106f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // aligning the first audio/video buffer times and only one of the
1107f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // two queues has data, we may starve that queue by not requesting
1108f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // more buffers from the decoder. If the other source then encounters
1109f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // a discontinuity that leads to flushing, we'll never find the
1110f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // corresponding discontinuity on the other queue.
1111f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // Therefore we'll stop syncing the queues if at least one of them
1112f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // is flushed.
1113bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    {
1114bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia         Mutex::Autolock autoLock(mLock);
1115bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia         syncQueuesDone_l();
1116a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu         setPauseStartedTimeRealUs(-1);
1117f83408b41bbd796b7923d719e7e3799ddc7acaffRonghua Wu         setAnchorTime(-1, -1);
1118bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
1119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1120cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1121f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1122bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1123bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1124bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1125f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
112628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            ++mAudioQueueGeneration;
112728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            prepareForMediaRenderingStart();
112828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
112928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            if (offloadingAudio()) {
1130a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu                setAudioFirstAnchorTime(-1);
113128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            }
113228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1133f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1134f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1135cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1136bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1137bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1138bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
1139bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->start();
1140bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        ++mVideoQueueGeneration;
1146cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1147c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1148c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1149c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1150c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
1151cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        prepareForMediaRenderingStart();
1152f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1153f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1154fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
11557137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
11567137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
11577137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
11587137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1160f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1161f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1162f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1163f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1164f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1165f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1167f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1168f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1169f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1170f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1171f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1172f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1173f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1174f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1175f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1176f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1177f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1178f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1179f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1180f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1181f933441648ef6a71dee783d733aac17b9508b452Andreas Huberbool NuPlayer::Renderer::dropBufferWhileFlushing(
1182f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
1183f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    bool flushing = false;
1184f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1185f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
1186f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        Mutex::Autolock autoLock(mFlushLock);
1187f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
1188f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            flushing = mFlushingAudio;
1189f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
1190f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            flushing = mFlushingVideo;
1191f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1192f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1193f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1194f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!flushing) {
1195f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1196f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1197f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1198f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1199f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1200f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1201f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1202f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1203f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1204f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1205f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
12063831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1207bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1208bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1209bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
12103831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
12113831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
1212f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorNumFramesWritten = -1;
12134110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
12144110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
12154110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
12164110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
12173831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
12183831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1219bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1220bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1221bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
12223a2956d148d81194e297408179e84a47a309ef48Wei Jia    ++mAudioQueueGeneration;
1223bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1224bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1225a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1226a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1227a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
1228a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    ++mAudioQueueGeneration;
1229a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1230a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1231b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
12328592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
12338592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        ALOGW("Renderer::onPause() called while already paused!");
12348592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
12358592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
1236d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    int64_t currentPositionUs;
1237231406d597cca1c9c009f870fbb62e46b8475186Wei Jia    int64_t pausePositionMediaTimeUs;
1238d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    if (getCurrentPositionFromAnchor(
1239d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia            &currentPositionUs, ALooper::GetNowUs()) == OK) {
1240231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        pausePositionMediaTimeUs = currentPositionUs;
1241cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang    } else {
1242cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang        // Set paused position to -1 (unavailabe) if we don't have anchor time
1243cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang        // This could happen if client does a seekTo() immediately followed by
1244cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang        // pause(). Renderer will be flushed with anchor time cleared. We don't
1245cec7febc48ff76b293ace0cc12a6288f13f72293Chong Zhang        // want to leave stale value in mPausePositionMediaTimeUs.
1246231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        pausePositionMediaTimeUs = -1;
1247d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    }
124828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
124928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
1250231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        mPausePositionMediaTimeUs = pausePositionMediaTimeUs;
125128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        ++mAudioQueueGeneration;
125228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        ++mVideoQueueGeneration;
125328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        prepareForMediaRenderingStart();
125473ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
1255a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setPauseStartedTimeRealUs(ALooper::GetNowUs());
125628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1257b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
125828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1259b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1260cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1261b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (mHasAudio) {
1262b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        mAudioSink->pause();
1263f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        startAudioOffloadPauseTimeout();
1264b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1265b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1266ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber    ALOGV("now paused audio queue has %d entries, video has %d entries",
1267ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1268b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1269b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1270b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1271b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1272b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1273b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1274b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1275b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (mHasAudio) {
1276f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        cancelAudioOffloadPauseTimeout();
1277b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        mAudioSink->start();
1278b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1279b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
128073ddd210ea572375198cac1d4960df793745fb4bWei Jia    Mutex::Autolock autoLock(mLock);
1281b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mPaused = false;
1282a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mPauseStartedTimeRealUs != -1) {
1283a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        int64_t newAnchorRealUs =
1284eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            mAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs;
1285f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        setAnchorTime(
1286f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar                mAnchorTimeMediaUs, newAnchorRealUs, mAnchorNumFramesWritten, true /* resume */);
128749966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia    }
1288b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1289b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mAudioQueue.empty()) {
1290bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1291b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1292b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1293b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
1294231406d597cca1c9c009f870fbb62e46b8475186Wei Jia        postDrainVideoQueue_l();
1295b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1296b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1297b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1298c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1299c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1300c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1301c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1302c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1303c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1304c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
130509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs()
130609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// as it acquires locks and may query the audio driver.
130709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung//
130809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// Some calls could conceivably retrieve extrapolated data instead of
130909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// accessing getTimestamp() or getPosition() every time a data buffer with
131009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// a media time is received.
131109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung//
131206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) {
13133a2956d148d81194e297408179e84a47a309ef48Wei Jia    uint32_t numFramesPlayed;
131406ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    int64_t numFramesPlayedAt;
131506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    AudioTimestamp ts;
131609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    static const int64_t kStaleTimestamp100ms = 100000;
131709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung
131806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    status_t res = mAudioSink->getTimestamp(ts);
131909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
132006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayed = ts.mPosition;
132106ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayedAt =
132206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar            ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
132309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        const int64_t timestampAge = nowUs - numFramesPlayedAt;
132409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        if (timestampAge > kStaleTimestamp100ms) {
132509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // This is an audio FIXME.
132609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // getTimestamp returns a timestamp which may come from audio mixing threads.
132709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // After pausing, the MixerThread may go idle, thus the mTime estimate may
132809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms,
132909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // the max latency should be about 25ms with an average around 12ms (to be verified).
133009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // For safety we use 100ms.
13312abde2c118a94f843a7450818c925d3f0b673cd3Andy Hung            ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)",
133209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung                    (long long)nowUs, (long long)numFramesPlayedAt);
133309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            numFramesPlayedAt = nowUs - kStaleTimestamp100ms;
133409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        }
133509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt);
133609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
133709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        numFramesPlayed = 0;
133809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        numFramesPlayedAt = nowUs;
133909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
134009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //        numFramesPlayed, (long long)numFramesPlayedAt);
134109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    } else {                         // case 3: transitory at new track or audio fast tracks.
134206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        res = mAudioSink->getPosition(&numFramesPlayed);
134306ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        CHECK_EQ(res, (status_t)OK);
134406ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayedAt = nowUs;
134506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayedAt += 1000LL * mAudioSink->latency() / 2; /* XXX */
134609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //ALOGD("getPosition: %d %lld", numFramesPlayed, numFramesPlayedAt);
134706ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    }
134809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung
134909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
135009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    //CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
1351eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000LL * mAudioSink->msecsPerFrame())
135206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar            + nowUs - numFramesPlayedAt;
135309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    if (durationUs < 0) {
135409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // Occurs when numFramesPlayed position is very small and the following:
135509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
135609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //     numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed.
135709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // (2) In case 3, using getPosition and adding mAudioSink->latency() to
135809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //     numFramesPlayedAt, by a time amount greater than numFramesPlayed.
135909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //
136009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // Both of these are transitory conditions.
13612abde2c118a94f843a7450818c925d3f0b673cd3Andy Hung        ALOGV("getPlayedOutAudioDurationUs: negative duration %lld set to zero", (long long)durationUs);
136209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        durationUs = 0;
136309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    }
136409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    ALOGV("getPlayedOutAudioDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
136509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt);
136609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    return durationUs;
136706ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar}
13683a2956d148d81194e297408179e84a47a309ef48Wei Jia
13690852917279f79a94907e9906d0533ae409a30f6aRonghua Wuvoid NuPlayer::Renderer::onAudioOffloadTearDown(AudioOffloadTearDownReason reason) {
1370f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (mAudioOffloadTornDown) {
1371f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1372f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1373f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    mAudioOffloadTornDown = true;
1374f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
1376d4cdba18ba7d0057ae54ec7efa5871b1a9d8becaWei Jia    if (getCurrentPositionOnLooper(&currentPositionUs) != OK) {
1377a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        currentPositionUs = 0;
137828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
137906ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
13803a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
13813a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
13823a2956d148d81194e297408179e84a47a309ef48Wei Jia
13833a2956d148d81194e297408179e84a47a309ef48Wei Jia    sp<AMessage> notify = mNotify->dup();
13843a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->setInt32("what", kWhatAudioOffloadTearDown);
13853a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->setInt64("positionUs", currentPositionUs);
13860852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
13873a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
13883a2956d148d81194e297408179e84a47a309ef48Wei Jia}
13893a2956d148d81194e297408179e84a47a309ef48Wei Jia
1390f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1391f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
139235d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->acquire();
1393f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, id());
1394f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->setInt32("generation", mAudioOffloadPauseTimeoutGeneration);
1395f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1396f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1397f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1398f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1399f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1400f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
140135d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->release(true);
1402f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        ++mAudioOffloadPauseTimeoutGeneration;
1403f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1404f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1405f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1406202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
14073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
14083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
14093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
14103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        uint32_t flags) {
14113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
14123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
14133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
14143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
14163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
14173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
14193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
14203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
14213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
14223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
14233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
14253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
14263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
14283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
14293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
14303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
14313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
14323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
14343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
14353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
14363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
14373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
14383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
14393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
14403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
14423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt32("bit-rate", &avgBitRate);
14433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
14453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
14463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
14473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
14483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
14493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
14503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
14513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
14523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
14543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
14553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
14563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
14573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
14583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
14593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
14603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
14613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
14623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
14633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.is_streaming = true;
14643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
14663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
14673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1468202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
14693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
1470f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1471f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
14723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1473d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1474d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1475d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
14763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
14773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
14783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
14793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
14803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
14813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
14823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
14833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    8 /* bufferCount */,
14843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
14853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1486d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
14873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
14883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
14903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
14913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
14923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
14933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
14943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
14953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
14963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
14973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                err = mAudioSink->start();
14983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
14993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
15003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
15013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
15023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
15033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
15043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
15053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
15063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
15073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
15083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
15093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
15103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1511d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1512d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1513f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
1514f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        const PcmInfo info = {
1515f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_channel_mask_t)channelMask,
1516f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_output_flags_t)pcmFlags,
1517f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1518f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                numChannels,
1519f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                sampleRate
1520f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        };
1521f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1522f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            ALOGV("openAudioSink: no change in pcm mode");
1523f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            // no change from previous configuration, everything ok.
1524f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            return OK;
1525f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        }
1526f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
15273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
15283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
15293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1530202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
15313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
15323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
15333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
15343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
15353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    8 /* bufferCount */,
15363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    NULL,
15373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    NULL,
1538202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                    (audio_output_flags_t)pcmFlags);
1539202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
1540202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
1541f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1542202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
1543202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
1544f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        mCurrentPcmInfo = info;
15453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->start();
15463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
15473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
15483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
15493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
1550a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    if (offloadingAudio()) {
1551a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        mAudioOffloadTornDown = false;
1552a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    }
1553202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
15543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
15553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
15563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
15573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
15583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1559f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
15603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
15613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
1562f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
1563f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1564