NuPlayerRenderer.cpp revision 238e1247a1fde2c7857ec243563126de72346a89
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    }
1444c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
1454c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    // Try to avoid racing condition in case callback is still on.
1464c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    Mutex::Autolock autoLock(mLock);
1474c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mUseAudioCallback = false;
1484c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    flushQueue(&mAudioQueue);
1494c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    flushQueue(&mVideoQueue);
1504c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mWakeLock.clear();
1514c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mMediaClock.clear();
1524c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mVideoScheduler.clear();
1534c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mNotify.clear();
1544c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mAudioSink.clear();
155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
157f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
158f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<ABuffer> &buffer,
160f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
1611d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
1627b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
163f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
1642d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
165f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
167f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
168f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
169f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
170f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
171f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1721d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
1737b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
174f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
175f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
176f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
177f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
178f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, rate);
1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
1863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
1913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (rate.mSpeed == 0.f) {
1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        onPause();
1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // don't call audiosink's setPlaybackRate if pausing, as pitch does not
1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // have to correspond to the any non-0 speed (e.g old speed). Keep
1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // settings nonetheless, using the old speed, in case audiosink changes.
1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AudioPlaybackRate newRate = rate;
1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        newRate.mSpeed = mPlaybackSettings.mSpeed;
1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mPlaybackSettings = newRate;
1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return OK;
2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
20227ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->setPlaybackRate(rate);
2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err != OK) {
2053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return err;
2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = rate;
2093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = rate.mSpeed;
2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, rate);
2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
22827ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->getPlaybackRate(rate);
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGW("correcting mismatch in internal/external playback rate");
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // get playback settings used by audiosink, as it may be
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // slightly off due to audiosink not taking small changes.
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mPlaybackSettings = *rate;
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mPaused) {
2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                rate->mSpeed = 0.f;
2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return err;
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *rate = mPlaybackSettings;
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, sync, videoFpsHint);
2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
2613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // TODO: support sync sources
2633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return INVALID_OPERATION;
2643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
2673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
2683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, sync, videoFps);
2743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetSyncSettings(
2803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
2813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *sync = mSyncSettings;
2823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *videoFps = -1.f;
2833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2849816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
2859816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
2867137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
2887b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
289f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
2907137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
2913b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia            clearAudioFirstAnchorTime_l();
2927b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioQueueGeneration;
2937b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
294f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
2957137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
2967b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoQueueGeneration;
2977b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoDrainGeneration;
298f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
2997b15cb33847e6282ea8352c98894683b796127f3Wei Jia
3007b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
3017b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mVideoLateByUs = 0;
3027b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mSyncQueues = false;
303f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
304f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
3051d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatFlush, this);
306f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
307f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
309f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
310f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
31128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
31228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
31328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
3141d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatDisableOffloadAudio, this))->post();
31528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
31628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
317a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
3181d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatEnableOffloadAudio, this))->post();
319a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
320a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
321b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
3221d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
323b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
324b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
325b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
3261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
327b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
328b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
329c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
3301d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
331c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
332c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
333c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
334c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
3354ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia// Called on any threads without mLock acquired.
3367b15cb33847e6282ea8352c98894683b796127f3Wei Jiastatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
3374ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
3384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (result == OK) {
3394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        return result;
3404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    // MediaClock has not started yet. Try to start it if possible.
3434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    {
3444ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        Mutex::Autolock autoLock(mLock);
3454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (mAudioFirstAnchorTimeMediaUs == -1) {
3464ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3474ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3484ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3494ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        AudioTimestamp ts;
3504ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        status_t res = mAudioSink->getTimestamp(ts);
3514ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (res != OK) {
3524ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3534ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3544ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3554ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        // AudioSink has rendered some frames.
3564ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowUs = ALooper::GetNowUs();
357d855a738735a3df8863b486f5d3b5e404cef15c1Wei Jia        int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
3584ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia                + mAudioFirstAnchorTimeMediaUs;
3594ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
3604ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3614ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3629816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
363a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3657b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
3667b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioFirstAnchorTimeMediaUs = -1;
3677b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->setStartingTimeMedia(-1);
368a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
369a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3707b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
371a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
3737b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mMediaClock->setStartingTimeMedia(mediaUs);
374a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
376a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3777b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAnchorTime_l() {
3787b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->clearAnchor();
3797b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = -1;
3807b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorNumFramesWritten = -1;
381a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
382a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
383a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
3847b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
385a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
386a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
387a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
388a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
3897b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
390a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
391a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
392a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
393202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
3943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
3953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
3963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
397202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
398202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        bool *isOffloaded) {
3991d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
4003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
4013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
4023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
4033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
4043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
4073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
408202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
409202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    if (!response->findInt32("err", &err)) {
410202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
411202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
412202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
413202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
414202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
415202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
416202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
4173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
4201d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
4213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
4233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
4243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
426f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
427f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
4283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
4293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
4313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
4323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
4343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
4353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
4373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
4383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
4403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
4413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
442202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
4433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
445202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
446202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
4473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4483f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
4563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4573f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
4613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
4633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
467bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
468bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
469bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
470bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
471bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
472bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
473f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
4753ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            mDrainAudioQueuePending = false;
4763ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia
477f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
4787b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
4797b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(true /* audio */)) {
480f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
481f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
483078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
484078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
485078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
486078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
487078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
488078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
489078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
490078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
491078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
492078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
493078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
494078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
495078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
496d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                if (mPlaybackRate > 1.0f) {
497d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                    delayUs /= mPlaybackRate;
498d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                }
499078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
500078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
501078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
502f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                delayUs /= 2;
503f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                // check the buffer size to estimate maximum delay permitted.
504f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                const int64_t maxDrainDelayUs = std::max(
505f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                        mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
506f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
507f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                        (long long)delayUs, (long long)maxDrainDelayUs);
5087b15cb33847e6282ea8352c98894683b796127f3Wei Jia                Mutex::Autolock autoLock(mLock);
509f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                postDrainAudioQueue_l(delayUs);
510078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
511f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
512f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
513f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
514f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
515f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
516f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
5177b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5187b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
519f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
520f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
522f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
523f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
524f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
525f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5267b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
530d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
531d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
532d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
5337b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5347b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
535d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
536d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
537d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
538d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
5397b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
540d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
541d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
542d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
543f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
544f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
545f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
546f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
547f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
548f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
549f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
550f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
551f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
552f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
553f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
554f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5557c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        case kWhatEOS:
5567c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        {
5577c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            int32_t generation;
5587c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("audioEOSGeneration", &generation));
5597c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            if (generation != mAudioEOSGeneration) {
5607c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia                break;
5617c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            }
5627c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            status_t finalResult;
5637c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("finalResult", &finalResult));
5647c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            notifyEOS(true /* audio */, finalResult);
5657c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            break;
5667c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        }
5677c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia
5683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigPlayback:
5699816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        {
5703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate;
5733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &rate);
5743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigPlayback(rate);
5753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetPlaybackSettings:
5823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
5863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetPlaybackSettings(&rate);
5873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
5893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, rate);
5903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
5913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigSync:
5973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
6013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFpsHint;
6023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &sync, &videoFpsHint);
6033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigSync(sync, videoFpsHint);
6043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
6083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
6093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetSyncSettings:
6113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
6123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
6133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGV("kWhatGetSyncSettings");
6163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
6173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFps = -1.f;
6183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetSyncSettings(&sync, &videoFps);
6193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
6213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, sync, videoFps);
6223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
6233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6259816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            break;
6269816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        }
6279816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
628f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
629f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
630f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
631f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
632f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
633f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
634bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
635bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
636bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
637bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
638bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
639bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
640a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
641a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
642a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
643a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
644a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
645a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
646b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
647b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
648b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
649b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
650b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
651b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
652b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
653b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
654b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
655b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
656b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
657b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
658c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
659c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
660c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
661c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
662c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
663c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
664c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
665c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
666faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        case kWhatAudioTearDown:
6673a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
668a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            int32_t reason;
669a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            CHECK(msg->findInt32("reason", &reason));
670a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia
671a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            onAudioTearDown((AudioTearDownReason)reason);
6723a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
6733a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
6743a2956d148d81194e297408179e84a47a309ef48Wei Jia
675f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
676f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
677f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
6787b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
679f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
680f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
681f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
6820852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
683faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToTimeout);
68435d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang            mWakeLock->release();
685f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
686f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
687f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
688f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
689f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
690f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
691f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
692f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
693f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
694bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
695005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
696f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
697f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
698f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
699f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
700f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
701f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
702f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
703b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
704b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    if (mPaused) {
705b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
706b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        if (diffUs > delayUs) {
707b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            delayUs = diffUs;
708b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        }
709b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    }
710b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung
711f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
7121d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
7137b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", mAudioDrainGeneration);
714078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
715f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
716f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
7177b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
7187b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioRenderingStartGeneration = mAudioDrainGeneration;
7197b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mVideoRenderingStartGeneration = mVideoDrainGeneration;
720b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung    mRenderingDataDelivered = false;
721cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
722cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
7237b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
7247b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
7257b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
726b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        mRenderingDataDelivered = true;
727b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mPaused) {
728b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            return;
729b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
730cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
731cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
732cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
733cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
734cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
735cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
736cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
737cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
738cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
739bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
740bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
741bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
742bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
743bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
744bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
745bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
746bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
747bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
748bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
749bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
750bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
751bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
752bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
753bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
754bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
755bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
756bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
757a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_STREAM_END");
7584c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia            me->notifyEOSCallback();
759bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
760bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
761bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
762bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
763bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
764a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
765a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            me->notifyAudioTearDown(kDueToError);
766bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
767bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
768bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
769bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
770bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
771bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
772bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
7734c74fde2ef5b582196b296a8263cd39143e7abcaWei Jiavoid NuPlayer::Renderer::notifyEOSCallback() {
7744c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    Mutex::Autolock autoLock(mLock);
7754c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
7764c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    if (!mUseAudioCallback) {
7774c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia        return;
7784c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    }
7794c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
7804c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
7814c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia}
7824c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
783bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
784bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
785bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
78685e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung    if (!mUseAudioCallback) {
787bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
788bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
789bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
790bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
791bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
792bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
7933e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
794a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
795bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
796a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        entry = &*mAudioQueue.begin();
797bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
798bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
799bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
800bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
801bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
802bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
803bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8043e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
8053e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
806bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
807bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
808a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
8097b15cb33847e6282ea8352c98894683b796127f3Wei Jia            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
810bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
811bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
812bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
813bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
814bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
815bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
816bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
817bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
818bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
819bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
820bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
821bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
822bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
823bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
824bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
825bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
826bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
827bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
828bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
8297b15cb33847e6282ea8352c98894683b796127f3Wei Jia
8307b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
831bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
832bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
833f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
834f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
8359816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        int64_t nowMediaUs =
836c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia            mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
8377b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // we don't know how much data we are queueing for offloaded tracks.
8389816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
839f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
840f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
841a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // for non-offloaded audio, we need to compute the frames written because
842a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // there is no EVENT_STREAM_END notification. The frames written gives
843a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // an estimate on the pending played out duration.
844a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    if (!offloadingAudio()) {
845a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
846a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    }
847a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
848bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
8491d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        (new AMessage(kWhatStopAudioSink, this))->post();
850a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // As there is currently no EVENT_STREAM_END callback notification for
851a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // non-offloaded audio tracks, we need to post the EOS ourselves.
852a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        if (!offloadingAudio()) {
853a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            int64_t postEOSDelayUs = 0;
854a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            if (mAudioSink->needsTrailingPadding()) {
855a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
856a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            }
857a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: notifyEOS "
858a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
859a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
860a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
861a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        }
862bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
863bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
864bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
865bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8669da0ce44f228408d73a4dea0be972c785095dcccChong Zhangvoid NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
8679da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
8689da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    bool foundEOS = false;
8699da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    while (it != mAudioQueue.end()) {
8709da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        int32_t eos;
8719da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        QueueEntry *entry = &*it++;
8729da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        if (entry->mBuffer == NULL
8739da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
8749da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            itEOS = it;
8759da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            foundEOS = true;
8769da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8779da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8789da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8799da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    if (foundEOS) {
8809da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // post all replies before EOS and drop the samples
8819da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        for (it = mAudioQueue.begin(); it != itEOS; it++) {
8829da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            if (it->mBuffer == NULL) {
8839da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                // delay doesn't matter as we don't even have an AudioTrack
8849da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                notifyEOS(true /* audio */, it->mFinalResult);
8859da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            } else {
8869da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                it->mNotifyConsumed->post();
8879da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            }
8889da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8899da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        mAudioQueue.erase(mAudioQueue.begin(), itEOS);
8909da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8919da0ce44f228408d73a4dea0be972c785095dcccChong Zhang}
8929da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
893078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
89458d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    // do not drain audio during teardown as queued buffers may be invalid.
89558d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    if (mAudioTornDown) {
89658d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung        return false;
89758d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    }
898230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // TODO: This call to getPosition checks if AudioTrack has been created
899230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
900230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // CHECKs on getPosition will fail.
901230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // We still need to figure out why AudioTrack is not created when
902230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // this function is called. One possible reason could be leftover
903230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // audio. Another possible place is to check whether decoder
904230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // has received INFO_FORMAT_CHANGED as the first buffer since
905230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // AudioSink is opened there, and possible interactions with flush
906230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // immediately after start. Investigate error message
907230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // "vorbis_dsp_synthesis returned -135", along with RTSP.
908078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
9092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
9109da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // When getPosition fails, renderer will not reschedule the draining
9119da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // unless new samples are queued.
9129da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // If we have pending EOS (or "eos" marker for discontinuities), we need
9139da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // to post these now as NuPlayerDecoder might be waiting for it.
9149da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        drainAudioQueueUntilLastEOS();
9159da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
9169da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        ALOGW("onDrainAudioQueue(): audio sink is not ready");
9172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
9182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
919078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
920230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia#if 0
921078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
922078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
923078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
924078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
925df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
926078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
9273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
928078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
929078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
930078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
931f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
932005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    uint32_t prevFramesWritten = mNumFramesWritten;
9337d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia    while (!mAudioQueue.empty()) {
934f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
935f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
936d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        mLastAudioBufferDrained = entry->mBufferOrdinal;
937d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
938f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
939f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
9405095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
9415095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
94206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
9435095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
9445095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
9452995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
946f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
947f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
948f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
9493491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
9503491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
9513491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
9523491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
9533491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
9543491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
9553491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
956078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
957c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
958c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
95981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        // ignore 0-sized buffer which could be EOS marker with no data
96081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
961f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
962f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
963a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
964a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mediaTimeUs / 1E6);
965eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
966f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
967f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
968f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
969f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9707d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
9717d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                                            copy, false /* blocking */);
972a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
973202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
9747d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            if (written == WOULD_BLOCK) {
975df809479696725faf5d3424b11fa8a07bd94cb5eWei Jia                ALOGV("AudioSink write would block when writing %zu bytes", copy);
9767d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            } else {
9777d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
9787665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // This can only happen when AudioSink was opened with doNotReconnect flag set to
9797665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // true, in which case the NuPlayer will handle the reconnect.
980a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                notifyAudioTearDown(kDueToError);
9817d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            }
982202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
983a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
984f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
985a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
98603cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia        size_t remainder = entry->mBuffer->size() - entry->mOffset;
98703cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia        if ((ssize_t)remainder < mAudioSink->frameSize()) {
98803cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            if (remainder > 0) {
98903cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
99003cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                        remainder);
99103cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                entry->mOffset += remainder;
99203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                copy -= remainder;
99303cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            }
99403cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia
995f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
996f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
9979b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
998f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
999f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1000f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1001a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
1002078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
1003cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
10047b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
10057b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1006d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            int64_t maxTimeMedia;
1007d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            maxTimeMedia =
1008d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                mAnchorTimeMediaUs +
1009d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
1010d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                                * 1000LL * mAudioSink->msecsPerFrame());
1011d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
1012d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia
10137b15cb33847e6282ea8352c98894683b796127f3Wei Jia            notifyIfMediaRenderingStarted_l();
10147b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
101543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1016a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
1017a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
1018a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
10197d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // AudioSink write is called in non-blocking mode.
10207d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // It may return with a short count when:
1021a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
102203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
102303cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            //    discarded.
10247d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 2) The data to be copied exceeds the available buffer in AudioSink.
10257d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
10267d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
1027a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
1028a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
1029a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
1030a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
1031a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
1032a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
10337d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // (Case 2, 3, 4)
1034a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
1035a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
10367d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
1037a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
1038a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
1039a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
1040f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
1041005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    // calculate whether we need to reschedule another write.
1042005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    bool reschedule = !mAudioQueue.empty()
1043005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            && (!mPaused
1044005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung                || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1045005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
1046005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1047005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    return reschedule;
1048f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1049f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10509816016afb2a13c6a866cd047d57020566a8b9a9Wei Jiaint64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
10519816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int32_t sampleRate = offloadingAudio() ?
10529816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
10534d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    if (sampleRate == 0) {
10544d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
10554d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        return 0;
10564d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    }
10579816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
10589816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
10599816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
10609816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
10619816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
106206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
10639816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1064d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia    if (mUseVirtualAudioSink) {
1065d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        int64_t nowUs = ALooper::GetNowUs();
1066d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        int64_t mediaUs;
1067d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
1068d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            return 0ll;
1069d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        } else {
1070d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1071d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        }
1072d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia    }
1073c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia    return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
10745095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
10755095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
1076a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
10779816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t realUs;
10789816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
10797b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If failed to get current position, e.g. due to audio clock is
10807b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // not ready, then just play out video immediately without delay.
1081eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
1082a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
10839816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return realUs;
1084a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
1085a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1086eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
10877b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1088eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
1089eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
1090eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
1091eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
1092eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
10937b15cb33847e6282ea8352c98894683b796127f3Wei Jia    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
10944ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
1095528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1096528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    if (mNextAudioClockUpdateTimeUs == -1) {
1097528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        AudioTimestamp ts;
1098528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1099528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1100528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        }
1101528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    }
110212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    int64_t nowUs = ALooper::GetNowUs();
1103528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    if (mNextAudioClockUpdateTimeUs >= 0) {
1104528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        if (nowUs >= mNextAudioClockUpdateTimeUs) {
1105528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1106528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
1107d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            mUseVirtualAudioSink = false;
1108528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1109528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        }
111012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    } else {
111112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        int64_t unused;
111212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
111312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
111412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                        > kMaxAllowedAudioSinkDelayUs)) {
111512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Enough data has been sent to AudioSink, but AudioSink has not rendered
111612b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // any data yet. Something is wrong with AudioSink, e.g., the device is not
111712b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // connected to audio out.
111812b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Switch to system clock. This essentially creates a virtual AudioSink with
111912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
112012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // This virtual AudioSink renders audio data starting from the very first sample
112112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // and it's paced by system clock.
112207af6518b7b7eeb730ded9c5fd6fd6fb3a462bc5Wei Jia            ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
112312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
1124d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            mUseVirtualAudioSink = true;
112512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        }
11264ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
11278edb3f85f58e8738582e8f9abbc018c85100b712Wei Jia    mAnchorNumFramesWritten = mNumFramesWritten;
11287b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = mediaTimeUs;
1129eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
1130eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
11317b15cb33847e6282ea8352c98894683b796127f3Wei Jia// Called without mLock acquired.
11327b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue() {
1133fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
11347b15cb33847e6282ea8352c98894683b796127f3Wei Jia            || getSyncQueues()
1135fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
1136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1138f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
1144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11451d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
11467b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
1147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
1149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
1150dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
1151dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
1152dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
1153dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
1154dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
115500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih    bool needRepostDrainVideoQueue = false;
1156dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
1157dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
1158dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
1159dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
1160d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
1161d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1162dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
1163f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1164f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
1165f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11677b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
11687b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
11697b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (mAnchorTimeMediaUs < 0) {
11707b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
11717b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mAnchorTimeMediaUs = mediaTimeUs;
11727b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = nowUs;
117325d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia            } else if (!mVideoSampleReceived) {
117425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                // Always render the first video frame.
117525d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                realTimeUs = nowUs;
117600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mAudioFirstAnchorTimeMediaUs < 0
117700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
11787b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
117900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
118000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                needRepostDrainVideoQueue = true;
118100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
118200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else {
118300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
11847b15cb33847e6282ea8352c98894683b796127f3Wei Jia            }
1185f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1186f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
11877b15cb33847e6282ea8352c98894683b796127f3Wei Jia            // smooth out videos >= 10fps
11887b15cb33847e6282ea8352c98894683b796127f3Wei Jia            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1189f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
1190d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
1191d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
1192d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
1193d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
1194d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
1195d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
119600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        int64_t postDelayUs = -1;
1197d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
119800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = 500000;
1199d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1200d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
1201d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
120200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        } else if (needRepostDrainVideoQueue) {
120300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mPlaybackRate > 0);
120400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
120500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
120600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
120700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs /= mPlaybackRate;
120800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        }
120900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih
121000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        if (postDelayUs >= 0) {
1211d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
1212d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
1213d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
1214238e1247a1fde2c7857ec243563126de72346a89Wei Jia            ALOGI("possible video time jump of %dms (%lld : %lld) or uninitialized media clock,"
1215238e1247a1fde2c7857ec243563126de72346a89Wei Jia                    " retrying in %dms",
1216238e1247a1fde2c7857ec243563126de72346a89Wei Jia                    (int)(delayUs / 1000), (long long)mediaTimeUs,
1217238e1247a1fde2c7857ec243563126de72346a89Wei Jia                    (long long)mAudioFirstAnchorTimeMediaUs, (int)(postDelayUs / 1000));
1218d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
1219d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
1220d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
1221f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1222f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1223dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1224dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1225dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1226dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
1227dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1228095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
1229dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
1230dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1231f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1232f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
1233f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1234f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1235f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
1236f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1237f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1238f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1239f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1240f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
1241f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1242f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
1243f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
1244f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1245c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
1246f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1247f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
1248f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
12493fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1250a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1251f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1252f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1253f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
125425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    int64_t nowUs = ALooper::GetNowUs();
1255d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
12562995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia    int64_t mediaTimeUs = -1;
1257d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
1258d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1259d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
1260d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1261d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
1262a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1263d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
1264f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1265fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
12663fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1267fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1268a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
1269fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
1270fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
1271fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
1272fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
12736d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
1274fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
12759816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            int64_t mediaUs = 0;
12769816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
1277fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
1278fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
12799816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia                    mediaUs) / 1E6);
12802995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia
12812995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            if (!(mFlags & FLAG_REAL_TIME)
12822995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mLastAudioMediaTimeUs != -1
12832995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mediaTimeUs > mLastAudioMediaTimeUs) {
12842995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // If audio ends before video, video continues to drive media clock.
12852995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // Also smooth out videos >= 10fps.
12862995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
12872995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            }
1288fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
1289078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
1290a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1291eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
1292a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
1293a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
12947b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
12957b15cb33847e6282ea8352c98894683b796127f3Wei Jia            clearAnchorTime_l();
129649966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
1297078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
1298f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
129925d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    // Always render the first video frame while keeping stats on A/V sync.
130025d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    if (!mVideoSampleReceived) {
130125d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        realTimeUs = nowUs;
130225d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        tooLate = false;
130325d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    }
130425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia
1305dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
1306683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
1307f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
1308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
1309f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
131043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1311fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
1312f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
1313fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1314fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
1315fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
1316fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
1317fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
13187b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
13197b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
1320fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
1321f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1322f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1323f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
1324f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
1325f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
1326f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
1327f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
1328f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
13295095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
13307c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    if (audio && delayUs > 0) {
13317c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        sp<AMessage> msg = new AMessage(kWhatEOS, this);
13327c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
13337c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("finalResult", finalResult);
13347c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->post(delayUs);
13357c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        return;
13367c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    }
1337f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1338f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
1339f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1340c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
13415095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
1342f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1343f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1344a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jiavoid NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1345a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1346a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    msg->setInt32("reason", reason);
1347a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    msg->post();
13483a2956d148d81194e297408179e84a47a309ef48Wei Jia}
13493a2956d148d81194e297408179e84a47a309ef48Wei Jia
1350f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1351f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1352f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1353f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13547b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
13557b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return;
13567b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
13577b15cb33847e6282ea8352c98894683b796127f3Wei Jia
13587b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (audio) {
13597b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasAudio = true;
13607b15cb33847e6282ea8352c98894683b796127f3Wei Jia    } else {
13617b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasVideo = true;
13627b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
1363a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
1365dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
1366dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
1367dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
1368dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
1369bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
1370bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
13712d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
13722d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
1373f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1374f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1375f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1376f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1377f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1378f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
1379f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
1380f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1381f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
1382d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
1383f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1384f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
13857b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1386f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1387bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1388f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1389f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
13907b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1391f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1392f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13937b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1394cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1395cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1396cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1397f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1398cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1399cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1400f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1401cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1402cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
1403bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
1404cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1405cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1406f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1407cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
1408cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
1409cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
1410cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
1411cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
1412cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
1413f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1414cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1415f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
1417cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1418cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
1419cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
1420cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
1421cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1422cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
1423cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
1424cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1425f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1426cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1427bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
1428f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1429f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1430bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
1431f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
1432f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1433f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1434f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1435f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
1436f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1437f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
1438bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1439f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1440f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1441f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
14427b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.unlock();
14437b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
14447b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.lock();
1445f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1446f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1447f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1448f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1449f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1450f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1451f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14527b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
1453f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1455f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1456f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1457f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1459f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
14647b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1465b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1466bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1467b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1468f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1469bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
14717b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (mVideoQueue.empty() && getSyncQueues()) {
14727b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1473bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1474b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1475f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
14767b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1477f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1478f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1479f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1480f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
14817137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1483f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
148428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
14857b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
148628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
14877137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
14887137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
14892995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = -1;
149028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
14917137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
14927137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
149328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
149428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
14957b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If we're currently syncing the queues, i.e. dropping audio while
14967b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // aligning the first audio/video buffer times and only one of the
14977b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // two queues has data, we may starve that queue by not requesting
14987b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // more buffers from the decoder. If the other source then encounters
14997b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // a discontinuity that leads to flushing, we'll never find the
15007b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // corresponding discontinuity on the other queue.
15017b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // Therefore we'll stop syncing the queues if at least one of them
15027b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // is flushed.
15037b15cb33847e6282ea8352c98894683b796127f3Wei Jia        syncQueuesDone_l();
15047b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
1505bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
1506f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1507cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1508f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1509bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1510bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1511bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1512f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15137b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
15147c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            ++mAudioEOSGeneration;
15157b15cb33847e6282ea8352c98894683b796127f3Wei Jia            prepareForMediaRenderingStart_l();
151628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1517a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            // the frame count will be reset after flush.
1518a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            clearAudioFirstAnchorTime_l();
151928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1520f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1522cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1523bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1524bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1525bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
152685e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            if (!mPaused) {
152785e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                mAudioSink->start();
152885e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            }
15299e7ed3315298b42db485963b182a572e9ab42f9fWei Jia        } else {
15309e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->pause();
15319e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->flush();
15329e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // Call stop() to signal to the AudioSink to completely fill the
15339e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // internal buffer before resuming playback.
1534b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            // FIXME: this is ignored after flush().
15359e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->stop();
1536b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            if (mPaused) {
1537b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // Race condition: if renderer is paused and audio sink is stopped,
1538b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // we need to make sure that the audio track buffer fully drains
1539b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // before delivering data.
1540b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // FIXME: remove this if we can detect if stop() is complete.
1541b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1542b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1543b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            } else {
15449e7ed3315298b42db485963b182a572e9ab42f9fWei Jia                mAudioSink->start();
15459e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            }
15469e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mNumFramesWritten = 0;
1547bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1548528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        mNextAudioClockUpdateTimeUs = -1;
1549f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1550f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1551f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1552f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1553cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1554c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1555c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1556c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1557c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
15587b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
15597b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
15607b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
1561f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1562f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1563fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
15647137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
15657137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
15667137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
15677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1568f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1569f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1570f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1571f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1572f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1573f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1574f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1575f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1576f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1577f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1578f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1579f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1580f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1581f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1582f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1583f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1584f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1585f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1586f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1587f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1588f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1589f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15907b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::dropBufferIfStale(
1591f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
15927b15cb33847e6282ea8352c98894683b796127f3Wei Jia    int32_t queueGeneration;
15937b15cb33847e6282ea8352c98894683b796127f3Wei Jia    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
1594f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15957b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (queueGeneration == getQueueGeneration(audio)) {
1596f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1597f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1598f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1599f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1600f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1601f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1602f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1603f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1604f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1605f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1606f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
16073831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1608bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1609bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1610bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
16113831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
16123831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
16137b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
16147b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
16157b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAnchorNumFramesWritten = -1;
16167b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
16174110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
16184110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
16194110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
16204110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
16213831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
16223831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1623bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1624bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1625bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
16267b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1627e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1628e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1629e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1630bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1631bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1632a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1633a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1634a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
16357b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1636e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1637e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1638e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1639a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1640a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1641b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
16428592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
16438592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
16448592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
16456d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar
164628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
164728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
1648005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        // we do not increment audio drain generation so that we fill audio buffer during pause.
16497b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
16507b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
165173ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
16529816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(0.0);
165328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1654b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
165528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1656b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1657cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
16588420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
16598420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    mAudioSink->pause();
16608420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    startAudioOffloadPauseTimeout();
1661b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16626d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar    ALOGV("now paused audio queue has %zu entries, video has %zu entries",
1663ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1664b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1665b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1666b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1667b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1668b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1669b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1670b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16718420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
16728420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    cancelAudioOffloadPauseTimeout();
16738420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    if (mAudioSink->ready()) {
167497c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        status_t err = mAudioSink->start();
167597c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        if (err != OK) {
167658d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung            ALOGE("cannot start AudioSink err %d", err);
1677a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            notifyAudioTearDown(kDueToError);
167897c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        }
1679b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1680b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16817b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
16827b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
16837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mPaused = false;
1684b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        // rendering started message may have been delayed if we were paused.
1685b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mRenderingDataDelivered) {
1686b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            notifyIfMediaRenderingStarted_l();
1687b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
16883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // configure audiosink as we did not do it when pausing
168927ea08e3811dc8057685258af52a7d40474eba16Wei Jia        if (mAudioSink != NULL && mAudioSink->ready()) {
16903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mAudioSink->setPlaybackRate(mPlaybackSettings);
16913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
16923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
16939816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(mPlaybackRate);
1694b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16957b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (!mAudioQueue.empty()) {
16967b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainAudioQueue_l();
16977b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
1698b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1699b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1700b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
17017b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1702b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1703b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1704b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1705c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1706c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1707c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1708c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1709c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1710c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1711c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
17127b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
17137b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
17147b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
17157b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
17167b15cb33847e6282ea8352c98894683b796127f3Wei Jia
17177b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
17187b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
17197b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
17207b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
17217b15cb33847e6282ea8352c98894683b796127f3Wei Jia
17227b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::getSyncQueues() {
17237b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
17247b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return mSyncQueues;
17257b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
17267b15cb33847e6282ea8352c98894683b796127f3Wei Jia
1727faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1728faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    if (mAudioTornDown) {
1729f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1730f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1731faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = true;
1732f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1733a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
17341a5c859016e743779e4db25855390b3ce523cd48Robert Shih    sp<AMessage> notify = mNotify->dup();
17351a5c859016e743779e4db25855390b3ce523cd48Robert Shih    if (getCurrentPosition(&currentPositionUs) == OK) {
17361a5c859016e743779e4db25855390b3ce523cd48Robert Shih        notify->setInt64("positionUs", currentPositionUs);
173728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
173806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
17393a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
17403a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
17413a2956d148d81194e297408179e84a47a309ef48Wei Jia
1742faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    notify->setInt32("what", kWhatAudioTearDown);
17430852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
17443a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
17453a2956d148d81194e297408179e84a47a309ef48Wei Jia}
17463a2956d148d81194e297408179e84a47a309ef48Wei Jia
1747f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1748f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
174935d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->acquire();
17501d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
17517b15cb33847e6282ea8352c98894683b796127f3Wei Jia        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
1752f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1753f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1754f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1755f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1756f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
175721afe805580c1fdf394415648fba8e1c482def60Andy Hung    // We may have called startAudioOffloadPauseTimeout() without
175821afe805580c1fdf394415648fba8e1c482def60Andy Hung    // the AudioSink open and with offloadingAudio enabled.
175921afe805580c1fdf394415648fba8e1c482def60Andy Hung    //
176021afe805580c1fdf394415648fba8e1c482def60Andy Hung    // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
176121afe805580c1fdf394415648fba8e1c482def60Andy Hung    // we always release the wakelock and increment the pause timeout generation.
176221afe805580c1fdf394415648fba8e1c482def60Andy Hung    //
176321afe805580c1fdf394415648fba8e1c482def60Andy Hung    // Note: The acquired wakelock prevents the device from suspending
176421afe805580c1fdf394415648fba8e1c482def60Andy Hung    // immediately after offload pause (in case a resume happens shortly thereafter).
176521afe805580c1fdf394415648fba8e1c482def60Andy Hung    mWakeLock->release(true);
176621afe805580c1fdf394415648fba8e1c482def60Andy Hung    ++mAudioOffloadPauseTimeoutGeneration;
1767f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1768f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1769202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
17703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
17713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
17723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
17733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        uint32_t flags) {
17743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
17753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
17763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
17773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
17793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
17803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
17823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
17833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
17843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
17853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
17863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
17883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
17893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
17913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
17923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
17933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
17943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
17953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
17973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
17983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
17993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
18003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
18013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
18023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
18033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
180546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            format->findInt32("bitrate", &avgBitRate);
18063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
18083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
18093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
18103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
18113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
18123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
18133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
18143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
18173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
18183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
18193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
18203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
18213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
18223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
18233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
18243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
18253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
18263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.is_streaming = true;
18273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
18293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
18303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1831202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
18323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
1833f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1834f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
18353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1836d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1837d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1838d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
18393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
18403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
1841a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
18423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
18433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
18443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
18453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
18463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
1847179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
18483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
18493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1850d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
18513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
18523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
18543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                err = mAudioSink->setPlaybackRate(mPlaybackSettings);
18553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
18563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
18573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
18583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
18593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
18603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
18613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
18623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
18633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
18643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
186585e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                if (!mPaused) { // for preview mode, don't start if paused
186685e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                    err = mAudioSink->start();
186785e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                }
18683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
18693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
18713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
18723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
18733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
18743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
18753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
1876a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                if (offloadOnly) {
1877a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                    notifyAudioTearDown(kForceNonOffload);
1878a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                }
18793ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            } else {
18803ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                mUseAudioCallback = true;  // offload mode transfers data through callback
18813ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
18823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
18843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
18853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
18863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1887d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1888d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1889f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
1890f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        const PcmInfo info = {
1891f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_channel_mask_t)channelMask,
1892f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_output_flags_t)pcmFlags,
1893f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1894f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                numChannels,
1895f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                sampleRate
1896f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        };
1897f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1898f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            ALOGV("openAudioSink: no change in pcm mode");
1899f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            // no change from previous configuration, everything ok.
1900f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            return OK;
1901f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        }
1902f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
19033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
19043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
19053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1906a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // Note: It is possible to set up the callback, but not use it to send audio data.
1907a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // This requires a fix in AudioSink to explicitly specify the transfer mode.
1908a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mUseAudioCallback = getUseAudioCallbackSetting();
19093ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        if (mUseAudioCallback) {
19103ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
19113ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        }
1912179652ee2a508361df1aa18e99000373886f0816Andy Hung
1913179652ee2a508361df1aa18e99000373886f0816Andy Hung        // Compute the desired buffer size.
1914179652ee2a508361df1aa18e99000373886f0816Andy Hung        // For callback mode, the amount of time before wakeup is about half the buffer size.
1915179652ee2a508361df1aa18e99000373886f0816Andy Hung        const uint32_t frameCount =
1916179652ee2a508361df1aa18e99000373886f0816Andy Hung                (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1917179652ee2a508361df1aa18e99000373886f0816Andy Hung
19187665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
19197665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // AudioSink. We don't want this when there's video because it will cause a video seek to
19207665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // the previous I frame. But we do want this when there's only audio because it will give
19217665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // NuPlayer a chance to switch from non-offload mode to offload mode.
19227665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // So we only set doNotReconnect when there's no video.
19237665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        const bool doNotReconnect = !hasVideo;
1924ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung
1925ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        // We should always be able to set our playback settings if the sink is closed.
1926ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
1927ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung                "onOpenAudioSink: can't set playback rate on closed sink");
1928202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
19293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
19303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
19313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
19323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
1933179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
1934a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1935a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? this : NULL,
1936faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    (audio_output_flags_t)pcmFlags,
1937faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    NULL,
19387665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                    doNotReconnect,
1939179652ee2a508361df1aa18e99000373886f0816Andy Hung                    frameCount);
1940202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
1941202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
19424d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia            mAudioSink->close();
1943f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1944202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
1945202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
1946f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        mCurrentPcmInfo = info;
1947005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        if (!mPaused) { // for preview mode, don't start if paused
1948005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            mAudioSink->start();
1949005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        }
19503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
19513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
19523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
19533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
1954faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = false;
1955202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
19563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
19573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
19583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
19593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
19603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1961f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
19623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
19633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
1964f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
1965f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1966