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/ADebug.h>
255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h>
26a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu#include <media/stagefright/foundation/AUtils.h>
2735d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang#include <media/stagefright/foundation/AWakeLock.h>
285833b6aad2c46ba516bdc8262f4fc4667e8018edWei Jia#include <media/stagefright/MediaClock.h>
29bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MediaErrors.h>
30bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MetaData.h>
313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang#include <media/stagefright/Utils.h>
32a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar#include <media/stagefright/VideoFrameScheduler.h>
337e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim#include <media/MediaCodecBuffer.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);
1479a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    if (mUseAudioCallback) {
1489a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        flushQueue(&mAudioQueue);
1499a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        flushQueue(&mVideoQueue);
1509a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    }
1514c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mWakeLock.clear();
1524c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mMediaClock.clear();
1534c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mVideoScheduler.clear();
1544c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mNotify.clear();
1554c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    mAudioSink.clear();
156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
157f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
158f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
1607e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim        const sp<MediaCodecBuffer> &buffer,
161f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
1621d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
1637b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
164f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
1657e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    msg->setObject("buffer", buffer);
166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
167f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
168f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
169f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
170f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
171f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
172f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1731d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
1747b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
175f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
176f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
177f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
178f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
179f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, rate);
1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
1863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (rate.mSpeed == 0.f) {
1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        onPause();
1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // don't call audiosink's setPlaybackRate if pausing, as pitch does not
1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // have to correspond to the any non-0 speed (e.g old speed). Keep
1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // settings nonetheless, using the old speed, in case audiosink changes.
1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AudioPlaybackRate newRate = rate;
1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        newRate.mSpeed = mPlaybackSettings.mSpeed;
1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mPlaybackSettings = newRate;
2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return OK;
2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
20327ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->setPlaybackRate(rate);
2053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err != OK) {
2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return err;
2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = rate;
2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = rate.mSpeed;
2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
2123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
2173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, rate);
2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
22927ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->getPlaybackRate(rate);
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGW("correcting mismatch in internal/external playback rate");
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // get playback settings used by audiosink, as it may be
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // slightly off due to audiosink not taking small changes.
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mPlaybackSettings = *rate;
2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mPaused) {
2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                rate->mSpeed = 0.f;
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return err;
2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *rate = mPlaybackSettings;
2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, sync, videoFpsHint);
2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
2613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
2623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // TODO: support sync sources
2643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return INVALID_OPERATION;
2653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
2683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
2693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, sync, videoFps);
2753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetSyncSettings(
2813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
2823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *sync = mSyncSettings;
2833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *videoFps = -1.f;
2843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2859816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
2869816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
2877137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
288f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
2897b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
290f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
2917137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
2923b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia            clearAudioFirstAnchorTime_l();
2937b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioQueueGeneration;
2947b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
295f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
2967137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
2977b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoQueueGeneration;
2987b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoDrainGeneration;
299f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
3007b15cb33847e6282ea8352c98894683b796127f3Wei Jia
3019a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        mMediaClock->clearAnchor();
3027b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mVideoLateByUs = 0;
3037b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mSyncQueues = false;
304f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
305f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
3061d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatFlush, this);
307f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
309f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
310f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
311f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
31228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
31328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
31428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
3151d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatDisableOffloadAudio, this))->post();
31628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
31728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
318a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
3191d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatEnableOffloadAudio, this))->post();
320a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
321a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
322b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
3231d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
324b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
325b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
326b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
3271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
328b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
329b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
330c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
3311d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
332c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
333c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
334c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
335c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
3364ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia// Called on any threads without mLock acquired.
3377b15cb33847e6282ea8352c98894683b796127f3Wei Jiastatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
3384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
3394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (result == OK) {
3404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        return result;
3414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    // MediaClock has not started yet. Try to start it if possible.
3444ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    {
3454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        Mutex::Autolock autoLock(mLock);
3464ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (mAudioFirstAnchorTimeMediaUs == -1) {
3474ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3484ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3494ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3504ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        AudioTimestamp ts;
3514ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        status_t res = mAudioSink->getTimestamp(ts);
3524ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (res != OK) {
3534ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3544ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3554ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3564ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        // AudioSink has rendered some frames.
3574ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowUs = ALooper::GetNowUs();
358d855a738735a3df8863b486f5d3b5e404cef15c1Wei Jia        int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
3594ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia                + mAudioFirstAnchorTimeMediaUs;
3604ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
3614ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3624ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3639816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
365a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3667b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
3677b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioFirstAnchorTimeMediaUs = -1;
3687b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->setStartingTimeMedia(-1);
369a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
370a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3717b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
373a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
3747b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mMediaClock->setStartingTimeMedia(mediaUs);
375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
376a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
377a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3789a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia// Called on renderer looper.
3799a3101b22b5115717faeac986b43fc6618fd3b30Wei Jiavoid NuPlayer::Renderer::clearAnchorTime() {
3807b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->clearAnchor();
3817b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = -1;
3827b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorNumFramesWritten = -1;
383a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
384a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
385a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
3867b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
387a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
388a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
389a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
390a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
3917b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
392a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
393a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
394a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
395202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
3963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
3973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
3983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
399202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
400c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar        bool *isOffloaded,
401c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar        bool isStreaming) {
4021d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
4033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
4043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
4053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
407c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar    msg->setInt32("isStreaming", isStreaming);
4083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
41066e4c4779f17198dd3cb0b13b97a7943c6eae3e5Leena Winterrowd    status_t postStatus = msg->postAndAwaitResponse(&response);
4113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
412202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
41366e4c4779f17198dd3cb0b13b97a7943c6eae3e5Leena Winterrowd    if (postStatus != OK || response.get() == nullptr || !response->findInt32("err", &err)) {
414202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
415202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
416202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
417202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
418202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
419202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
420202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
4213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
4241d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
4253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
4273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
4283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4309a3101b22b5115717faeac986b43fc6618fd3b30Wei Jiavoid NuPlayer::Renderer::changeAudioFormat(
4319a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        const sp<AMessage> &format,
4329a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        bool offloadOnly,
4339a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        bool hasVideo,
4349a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        uint32_t flags,
435c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar        bool isStreaming,
4369a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        const sp<AMessage> &notify) {
4379a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    sp<AMessage> meta = new AMessage;
4389a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    meta->setMessage("format", format);
4399a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    meta->setInt32("offload-only", offloadOnly);
4409a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    meta->setInt32("has-video", hasVideo);
4419a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    meta->setInt32("flags", flags);
442c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar    meta->setInt32("isStreaming", isStreaming);
4439a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
4449a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    sp<AMessage> msg = new AMessage(kWhatChangeAudioFormat, this);
4459a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(true /* audio */));
4469a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    msg->setMessage("notify", notify);
4479a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    msg->setMessage("meta", meta);
4489a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    msg->post();
4499a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia}
4509a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
451f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
452f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
4533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
4543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
4563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
4573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
4593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
4603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
4623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
4633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
4653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
4663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
467c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar            uint32_t isStreaming;
468c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar            CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
469c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar
470c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
4713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
473202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
474202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
4753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4763f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
4843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4853f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
4893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
4913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
495bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
496bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
497bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
498bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
499bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
500bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
5019a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        case kWhatChangeAudioFormat:
5029a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        {
5039a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            int32_t queueGeneration;
5049a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            CHECK(msg->findInt32("queueGeneration", &queueGeneration));
5059a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5069a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            sp<AMessage> notify;
5079a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            CHECK(msg->findMessage("notify", &notify));
5089a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5099a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            if (offloadingAudio()) {
5109a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                ALOGW("changeAudioFormat should NOT be called in offload mode");
5119a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                notify->setInt32("err", INVALID_OPERATION);
5129a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                notify->post();
5139a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                break;
5149a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            }
5159a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5169a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            sp<AMessage> meta;
5179a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            CHECK(msg->findMessage("meta", &meta));
5189a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5199a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            if (queueGeneration != getQueueGeneration(true /* audio */)
5209a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                    || mAudioQueue.empty()) {
5219a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                onChangeAudioFormat(meta, notify);
5229a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                break;
5239a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            }
5249a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5259a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            QueueEntry entry;
5269a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            entry.mNotifyConsumed = notify;
5279a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            entry.mMeta = meta;
5289a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5299a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            Mutex::Autolock autoLock(mLock);
5309a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            mAudioQueue.push_back(entry);
5319a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            postDrainAudioQueue_l();
5329a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
5339a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            break;
5349a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        }
5359a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
536f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
537f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
5383ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            mDrainAudioQueuePending = false;
5393ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia
540f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
5417b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5427b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(true /* audio */)) {
543f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
544f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
545f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
546078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
547078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
548078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
549078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
550078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
551078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
552078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
553078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
554078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
555078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
556078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
557078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
558078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
559d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                if (mPlaybackRate > 1.0f) {
560d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                    delayUs /= mPlaybackRate;
561d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                }
562078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
563078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
564078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
565f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                delayUs /= 2;
566f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                // check the buffer size to estimate maximum delay permitted.
567f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                const int64_t maxDrainDelayUs = std::max(
568f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                        mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */);
569f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld",
570f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                        (long long)delayUs, (long long)maxDrainDelayUs);
5717b15cb33847e6282ea8352c98894683b796127f3Wei Jia                Mutex::Autolock autoLock(mLock);
572f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung                postDrainAudioQueue_l(delayUs);
573078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
574f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
575f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
576f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
577f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
578f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
579f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
5807b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5817b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
582f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
583f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
584f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
585f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
586f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
587f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
588f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5897b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
590f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
591f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
592f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
593d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
594d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
595d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
5967b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5977b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
598d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
599d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
600d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
601d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
6027b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
603d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
604d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
605d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
606f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
607f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
608f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
609f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
610f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
611f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
612f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
613f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
614f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
615f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
616f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
617f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
6187c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        case kWhatEOS:
6197c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        {
6207c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            int32_t generation;
6217c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("audioEOSGeneration", &generation));
6227c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            if (generation != mAudioEOSGeneration) {
6237c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia                break;
6247c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            }
6257c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            status_t finalResult;
6267c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("finalResult", &finalResult));
6277c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            notifyEOS(true /* audio */, finalResult);
6287c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            break;
6297c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        }
6307c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia
6313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigPlayback:
6329816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        {
6333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
6343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate;
6363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &rate);
6373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigPlayback(rate);
6383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
6423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
6433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetPlaybackSettings:
6453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
6463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
6473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
6493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetPlaybackSettings(&rate);
6503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
6523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, rate);
6533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
6543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
6573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
6583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigSync:
6603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
6613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
6623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
6643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFpsHint;
6653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &sync, &videoFpsHint);
6663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigSync(sync, videoFpsHint);
6673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
6713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
6723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetSyncSettings:
6743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
6753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
6763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
6773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
6783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGV("kWhatGetSyncSettings");
6793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
6803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFps = -1.f;
6813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetSyncSettings(&sync, &videoFps);
6823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
6833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
6843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, sync, videoFps);
6853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
6863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6889816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            break;
6899816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        }
6909816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
691f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
692f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
693f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
694f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
695f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
696f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
697bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
698bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
699bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
700bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
701bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
702bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
703a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
704a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
705a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
706a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
707a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
708a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
709b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
710b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
711b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
712b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
713b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
714b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
715b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
716b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
717b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
718b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
719b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
720b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
721c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
722c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
723c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
724c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
725c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
726c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
727c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
728c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
729faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        case kWhatAudioTearDown:
7303a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
731a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            int32_t reason;
732a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            CHECK(msg->findInt32("reason", &reason));
733a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia
734a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            onAudioTearDown((AudioTearDownReason)reason);
7353a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
7363a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
7373a2956d148d81194e297408179e84a47a309ef48Wei Jia
738f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
739f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
740f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
7417b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
742f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
743f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
744f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
7450852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
746faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToTimeout);
74735d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang            mWakeLock->release();
748f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
749f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
750f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
751f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
752f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
753f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
754f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
755f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
756f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
757bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
758005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
759f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
760f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
761f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
762f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
763f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
764f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
765f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
766b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
767b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    if (mPaused) {
768b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
769b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        if (diffUs > delayUs) {
770b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            delayUs = diffUs;
771b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        }
772b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    }
773b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung
774f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
7751d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
7767b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", mAudioDrainGeneration);
777078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
778f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
779f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
7807b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
7817b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioRenderingStartGeneration = mAudioDrainGeneration;
7827b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mVideoRenderingStartGeneration = mVideoDrainGeneration;
783b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung    mRenderingDataDelivered = false;
784cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
785cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
7867b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
7877b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
7887b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
789b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        mRenderingDataDelivered = true;
790b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mPaused) {
791b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            return;
792b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
793cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
794cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
795cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
796cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
797cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
798cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
799cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
800cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
801cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
802bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
803bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
804bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
805bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
806bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
807bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
808bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
809bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
810bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
811bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
812bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
813bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
814bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
815bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
816bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
817bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
818bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
819bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
820a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_STREAM_END");
8214c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia            me->notifyEOSCallback();
822bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
823bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
824bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
825bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
826bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
827a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
828a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            me->notifyAudioTearDown(kDueToError);
829bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
830bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
831bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
832bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
833bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
834bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
835bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8364c74fde2ef5b582196b296a8263cd39143e7abcaWei Jiavoid NuPlayer::Renderer::notifyEOSCallback() {
8374c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    Mutex::Autolock autoLock(mLock);
8384c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
8394c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    if (!mUseAudioCallback) {
8404c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia        return;
8414c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    }
8424c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
8434c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia    notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
8444c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia}
8454c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia
846bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
847bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
848bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
84985e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung    if (!mUseAudioCallback) {
850bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
851bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
852bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
853bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
854bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
855bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
8563e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
857a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
858bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
859a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        entry = &*mAudioQueue.begin();
860bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
861bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
862bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
863bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
864bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
865bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
866bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8673e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
8683e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
869bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
870bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
871a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
8727b15cb33847e6282ea8352c98894683b796127f3Wei Jia            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
873bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
874bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
875bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
876bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
877bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
878bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
879bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
880bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
881bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
882bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
883bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
884bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
885bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
886bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
887bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
888bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
889bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
890bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
891bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
8927b15cb33847e6282ea8352c98894683b796127f3Wei Jia
8937b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
894bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
895bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
896f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
897f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
8989816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        int64_t nowMediaUs =
899c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia            mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
9007b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // we don't know how much data we are queueing for offloaded tracks.
9019816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
902f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
903f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
904a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // for non-offloaded audio, we need to compute the frames written because
905a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // there is no EVENT_STREAM_END notification. The frames written gives
906a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // an estimate on the pending played out duration.
907a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    if (!offloadingAudio()) {
908a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
909a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    }
910a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
911bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
9121d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        (new AMessage(kWhatStopAudioSink, this))->post();
913a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // As there is currently no EVENT_STREAM_END callback notification for
914a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // non-offloaded audio tracks, we need to post the EOS ourselves.
915a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        if (!offloadingAudio()) {
916a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            int64_t postEOSDelayUs = 0;
917a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            if (mAudioSink->needsTrailingPadding()) {
918a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
919a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            }
920a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: notifyEOS "
921a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
922a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
923a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
924a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        }
925bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
926bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
927bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
928bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
9299da0ce44f228408d73a4dea0be972c785095dcccChong Zhangvoid NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
9309da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
9319da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    bool foundEOS = false;
9329da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    while (it != mAudioQueue.end()) {
9339da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        int32_t eos;
9349da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        QueueEntry *entry = &*it++;
9359a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        if ((entry->mBuffer == nullptr && entry->mNotifyConsumed == nullptr)
9369da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
9379da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            itEOS = it;
9389da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            foundEOS = true;
9399da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
9409da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
9419da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
9429da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    if (foundEOS) {
9439da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // post all replies before EOS and drop the samples
9449da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        for (it = mAudioQueue.begin(); it != itEOS; it++) {
9459a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            if (it->mBuffer == nullptr) {
9469a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                if (it->mNotifyConsumed == nullptr) {
9479a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                    // delay doesn't matter as we don't even have an AudioTrack
9489a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                    notifyEOS(true /* audio */, it->mFinalResult);
9499a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                } else {
9509a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                    // TAG for re-opening audio sink.
9519a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                    onChangeAudioFormat(it->mMeta, it->mNotifyConsumed);
9529a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                }
9539da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            } else {
9549da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                it->mNotifyConsumed->post();
9559da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            }
9569da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
9579da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        mAudioQueue.erase(mAudioQueue.begin(), itEOS);
9589da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
9599da0ce44f228408d73a4dea0be972c785095dcccChong Zhang}
9609da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
961078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
96258d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    // do not drain audio during teardown as queued buffers may be invalid.
96358d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    if (mAudioTornDown) {
96458d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung        return false;
96558d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    }
966230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // TODO: This call to getPosition checks if AudioTrack has been created
967230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
968230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // CHECKs on getPosition will fail.
969230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // We still need to figure out why AudioTrack is not created when
970230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // this function is called. One possible reason could be leftover
971230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // audio. Another possible place is to check whether decoder
972230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // has received INFO_FORMAT_CHANGED as the first buffer since
973230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // AudioSink is opened there, and possible interactions with flush
974230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // immediately after start. Investigate error message
975230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // "vorbis_dsp_synthesis returned -135", along with RTSP.
976078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
9772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
9789da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // When getPosition fails, renderer will not reschedule the draining
9799da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // unless new samples are queued.
9809da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // If we have pending EOS (or "eos" marker for discontinuities), we need
9819da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // to post these now as NuPlayerDecoder might be waiting for it.
9829da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        drainAudioQueueUntilLastEOS();
9839da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
9849da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        ALOGW("onDrainAudioQueue(): audio sink is not ready");
9852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
9862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
987078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
988230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia#if 0
989078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
990078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
991078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
992078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
993df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
994078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
9953856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
996078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
997078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
998078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
999f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1000005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    uint32_t prevFramesWritten = mNumFramesWritten;
10017d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia    while (!mAudioQueue.empty()) {
1002f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
1003f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1004f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
10059a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            if (entry->mNotifyConsumed != nullptr) {
10069a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                // TAG for re-open audio sink.
10079a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
10089a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                mAudioQueue.erase(mAudioQueue.begin());
10099a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia                continue;
10109a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            }
10119a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
1012f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
101362d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George            if (mPaused) {
101462d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George                // Do not notify EOS when paused.
101562d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George                // This is needed to avoid switch to next clip while in pause.
101662d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George                ALOGV("onDrainAudioQueue(): Do not notify EOS when paused");
101762d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George                return false;
101862d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George            }
101962d4e07eb5f99bd469f92897e47f5598abef99d3Haynes Mathew George
10205095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
10215095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
102206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
10235095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
10245095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
10252995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1026f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1027f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
1028f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
10293491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
10303491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
10313491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
10323491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
10333491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
10343491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
10353491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
1036078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
1037c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
1038c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
10399a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        mLastAudioBufferDrained = entry->mBufferOrdinal;
10409a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
104181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        // ignore 0-sized buffer which could be EOS marker with no data
104281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
1043f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
1044f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1045a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
1046a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mediaTimeUs / 1E6);
1047eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
1048f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1049f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1050f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
1051f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10527d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
10537d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                                            copy, false /* blocking */);
1054a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
1055202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
10567d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            if (written == WOULD_BLOCK) {
1057df809479696725faf5d3424b11fa8a07bd94cb5eWei Jia                ALOGV("AudioSink write would block when writing %zu bytes", copy);
10587d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            } else {
10597d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
10607665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // This can only happen when AudioSink was opened with doNotReconnect flag set to
10617665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // true, in which case the NuPlayer will handle the reconnect.
1062a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                notifyAudioTearDown(kDueToError);
10637d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            }
1064202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
1065a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
1066f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1067a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
106803cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia        size_t remainder = entry->mBuffer->size() - entry->mOffset;
106903cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia        if ((ssize_t)remainder < mAudioSink->frameSize()) {
107003cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            if (remainder > 0) {
107103cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.",
107203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                        remainder);
107303cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                entry->mOffset += remainder;
107403cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia                copy -= remainder;
107503cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            }
107603cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia
1077f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1078f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
10799b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
1080f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
1081f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1082f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1083a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
1084078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
1085cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
10867b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
10877b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1088d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            int64_t maxTimeMedia;
1089d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            maxTimeMedia =
1090d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                mAnchorTimeMediaUs +
1091d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
1092d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                                * 1000LL * mAudioSink->msecsPerFrame());
1093d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
1094d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia
10957b15cb33847e6282ea8352c98894683b796127f3Wei Jia            notifyIfMediaRenderingStarted_l();
10967b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
109743c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1098a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
1099a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
1100a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
11017d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // AudioSink write is called in non-blocking mode.
11027d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // It may return with a short count when:
1103a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
110403cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            // 1) Size to be copied is not a multiple of the frame size. Fractional frames are
110503cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia            //    discarded.
11067d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 2) The data to be copied exceeds the available buffer in AudioSink.
11077d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
11087d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
1109a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
1110a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
1111a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
1112a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
1113a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
1114a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
11157d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // (Case 2, 3, 4)
1116a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
1117a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
11187d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
1119a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
1120a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
1121a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
1122f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
1123005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    // calculate whether we need to reschedule another write.
1124005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    bool reschedule = !mAudioQueue.empty()
1125005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            && (!mPaused
1126005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung                || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1127005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
1128005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1129005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    return reschedule;
1130f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1131f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11329816016afb2a13c6a866cd047d57020566a8b9a9Wei Jiaint64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
11339816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int32_t sampleRate = offloadingAudio() ?
11349816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
11354d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    if (sampleRate == 0) {
11364d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
11374d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        return 0;
11384d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    }
11399816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
11409816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
11419816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
11429816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
11439816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
114406ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
11459816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1146d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia    if (mUseVirtualAudioSink) {
1147d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        int64_t nowUs = ALooper::GetNowUs();
1148d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        int64_t mediaUs;
1149d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) {
1150d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            return 0ll;
1151d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        } else {
1152d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs);
1153d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia        }
1154d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia    }
1155c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia    return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
11565095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
11575095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
1158a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
11599816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t realUs;
11609816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
11617b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If failed to get current position, e.g. due to audio clock is
11627b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // not ready, then just play out video immediately without delay.
1163eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
1164a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
11659816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return realUs;
1166a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
1167a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1168eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
11697b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1170eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
1171eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
1172eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
1173eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
1174eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
11757b15cb33847e6282ea8352c98894683b796127f3Wei Jia    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
11764ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
1177528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start
1178528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    if (mNextAudioClockUpdateTimeUs == -1) {
1179528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        AudioTimestamp ts;
1180528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) {
1181528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mNextAudioClockUpdateTimeUs = 0; // start our clock updates
1182528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        }
1183528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    }
118412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    int64_t nowUs = ALooper::GetNowUs();
1185528c8403ad2ede53054a706a20c00b710fa08166Andy Hung    if (mNextAudioClockUpdateTimeUs >= 0) {
1186528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        if (nowUs >= mNextAudioClockUpdateTimeUs) {
1187528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
1188528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
1189d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            mUseVirtualAudioSink = false;
1190528c8403ad2ede53054a706a20c00b710fa08166Andy Hung            mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs;
1191528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        }
119212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    } else {
119312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        int64_t unused;
119412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
119512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
119612b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                        > kMaxAllowedAudioSinkDelayUs)) {
119712b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Enough data has been sent to AudioSink, but AudioSink has not rendered
119812b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // any data yet. Something is wrong with AudioSink, e.g., the device is not
119912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // connected to audio out.
120012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Switch to system clock. This essentially creates a virtual AudioSink with
120112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
120212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // This virtual AudioSink renders audio data starting from the very first sample
120312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // and it's paced by system clock.
120407af6518b7b7eeb730ded9c5fd6fd6fb3a462bc5Wei Jia            ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
120512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
1206d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia            mUseVirtualAudioSink = true;
120712b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        }
12084ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
12098edb3f85f58e8738582e8f9abbc018c85100b712Wei Jia    mAnchorNumFramesWritten = mNumFramesWritten;
12107b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = mediaTimeUs;
1211eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
1212eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
12137b15cb33847e6282ea8352c98894683b796127f3Wei Jia// Called without mLock acquired.
12147b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue() {
1215fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
12167b15cb33847e6282ea8352c98894683b796127f3Wei Jia            || getSyncQueues()
1217fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
1218f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1219f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1220f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1221f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1222f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1223f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1224f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1225f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
1226f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
12271d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
12287b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
1229f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1230f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
1231f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
1232dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
1233dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
1234dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
1235dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
1236dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
123700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih    bool needRepostDrainVideoQueue = false;
1238dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
1239dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
1240dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
1241dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
1242d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
1243d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1244dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
1245f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1246f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
1247f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1248f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
12497b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
12507b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
12517b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (mAnchorTimeMediaUs < 0) {
12527b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
12537b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mAnchorTimeMediaUs = mediaTimeUs;
12547b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = nowUs;
125525d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia            } else if (!mVideoSampleReceived) {
125625d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                // Always render the first video frame.
125725d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                realTimeUs = nowUs;
125800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mAudioFirstAnchorTimeMediaUs < 0
125900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
12607b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
126100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
126200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                needRepostDrainVideoQueue = true;
126300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
126400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else {
126500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
12667b15cb33847e6282ea8352c98894683b796127f3Wei Jia            }
1267f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1268f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
12697b15cb33847e6282ea8352c98894683b796127f3Wei Jia            // smooth out videos >= 10fps
12707b15cb33847e6282ea8352c98894683b796127f3Wei Jia            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1271f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
1272d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
1273d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
1274d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
1275d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
1276d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
1277d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
127800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        int64_t postDelayUs = -1;
1279d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
128000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = 500000;
1281d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1282d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
1283d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
128400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        } else if (needRepostDrainVideoQueue) {
128500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mPlaybackRate > 0);
128600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
128700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
128800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
128900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs /= mPlaybackRate;
129000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        }
129100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih
129200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        if (postDelayUs >= 0) {
1293d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
1294d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
1295d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
1296238e1247a1fde2c7857ec243563126de72346a89Wei Jia            ALOGI("possible video time jump of %dms (%lld : %lld) or uninitialized media clock,"
1297238e1247a1fde2c7857ec243563126de72346a89Wei Jia                    " retrying in %dms",
1298238e1247a1fde2c7857ec243563126de72346a89Wei Jia                    (int)(delayUs / 1000), (long long)mediaTimeUs,
1299238e1247a1fde2c7857ec243563126de72346a89Wei Jia                    (long long)mAudioFirstAnchorTimeMediaUs, (int)(postDelayUs / 1000));
1300d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
1301d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
1302d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
1303f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1304f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1305dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1306dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1307dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1308dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
1309dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1310095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
1311dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
1312dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1313f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1314f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
1315f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1316f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1317f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
1318f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1319f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1320f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1321f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1322f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
1323f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1324f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
1325f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
1326f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1327c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
1328f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1329f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
1330f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
13313fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1332a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1333f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1334f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1335f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
133625d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    int64_t nowUs = ALooper::GetNowUs();
1337d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
13382995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia    int64_t mediaTimeUs = -1;
1339d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
1340d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1341d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
1342d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1343d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
1344a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1345d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
1346f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1347fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
13483fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1349fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1350a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
1351fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
1352fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
1353fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
1354fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
13556d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
1356fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
13579816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            int64_t mediaUs = 0;
13589816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
1359fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
1360fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
13619816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia                    mediaUs) / 1E6);
13622995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia
13632995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            if (!(mFlags & FLAG_REAL_TIME)
13642995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mLastAudioMediaTimeUs != -1
13652995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mediaTimeUs > mLastAudioMediaTimeUs) {
13662995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // If audio ends before video, video continues to drive media clock.
13672995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // Also smooth out videos >= 10fps.
13682995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
13692995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            }
1370fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
1371078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
1372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1373eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
1374a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
1375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
13769a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            clearAnchorTime();
137749966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
1378078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
1379f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
138025d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    // Always render the first video frame while keeping stats on A/V sync.
138125d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    if (!mVideoSampleReceived) {
138225d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        realTimeUs = nowUs;
138325d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        tooLate = false;
138425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    }
138525d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia
1386dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
1387683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
1388f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
1389f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
1390f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
139143c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1392fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
1393f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
1394fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1395fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
1396fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
1397fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
1398fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
13997b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
14007b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
1401fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
1402f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1403f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1404f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
1405f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
1406f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
1407f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
1408f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
1409f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
14105095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
14117c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    if (audio && delayUs > 0) {
14127c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        sp<AMessage> msg = new AMessage(kWhatEOS, this);
14137c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
14147c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("finalResult", finalResult);
14157c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->post(delayUs);
14167c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        return;
14177c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    }
1418f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1419f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
1420f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1421c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
14225095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
1423f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1424f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1425a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jiavoid NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) {
1426a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this);
1427a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    msg->setInt32("reason", reason);
1428a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia    msg->post();
14293a2956d148d81194e297408179e84a47a309ef48Wei Jia}
14303a2956d148d81194e297408179e84a47a309ef48Wei Jia
1431f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1432f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1433f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1434f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14357b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
14367b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return;
14377b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
14387b15cb33847e6282ea8352c98894683b796127f3Wei Jia
14397b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (audio) {
14407b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasAudio = true;
14417b15cb33847e6282ea8352c98894683b796127f3Wei Jia    } else {
14427b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasVideo = true;
14437b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
1444a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1445a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
1446dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
1447dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
1448dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
1449dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
1450bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
1451bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
14527e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    sp<RefBase> obj;
14537e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    CHECK(msg->findObject("buffer", &obj));
14547e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
1455f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1456f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1457f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1459f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
1461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
1462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
1464d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
1465f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1466f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
14677b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1468f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1469bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1471f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
14727b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1473f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14757b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1476cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1477cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1478cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1479f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14807e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    sp<MediaCodecBuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
14817e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    sp<MediaCodecBuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1483cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1484cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
1485bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
1486cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1487cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1488f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1489cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
1490cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
1491cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
1492cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
1493cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
1494cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
1495f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1496cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1497f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
1499cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1500cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
1501cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
1502cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
1503cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1504cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
1505cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
1506cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1507f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1508cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1509bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
1510f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1511f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1512bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
1513f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
1514f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1515f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1516f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1517f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
1518f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1519f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
1520bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1522f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1523f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
15247b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.unlock();
15257b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
15267b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.lock();
1527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1530f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1531f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1532f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1533f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15347b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
1535f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1536f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1537f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1538f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1539f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1540f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1541f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1542f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1543f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1544f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1545f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
15467b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1547b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1548bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1549b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1550f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1551bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1552f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
15537b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (mVideoQueue.empty() && getSyncQueues()) {
15547b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1555bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1556b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1557f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
15587b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1559f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1560f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1561f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1562f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
15637137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1564f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1565f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
156628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
15677b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
156828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
15697137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
15707137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
15712995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = -1;
157228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
15737137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
15747137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
157528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
157628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
15777b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If we're currently syncing the queues, i.e. dropping audio while
15787b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // aligning the first audio/video buffer times and only one of the
15797b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // two queues has data, we may starve that queue by not requesting
15807b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // more buffers from the decoder. If the other source then encounters
15817b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // a discontinuity that leads to flushing, we'll never find the
15827b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // corresponding discontinuity on the other queue.
15837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // Therefore we'll stop syncing the queues if at least one of them
15847b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // is flushed.
15857b15cb33847e6282ea8352c98894683b796127f3Wei Jia        syncQueuesDone_l();
1586bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
15879a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    clearAnchorTime();
1588f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1589cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1590f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1591bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1592bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1593bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1594f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15957b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
15967c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            ++mAudioEOSGeneration;
15977b15cb33847e6282ea8352c98894683b796127f3Wei Jia            prepareForMediaRenderingStart_l();
159828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1599a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            // the frame count will be reset after flush.
1600a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            clearAudioFirstAnchorTime_l();
160128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1602f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1603f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1604cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1605bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1606bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1607bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
160885e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            if (!mPaused) {
160985e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                mAudioSink->start();
161085e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            }
16119e7ed3315298b42db485963b182a572e9ab42f9fWei Jia        } else {
16129e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->pause();
16139e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->flush();
16149e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // Call stop() to signal to the AudioSink to completely fill the
16159e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // internal buffer before resuming playback.
1616b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            // FIXME: this is ignored after flush().
16179e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->stop();
1618b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            if (mPaused) {
1619b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // Race condition: if renderer is paused and audio sink is stopped,
1620b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // we need to make sure that the audio track buffer fully drains
1621b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // before delivering data.
1622b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // FIXME: remove this if we can detect if stop() is complete.
1623b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1624b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1625b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            } else {
16269e7ed3315298b42db485963b182a572e9ab42f9fWei Jia                mAudioSink->start();
16279e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            }
16289e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mNumFramesWritten = 0;
1629bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1630528c8403ad2ede53054a706a20c00b710fa08166Andy Hung        mNextAudioClockUpdateTimeUs = -1;
1631f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1632f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1633f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1634f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1635cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1636c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1637c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1638c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1639c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
16407b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
16417b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
16427b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
1643f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1644f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1645fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
16467137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
16477137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
16487137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
16497137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1650f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1651f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1652f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1653f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1654f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1655f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1656f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1657f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
16589a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        } else if (entry->mNotifyConsumed != nullptr) {
16599a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            // Is it needed to open audio sink now?
16609a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia            onChangeAudioFormat(entry->mMeta, entry->mNotifyConsumed);
1661f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1662f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1663f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1664f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1665f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1666f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1667f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1668f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1669f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1670f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1671f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1672f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1673f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1674f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
16757b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::dropBufferIfStale(
1676f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
16777b15cb33847e6282ea8352c98894683b796127f3Wei Jia    int32_t queueGeneration;
16787b15cb33847e6282ea8352c98894683b796127f3Wei Jia    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
1679f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
16807b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (queueGeneration == getQueueGeneration(audio)) {
1681f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1682f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1683f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1684f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1685f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1686f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1687f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1688f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1689f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1690f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1691f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
16923831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1693bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1694bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1695bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
16963831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
16973831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
16989a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    mAnchorNumFramesWritten = -1;
16994110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
17004110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
17014110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
17024110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
17033831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
17043831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1705bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1706bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1707bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
17087b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1709e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1710e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1711e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1712bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1713bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1714a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1715a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1716a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
17177b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1718e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1719e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1720e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1721a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1722a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1723b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
17248592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
17258592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
17268592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
17276d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar
172828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
172928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
1730005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        // we do not increment audio drain generation so that we fill audio buffer during pause.
17317b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
17327b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
173373ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
17349816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(0.0);
173528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1736b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
173728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1738b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1739cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
17408420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
17418420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    mAudioSink->pause();
17428420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    startAudioOffloadPauseTimeout();
1743b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
17446d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar    ALOGV("now paused audio queue has %zu entries, video has %zu entries",
1745ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1746b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1747b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1748b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1749b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1750b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1751b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1752b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
17538420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
17548420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    cancelAudioOffloadPauseTimeout();
17558420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    if (mAudioSink->ready()) {
175697c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        status_t err = mAudioSink->start();
175797c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        if (err != OK) {
175858d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung            ALOGE("cannot start AudioSink err %d", err);
1759a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia            notifyAudioTearDown(kDueToError);
176097c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        }
1761b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1762b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
17637b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
17647b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
17657b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mPaused = false;
1766b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        // rendering started message may have been delayed if we were paused.
1767b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mRenderingDataDelivered) {
1768b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            notifyIfMediaRenderingStarted_l();
1769b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
17703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // configure audiosink as we did not do it when pausing
177127ea08e3811dc8057685258af52a7d40474eba16Wei Jia        if (mAudioSink != NULL && mAudioSink->ready()) {
17723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mAudioSink->setPlaybackRate(mPlaybackSettings);
17733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
17743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
17759816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(mPlaybackRate);
1776b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
17777b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (!mAudioQueue.empty()) {
17787b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainAudioQueue_l();
17797b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
1780b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1781b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1782b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
17837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1784b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1785b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1786b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1787c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1788c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1789c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1790c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1791c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1792c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1793c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
17947b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
17957b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
17967b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
17977b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
17987b15cb33847e6282ea8352c98894683b796127f3Wei Jia
17997b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
18007b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
18017b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
18027b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
18037b15cb33847e6282ea8352c98894683b796127f3Wei Jia
18047b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::getSyncQueues() {
18057b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
18067b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return mSyncQueues;
18077b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
18087b15cb33847e6282ea8352c98894683b796127f3Wei Jia
1809faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1810faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    if (mAudioTornDown) {
1811f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1812f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1813faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = true;
1814f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1815a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
18161a5c859016e743779e4db25855390b3ce523cd48Robert Shih    sp<AMessage> notify = mNotify->dup();
18171a5c859016e743779e4db25855390b3ce523cd48Robert Shih    if (getCurrentPosition(&currentPositionUs) == OK) {
18181a5c859016e743779e4db25855390b3ce523cd48Robert Shih        notify->setInt64("positionUs", currentPositionUs);
181928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
182006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
18213a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
18223a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
18233a2956d148d81194e297408179e84a47a309ef48Wei Jia
1824faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    notify->setInt32("what", kWhatAudioTearDown);
18250852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
18263a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
18273a2956d148d81194e297408179e84a47a309ef48Wei Jia}
18283a2956d148d81194e297408179e84a47a309ef48Wei Jia
1829f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1830f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
183135d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->acquire();
18321d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
18337b15cb33847e6282ea8352c98894683b796127f3Wei Jia        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
1834f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1835f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1836f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1837f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1838f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
183921afe805580c1fdf394415648fba8e1c482def60Andy Hung    // We may have called startAudioOffloadPauseTimeout() without
184021afe805580c1fdf394415648fba8e1c482def60Andy Hung    // the AudioSink open and with offloadingAudio enabled.
184121afe805580c1fdf394415648fba8e1c482def60Andy Hung    //
184221afe805580c1fdf394415648fba8e1c482def60Andy Hung    // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless
184321afe805580c1fdf394415648fba8e1c482def60Andy Hung    // we always release the wakelock and increment the pause timeout generation.
184421afe805580c1fdf394415648fba8e1c482def60Andy Hung    //
184521afe805580c1fdf394415648fba8e1c482def60Andy Hung    // Note: The acquired wakelock prevents the device from suspending
184621afe805580c1fdf394415648fba8e1c482def60Andy Hung    // immediately after offload pause (in case a resume happens shortly thereafter).
184721afe805580c1fdf394415648fba8e1c482def60Andy Hung    mWakeLock->release(true);
184821afe805580c1fdf394415648fba8e1c482def60Andy Hung    ++mAudioOffloadPauseTimeoutGeneration;
1849f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1850f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1851202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
18523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
18533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
18543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
1855c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar        uint32_t flags,
1856c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar        bool isStreaming) {
18573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
18583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
18593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
18603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
18623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
18633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
18653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
18663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
18673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
18683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
18693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
18713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
18723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
18743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
18753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
18763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
18773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
18783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
18803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
18813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
18823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
18833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
18843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
18853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
18863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
188846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            format->findInt32("bitrate", &avgBitRate);
18893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
18913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
18923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
18933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
18943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
18953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
18963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
18973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
19003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
19013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
19023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
19033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
19043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
19053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
19063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
19073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
19083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
1909c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar            offloadInfo.is_streaming = isStreaming;
19103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
19113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
19123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
19133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1914202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
19153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
1916f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1917f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
19183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1919d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1920d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1921d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
19223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
19233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
1924a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
19253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
19263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
19273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
19283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
19293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
1930179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
19313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
19323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1933d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
19343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
19353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
19363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
19373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                err = mAudioSink->setPlaybackRate(mPlaybackSettings);
19383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
19393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
19403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
19413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
19423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
19433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
19443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
19453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
19463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
19473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
194885e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                if (!mPaused) { // for preview mode, don't start if paused
194985e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                    err = mAudioSink->start();
195085e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                }
19513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
19523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
19533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
19543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
19553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
19563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
19573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
19583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
1959a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                if (offloadOnly) {
1960a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                    notifyAudioTearDown(kForceNonOffload);
1961a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia                }
19623ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            } else {
19633ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                mUseAudioCallback = true;  // offload mode transfers data through callback
19643ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
19653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
19663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
19673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
19683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
19693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1970d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1971d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1972f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
1973f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        const PcmInfo info = {
1974f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_channel_mask_t)channelMask,
1975f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_output_flags_t)pcmFlags,
1976f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1977f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                numChannels,
1978f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                sampleRate
1979f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        };
1980f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1981f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            ALOGV("openAudioSink: no change in pcm mode");
1982f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            // no change from previous configuration, everything ok.
1983f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            return OK;
1984f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        }
1985f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
19863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
19873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
19883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1989a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // Note: It is possible to set up the callback, but not use it to send audio data.
1990a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // This requires a fix in AudioSink to explicitly specify the transfer mode.
1991a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mUseAudioCallback = getUseAudioCallbackSetting();
19923ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        if (mUseAudioCallback) {
19933ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
19943ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        }
1995179652ee2a508361df1aa18e99000373886f0816Andy Hung
1996179652ee2a508361df1aa18e99000373886f0816Andy Hung        // Compute the desired buffer size.
1997179652ee2a508361df1aa18e99000373886f0816Andy Hung        // For callback mode, the amount of time before wakeup is about half the buffer size.
1998179652ee2a508361df1aa18e99000373886f0816Andy Hung        const uint32_t frameCount =
1999179652ee2a508361df1aa18e99000373886f0816Andy Hung                (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
2000179652ee2a508361df1aa18e99000373886f0816Andy Hung
20017665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
20027665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // AudioSink. We don't want this when there's video because it will cause a video seek to
20037665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // the previous I frame. But we do want this when there's only audio because it will give
20047665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // NuPlayer a chance to switch from non-offload mode to offload mode.
20057665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // So we only set doNotReconnect when there's no video.
20067665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        const bool doNotReconnect = !hasVideo;
2007ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung
2008ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        // We should always be able to set our playback settings if the sink is closed.
2009ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK,
2010ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung                "onOpenAudioSink: can't set playback rate on closed sink");
2011202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
20123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
20133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
20143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
20153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
2016179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
2017a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
2018a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? this : NULL,
2019faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    (audio_output_flags_t)pcmFlags,
2020faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    NULL,
20217665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                    doNotReconnect,
2022179652ee2a508361df1aa18e99000373886f0816Andy Hung                    frameCount);
2023202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
2024202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
20254d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia            mAudioSink->close();
2026f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
2027202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
2028202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
2029f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        mCurrentPcmInfo = info;
2030005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        if (!mPaused) { // for preview mode, don't start if paused
2031005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            mAudioSink->start();
2032005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        }
20333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
20343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
20353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
20363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
2037faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = false;
2038202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
20393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
20403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
20413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
20423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
20433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
2044f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
20453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
20463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
20479a3101b22b5115717faeac986b43fc6618fd3b30Wei Jiavoid NuPlayer::Renderer::onChangeAudioFormat(
20489a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        const sp<AMessage> &meta, const sp<AMessage> &notify) {
20499a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    sp<AMessage> format;
20509a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    CHECK(meta->findMessage("format", &format));
20519a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
20529a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    int32_t offloadOnly;
20539a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    CHECK(meta->findInt32("offload-only", &offloadOnly));
20549a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
20559a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    int32_t hasVideo;
20569a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    CHECK(meta->findInt32("has-video", &hasVideo));
20579a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
20589a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    uint32_t flags;
20599a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    CHECK(meta->findInt32("flags", (int32_t *)&flags));
20609a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
2061c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar    uint32_t isStreaming;
2062c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar    CHECK(meta->findInt32("isStreaming", (int32_t *)&isStreaming));
2063c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar
2064c387f2b719a1a26c8306f77d79cc9a6f26b36813Dhananjay Kumar    status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
20659a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
20669a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    if (err != OK) {
20679a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia        notify->setInt32("err", err);
20689a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    }
20699a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia    notify->post();
20709a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia}
20719a3101b22b5115717faeac986b43fc6618fd3b30Wei Jia
2072f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
2073f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
2074