NuPlayerRenderer.cpp revision 3491232a7c0d953fa021f6a81baee64c44f364f3
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>
27bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MediaErrors.h>
28bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MetaData.h>
293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang#include <media/stagefright/Utils.h>
30f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
31dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar#include <VideoFrameScheduler.h>
32dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
33095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar#include <inttypes.h>
34095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar
35f933441648ef6a71dee783d733aac17b9508b452Andreas Hubernamespace android {
36f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
37f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
38f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// is closed to allow the audio DSP to power down.
39a5d316fd802cfc92954527f27e6f32206a896113Eric Laurentstatic const int64_t kOffloadPauseMaxUs = 10000000ll;
40f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
41714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber// static
42714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huberconst int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
43714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber
44f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::Renderer(
45f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<MediaPlayerBase::AudioSink> &sink,
46d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        const sp<AMessage> &notify,
47d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        uint32_t flags)
48f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    : mAudioSink(sink),
49f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNotify(notify),
50d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber      mFlags(flags),
51f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNumFramesWritten(0),
52f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainAudioQueuePending(false),
53f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainVideoQueuePending(false),
54f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mAudioQueueGeneration(0),
55f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mVideoQueueGeneration(0),
56a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mAudioFirstAnchorTimeMediaUs(-1),
57eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeMediaUs(-1),
58eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeRealUs(-1),
59f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorNumFramesWritten(-1),
60f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorMaxMediaUs(-1),
61a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mVideoLateByUs(0ll),
62bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasAudio(false),
63bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasVideo(false),
64a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mPauseStartedTimeRealUs(-1),
65a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mFlushingAudio(false),
66a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mFlushingVideo(false),
677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteAudio(false),
687137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteVideo(false),
69bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mSyncQueues(false),
70714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber      mPaused(false),
7109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung      mVideoSampleReceived(false),
72f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong      mVideoRenderingStarted(false),
73cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mVideoRenderingStartGeneration(0),
74cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mAudioRenderingStartGeneration(0),
75f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu      mAudioOffloadPauseTimeoutGeneration(0),
763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang      mAudioOffloadTornDown(false),
77d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
78d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mTotalBuffersQueued(0),
79d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mLastAudioBufferDrained(0) {
80f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
81f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
82f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::~Renderer() {
83bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
84bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->stop();
85bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->flush();
86bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->close();
87bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
88f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
89f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
90f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
92f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<ABuffer> &buffer,
93f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
95f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
962d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
97f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
98f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
99f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
100f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
101f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
102f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
103f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
104f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
105f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
106f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
107f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
108f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
109f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1107137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
111f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
112f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        Mutex::Autolock autoLock(mFlushLock);
113f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
1147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
11528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            if (mFlushingAudio) {
11628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia                return;
11728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            }
118f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mFlushingAudio = true;
119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
1207137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
12128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            if (mFlushingVideo) {
12228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia                return;
12328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            }
124f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mFlushingVideo = true;
125f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
126f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
127f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
128f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFlush, id());
129f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
130f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
131f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
132f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
133f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
134bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
13514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // CHECK(mAudioQueue.empty());
13614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    // CHECK(mVideoQueue.empty());
137a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    setAudioFirstAnchorTime(-1);
138eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    setAnchorTime(-1, -1);
139a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    setVideoLateByUs(0);
14014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mSyncQueues = false;
141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalAudioSinkChanged() {
14428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    (new AMessage(kWhatAudioSinkChanged, id()))->post();
14528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
14628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
14728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
14828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
14928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
15028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
151a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
152a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    (new AMessage(kWhatEnableOffloadAudio, id()))->post();
153a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
154a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
155b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
156b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    (new AMessage(kWhatPause, id()))->post();
157b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
158b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
159b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
160b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    (new AMessage(kWhatResume, id()))->post();
161b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
162b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
163c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
164c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, id());
165c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
166c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
167c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
168c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
169a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wustatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
170a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return getCurrentPosition(mediaUs, ALooper::GetNowUs());
171a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
172a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
173f592671336be0a061799033e47ceeacb648ed3bfLajos Molnarstatus_t NuPlayer::Renderer::getCurrentPosition(
174f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
175a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
176a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (!mHasAudio && !mHasVideo) {
177a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        return NO_INIT;
178a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
179a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
180eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mAnchorTimeMediaUs < 0) {
181eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return NO_INIT;
182eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
183f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
184eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
185a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
186eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mPauseStartedTimeRealUs != -1) {
187eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        positionUs -= (nowUs - mPauseStartedTimeRealUs);
188eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
189eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
190f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    // limit position to the last queued media time (for video only stream
191f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    // position will be discrete as we don't know how long each frame lasts)
192f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAnchorMaxMediaUs >= 0 && !allowPastQueuedVideo) {
193f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (positionUs > mAnchorMaxMediaUs) {
194f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            positionUs = mAnchorMaxMediaUs;
195f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
196f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
197f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
198eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (positionUs < mAudioFirstAnchorTimeMediaUs) {
199eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        positionUs = mAudioFirstAnchorTimeMediaUs;
200a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
201eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
202a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    *mediaUs = (positionUs <= 0) ? 0 : positionUs;
203a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return OK;
204a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
205a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
206a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setHasMedia(bool audio) {
207a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
208a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (audio) {
209a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mHasAudio = true;
210a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    } else {
211a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mHasVideo = true;
212a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
213a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
214a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
215a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) {
216a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
217a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mAudioFirstAnchorTimeMediaUs = mediaUs;
218a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
219a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
220a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) {
221a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
222a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
223a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
224a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
225a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
226a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
227f592671336be0a061799033e47ceeacb648ed3bfLajos Molnarvoid NuPlayer::Renderer::setAnchorTime(
228f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t mediaUs, int64_t realUs, int64_t numFramesWritten, bool resume) {
229a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
230eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    mAnchorTimeMediaUs = mediaUs;
231eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    mAnchorTimeRealUs = realUs;
232f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorNumFramesWritten = numFramesWritten;
233eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (resume) {
234eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        mPauseStartedTimeRealUs = -1;
235eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
236a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
237a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
238a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
239a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
240a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
241a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
242a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
243a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
244a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
245a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
246a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
247a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
248a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) {
249a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    Mutex::Autolock autoLock(mTimeLock);
250a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mPauseStartedTimeRealUs = realUs;
251a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
252a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
253202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
2543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
2553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
2563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
257202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
258202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        bool *isOffloaded) {
2593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, id());
2603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
2613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
2623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
2633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
2643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
2653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
2663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
2673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
268202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
269202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    if (!response->findInt32("err", &err)) {
270202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
271202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
272202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
273202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
274202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
275202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
276202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
2773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
2783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
2793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
2803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, id());
2813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
2823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
2833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
2843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
2853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
286f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
2883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
2893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
2903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
2913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
2923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
2933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
2943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
2953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
2963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
2973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
2983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
2993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
3003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
3013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
302202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
3033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
305202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
306202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
3073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t replyID;
3093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
3103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
3113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
3133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
3143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
3163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
3173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t replyID;
3183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
3193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
3213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
3233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
3243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
3253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
3263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
327bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
328bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
329bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
330bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
331bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
332bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
333f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
334f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
335f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
336f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(msg->findInt32("generation", &generation));
337f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            if (generation != mAudioQueueGeneration) {
338f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
339f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
340f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
341f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainAudioQueuePending = false;
342f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
343078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
344078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
345078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
346078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
347078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
348078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
349078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
350078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
351078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
352078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
353078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
354078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
355078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
356078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
357078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
358078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
359bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                // kWhatDrainAudioQueue is used for non-offloading mode,
360bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                // and mLock is used only for offloading mode. Therefore,
361bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                // no need to acquire mLock here.
362bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                postDrainAudioQueue_l(delayUs / 2);
363078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
364f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
365f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
366f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
367f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
368f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
369f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
370f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(msg->findInt32("generation", &generation));
371f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            if (generation != mVideoQueueGeneration) {
372f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
373f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
374f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
375f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
376f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
377f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
378f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
379f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            postDrainVideoQueue();
380f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
381f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
382f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
383d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
384d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
385d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
386d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            CHECK(msg->findInt32("generation", &generation));
387d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (generation != mVideoQueueGeneration) {
388d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
389d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
390d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
391d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
392d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            postDrainVideoQueue();
393d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
394d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
395d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
396f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
397f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
398f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
399f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
400f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
401f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
402f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
403f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
404f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
405f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
406f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
407f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
408f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
409f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
410f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
411f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
412f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
413f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
4143831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        case kWhatAudioSinkChanged:
4153831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        {
4163831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber            onAudioSinkChanged();
4173831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber            break;
4183831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber        }
4193831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
420bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
421bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
422bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
423bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
424bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
425bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
426a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
427a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
428a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
429a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
430a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
431a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
432b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
433b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
434b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
435b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
436b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
437b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
438b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
439b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
440b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
441b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
442b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
443b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
444c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
445c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
446c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
447c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
448c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
449c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
450c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
451c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
4523a2956d148d81194e297408179e84a47a309ef48Wei Jia        case kWhatAudioOffloadTearDown:
4533a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
4540852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            onAudioOffloadTearDown(kDueToError);
4553a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
4563a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
4573a2956d148d81194e297408179e84a47a309ef48Wei Jia
458f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
459f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
460f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
461f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            CHECK(msg->findInt32("generation", &generation));
462f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
463f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
464f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
4650852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
4660852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            onAudioOffloadTearDown(kDueToTimeout);
467f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
468f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
469f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
471f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
472f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
473f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
475f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
476bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
477bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (mDrainAudioQueuePending || mSyncQueues || mPaused
478bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            || offloadingAudio()) {
479f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
480f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
481f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
483f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
484f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
485f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
486f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
487f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
488f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("generation", mAudioQueueGeneration);
489078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
490f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
491f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
492cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnarvoid NuPlayer::Renderer::prepareForMediaRenderingStart() {
493cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    mAudioRenderingStartGeneration = mAudioQueueGeneration;
494cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    mVideoRenderingStartGeneration = mVideoQueueGeneration;
495cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
496cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
497cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnarvoid NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
498cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
499cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration == mAudioQueueGeneration) {
500cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
501cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
502cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
503cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
504cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
505cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
506cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
507cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
508cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
509bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
510bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
511bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
512bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
513bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
514bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
515bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
516bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
517bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
518bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
519bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
520bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
521bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
522bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
523bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
524bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
525bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
526bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
527bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
528bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
529bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
530bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
531bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
532bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
5333a2956d148d81194e297408179e84a47a309ef48Wei Jia            me->notifyAudioOffloadTearDown();
534bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
535bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
536bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
537bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
538bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
539bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
540bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
541bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
542bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
543bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
54473ddd210ea572375198cac1d4960df793745fb4bWei Jia    if (!offloadingAudio() || mPaused) {
545bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
546bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
547bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
548bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
549bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
550bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
5513e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
552bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
553bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        QueueEntry *entry = &*mAudioQueue.begin();
554bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
555bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
556bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
557bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
558bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
559bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
560bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
561bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
5623e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
5633e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
564bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
565bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
566bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
567f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
568bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
569bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
570bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
571bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
572bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
573bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
574bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
575bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
576bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
577bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
578bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
579bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
580bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
581bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
582bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
583bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
584bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
585bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
586bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
587bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        notifyIfMediaRenderingStarted();
588bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
589bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
590f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
591f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
592f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        setAnchorTime(mAudioFirstAnchorTimeMediaUs, nowUs - getPlayedOutAudioDurationUs(nowUs));
593f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
594f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
595f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    // we don't know how much data we are queueing for offloaded tracks
596f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorMaxMediaUs = -1;
597f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
598bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
599bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        (new AMessage(kWhatStopAudioSink, id()))->post();
600bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
601bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
602bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
603bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
604bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
605078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
606078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
6072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
6082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
6092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
610078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
611078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
612078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
613078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
614078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#if 0
615078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
616df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
617078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
6183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
619078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
620078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
621078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
622f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
623078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    size_t numBytesAvailableToWrite =
624078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        numFramesAvailableToWrite * mAudioSink->frameSize();
625078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
626078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
627f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
628f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
629d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        mLastAudioBufferDrained = entry->mBufferOrdinal;
630d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
631f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
632f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
6335095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
6345095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
63506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
6365095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
6375095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
638f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
639f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
640f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
6413491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
6423491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
6433491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
6443491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
6453491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
6463491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
6473491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
648078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
649c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
650c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
651f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mOffset == 0) {
652f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
653f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
6543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
655eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
656f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
657f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
658f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
659f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (copy > numBytesAvailableToWrite) {
660f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            copy = numBytesAvailableToWrite;
661f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
662f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
663a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset, copy);
664a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
665202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
666202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
667202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
668a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
669f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
670a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
671f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mOffset == entry->mBuffer->size()) {
672f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
673f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
6749b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
675f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
676f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
677f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
678a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        numBytesAvailableToWrite -= written;
679a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
680078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
681cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
682cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notifyIfMediaRenderingStarted();
68343c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
684a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
685a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
686a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
687a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // AudioSink write should block until exactly the number of bytes are delivered.
688a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // But it may return with a short count (without an error) when:
689a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
690a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
691a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // 2) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
692a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
693a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
694a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
695a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
696a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
697a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
698a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 2)
699a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
700a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
701a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            ALOGW("AudioSink write short frame count %zd < %zu", written, copy);
702a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
703a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
704a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
705f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorMaxMediaUs =
706f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        mAnchorTimeMediaUs +
707f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar                (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
708f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar                        * 1000LL * mAudioSink->msecsPerFrame());
709f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
710078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    return !mAudioQueue.empty();
711f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
712f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
71306ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
71406ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    int64_t writtenAudioDurationUs =
71506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        mNumFramesWritten * 1000LL * mAudioSink->msecsPerFrame();
71606ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs);
7175095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
7185095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
719a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
720a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
721f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (getCurrentPosition(&currentPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
722eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        // If failed to get current position, e.g. due to audio clock is not ready, then just
723eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        // play out video immediately without delay.
724eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
725a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
726a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return (mediaTimeUs - currentPositionUs) + nowUs;
727a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
728a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
729eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
730eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
731eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
732eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
733eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
734eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
735eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
736eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    int64_t nowUs = ALooper::GetNowUs();
737f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    setAnchorTime(
738f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs), mNumFramesWritten);
739eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
740eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
741f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::postDrainVideoQueue() {
742fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
743fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || mSyncQueues
744fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
745f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
746f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
747f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
748f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
749f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
750f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
751f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
752f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
753f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
754f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
755f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("generation", mVideoQueueGeneration);
756f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
757f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
758f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
759dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
760dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
761dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
762dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
763dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
764dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
765dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
766dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
767dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
768d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
769d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
770dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
771f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
772f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
773f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
774f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
775eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (mAnchorTimeMediaUs < 0) {
776eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            setAnchorTime(mediaTimeUs, nowUs);
777474d7c778b63aa33dcf25a92e23a52c1c47f0ac1Wei Jia            mAnchorMaxMediaUs = mediaTimeUs;
778dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            realTimeUs = nowUs;
779f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
780a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
781f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
782f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
783f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar            mAnchorMaxMediaUs = mediaTimeUs + 100000; // smooth out videos >= 10fps
784f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
785d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
786d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
787d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
788d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
789d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
790d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
791d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
792d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int64_t postDelayUs = 500000;
793d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
794d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
795d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
796d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
797d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
798d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
799d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            ALOGI("possible video time jump of %dms, retrying in %dms",
800d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                    (int)(delayUs / 1000), (int)(postDelayUs / 1000));
801d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
802d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
803d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
804f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
805f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
806dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
807dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
808dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
809dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
810dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
811095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
812dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
813dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
814f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
815f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
816f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
817f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
818f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
819f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
820f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
821f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
822f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
823f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
824f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
825f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
826f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
827f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
828c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
829f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
830f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
831f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
8323fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
833a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
834f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
835f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
836f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
837a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t nowUs = -1;
838d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
839d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
840d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
841d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
842d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
843d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
844d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
845a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        nowUs = ALooper::GetNowUs();
846a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
847d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
848f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
849fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
8503fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
851fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
852a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        if (nowUs == -1) {
853a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            nowUs = ALooper::GetNowUs();
854a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        }
855a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
856fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
857fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
858fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
859fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
860fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                 mVideoLateByUs, mVideoLateByUs / 1E6);
861fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
862fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
863fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
864eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu                    (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
865fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
866078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
867a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
868eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
869a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
870a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
871eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            setAnchorTime(-1, -1);
87249966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
873078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
874f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
875dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
876683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
877f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
878f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
879f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
88043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
881fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
882f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
883fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
884fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
885fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
886fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
887fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
888fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        notifyIfMediaRenderingStarted();
889fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
890f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
891f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
892f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
893f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
894f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
895f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
896f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
897f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
8985095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
899f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
900f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
901f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
902c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
9035095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
904f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
905f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9063a2956d148d81194e297408179e84a47a309ef48Wei Jiavoid NuPlayer::Renderer::notifyAudioOffloadTearDown() {
9073a2956d148d81194e297408179e84a47a309ef48Wei Jia    (new AMessage(kWhatAudioOffloadTearDown, id()))->post();
9083a2956d148d81194e297408179e84a47a309ef48Wei Jia}
9093a2956d148d81194e297408179e84a47a309ef48Wei Jia
910f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
911f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
912f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
913f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
914a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    setHasMedia(audio);
915a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
916a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
917dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
918dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
919dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
920dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
921bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
922bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
923f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (dropBufferWhileFlushing(audio, msg)) {
924f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
925f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
926f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9272d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
9282d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
929f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
930f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
931f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
932f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
933f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
934f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
935f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
936f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
937f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
938d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
939f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
940f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
941bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        Mutex::Autolock autoLock(mLock);
942f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
943bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
944f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
945f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
946f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        postDrainVideoQueue();
947f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
948f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
949bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
950cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
951cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
952cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
953f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
954cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
955cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
956f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
957cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
958cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
959bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
960cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
961cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
962f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
963cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
964cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
965cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
966cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
967cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
968cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
969f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
970cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
971f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
973cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
974cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
975cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
976cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
977cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
978cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
979cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
980cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
981f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
982cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
983bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
984f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
985f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
986bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
987f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
988f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
989f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
990f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
991f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
992f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
993f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
994bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
995f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
996f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
997f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
998f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        postDrainVideoQueue();
999f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1000f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1001f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1002f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1003f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1004f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1005f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1006f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (dropBufferWhileFlushing(audio, msg)) {
1007f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1008f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1009f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1010f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1011f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1012f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1013f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1014f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1015f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1016f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1017f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1018bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        Mutex::Autolock autoLock(mLock);
1019b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1020bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1021b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1022f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1023bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1024f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1025b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mVideoQueue.empty() && mSyncQueues) {
1026bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1027bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1028b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1029f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
1030f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        postDrainVideoQueue();
1031f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1032f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1033f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1034f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
10357137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1036f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1037f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
103828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
103928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mFlushLock);
104028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
104128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            mFlushingAudio = false;
10427137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
10437137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
104428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
104528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            mFlushingVideo = false;
10467137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
10477137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
104828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
104928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
105028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1051f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // If we're currently syncing the queues, i.e. dropping audio while
1052f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // aligning the first audio/video buffer times and only one of the
1053f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // two queues has data, we may starve that queue by not requesting
1054f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // more buffers from the decoder. If the other source then encounters
1055f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // a discontinuity that leads to flushing, we'll never find the
1056f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // corresponding discontinuity on the other queue.
1057f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // Therefore we'll stop syncing the queues if at least one of them
1058f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    // is flushed.
1059bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    {
1060bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia         Mutex::Autolock autoLock(mLock);
1061bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia         syncQueuesDone_l();
1062a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu         setPauseStartedTimeRealUs(-1);
1063f83408b41bbd796b7923d719e7e3799ddc7acaffRonghua Wu         setAnchorTime(-1, -1);
1064bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
1065f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1066cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1067f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1068bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1069bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1070bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1071f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
107228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            ++mAudioQueueGeneration;
107328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            prepareForMediaRenderingStart();
107428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
107528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            if (offloadingAudio()) {
1076a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu                setAudioFirstAnchorTime(-1);
107728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia            }
107828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1079f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1080f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1081cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1082bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1083bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1084bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
1085bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->start();
1086bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1087f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1088f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1089f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1090f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1091f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        ++mVideoQueueGeneration;
1092cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1093c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1094c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1095c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1096c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
1097cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        prepareForMediaRenderingStart();
1098f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1099f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1100fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
11017137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
11027137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
11037137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
11047137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1105f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1106f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1107f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1108f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1109f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1110f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1111f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1112f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1113f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1114f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1115f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1116f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1117f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1118f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1120f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1121f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1122f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1123f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1124f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1125f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1126f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1127f933441648ef6a71dee783d733aac17b9508b452Andreas Huberbool NuPlayer::Renderer::dropBufferWhileFlushing(
1128f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
1129f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    bool flushing = false;
1130f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1131f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
1132f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        Mutex::Autolock autoLock(mFlushLock);
1133f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
1134f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            flushing = mFlushingAudio;
1135f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
1136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            flushing = mFlushingVideo;
1137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1138f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!flushing) {
1141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1146f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1150f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1151f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11523831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1153bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1154bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1155bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
11563831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
11573831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
1158f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    mAnchorNumFramesWritten = -1;
11594110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
11604110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
11614110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
11624110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
11633831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
11643831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1165bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1166bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1167bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
11683a2956d148d81194e297408179e84a47a309ef48Wei Jia    ++mAudioQueueGeneration;
1169bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1170bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1171a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1172a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1173a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
1174a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    ++mAudioQueueGeneration;
1175a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1176a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1177b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
11788592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
11798592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        ALOGW("Renderer::onPause() called while already paused!");
11808592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
11818592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
118228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
118328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
118428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        ++mAudioQueueGeneration;
118528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        ++mVideoQueueGeneration;
118628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        prepareForMediaRenderingStart();
118773ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
1188a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setPauseStartedTimeRealUs(ALooper::GetNowUs());
118928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1190b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
119128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1192b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1193cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1194b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (mHasAudio) {
1195b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        mAudioSink->pause();
1196f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        startAudioOffloadPauseTimeout();
1197b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1198b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1199ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber    ALOGV("now paused audio queue has %d entries, video has %d entries",
1200ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1201b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1202b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1203b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1204b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1205b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1206b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1207b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1208b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (mHasAudio) {
1209f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        cancelAudioOffloadPauseTimeout();
1210b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        mAudioSink->start();
1211b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1212b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
121373ddd210ea572375198cac1d4960df793745fb4bWei Jia    Mutex::Autolock autoLock(mLock);
1214b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mPaused = false;
1215a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mPauseStartedTimeRealUs != -1) {
1216a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        int64_t newAnchorRealUs =
1217eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            mAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs;
1218f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        setAnchorTime(
1219f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar                mAnchorTimeMediaUs, newAnchorRealUs, mAnchorNumFramesWritten, true /* resume */);
122049966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia    }
1221b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1222b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mAudioQueue.empty()) {
1223bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1224b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1225b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1226b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
1227b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        postDrainVideoQueue();
1228b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1229b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1230b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1231c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1232c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1233c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1234c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1235c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1236c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1237c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
123809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs()
123909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// as it acquires locks and may query the audio driver.
124009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung//
124109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// Some calls could conceivably retrieve extrapolated data instead of
124209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// accessing getTimestamp() or getPosition() every time a data buffer with
124309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung// a media time is received.
124409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung//
124506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) {
12463a2956d148d81194e297408179e84a47a309ef48Wei Jia    uint32_t numFramesPlayed;
124706ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    int64_t numFramesPlayedAt;
124806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    AudioTimestamp ts;
124909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    static const int64_t kStaleTimestamp100ms = 100000;
125009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung
125106ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    status_t res = mAudioSink->getTimestamp(ts);
125209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    if (res == OK) {                 // case 1: mixing audio tracks and offloaded tracks.
125306ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayed = ts.mPosition;
125406ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayedAt =
125506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar            ts.mTime.tv_sec * 1000000LL + ts.mTime.tv_nsec / 1000;
125609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        const int64_t timestampAge = nowUs - numFramesPlayedAt;
125709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        if (timestampAge > kStaleTimestamp100ms) {
125809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // This is an audio FIXME.
125909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // getTimestamp returns a timestamp which may come from audio mixing threads.
126009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // After pausing, the MixerThread may go idle, thus the mTime estimate may
126109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // become stale. Assuming that the MixerThread runs 20ms, with FastMixer at 5ms,
126209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // the max latency should be about 25ms with an average around 12ms (to be verified).
126309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            // For safety we use 100ms.
12642abde2c118a94f843a7450818c925d3f0b673cd3Andy Hung            ALOGV("getTimestamp: returned stale timestamp nowUs(%lld) numFramesPlayedAt(%lld)",
126509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung                    (long long)nowUs, (long long)numFramesPlayedAt);
126609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            numFramesPlayedAt = nowUs - kStaleTimestamp100ms;
126709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        }
126809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //ALOGD("getTimestamp: OK %d %lld", numFramesPlayed, (long long)numFramesPlayedAt);
126909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    } else if (res == WOULD_BLOCK) { // case 2: transitory state on start of a new track
127009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        numFramesPlayed = 0;
127109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        numFramesPlayedAt = nowUs;
127209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //ALOGD("getTimestamp: WOULD_BLOCK %d %lld",
127309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //        numFramesPlayed, (long long)numFramesPlayedAt);
127409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    } else {                         // case 3: transitory at new track or audio fast tracks.
127506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        res = mAudioSink->getPosition(&numFramesPlayed);
127606ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        CHECK_EQ(res, (status_t)OK);
127706ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayedAt = nowUs;
127806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar        numFramesPlayedAt += 1000LL * mAudioSink->latency() / 2; /* XXX */
127909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //ALOGD("getPosition: %d %lld", numFramesPlayed, numFramesPlayedAt);
128006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar    }
128109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung
128209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
128309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    //CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
1284eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000LL * mAudioSink->msecsPerFrame())
128506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar            + nowUs - numFramesPlayedAt;
128609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    if (durationUs < 0) {
128709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // Occurs when numFramesPlayed position is very small and the following:
128809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // (1) In case 1, the time nowUs is computed before getTimestamp() is called and
128909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //     numFramesPlayedAt is greater than nowUs by time more than numFramesPlayed.
129009e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // (2) In case 3, using getPosition and adding mAudioSink->latency() to
129109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //     numFramesPlayedAt, by a time amount greater than numFramesPlayed.
129209e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        //
129309e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        // Both of these are transitory conditions.
12942abde2c118a94f843a7450818c925d3f0b673cd3Andy Hung        ALOGV("getPlayedOutAudioDurationUs: negative duration %lld set to zero", (long long)durationUs);
129509e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung        durationUs = 0;
129609e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    }
129709e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    ALOGV("getPlayedOutAudioDurationUs(%lld) nowUs(%lld) frames(%u) framesAt(%lld)",
129809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung            (long long)durationUs, (long long)nowUs, numFramesPlayed, (long long)numFramesPlayedAt);
129909e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung    return durationUs;
130006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar}
13013a2956d148d81194e297408179e84a47a309ef48Wei Jia
13020852917279f79a94907e9906d0533ae409a30f6aRonghua Wuvoid NuPlayer::Renderer::onAudioOffloadTearDown(AudioOffloadTearDownReason reason) {
1303f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (mAudioOffloadTornDown) {
1304f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1305f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1306f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    mAudioOffloadTornDown = true;
1307f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1308a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
1309a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (getCurrentPosition(&currentPositionUs) != OK) {
1310a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        currentPositionUs = 0;
131128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
131206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
13133a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
13143a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
13153a2956d148d81194e297408179e84a47a309ef48Wei Jia
13163a2956d148d81194e297408179e84a47a309ef48Wei Jia    sp<AMessage> notify = mNotify->dup();
13173a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->setInt32("what", kWhatAudioOffloadTearDown);
13183a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->setInt64("positionUs", currentPositionUs);
13190852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
13203a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
13213a2956d148d81194e297408179e84a47a309ef48Wei Jia}
13223a2956d148d81194e297408179e84a47a309ef48Wei Jia
1323f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1324f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
1325f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, id());
1326f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->setInt32("generation", mAudioOffloadPauseTimeoutGeneration);
1327f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1328f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1329f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1330f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1331f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1332f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
1333f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        ++mAudioOffloadPauseTimeoutGeneration;
1334f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1335f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1336f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1337202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
13383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
13393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
13403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
13413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        uint32_t flags) {
13423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
13433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
13443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
13453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
13473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
13483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
13503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
13513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
13523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
13533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
13543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
13563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
13573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
13593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
13603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
13613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
13623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
13633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
13653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
13663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
13673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
13683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
13693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
13703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
13713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
13733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt32("bit-rate", &avgBitRate);
13743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
13763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
13773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
13783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
13793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
13803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
13813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
13823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
13833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
13853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
13863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
13873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
13883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
13893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
13903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
13913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
13923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
13933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
13943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.is_streaming = true;
13953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
13963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
13973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
13983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1399202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
14003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
14013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1402d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1403d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1404d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
14053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
14063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
14073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
14083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
14093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
14103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
14113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
14123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    8 /* bufferCount */,
14133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
14143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1415d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
14163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
14173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
14193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
14203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
14213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
14223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
14233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
14243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
14253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
14263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                err = mAudioSink->start();
14273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
14283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
14293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
14303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
14313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
14323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
14333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
14343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
14353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
14363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
14373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
14383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
14393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1440d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1441d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
14423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
14433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
14443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1445202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
14463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
14473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
14483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
14493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
14503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    8 /* bufferCount */,
14513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    NULL,
14523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    NULL,
1453202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                    (audio_output_flags_t)pcmFlags);
1454202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
1455202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
1456202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
1457202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
14583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->start();
14593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
14603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
14613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
14623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
1463a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    if (offloadingAudio()) {
1464a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        mAudioOffloadTornDown = false;
1465a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    }
1466202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
14673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
14683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
14693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
14703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
14713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
14723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
14733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
1474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
1475f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1476