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"
22f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung#include <algorithm>
23a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung#include <cutils/properties.h>
24f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
25f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ADebug.h>
265bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h>
27a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu#include <media/stagefright/foundation/AUtils.h>
2835d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang#include <media/stagefright/foundation/AWakeLock.h>
295833b6aad2c46ba516bdc8262f4fc4667e8018edWei Jia#include <media/stagefright/MediaClock.h>
30bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MediaErrors.h>
31bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MetaData.h>
323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang#include <media/stagefright/Utils.h>
33a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar#include <media/stagefright/VideoFrameScheduler.h>
34dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
35095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar#include <inttypes.h>
36095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar
37f933441648ef6a71dee783d733aac17b9508b452Andreas Hubernamespace android {
38f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
39a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung/*
40a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung * Example of common configuration settings in shell script form
41a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
42a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
43a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   adb shell setprop audio.offload.disable 1
44a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
45a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
46a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   adb shell setprop audio.offload.video 1
47a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
48a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   #Use audio callbacks for PCM data
49a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   adb shell setprop media.stagefright.audio.cbk 1
50a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
51288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung   #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
52288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung   adb shell setprop media.stagefright.audio.deep 1
53288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung
54179652ee2a508361df1aa18e99000373886f0816Andy Hung   #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
55179652ee2a508361df1aa18e99000373886f0816Andy Hung   adb shell setprop media.stagefright.audio.sink 1000
56179652ee2a508361df1aa18e99000373886f0816Andy Hung
57a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung * These configurations take effect for the next track played (not the current track).
58a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung */
59a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
60a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hungstatic inline bool getUseAudioCallbackSetting() {
61a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
62a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung}
63a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
64179652ee2a508361df1aa18e99000373886f0816Andy Hungstatic inline int32_t getAudioSinkPcmMsSetting() {
65179652ee2a508361df1aa18e99000373886f0816Andy Hung    return property_get_int32(
66179652ee2a508361df1aa18e99000373886f0816Andy Hung            "media.stagefright.audio.sink", 500 /* default_value */);
67179652ee2a508361df1aa18e99000373886f0816Andy Hung}
68179652ee2a508361df1aa18e99000373886f0816Andy Hung
69f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
70f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// is closed to allow the audio DSP to power down.
71a5d316fd802cfc92954527f27e6f32206a896113Eric Laurentstatic const int64_t kOffloadPauseMaxUs = 10000000ll;
72f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
7312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia// Maximum allowed delay from AudioSink, 1.5 seconds.
7412b6265f1d4be368957f91104d5210cf604ac4ccWei Jiastatic const int64_t kMaxAllowedAudioSinkDelayUs = 1500000ll;
7512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia
76528c8403ad2ede53054a706a20c00b710fa08166Andy Hungstatic const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000;
77528c8403ad2ede53054a706a20c00b710fa08166Andy Hung
78714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber// static
79f0e83644637bd05852c244df481f21a0d435ff66Andy Hungconst NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
80f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_CHANNEL_NONE,
81f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_OUTPUT_FLAG_NONE,
82f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_FORMAT_INVALID,
83f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0, // mNumChannels
84f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0 // mSampleRate
85f0e83644637bd05852c244df481f21a0d435ff66Andy Hung};
86f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
87f0e83644637bd05852c244df481f21a0d435ff66Andy Hung// static
88714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huberconst int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
89714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber
90f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::Renderer(
91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<MediaPlayerBase::AudioSink> &sink,
92d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        const sp<AMessage> &notify,
93d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        uint32_t flags)
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    : mAudioSink(sink),
95d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia      mUseVirtualAudioSink(false),
96f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNotify(notify),
97d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber      mFlags(flags),
98f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNumFramesWritten(0),
99f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainAudioQueuePending(false),
100f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainVideoQueuePending(false),
101f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mAudioQueueGeneration(0),
102f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mVideoQueueGeneration(0),
1037b15cb33847e6282ea8352c98894683b796127f3Wei Jia      mAudioDrainGeneration(0),
1047b15cb33847e6282ea8352c98894683b796127f3Wei Jia      mVideoDrainGeneration(0),
1057c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia      mAudioEOSGeneration(0),
1063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar      mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
107a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mAudioFirstAnchorTimeMediaUs(-1),
108eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeMediaUs(-1),
109f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorNumFramesWritten(-1),
110a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mVideoLateByUs(0ll),
111bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasAudio(false),
112bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasVideo(false),
1137137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteAudio(false),
1147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteVideo(false),
115bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mSyncQueues(false),
116714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber      mPaused(false),
117b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung      mPauseDrainAudioAllowedUs(0),
11809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung      mVideoSampleReceived(false),
119f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong      mVideoRenderingStarted(false),
120cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mVideoRenderingStartGeneration(0),
121cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mAudioRenderingStartGeneration(0),
122b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung      mRenderingDataDelivered(false),
123528c8403ad2ede53054a706a20c00b710fa08166Andy Hung      mNextAudioClockUpdateTimeUs(-1),
1242995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia      mLastAudioMediaTimeUs(-1),
125f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu      mAudioOffloadPauseTimeoutGeneration(0),
126faeb0f291330134dc4468359a36e099aae508449Ronghua Wu      mAudioTornDown(false),
127d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
128f0e83644637bd05852c244df481f21a0d435ff66Andy Hung      mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
129d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mTotalBuffersQueued(0),
13035d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mLastAudioBufferDrained(0),
131a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung      mUseAudioCallback(false),
13235d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mWakeLock(new AWakeLock()) {
1337b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock = new MediaClock;
1343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = mPlaybackSettings.mSpeed;
1353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
138f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::~Renderer() {
139bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
140bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->stop();
141bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->flush();
142bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->close();
143bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
146f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<ABuffer> &buffer,
149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
1501d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
1517b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
152f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
1532d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
154f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
157f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
158f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
160f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1611d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
1627b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
163f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
164f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
165f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
167f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
1693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
1703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, rate);
1713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
1723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
1733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
1743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
1753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
1773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (rate.mSpeed == 0.f) {
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        onPause();
1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // don't call audiosink's setPlaybackRate if pausing, as pitch does not
1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // have to correspond to the any non-0 speed (e.g old speed). Keep
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // settings nonetheless, using the old speed, in case audiosink changes.
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AudioPlaybackRate newRate = rate;
1863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        newRate.mSpeed = mPlaybackSettings.mSpeed;
1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mPlaybackSettings = newRate;
1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return OK;
1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
19127ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->setPlaybackRate(rate);
1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err != OK) {
1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return err;
1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = rate;
1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = rate.mSpeed;
1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
2053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, rate);
2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
21727ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->getPlaybackRate(rate);
2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGW("correcting mismatch in internal/external playback rate");
2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // get playback settings used by audiosink, as it may be
2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // slightly off due to audiosink not taking small changes.
2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mPlaybackSettings = *rate;
2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mPaused) {
2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                rate->mSpeed = 0.f;
2283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return err;
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *rate = mPlaybackSettings;
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, sync, videoFpsHint);
2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // TODO: support sync sources
2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return INVALID_OPERATION;
2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, sync, videoFps);
2633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetSyncSettings(
2693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
2703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *sync = mSyncSettings;
2713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *videoFps = -1.f;
2723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2739816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
2749816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
2757137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
276f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
2777b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
278f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
2797137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
2803b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia            clearAudioFirstAnchorTime_l();
2817b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioQueueGeneration;
2827b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
283f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
2847137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
2857b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoQueueGeneration;
2867b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoDrainGeneration;
287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
2887b15cb33847e6282ea8352c98894683b796127f3Wei Jia
2897b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
2907b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mVideoLateByUs = 0;
2917b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mSyncQueues = false;
292f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
293f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
2941d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatFlush, this);
295f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
296f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
297f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
298f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
299f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
30028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
30128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
30228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
3031d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatDisableOffloadAudio, this))->post();
30428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
30528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
306a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
3071d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatEnableOffloadAudio, this))->post();
308a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
309a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
310b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
3111d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
312b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
313b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
314b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
3151d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
316b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
317b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
318c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
3191d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
320c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
321c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
322c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
323c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
3244ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia// Called on any threads without mLock acquired.
3257b15cb33847e6282ea8352c98894683b796127f3Wei Jiastatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
3264ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
3274ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (result == OK) {
3284ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        return result;
3294ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3304ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3314ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    // MediaClock has not started yet. Try to start it if possible.
3324ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    {
3334ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        Mutex::Autolock autoLock(mLock);
3344ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (mAudioFirstAnchorTimeMediaUs == -1) {
3354ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3364ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3374ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        AudioTimestamp ts;
3394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        status_t res = mAudioSink->getTimestamp(ts);
3404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (res != OK) {
3414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3444ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        // AudioSink has rendered some frames.
3454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowUs = ALooper::GetNowUs();
346d855a738735a3df8863b486f5d3b5e404cef15c1Wei Jia        int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
3474ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia                + mAudioFirstAnchorTimeMediaUs;
3484ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
3494ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3504ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3519816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
352a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
353a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3547b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
3557b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioFirstAnchorTimeMediaUs = -1;
3567b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->setStartingTimeMedia(-1);
357a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
358a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3597b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
360a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
361a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
3627b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mMediaClock->setStartingTimeMedia(mediaUs);
363a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
365a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3667b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAnchorTime_l() {
3677b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->clearAnchor();
3687b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = -1;
3697b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorNumFramesWritten = -1;
370a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
371a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
3737b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
374a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
376a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
377a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
3787b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
379a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
380a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
381a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
382202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
3833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
3843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
3853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
386202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
387202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        bool *isOffloaded) {
3881d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
3893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
3903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
3913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
3923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
3933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
3953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
3963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
397202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
398202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    if (!response->findInt32("err", &err)) {
399202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
400202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
401202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
402202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
403202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
404202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
405202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
4091d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
4103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
4123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
4133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
415f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
416f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
4173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
4183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
4203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
4213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
4233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
4243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
4263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
4273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
4293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
4303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
431202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
4323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
434202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
435202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
4363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4373f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
4453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4463f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
4503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
4523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
456bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
457bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
458bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
459bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
460bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
461bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
4643ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            mDrainAudioQueuePending = false;
4653ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia
466f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
4677b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
4687b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(true /* audio */)) {
469f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
471f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
472078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
473078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
474078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
475078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
476078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
477078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
478078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
479078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
480078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
481078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
482078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
483078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
484078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
485d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                if (mPlaybackRate > 1.0f) {
486d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                    delayUs /= mPlaybackRate;
487d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                }
488078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
489078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
490078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
491f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                delayUs /= 2;
492f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                // check the buffer size to estimate maximum delay permitted.
493f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                const int64_t maxDrainDelayUs = std::max(
494f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                        mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
495f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
496f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                        (long long)delayUs, (long long)maxDrainDelayUs);
4977b15cb33847e6282ea8352c98894683b796127f3Wei Jia                Mutex::Autolock autoLock(mLock);
498f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                postDrainAudioQueue_l(delayUs);
499078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
500f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
501f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
502f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
503f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
504f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
505f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
5067b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5077b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
508f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
509f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
510f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
511f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
512f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
513f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
514f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5157b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
516f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
517f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
518f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
519d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
520d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
521d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
5227b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5237b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
524d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
525d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
526d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
527d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
5287b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
529d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
530d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
531d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
532f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
533f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
534f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
535f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
536f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
537f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
538f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
539f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
540f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
541f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
542f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
543f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5447c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        case kWhatEOS:
5457c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        {
5467c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            int32_t generation;
5477c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("audioEOSGeneration", &generation));
5487c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            if (generation != mAudioEOSGeneration) {
5497c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia                break;
5507c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            }
5517c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            status_t finalResult;
5527c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("finalResult", &finalResult));
5537c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            notifyEOS(true /* audio */, finalResult);
5547c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            break;
5557c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        }
5567c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia
5573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigPlayback:
5589816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        {
5593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate;
5623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &rate);
5633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigPlayback(rate);
5643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetPlaybackSettings:
5713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
5753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetPlaybackSettings(&rate);
5763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
5783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, rate);
5793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
5803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigSync:
5863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
5903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFpsHint;
5913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &sync, &videoFpsHint);
5923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigSync(sync, videoFpsHint);
5933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetSyncSettings:
6003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
6013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
6023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGV("kWhatGetSyncSettings");
6053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
6063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFps = -1.f;
6073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetSyncSettings(&sync, &videoFps);
6083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
6103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, sync, videoFps);
6113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
6123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6149816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            break;
6159816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        }
6169816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
617f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
618f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
619f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
620f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
621f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
622f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
623bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
624bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
625bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
626bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
627bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
628bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
629a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
630a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
631a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
632a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
633a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
634a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
635b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
636b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
637b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
638b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
639b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
640b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
641b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
642b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
643b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
644b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
645b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
646b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
647c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
648c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
649c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
650c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
651c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
652c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
653c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
654c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
655faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        case kWhatAudioTearDown:
6563a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
657a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            int32_t reason;
658a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            CHECK(msg->findInt32("reason", &reason));
659a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia
660a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            onAudioTearDown((AudioTearDownReason)reason);
6613a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
6623a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
6633a2956d148d81194e297408179e84a47a309ef48Wei Jia
664f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
665f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
666f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
6677b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
668f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
669f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
670f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
6710852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
672faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToTimeout);
67335d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang            mWakeLock->release();
674f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
675f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
676f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
677f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
678f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
679f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
680f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
681f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
682f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
683bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
684005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
685f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
686f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
687f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
688f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
689f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
690f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
691f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
692b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
693b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    if (mPaused) {
694b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
695b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        if (diffUs > delayUs) {
696b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            delayUs = diffUs;
697b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        }
698b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    }
699b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung
700f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
7011d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
7027b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", mAudioDrainGeneration);
703078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
704f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
705f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
7067b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
7077b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioRenderingStartGeneration = mAudioDrainGeneration;
7087b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mVideoRenderingStartGeneration = mVideoDrainGeneration;
709b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung    mRenderingDataDelivered = false;
710cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
711cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
7127b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
7137b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
7147b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
715b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        mRenderingDataDelivered = true;
716b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mPaused) {
717b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            return;
718b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
719cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
720cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
721cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
722cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
723cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
724cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
725cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
726cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
727cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
728bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
729bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
730bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
731bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
732bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
733bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
734bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
735bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
736bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
737bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
738bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
739bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
740bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
741bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
742bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
743bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
744bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
745bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
746a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_STREAM_END");
747bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
748bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
749bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
750bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
751bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
752bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
753a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
754a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            me->notifyAudioTearDown(kDueToError);
755bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
756bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
757bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
758bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
759bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
760bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
761bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
762bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
763bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
764bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
76585e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung    if (!mUseAudioCallback) {
766bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
767bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
768bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
769bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
770bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
771bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
7723e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
773a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
774bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
775a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        entry = &*mAudioQueue.begin();
776bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
777bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
778bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
779bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
780bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
781bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
782bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
7833e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
7843e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
785bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
786bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
787a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
7887b15cb33847e6282ea8352c98894683b796127f3Wei Jia            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
789bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
790bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
791bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
792bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
793bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
794bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
795bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
796bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
797bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
798bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
799bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
800bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
801bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
802bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
803bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
804bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
805bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
806bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
807bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
8087b15cb33847e6282ea8352c98894683b796127f3Wei Jia
8097b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
810bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
811bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
812f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
813f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
8149816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        int64_t nowMediaUs =
815c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia            mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
8167b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // we don't know how much data we are queueing for offloaded tracks.
8179816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
818f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
819f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
820a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // for non-offloaded audio, we need to compute the frames written because
821a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // there is no EVENT_STREAM_END notification. The frames written gives
822a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // an estimate on the pending played out duration.
823a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    if (!offloadingAudio()) {
824a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
825a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    }
826a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
827bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
8281d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        (new AMessage(kWhatStopAudioSink, this))->post();
829a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // As there is currently no EVENT_STREAM_END callback notification for
830a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // non-offloaded audio tracks, we need to post the EOS ourselves.
831a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        if (!offloadingAudio()) {
832a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            int64_t postEOSDelayUs = 0;
833a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            if (mAudioSink->needsTrailingPadding()) {
834a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
835a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            }
836a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: notifyEOS "
837a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
838a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
839a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
840a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        }
841bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
842bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
843bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
844bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8459da0ce44f228408d73a4dea0be972c785095dcccChong Zhangvoid NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
8469da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
8479da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    bool foundEOS = false;
8489da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    while (it != mAudioQueue.end()) {
8499da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        int32_t eos;
8509da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        QueueEntry *entry = &*it++;
8519da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        if (entry->mBuffer == NULL
8529da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
8539da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            itEOS = it;
8549da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            foundEOS = true;
8559da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8569da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8579da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8589da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    if (foundEOS) {
8599da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // post all replies before EOS and drop the samples
8609da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        for (it = mAudioQueue.begin(); it != itEOS; it++) {
8619da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            if (it->mBuffer == NULL) {
8629da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                // delay doesn't matter as we don't even have an AudioTrack
8639da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                notifyEOS(true /* audio */, it->mFinalResult);
8649da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            } else {
8659da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                it->mNotifyConsumed->post();
8669da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            }
8679da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8689da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        mAudioQueue.erase(mAudioQueue.begin(), itEOS);
8699da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8709da0ce44f228408d73a4dea0be972c785095dcccChong Zhang}
8719da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
872078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
87358d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    // do not drain audio during teardown as queued buffers may be invalid.
87458d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    if (mAudioTornDown) {
87558d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung        return false;
87658d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    }
877230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // TODO: This call to getPosition checks if AudioTrack has been created
878230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
879230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // CHECKs on getPosition will fail.
880230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // We still need to figure out why AudioTrack is not created when
881230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // this function is called. One possible reason could be leftover
882230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // audio. Another possible place is to check whether decoder
883230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // has received INFO_FORMAT_CHANGED as the first buffer since
884230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // AudioSink is opened there, and possible interactions with flush
885230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // immediately after start. Investigate error message
886230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // "vorbis_dsp_synthesis returned -135", along with RTSP.
887078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
8882bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
8899da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // When getPosition fails, renderer will not reschedule the draining
8909da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // unless new samples are queued.
8919da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // If we have pending EOS (or "eos" marker for discontinuities), we need
8929da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // to post these now as NuPlayerDecoder might be waiting for it.
8939da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        drainAudioQueueUntilLastEOS();
8949da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8959da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        ALOGW("onDrainAudioQueue(): audio sink is not ready");
8962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
8972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
898078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
899230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia#if 0
900078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
901078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
902078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
903078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
904df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
905078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
9063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
907078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
908078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
909078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
910f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
911005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    uint32_t prevFramesWritten = mNumFramesWritten;
9127d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia    while (!mAudioQueue.empty()) {
913f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
914f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
915d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        mLastAudioBufferDrained = entry->mBufferOrdinal;
916d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
917f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
918f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
9195095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
9205095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
92106ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
9225095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
9235095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
9242995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
925f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
926f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
927f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
9283491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
9293491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
9303491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
9313491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
9323491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
9333491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
9343491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
935078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
936c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
937c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
93881636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        // ignore 0-sized buffer which could be EOS marker with no data
93981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
940f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
941f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
942a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
943a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mediaTimeUs / 1E6);
944eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
945f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
946f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
947f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
948f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9497d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
9507d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                                            copy, false /* blocking */);
951a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
952202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
9537d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            if (written == WOULD_BLOCK) {
954df809479696725faf5d3424b11fa8a07bd94cb5eWei Jia                ALOGV("AudioSink write would block when writing %zu bytes", copy);
9557d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            } else {
9567d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
9577665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // This can only happen when AudioSink was opened with doNotReconnect flag set to
9587665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // true, in which case the NuPlayer will handle the reconnect.
959a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                notifyAudioTearDown(kDueToError);
9607d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            }
961202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
962a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
963f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
964a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
96503cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia        size_t remainder = entry->mBuffer->size() - entry->mOffset;
96603cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia        if ((ssize_t)remainder < mAudioSink->frameSize()) {
96703cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            if (remainder > 0) {
96803cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
96903cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                        remainder);
97003cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                entry->mOffset += remainder;
97103cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                copy -= remainder;
97203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            }
97303cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia
974f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
975f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
9769b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
977f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
978f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
979f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
980a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
981078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
982cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
9837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
9847b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
985d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            int64_t maxTimeMedia;
986d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            maxTimeMedia =
987d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                mAnchorTimeMediaUs +
988d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
989d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                                * 1000LL * mAudioSink->msecsPerFrame());
990d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
991d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia
9927b15cb33847e6282ea8352c98894683b796127f3Wei Jia            notifyIfMediaRenderingStarted_l();
9937b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
99443c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
995a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
996a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
997a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
9987d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // AudioSink write is called in non-blocking mode.
9997d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // It may return with a short count when:
1000a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
100103cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
100203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            //    discarded.
10037d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 2) The data to be copied exceeds the available buffer in AudioSink.
10047d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
10057d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
1006a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
1007a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
1008a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
1009a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
1010a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
1011a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
10127d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // (Case 2, 3, 4)
1013a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
1014a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
10157d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
1016a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
1017a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
1018a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
1019f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
1020005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    // calculate whether we need to reschedule another write.
1021005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    bool reschedule = !mAudioQueue.empty()
1022005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            && (!mPaused
1023005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung                || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1024005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
1025005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1026005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    return reschedule;
1027f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1028f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10299816016afb2a13c6a866cd047d57020566a8b9a9Wei Jiaint64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
10309816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int32_t sampleRate = offloadingAudio() ?
10319816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
10324d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    if (sampleRate == 0) {
10334d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
10344d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        return 0;
10354d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    }
10369816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
10379816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
10389816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
10399816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
10409816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
104106ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
10429816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1043d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia    if (mUseVirtualAudioSink) {
1044d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        int64_t nowUs = ALooper::GetNowUs();
1045d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        int64_t mediaUs;
1046d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
1047d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            return 0ll;
1048d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        } else {
1049d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1050d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        }
1051d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia    }
1052c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia    return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
10535095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
10545095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
1055a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
10569816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t realUs;
10579816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
10587b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If failed to get current position, e.g. due to audio clock is
10597b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // not ready, then just play out video immediately without delay.
1060eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
1061a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
10629816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return realUs;
1063a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
1064a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1065eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
10667b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1067eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
1068eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
1069eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
1070eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
1071eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
10727b15cb33847e6282ea8352c98894683b796127f3Wei Jia    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
10734ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
1074528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1075528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    if (mNextAudioClockUpdateTimeUs == -1) {
1076528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        AudioTimestamp ts;
1077528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1078528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1079528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        }
1080528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    }
108112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    int64_t nowUs = ALooper::GetNowUs();
1082528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    if (mNextAudioClockUpdateTimeUs >= 0) {
1083528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        if (nowUs >= mNextAudioClockUpdateTimeUs) {
1084528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1085528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
1086d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            mUseVirtualAudioSink = false;
1087528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1088528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        }
108912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    } else {
109012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        int64_t unused;
109112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
109212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
109312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                        > kMaxAllowedAudioSinkDelayUs)) {
109412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Enough data has been sent to AudioSink, but AudioSink has not rendered
109512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // any data yet. Something is wrong with AudioSink, e.g., the device is not
109612b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // connected to audio out.
109712b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Switch to system clock. This essentially creates a virtual AudioSink with
109812b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
109912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // This virtual AudioSink renders audio data starting from the very first sample
110012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // and it's paced by system clock.
110107af6518b7b7eeb730ded9c5fd6fd6fb3a462bc5Wei Jia            ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
110212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
1103d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            mUseVirtualAudioSink = true;
110412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        }
11054ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
11068edb3f85f58e8738582e8f9abbc018c85100b712Wei Jia    mAnchorNumFramesWritten = mNumFramesWritten;
11077b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = mediaTimeUs;
1108eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
1109eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
11107b15cb33847e6282ea8352c98894683b796127f3Wei Jia// Called without mLock acquired.
11117b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue() {
1112fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
11137b15cb33847e6282ea8352c98894683b796127f3Wei Jia            || getSyncQueues()
1114fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
1115f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1116f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1117f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1118f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1120f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1121f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1122f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
1123f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11241d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
11257b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
1126f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1127f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
1128f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
1129dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
1130dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
1131dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
1132dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
1133dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
113400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih    bool needRepostDrainVideoQueue = false;
1135dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
1136dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
1137dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
1138dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
1139d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
1140d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1141dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
1142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
1144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11467b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
11477b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
11487b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (mAnchorTimeMediaUs < 0) {
11497b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
11507b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mAnchorTimeMediaUs = mediaTimeUs;
11517b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = nowUs;
115225d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia            } else if (!mVideoSampleReceived) {
115325d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                // Always render the first video frame.
115425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                realTimeUs = nowUs;
115500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mAudioFirstAnchorTimeMediaUs < 0
115600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
11577b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
115800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
115900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                needRepostDrainVideoQueue = true;
116000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
116100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else {
116200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
11637b15cb33847e6282ea8352c98894683b796127f3Wei Jia            }
1164f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1165f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
11667b15cb33847e6282ea8352c98894683b796127f3Wei Jia            // smooth out videos >= 10fps
11677b15cb33847e6282ea8352c98894683b796127f3Wei Jia            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1168f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
1169d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
1170d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
1171d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
1172d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
1173d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
1174d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
117500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        int64_t postDelayUs = -1;
1176d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
117700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = 500000;
1178d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1179d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
1180d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
118100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        } else if (needRepostDrainVideoQueue) {
118200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mPlaybackRate > 0);
118300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
118400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
118500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
118600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs /= mPlaybackRate;
118700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        }
118800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih
118900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        if (postDelayUs >= 0) {
1190d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
1191d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
1192d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
119300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            ALOGI("possible video time jump of %dms or uninitialized media clock, retrying in %dms",
1194d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                    (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1195d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
1196d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
1197d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
1198f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1199f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1200dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1201dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1202dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1203dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
1204dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1205095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
1206dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
1207dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1208f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1209f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
1210f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1211f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1212f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
1213f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1214f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1215f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1216f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1217f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
1218f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1219f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
1220f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
1221f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1222c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
1223f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1224f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
1225f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
12263fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1227a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1228f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1229f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1230f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
123125d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    int64_t nowUs = ALooper::GetNowUs();
1232d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
12332995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia    int64_t mediaTimeUs = -1;
1234d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
1235d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1236d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
1237d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1238d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
1239a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1240d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
1241f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1242fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
12433fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1244fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1245a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
1246fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
1247fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
1248fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
1249fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
12506d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
1251fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
12529816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            int64_t mediaUs = 0;
12539816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
1254fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
1255fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
12569816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia                    mediaUs) / 1E6);
12572995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia
12582995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            if (!(mFlags & FLAG_REAL_TIME)
12592995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mLastAudioMediaTimeUs != -1
12602995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mediaTimeUs > mLastAudioMediaTimeUs) {
12612995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // If audio ends before video, video continues to drive media clock.
12622995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // Also smooth out videos >= 10fps.
12632995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
12642995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            }
1265fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
1266078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
1267a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1268eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
1269a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
1270a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
12717b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
12727b15cb33847e6282ea8352c98894683b796127f3Wei Jia            clearAnchorTime_l();
127349966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
1274078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
1275f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
127625d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    // Always render the first video frame while keeping stats on A/V sync.
127725d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    if (!mVideoSampleReceived) {
127825d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        realTimeUs = nowUs;
127925d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        tooLate = false;
128025d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    }
128125d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia
1282dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
1283683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
1284f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
1285f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
1286f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
128743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1288fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
1289f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
1290fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1291fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
1292fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
1293fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
1294fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
12957b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
12967b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
1297fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
1298f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1299f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1300f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
1301f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
1302f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
1303f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
1304f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
1305f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
13065095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
13077c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    if (audio && delayUs > 0) {
13087c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        sp<AMessage> msg = new AMessage(kWhatEOS, this);
13097c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
13107c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("finalResult", finalResult);
13117c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->post(delayUs);
13127c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        return;
13137c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    }
1314f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1315f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
1316f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1317c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
13185095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
1319f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1320f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1321a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jiavoid NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1322a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1323a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    msg->setInt32("reason", reason);
1324a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    msg->post();
13253a2956d148d81194e297408179e84a47a309ef48Wei Jia}
13263a2956d148d81194e297408179e84a47a309ef48Wei Jia
1327f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1328f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1329f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1330f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13317b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
13327b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return;
13337b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
13347b15cb33847e6282ea8352c98894683b796127f3Wei Jia
13357b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (audio) {
13367b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasAudio = true;
13377b15cb33847e6282ea8352c98894683b796127f3Wei Jia    } else {
13387b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasVideo = true;
13397b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
1340a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1341a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
1342dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
1343dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
1344dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
1345dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
1346bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
1347bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
13482d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
13492d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
1350f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1351f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1352f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1353f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1354f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1355f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
1356f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
1357f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1358f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
1359d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
1360f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1361f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
13627b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1363f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1364bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1365f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1366f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
13677b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1368f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1369f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13707b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1371cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1372cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1373cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1374f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1375cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1376cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1377f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1378cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1379cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
1380bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
1381cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1382cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1383f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1384cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
1385cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
1386cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
1387cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
1388cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
1389cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
1390f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1391cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1392f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
1394cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1395cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
1396cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
1397cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
1398cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1399cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
1400cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
1401cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1402f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1403cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1404bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
1405f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1406f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1407bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
1408f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
1409f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1410f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1411f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1412f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
1413f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1414f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
1415bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1416f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1417f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1418f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
14197b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.unlock();
14207b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
14217b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.lock();
1422f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1423f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1424f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1425f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1426f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1427f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1428f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14297b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
1430f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1431f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1432f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1433f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1434f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1435f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1436f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1437f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1438f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1439f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1440f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
14417b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1442b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1443bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1444b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1445f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1446bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1447f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
14487b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (mVideoQueue.empty() && getSyncQueues()) {
14497b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1450bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1451b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1452f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
14537b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1455f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1456f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1457f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
14587137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1459f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
146128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
14627b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
146328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
14647137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
14657137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
14662995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = -1;
146728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
14687137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
14697137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
147028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
147128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
14727b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If we're currently syncing the queues, i.e. dropping audio while
14737b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // aligning the first audio/video buffer times and only one of the
14747b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // two queues has data, we may starve that queue by not requesting
14757b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // more buffers from the decoder. If the other source then encounters
14767b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // a discontinuity that leads to flushing, we'll never find the
14777b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // corresponding discontinuity on the other queue.
14787b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // Therefore we'll stop syncing the queues if at least one of them
14797b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // is flushed.
14807b15cb33847e6282ea8352c98894683b796127f3Wei Jia        syncQueuesDone_l();
14817b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
1482bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
1483f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1484cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1485f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1486bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1487bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1488bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1489f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14907b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
14917c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            ++mAudioEOSGeneration;
14927b15cb33847e6282ea8352c98894683b796127f3Wei Jia            prepareForMediaRenderingStart_l();
149328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1494a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            // the frame count will be reset after flush.
1495a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            clearAudioFirstAnchorTime_l();
149628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1497f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1498f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1499cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1500bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1501bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1502bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
150385e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            if (!mPaused) {
150485e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                mAudioSink->start();
150585e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            }
15069e7ed3315298b42db485963b182a572e9ab42f9fWei Jia        } else {
15079e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->pause();
15089e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->flush();
15099e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // Call stop() to signal to the AudioSink to completely fill the
15109e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // internal buffer before resuming playback.
1511b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            // FIXME: this is ignored after flush().
15129e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->stop();
1513b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            if (mPaused) {
1514b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // Race condition: if renderer is paused and audio sink is stopped,
1515b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // we need to make sure that the audio track buffer fully drains
1516b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // before delivering data.
1517b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // FIXME: remove this if we can detect if stop() is complete.
1518b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1519b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1520b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            } else {
15219e7ed3315298b42db485963b182a572e9ab42f9fWei Jia                mAudioSink->start();
15229e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            }
15239e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mNumFramesWritten = 0;
1524bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1525528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        mNextAudioClockUpdateTimeUs = -1;
1526f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1530cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1531c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1532c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1533c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1534c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
15357b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
15367b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
15377b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
1538f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1539f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1540fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
15417137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
15427137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
15437137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
15447137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1545f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1546f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1547f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1548f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1549f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1550f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1551f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1552f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1553f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1554f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1555f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1556f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1557f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1558f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1559f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1560f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1561f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1562f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1563f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1564f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1565f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1566f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15677b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::dropBufferIfStale(
1568f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
15697b15cb33847e6282ea8352c98894683b796127f3Wei Jia    int32_t queueGeneration;
15707b15cb33847e6282ea8352c98894683b796127f3Wei Jia    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
1571f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15727b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (queueGeneration == getQueueGeneration(audio)) {
1573f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1574f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1575f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1576f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1577f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1578f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1579f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1580f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1581f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1582f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1583f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15843831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1585bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1586bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1587bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
15883831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
15893831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
15907b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
15917b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
15927b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAnchorNumFramesWritten = -1;
15937b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
15944110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
15954110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
15964110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
15974110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
15983831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
15993831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1600bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1601bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1602bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
16037b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1604e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1605e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1606e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1607bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1608bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1609a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1610a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1611a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
16127b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1613e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1614e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1615e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1616a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1617a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1618b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
16198592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
16208592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
16218592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
16226d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar
162328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
162428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
1625005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        // we do not increment audio drain generation so that we fill audio buffer during pause.
16267b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
16277b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
162873ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
16299816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(0.0);
163028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1631b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
163228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1633b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1634cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
16358420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
16368420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    mAudioSink->pause();
16378420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    startAudioOffloadPauseTimeout();
1638b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16396d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar    ALOGV("now paused audio queue has %zu entries, video has %zu entries",
1640ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1641b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1642b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1643b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1644b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1645b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1646b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1647b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16488420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
16498420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    cancelAudioOffloadPauseTimeout();
16508420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    if (mAudioSink->ready()) {
165197c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        status_t err = mAudioSink->start();
165297c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        if (err != OK) {
165358d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung            ALOGE("cannot start AudioSink err %d", err);
1654a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            notifyAudioTearDown(kDueToError);
165597c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        }
1656b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1657b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16587b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
16597b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
16607b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mPaused = false;
1661b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        // rendering started message may have been delayed if we were paused.
1662b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mRenderingDataDelivered) {
1663b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            notifyIfMediaRenderingStarted_l();
1664b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
16653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // configure audiosink as we did not do it when pausing
166627ea08e3811dc8057685258af52a7d40474eba16Wei Jia        if (mAudioSink != NULL && mAudioSink->ready()) {
16673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mAudioSink->setPlaybackRate(mPlaybackSettings);
16683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
16693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
16709816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(mPlaybackRate);
1671b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16727b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (!mAudioQueue.empty()) {
16737b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainAudioQueue_l();
16747b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
1675b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1676b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1677b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
16787b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1679b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1680b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1681b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1682c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1683c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1684c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1685c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1686c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1687c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1688c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
16897b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
16907b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16917b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
16927b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16937b15cb33847e6282ea8352c98894683b796127f3Wei Jia
16947b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
16957b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16967b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
16977b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16987b15cb33847e6282ea8352c98894683b796127f3Wei Jia
16997b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::getSyncQueues() {
17007b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
17017b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return mSyncQueues;
17027b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
17037b15cb33847e6282ea8352c98894683b796127f3Wei Jia
1704faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1705faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    if (mAudioTornDown) {
1706f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1707f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1708faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = true;
1709f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1710a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
17111a5c859016e743779e4db25855390b3ce523cd48Robert Shih    sp<AMessage> notify = mNotify->dup();
17121a5c859016e743779e4db25855390b3ce523cd48Robert Shih    if (getCurrentPosition(&currentPositionUs) == OK) {
17131a5c859016e743779e4db25855390b3ce523cd48Robert Shih        notify->setInt64("positionUs", currentPositionUs);
171428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
171506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
17163a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
17173a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
17183a2956d148d81194e297408179e84a47a309ef48Wei Jia
1719faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    notify->setInt32("what", kWhatAudioTearDown);
17200852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
17213a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
17223a2956d148d81194e297408179e84a47a309ef48Wei Jia}
17233a2956d148d81194e297408179e84a47a309ef48Wei Jia
1724f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1725f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
172635d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->acquire();
17271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
17287b15cb33847e6282ea8352c98894683b796127f3Wei Jia        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
1729f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1730f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1731f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1732f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1733f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
173421afe805580c1fdf394415648fba8e1c482def60Andy Hung    // We may have called startAudioOffloadPauseTimeout() without
173521afe805580c1fdf394415648fba8e1c482def60Andy Hung    // the AudioSink open and with offloadingAudio enabled.
173621afe805580c1fdf394415648fba8e1c482def60Andy Hung    //
173721afe805580c1fdf394415648fba8e1c482def60Andy Hung    // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
173821afe805580c1fdf394415648fba8e1c482def60Andy Hung    // we always release the wakelock and increment the pause timeout generation.
173921afe805580c1fdf394415648fba8e1c482def60Andy Hung    //
174021afe805580c1fdf394415648fba8e1c482def60Andy Hung    // Note: The acquired wakelock prevents the device from suspending
174121afe805580c1fdf394415648fba8e1c482def60Andy Hung    // immediately after offload pause (in case a resume happens shortly thereafter).
174221afe805580c1fdf394415648fba8e1c482def60Andy Hung    mWakeLock->release(true);
174321afe805580c1fdf394415648fba8e1c482def60Andy Hung    ++mAudioOffloadPauseTimeoutGeneration;
1744f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1745f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1746202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
17473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
17483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
17493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
17503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        uint32_t flags) {
17513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
17523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
17533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
17543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
17563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
17573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
17593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
17603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
17613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
17623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
17633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
17653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
17663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
17683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
17693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
17703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
17713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
17723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
17743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
17753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
17763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
17773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
17783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
17793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
17803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
178246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            format->findInt32("bitrate", &avgBitRate);
17833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
17853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
17863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
17873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
17883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
17893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
17903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
17913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
17923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
17943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
17953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
17963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
17973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
17983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
17993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
18003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
18013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
18023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
18033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.is_streaming = true;
18043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
18063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
18073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1808202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
18093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
1810f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1811f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
18123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1813d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1814d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1815d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
18163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
18173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
1818a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
18193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
18203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
18213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
18223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
18233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
1824179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
18253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
18263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1827d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
18283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
18293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
18313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                err = mAudioSink->setPlaybackRate(mPlaybackSettings);
18323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
18333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
18343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
18353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
18363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
18373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
18383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
18393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
18403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
18413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
184285e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                if (!mPaused) { // for preview mode, don't start if paused
184385e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                    err = mAudioSink->start();
184485e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                }
18453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
18463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
18483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
18493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
18503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
18513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
18523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
1853a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                if (offloadOnly) {
1854a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                    notifyAudioTearDown(kForceNonOffload);
1855a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                }
18563ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            } else {
18573ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                mUseAudioCallback = true;  // offload mode transfers data through callback
18583ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
18593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
18613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
18623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
18633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1864d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1865d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1866f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
1867f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        const PcmInfo info = {
1868f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_channel_mask_t)channelMask,
1869f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_output_flags_t)pcmFlags,
1870f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1871f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                numChannels,
1872f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                sampleRate
1873f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        };
1874f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1875f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            ALOGV("openAudioSink: no change in pcm mode");
1876f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            // no change from previous configuration, everything ok.
1877f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            return OK;
1878f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        }
1879f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
18803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
18813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
18823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1883a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // Note: It is possible to set up the callback, but not use it to send audio data.
1884a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // This requires a fix in AudioSink to explicitly specify the transfer mode.
1885a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mUseAudioCallback = getUseAudioCallbackSetting();
18863ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        if (mUseAudioCallback) {
18873ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
18883ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        }
1889179652ee2a508361df1aa18e99000373886f0816Andy Hung
1890179652ee2a508361df1aa18e99000373886f0816Andy Hung        // Compute the desired buffer size.
1891179652ee2a508361df1aa18e99000373886f0816Andy Hung        // For callback mode, the amount of time before wakeup is about half the buffer size.
1892179652ee2a508361df1aa18e99000373886f0816Andy Hung        const uint32_t frameCount =
1893179652ee2a508361df1aa18e99000373886f0816Andy Hung                (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1894179652ee2a508361df1aa18e99000373886f0816Andy Hung
18957665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
18967665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // AudioSink. We don't want this when there's video because it will cause a video seek to
18977665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // the previous I frame. But we do want this when there's only audio because it will give
18987665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // NuPlayer a chance to switch from non-offload mode to offload mode.
18997665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // So we only set doNotReconnect when there's no video.
19007665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        const bool doNotReconnect = !hasVideo;
1901ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung
1902ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        // We should always be able to set our playback settings if the sink is closed.
1903ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
1904ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung                "onOpenAudioSink: can't set playback rate on closed sink");
1905202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
19063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
19073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
19083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
19093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
1910179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
1911a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1912a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? this : NULL,
1913faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    (audio_output_flags_t)pcmFlags,
1914faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    NULL,
19157665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                    doNotReconnect,
1916179652ee2a508361df1aa18e99000373886f0816Andy Hung                    frameCount);
1917202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
1918202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
19194d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia            mAudioSink->close();
1920f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1921202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
1922202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
1923f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        mCurrentPcmInfo = info;
1924005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        if (!mPaused) { // for preview mode, don't start if paused
1925005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            mAudioSink->start();
1926005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        }
19273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
19283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
19293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
19303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
1931faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = false;
1932202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
19333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
19343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
19353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
19363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
19373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1938f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
19393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
19403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
1941f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
1942f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1943