NuPlayerRenderer.cpp revision c4ac8173f911aeac8d5006b19ba48fb51a865115
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"
22a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung#include <cutils/properties.h>
23f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
24f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ADebug.h>
255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h>
26a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu#include <media/stagefright/foundation/AUtils.h>
2735d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang#include <media/stagefright/foundation/AWakeLock.h>
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>
33dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
34095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar#include <inttypes.h>
35095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar
36f933441648ef6a71dee783d733aac17b9508b452Andreas Hubernamespace android {
37f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
38a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung/*
39a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung * Example of common configuration settings in shell script form
40a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
41a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager
42a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   adb shell setprop audio.offload.disable 1
43a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
44a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager
45a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   adb shell setprop audio.offload.video 1
46a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
47a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   #Use audio callbacks for PCM data
48a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung   adb shell setprop media.stagefright.audio.cbk 1
49a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
50288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung   #Use deep buffer for PCM data with video (it is generally enabled for audio-only)
51288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung   adb shell setprop media.stagefright.audio.deep 1
52288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung
53179652ee2a508361df1aa18e99000373886f0816Andy Hung   #Set size of buffers for pcm audio sink in msec (example: 1000 msec)
54179652ee2a508361df1aa18e99000373886f0816Andy Hung   adb shell setprop media.stagefright.audio.sink 1000
55179652ee2a508361df1aa18e99000373886f0816Andy Hung
56a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung * These configurations take effect for the next track played (not the current track).
57a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung */
58a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
59a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hungstatic inline bool getUseAudioCallbackSetting() {
60a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    return property_get_bool("media.stagefright.audio.cbk", false /* default_value */);
61a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung}
62a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
63179652ee2a508361df1aa18e99000373886f0816Andy Hungstatic inline int32_t getAudioSinkPcmMsSetting() {
64179652ee2a508361df1aa18e99000373886f0816Andy Hung    return property_get_int32(
65179652ee2a508361df1aa18e99000373886f0816Andy Hung            "media.stagefright.audio.sink", 500 /* default_value */);
66179652ee2a508361df1aa18e99000373886f0816Andy Hung}
67179652ee2a508361df1aa18e99000373886f0816Andy Hung
68f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink
69f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// is closed to allow the audio DSP to power down.
70a5d316fd802cfc92954527f27e6f32206a896113Eric Laurentstatic const int64_t kOffloadPauseMaxUs = 10000000ll;
71f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
72714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber// static
73f0e83644637bd05852c244df481f21a0d435ff66Andy Hungconst NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
74f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_CHANNEL_NONE,
75f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_OUTPUT_FLAG_NONE,
76f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_FORMAT_INVALID,
77f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0, // mNumChannels
78f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0 // mSampleRate
79f0e83644637bd05852c244df481f21a0d435ff66Andy Hung};
80f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
81f0e83644637bd05852c244df481f21a0d435ff66Andy Hung// static
82714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huberconst int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
83714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber
84f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::Renderer(
85f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<MediaPlayerBase::AudioSink> &sink,
86d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        const sp<AMessage> &notify,
87d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        uint32_t flags)
88f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    : mAudioSink(sink),
89f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNotify(notify),
90d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber      mFlags(flags),
91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNumFramesWritten(0),
92f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainAudioQueuePending(false),
93f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainVideoQueuePending(false),
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mAudioQueueGeneration(0),
95f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mVideoQueueGeneration(0),
967b15cb33847e6282ea8352c98894683b796127f3Wei Jia      mAudioDrainGeneration(0),
977b15cb33847e6282ea8352c98894683b796127f3Wei Jia      mVideoDrainGeneration(0),
987c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia      mAudioEOSGeneration(0),
993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar      mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
100a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mAudioFirstAnchorTimeMediaUs(-1),
101eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeMediaUs(-1),
102f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorNumFramesWritten(-1),
103a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mVideoLateByUs(0ll),
104bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasAudio(false),
105bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasVideo(false),
1067137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteAudio(false),
1077137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteVideo(false),
108bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mSyncQueues(false),
109714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber      mPaused(false),
110b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung      mPauseDrainAudioAllowedUs(0),
11109e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung      mVideoSampleReceived(false),
112f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong      mVideoRenderingStarted(false),
113cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mVideoRenderingStartGeneration(0),
114cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mAudioRenderingStartGeneration(0),
115b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung      mRenderingDataDelivered(false),
1162995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia      mLastAudioMediaTimeUs(-1),
117f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu      mAudioOffloadPauseTimeoutGeneration(0),
118faeb0f291330134dc4468359a36e099aae508449Ronghua Wu      mAudioTornDown(false),
119d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
120f0e83644637bd05852c244df481f21a0d435ff66Andy Hung      mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
121d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mTotalBuffersQueued(0),
12235d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mLastAudioBufferDrained(0),
123a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung      mUseAudioCallback(false),
12435d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mWakeLock(new AWakeLock()) {
1257b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock = new MediaClock;
1263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = mPlaybackSettings.mSpeed;
1273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
128f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
129f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
130f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::~Renderer() {
131bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
132bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->stop();
133bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->flush();
134bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->close();
135bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
138f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<ABuffer> &buffer,
141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
1421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
1437b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
1452d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
146f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
150f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
151f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
152f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1531d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
1547b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
157f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
158f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
1613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
1623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, rate);
1633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
1643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
1653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
1663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
1673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
1693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
1723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (rate.mSpeed == 0.f) {
1733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        onPause();
1743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // don't call audiosink's setPlaybackRate if pausing, as pitch does not
1753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // have to correspond to the any non-0 speed (e.g old speed). Keep
1763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // settings nonetheless, using the old speed, in case audiosink changes.
1773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AudioPlaybackRate newRate = rate;
1783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        newRate.mSpeed = mPlaybackSettings.mSpeed;
1793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mPlaybackSettings = newRate;
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return OK;
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
18327ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->setPlaybackRate(rate);
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err != OK) {
1863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return err;
1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = rate;
1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = rate.mSpeed;
1913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, rate);
2033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
20927ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->getPlaybackRate(rate);
2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGW("correcting mismatch in internal/external playback rate");
2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // get playback settings used by audiosink, as it may be
2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // slightly off due to audiosink not taking small changes.
2173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mPlaybackSettings = *rate;
2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mPaused) {
2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                rate->mSpeed = 0.f;
2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return err;
2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *rate = mPlaybackSettings;
2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
2293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, sync, videoFpsHint);
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // TODO: support sync sources
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return INVALID_OPERATION;
2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, sync, videoFps);
2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetSyncSettings(
2613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
2623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *sync = mSyncSettings;
2633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *videoFps = -1.f;
2643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2659816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
2669816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
2677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
268f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
2697b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
270f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
2717137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
2723b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia            clearAudioFirstAnchorTime_l();
2737b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioQueueGeneration;
2747b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
275f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
2767137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
2777b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoQueueGeneration;
2787b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoDrainGeneration;
279f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
2807b15cb33847e6282ea8352c98894683b796127f3Wei Jia
2817b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
2827b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mVideoLateByUs = 0;
2837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mSyncQueues = false;
284f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
285f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
2861d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatFlush, this);
287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
288f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
289f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
290f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
291f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
29228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
29328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
29428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
2951d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatDisableOffloadAudio, this))->post();
29628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
29728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
298a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
2991d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatEnableOffloadAudio, this))->post();
300a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
301a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
302b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
3031d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
304b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
305b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
306b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
3071d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
308b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
309b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
310c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
3111d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
312c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
313c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
314c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
315c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
3164ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia// Called on any threads without mLock acquired.
3177b15cb33847e6282ea8352c98894683b796127f3Wei Jiastatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
3184ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
3194ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (result == OK) {
3204ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        return result;
3214ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3224ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3234ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    // MediaClock has not started yet. Try to start it if possible.
3244ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    {
3254ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        Mutex::Autolock autoLock(mLock);
3264ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (mAudioFirstAnchorTimeMediaUs == -1) {
3274ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3284ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3294ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3304ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        AudioTimestamp ts;
3314ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        status_t res = mAudioSink->getTimestamp(ts);
3324ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (res != OK) {
3334ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3344ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3354ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3364ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        // AudioSink has rendered some frames.
3374ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowUs = ALooper::GetNowUs();
3384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowMediaUs = getPlayedOutAudioDurationUs(nowUs)
3394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia                + mAudioFirstAnchorTimeMediaUs;
3404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
3414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3439816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
344a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
345a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3467b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
3477b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioFirstAnchorTimeMediaUs = -1;
3487b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->setStartingTimeMedia(-1);
349a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
350a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3517b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
352a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
353a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
3547b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mMediaClock->setStartingTimeMedia(mediaUs);
355a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
356a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
357a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3587b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAnchorTime_l() {
3597b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->clearAnchor();
3607b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = -1;
3617b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorNumFramesWritten = -1;
362a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
363a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
3657b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
366a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
367a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
368a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
369a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
3707b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
371a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
373a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
374202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
3753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
3763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
3773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
378202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
379202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        bool *isOffloaded) {
3801d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
3813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
3823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
3833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
3843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
3853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
3873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
3883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
389202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
390202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    if (!response->findInt32("err", &err)) {
391202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
392202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
393202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
394202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
395202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
396202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
397202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
3983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
3993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
4011d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
4023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
4043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
4053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
407f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
408f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
4093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
4103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
4123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
4133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
4153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
4163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
4183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
4193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
4213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
4223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
423202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
4243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
426202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
427202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
4283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4293f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
4373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4383f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
4423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
4443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
448bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
449bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
450bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
451bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
452bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
453bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
455f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
4563ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            mDrainAudioQueuePending = false;
4573ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia
458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
4597b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
4607b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(true /* audio */)) {
461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
464078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
465078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
466078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
467078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
468078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
469078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
470078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
471078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
472078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
473078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
474078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
475078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
476078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
477d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                if (mPlaybackRate > 1.0f) {
478d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                    delayUs /= mPlaybackRate;
479d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                }
480078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
481078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
482078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
4837b15cb33847e6282ea8352c98894683b796127f3Wei Jia                Mutex::Autolock autoLock(mLock);
484bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                postDrainAudioQueue_l(delayUs / 2);
485078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
486f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
487f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
488f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
489f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
490f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
491f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
4927b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
4937b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
494f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
495f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
496f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
497f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
498f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
499f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
500f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5017b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
502f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
503f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
504f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
505d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
506d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
507d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
5087b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5097b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
510d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
511d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
512d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
513d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
5147b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
515d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
516d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
517d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
518f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
519f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
520f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
522f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
523f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
524f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
525f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
526f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5307c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        case kWhatEOS:
5317c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        {
5327c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            int32_t generation;
5337c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("audioEOSGeneration", &generation));
5347c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            if (generation != mAudioEOSGeneration) {
5357c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia                break;
5367c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            }
5377c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            status_t finalResult;
5387c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("finalResult", &finalResult));
5397c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            notifyEOS(true /* audio */, finalResult);
5407c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            break;
5417c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        }
5427c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia
5433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigPlayback:
5449816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        {
5453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate;
5483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &rate);
5493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigPlayback(rate);
5503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetPlaybackSettings:
5573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
5613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetPlaybackSettings(&rate);
5623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
5643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, rate);
5653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
5663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigSync:
5723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
5763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFpsHint;
5773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &sync, &videoFpsHint);
5783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigSync(sync, videoFpsHint);
5793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetSyncSettings:
5863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGV("kWhatGetSyncSettings");
5913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
5923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFps = -1.f;
5933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetSyncSettings(&sync, &videoFps);
5943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
5963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, sync, videoFps);
5973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
5983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6009816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            break;
6019816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        }
6029816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
603f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
604f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
605f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
606f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
607f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
608f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
609bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
610bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
611bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
612bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
613bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
614bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
615a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
616a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
617a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
618a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
619a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
620a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
621b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
622b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
623b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
624b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
625b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
626b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
627b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
628b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
629b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
630b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
631b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
632b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
633c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
634c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
635c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
636c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
637c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
638c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
639c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
640c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
641faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        case kWhatAudioTearDown:
6423a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
643faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToError);
6443a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
6453a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
6463a2956d148d81194e297408179e84a47a309ef48Wei Jia
647f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
648f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
649f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
6507b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
651f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
652f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
653f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
6540852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
655faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToTimeout);
65635d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang            mWakeLock->release();
657f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
658f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
659f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
660f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
661f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
662f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
663f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
664f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
665f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
666bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
667005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
668f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
669f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
670f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
671f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
672f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
673f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
674f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
675b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
676b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    if (mPaused) {
677b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
678b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        if (diffUs > delayUs) {
679b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            delayUs = diffUs;
680b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        }
681b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    }
682b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung
683f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
6841d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
6857b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", mAudioDrainGeneration);
686078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
687f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
688f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
6897b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
6907b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioRenderingStartGeneration = mAudioDrainGeneration;
6917b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mVideoRenderingStartGeneration = mVideoDrainGeneration;
692b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung    mRenderingDataDelivered = false;
693cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
694cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
6957b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
6967b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
6977b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
698b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        mRenderingDataDelivered = true;
699b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mPaused) {
700b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            return;
701b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
702cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
703cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
704cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
705cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
706cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
707cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
708cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
709cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
710cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
711bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
712bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
713bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
714bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
715bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
716bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
717bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
718bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
719bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
720bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
721bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
722bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
723bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
724bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
725bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
726bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
727bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
728bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
729a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_STREAM_END");
730bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
731bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
732bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
733bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
734bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
735bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
736a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
737faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            me->notifyAudioTearDown();
738bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
739bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
740bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
741bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
742bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
743bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
744bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
745bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
746bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
747bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
74885e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung    if (!mUseAudioCallback) {
749bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
750bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
751bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
752bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
753bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
754bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
7553e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
756a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
757bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
758a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        entry = &*mAudioQueue.begin();
759bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
760bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
761bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
762bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
763bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
764bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
765bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
7663e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
7673e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
768bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
769bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
770a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
7717b15cb33847e6282ea8352c98894683b796127f3Wei Jia            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
772bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
773bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
774bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
775bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
776bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
777bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
778bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
779bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
780bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
781bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
782bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
783bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
784bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
785bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
786bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
787bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
788bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
789bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
790bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
7917b15cb33847e6282ea8352c98894683b796127f3Wei Jia
7927b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
793bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
794bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
795f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
796f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
7979816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        int64_t nowMediaUs =
798c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia            mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
7997b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // we don't know how much data we are queueing for offloaded tracks.
8009816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
801f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
802f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
803a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // for non-offloaded audio, we need to compute the frames written because
804a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // there is no EVENT_STREAM_END notification. The frames written gives
805a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // an estimate on the pending played out duration.
806a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    if (!offloadingAudio()) {
807a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
808a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    }
809a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
810bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
8111d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        (new AMessage(kWhatStopAudioSink, this))->post();
812a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // As there is currently no EVENT_STREAM_END callback notification for
813a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // non-offloaded audio tracks, we need to post the EOS ourselves.
814a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        if (!offloadingAudio()) {
815a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            int64_t postEOSDelayUs = 0;
816a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            if (mAudioSink->needsTrailingPadding()) {
817a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
818a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            }
819a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: notifyEOS "
820a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
821a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
822a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
823a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        }
824bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
825bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
826bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
827bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8289da0ce44f228408d73a4dea0be972c785095dcccChong Zhangvoid NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
8299da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
8309da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    bool foundEOS = false;
8319da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    while (it != mAudioQueue.end()) {
8329da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        int32_t eos;
8339da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        QueueEntry *entry = &*it++;
8349da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        if (entry->mBuffer == NULL
8359da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
8369da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            itEOS = it;
8379da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            foundEOS = true;
8389da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8399da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8409da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8419da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    if (foundEOS) {
8429da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // post all replies before EOS and drop the samples
8439da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        for (it = mAudioQueue.begin(); it != itEOS; it++) {
8449da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            if (it->mBuffer == NULL) {
8459da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                // delay doesn't matter as we don't even have an AudioTrack
8469da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                notifyEOS(true /* audio */, it->mFinalResult);
8479da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            } else {
8489da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                it->mNotifyConsumed->post();
8499da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            }
8509da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8519da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        mAudioQueue.erase(mAudioQueue.begin(), itEOS);
8529da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8539da0ce44f228408d73a4dea0be972c785095dcccChong Zhang}
8549da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
855078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
85658d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    // do not drain audio during teardown as queued buffers may be invalid.
85758d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    if (mAudioTornDown) {
85858d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung        return false;
85958d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    }
860230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // TODO: This call to getPosition checks if AudioTrack has been created
861230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
862230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // CHECKs on getPosition will fail.
863230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // We still need to figure out why AudioTrack is not created when
864230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // this function is called. One possible reason could be leftover
865230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // audio. Another possible place is to check whether decoder
866230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // has received INFO_FORMAT_CHANGED as the first buffer since
867230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // AudioSink is opened there, and possible interactions with flush
868230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // immediately after start. Investigate error message
869230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // "vorbis_dsp_synthesis returned -135", along with RTSP.
870078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
8712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
8729da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // When getPosition fails, renderer will not reschedule the draining
8739da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // unless new samples are queued.
8749da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // If we have pending EOS (or "eos" marker for discontinuities), we need
8759da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // to post these now as NuPlayerDecoder might be waiting for it.
8769da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        drainAudioQueueUntilLastEOS();
8779da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8789da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        ALOGW("onDrainAudioQueue(): audio sink is not ready");
8792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
8802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
881078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
882230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia#if 0
883078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
884078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
885078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
886078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
887df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
888078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
8893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
890078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
891078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
892078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
893f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
894005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    uint32_t prevFramesWritten = mNumFramesWritten;
8957d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia    while (!mAudioQueue.empty()) {
896f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
897f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
898d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        mLastAudioBufferDrained = entry->mBufferOrdinal;
899d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
900f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
901f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
9025095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
9035095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
90406ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
9055095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
9065095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
9072995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
908f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
909f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
910f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
9113491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
9123491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
9133491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
9143491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
9153491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
9163491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
9173491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
918078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
919c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
920c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
92181636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        // ignore 0-sized buffer which could be EOS marker with no data
92281636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
923f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
924f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
925a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
926a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mediaTimeUs / 1E6);
927eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
928f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
929f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
930f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
931f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9327d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
9337d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                                            copy, false /* blocking */);
934a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
935202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
9367d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            if (written == WOULD_BLOCK) {
937df809479696725faf5d3424b11fa8a07bd94cb5eWei Jia                ALOGV("AudioSink write would block when writing %zu bytes", copy);
9387d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            } else {
9397d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
9407665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // This can only happen when AudioSink was opened with doNotReconnect flag set to
9417665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // true, in which case the NuPlayer will handle the reconnect.
942faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                notifyAudioTearDown();
9437d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            }
944202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
945a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
946f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
947a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
948f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mOffset == entry->mBuffer->size()) {
949f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
950f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
9519b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
952f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
953f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
954f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
955a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
956078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
957cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
9587b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
9597b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
960d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            int64_t maxTimeMedia;
961d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            maxTimeMedia =
962d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                mAnchorTimeMediaUs +
963d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
964d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                                * 1000LL * mAudioSink->msecsPerFrame());
965d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
966d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia
9677b15cb33847e6282ea8352c98894683b796127f3Wei Jia            notifyIfMediaRenderingStarted_l();
9687b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
96943c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
970a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
971a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
972a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
9737d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // AudioSink write is called in non-blocking mode.
9747d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // It may return with a short count when:
975a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
976a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
9777d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 2) The data to be copied exceeds the available buffer in AudioSink.
9787d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
9797d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
980a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
981a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
982a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
983a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
984a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
985a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
9867d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // (Case 2, 3, 4)
987a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
988a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
9897d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
990a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
991a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
992a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
993f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
994005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    // calculate whether we need to reschedule another write.
995005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    bool reschedule = !mAudioQueue.empty()
996005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            && (!mPaused
997005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung                || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
998005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
999005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1000005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    return reschedule;
1001f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1002f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10039816016afb2a13c6a866cd047d57020566a8b9a9Wei Jiaint64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
10049816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int32_t sampleRate = offloadingAudio() ?
10059816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
10064d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    if (sampleRate == 0) {
10074d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
10084d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        return 0;
10094d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    }
10109816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
10119816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
10129816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
10139816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
10149816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
101506ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
10169816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1017c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia    return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
10185095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
10195095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
1020a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
10219816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t realUs;
10229816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
10237b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If failed to get current position, e.g. due to audio clock is
10247b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // not ready, then just play out video immediately without delay.
1025eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
1026a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
10279816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return realUs;
1028a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
1029a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1030eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
10317b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1032eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
1033eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
1034eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
1035eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
1036eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
10377b15cb33847e6282ea8352c98894683b796127f3Wei Jia    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
10384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
10394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    AudioTimestamp ts;
10404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t res = mAudioSink->getTimestamp(ts);
10414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (res == OK) {
10424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowUs = ALooper::GetNowUs();
10434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
10444ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
10454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
10468edb3f85f58e8738582e8f9abbc018c85100b712Wei Jia    mAnchorNumFramesWritten = mNumFramesWritten;
10477b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = mediaTimeUs;
1048eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
1049eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
10507b15cb33847e6282ea8352c98894683b796127f3Wei Jia// Called without mLock acquired.
10517b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue() {
1052fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
10537b15cb33847e6282ea8352c98894683b796127f3Wei Jia            || getSyncQueues()
1054fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
1055f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1056f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1057f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1058f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1059f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1060f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1061f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1062f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
1063f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10641d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
10657b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
1066f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1067f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
1068f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
1069dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
1070dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
1071dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
1072dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
1073dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1074dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
1075dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
1076dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
1077dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
1078d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
1079d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1080dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
1081f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1082f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
1083f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1084f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10857b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
10867b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
10877b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (mAnchorTimeMediaUs < 0) {
10887b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
10897b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mAnchorTimeMediaUs = mediaTimeUs;
10907b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = nowUs;
10917b15cb33847e6282ea8352c98894683b796127f3Wei Jia            } else {
10927b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
10937b15cb33847e6282ea8352c98894683b796127f3Wei Jia            }
1094f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1095f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
10967b15cb33847e6282ea8352c98894683b796127f3Wei Jia            // smooth out videos >= 10fps
10977b15cb33847e6282ea8352c98894683b796127f3Wei Jia            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1098f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
1099d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
1100d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
1101d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
1102d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
1103d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
1104d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
1105d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
1106d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int64_t postDelayUs = 500000;
1107d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1108d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
1109d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
1110d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
1111d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
1112d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
1113d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            ALOGI("possible video time jump of %dms, retrying in %dms",
1114d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                    (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1115d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
1116d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
1117d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
1118f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1119f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1120dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1121dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1122dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1123dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
1124dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1125095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
1126dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
1127dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1128f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1129f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
1130f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1131f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1132f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
1133f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1134f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1135f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
1138f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
1140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
1141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1142c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
1143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
1145f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
11463fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1147a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1150f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1151a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t nowUs = -1;
1152d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
11532995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia    int64_t mediaTimeUs = -1;
1154d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
1155d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1156d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
1157d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1158d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
1159a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        nowUs = ALooper::GetNowUs();
1160a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1161d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
1162f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1163fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
11643fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1165fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1166a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        if (nowUs == -1) {
1167a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            nowUs = ALooper::GetNowUs();
1168a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        }
1169a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
1170fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
1171fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
1172fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
1173fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
11746d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
1175fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
11769816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            int64_t mediaUs = 0;
11779816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
1178fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
1179fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
11809816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia                    mediaUs) / 1E6);
11812995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia
11822995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            if (!(mFlags & FLAG_REAL_TIME)
11832995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mLastAudioMediaTimeUs != -1
11842995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mediaTimeUs > mLastAudioMediaTimeUs) {
11852995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // If audio ends before video, video continues to drive media clock.
11862995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // Also smooth out videos >= 10fps.
11872995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
11882995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            }
1189fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
1190078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
1191a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1192eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
1193a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
1194a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
11957b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
11967b15cb33847e6282ea8352c98894683b796127f3Wei Jia            clearAnchorTime_l();
119749966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
1198078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
1199f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1200dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
1201683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
1202f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
1203f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
1204f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
120543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1206fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
1207f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
1208fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1209fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
1210fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
1211fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
1212fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
12137b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
12147b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
1215fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
1216f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1217f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1218f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
1219f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
1220f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
1221f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
1222f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
1223f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
12245095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
12257c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    if (audio && delayUs > 0) {
12267c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        sp<AMessage> msg = new AMessage(kWhatEOS, this);
12277c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
12287c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("finalResult", finalResult);
12297c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->post(delayUs);
12307c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        return;
12317c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    }
1232f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1233f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
1234f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1235c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
12365095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
1237f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1238f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1239faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::notifyAudioTearDown() {
1240faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    (new AMessage(kWhatAudioTearDown, this))->post();
12413a2956d148d81194e297408179e84a47a309ef48Wei Jia}
12423a2956d148d81194e297408179e84a47a309ef48Wei Jia
1243f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1244f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1245f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1246f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
12477b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
12487b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return;
12497b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
12507b15cb33847e6282ea8352c98894683b796127f3Wei Jia
12517b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (audio) {
12527b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasAudio = true;
12537b15cb33847e6282ea8352c98894683b796127f3Wei Jia    } else {
12547b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasVideo = true;
12557b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
1256a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1257a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
1258dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
1259dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
1260dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
1261dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
1262bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
1263bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
12642d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
12652d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
1266f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1267f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1268f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1269f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1270f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1271f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
1272f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
1273f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1274f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
1275d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
1276f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1277f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
12787b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1279f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1280bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1281f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1282f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
12837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1284f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1285f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
12867b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1287cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1288cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1289cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1290f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1291cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1292cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1293f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1294cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1295cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
1296bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
1297cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1298cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1299f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1300cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
1301cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
1302cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
1303cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
1304cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
1305cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
1306f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1307cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
1310cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1311cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
1312cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
1313cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
1314cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1315cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
1316cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
1317cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1318f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1319cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1320bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
1321f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1322f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1323bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
1324f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
1325f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1326f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1327f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1328f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
1329f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1330f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
1331bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1332f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1333f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1334f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
13357b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.unlock();
13367b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
13377b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.lock();
1338f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1339f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1340f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1341f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1342f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1343f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1344f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13457b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
1346f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1347f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1348f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1349f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1350f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1351f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1352f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1353f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1354f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1355f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1356f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
13577b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1358b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1359bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1360b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1361f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1362bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1363f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
13647b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (mVideoQueue.empty() && getSyncQueues()) {
13657b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1366bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1367b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1368f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
13697b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1370f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1371f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1372f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1373f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
13747137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1375f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1376f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
137728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
13787b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
137928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
13807137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
13817137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
13822995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = -1;
138328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
13847137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
13857137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
138628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
138728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
13887b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If we're currently syncing the queues, i.e. dropping audio while
13897b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // aligning the first audio/video buffer times and only one of the
13907b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // two queues has data, we may starve that queue by not requesting
13917b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // more buffers from the decoder. If the other source then encounters
13927b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // a discontinuity that leads to flushing, we'll never find the
13937b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // corresponding discontinuity on the other queue.
13947b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // Therefore we'll stop syncing the queues if at least one of them
13957b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // is flushed.
13967b15cb33847e6282ea8352c98894683b796127f3Wei Jia        syncQueuesDone_l();
13977b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
1398bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
1399f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1400cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1401f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1402bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1403bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1404bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1405f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14067b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
14077c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            ++mAudioEOSGeneration;
14087b15cb33847e6282ea8352c98894683b796127f3Wei Jia            prepareForMediaRenderingStart_l();
140928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1410a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            // the frame count will be reset after flush.
1411a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            clearAudioFirstAnchorTime_l();
141228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1413f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1414f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1415cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1416bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1417bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1418bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
141985e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            if (!mPaused) {
142085e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                mAudioSink->start();
142185e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            }
14229e7ed3315298b42db485963b182a572e9ab42f9fWei Jia        } else {
14239e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->pause();
14249e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->flush();
14259e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // Call stop() to signal to the AudioSink to completely fill the
14269e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // internal buffer before resuming playback.
1427b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            // FIXME: this is ignored after flush().
14289e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->stop();
1429b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            if (mPaused) {
1430b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // Race condition: if renderer is paused and audio sink is stopped,
1431b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // we need to make sure that the audio track buffer fully drains
1432b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // before delivering data.
1433b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // FIXME: remove this if we can detect if stop() is complete.
1434b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1435b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1436b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            } else {
14379e7ed3315298b42db485963b182a572e9ab42f9fWei Jia                mAudioSink->start();
14389e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            }
14399e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mNumFramesWritten = 0;
1440bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1441f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1442f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1443f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1444f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1445cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1446c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1447c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1448c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1449c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
14507b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
14517b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
14527b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
1453f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1455fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
14567137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
14577137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
14587137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
14597137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1462f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1464f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1465f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1466f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1467f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1468f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1469f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1471f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1472f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1473f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1475f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1476f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1477f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1478f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1479f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1480f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1481f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14827b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::dropBufferIfStale(
1483f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
14847b15cb33847e6282ea8352c98894683b796127f3Wei Jia    int32_t queueGeneration;
14857b15cb33847e6282ea8352c98894683b796127f3Wei Jia    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
1486f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14877b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (queueGeneration == getQueueGeneration(audio)) {
1488f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1489f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1490f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1491f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1492f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1493f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1494f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1495f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1496f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1497f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1498f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14993831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1500bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1501bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1502bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
15033831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
15043831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
15057b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
15067b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
15077b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAnchorNumFramesWritten = -1;
15087b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
15094110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
15104110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
15114110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
15124110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
15133831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
15143831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1515bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1516bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1517bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
15187b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1519e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1520e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1521e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1522bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1523bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1524a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1525a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1526a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
15277b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1528e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1529e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1530e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1531a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1532a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1533b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
15348592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
15358592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
15368592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
15376d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar
153828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
153928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
1540005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        // we do not increment audio drain generation so that we fill audio buffer during pause.
15417b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
15427b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
154373ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
15449816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(0.0);
154528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1546b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
154728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1548b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1549cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1550b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (mHasAudio) {
1551b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        mAudioSink->pause();
1552f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        startAudioOffloadPauseTimeout();
1553b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1554b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
15556d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar    ALOGV("now paused audio queue has %zu entries, video has %zu entries",
1556ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1557b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1558b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1559b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1560b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1561b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1562b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1563b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1564b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (mHasAudio) {
1565f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        cancelAudioOffloadPauseTimeout();
156697c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        status_t err = mAudioSink->start();
156797c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        if (err != OK) {
156858d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung            ALOGE("cannot start AudioSink err %d", err);
156997c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent            notifyAudioTearDown();
157097c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        }
1571b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1572b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
15737b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
15747b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
15757b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mPaused = false;
1576b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        // rendering started message may have been delayed if we were paused.
1577b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mRenderingDataDelivered) {
1578b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            notifyIfMediaRenderingStarted_l();
1579b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
15803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // configure audiosink as we did not do it when pausing
158127ea08e3811dc8057685258af52a7d40474eba16Wei Jia        if (mAudioSink != NULL && mAudioSink->ready()) {
15823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mAudioSink->setPlaybackRate(mPlaybackSettings);
15833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
15843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
15859816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(mPlaybackRate);
1586b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
15877b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (!mAudioQueue.empty()) {
15887b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainAudioQueue_l();
15897b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
1590b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1591b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1592b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
15937b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1594b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1595b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1596b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1597c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1598c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1599c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1600c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1601c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1602c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1603c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
16047b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
16057b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16067b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
16077b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16087b15cb33847e6282ea8352c98894683b796127f3Wei Jia
16097b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
16107b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16117b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
16127b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16137b15cb33847e6282ea8352c98894683b796127f3Wei Jia
16147b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::getSyncQueues() {
16157b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16167b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return mSyncQueues;
16177b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16187b15cb33847e6282ea8352c98894683b796127f3Wei Jia
1619faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1620faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    if (mAudioTornDown) {
1621f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1622f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1623faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = true;
1624f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1625a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
16261a5c859016e743779e4db25855390b3ce523cd48Robert Shih    sp<AMessage> notify = mNotify->dup();
16271a5c859016e743779e4db25855390b3ce523cd48Robert Shih    if (getCurrentPosition(&currentPositionUs) == OK) {
16281a5c859016e743779e4db25855390b3ce523cd48Robert Shih        notify->setInt64("positionUs", currentPositionUs);
162928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
163006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
16313a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
16323a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
16333a2956d148d81194e297408179e84a47a309ef48Wei Jia
1634faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    notify->setInt32("what", kWhatAudioTearDown);
16350852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
16363a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
16373a2956d148d81194e297408179e84a47a309ef48Wei Jia}
16383a2956d148d81194e297408179e84a47a309ef48Wei Jia
1639f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1640f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
164135d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->acquire();
16421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
16437b15cb33847e6282ea8352c98894683b796127f3Wei Jia        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
1644f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1645f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1646f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1647f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1648f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1649f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
165035d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->release(true);
1651f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        ++mAudioOffloadPauseTimeoutGeneration;
1652f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1653f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1654f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1655202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
16563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
16573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
16583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
16593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        uint32_t flags) {
16603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
16613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
16623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
16633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
16653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
16663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
16683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
16693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
16703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
16713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
16723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
16743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
16753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
16773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
16783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
16793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
16803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
16813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
16833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
16843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
16853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
16863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
16873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
16883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
16893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
16913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt32("bit-rate", &avgBitRate);
16923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
16933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
16943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
16953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
16963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
16973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
16983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
16993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
17003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
17013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
17033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
17043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
17053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
17063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
17073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
17083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
17093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
17103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
17113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
17123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.is_streaming = true;
17133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
17153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
17163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1717202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
17183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
1719f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1720f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
17213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1722d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1723d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1724d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
17253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
17263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
1727a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
17283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
17293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
17303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
17313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
17323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
1733179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
17343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
17353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1736d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
17373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
17383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
17403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                err = mAudioSink->setPlaybackRate(mPlaybackSettings);
17413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
17423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
17433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
17443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
17453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
17463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
17473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
17483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
17493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
17503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
175185e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                if (!mPaused) { // for preview mode, don't start if paused
175285e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                    err = mAudioSink->start();
175385e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                }
17543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
17553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
17563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
17573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
17583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
17593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
17603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
17613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
17623ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            } else {
17633ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                mUseAudioCallback = true;  // offload mode transfers data through callback
17643ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
17653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
17663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
17673b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
17683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
17693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1770d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1771d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1772f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
1773f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        const PcmInfo info = {
1774f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_channel_mask_t)channelMask,
1775f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_output_flags_t)pcmFlags,
1776f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1777f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                numChannels,
1778f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                sampleRate
1779f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        };
1780f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1781f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            ALOGV("openAudioSink: no change in pcm mode");
1782f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            // no change from previous configuration, everything ok.
1783f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            return OK;
1784f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        }
1785f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
17863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
17873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
17883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1789a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // Note: It is possible to set up the callback, but not use it to send audio data.
1790a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // This requires a fix in AudioSink to explicitly specify the transfer mode.
1791a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mUseAudioCallback = getUseAudioCallbackSetting();
17923ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        if (mUseAudioCallback) {
17933ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
17943ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        }
1795179652ee2a508361df1aa18e99000373886f0816Andy Hung
1796179652ee2a508361df1aa18e99000373886f0816Andy Hung        // Compute the desired buffer size.
1797179652ee2a508361df1aa18e99000373886f0816Andy Hung        // For callback mode, the amount of time before wakeup is about half the buffer size.
1798179652ee2a508361df1aa18e99000373886f0816Andy Hung        const uint32_t frameCount =
1799179652ee2a508361df1aa18e99000373886f0816Andy Hung                (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1800179652ee2a508361df1aa18e99000373886f0816Andy Hung
18017665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
18027665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // AudioSink. We don't want this when there's video because it will cause a video seek to
18037665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // the previous I frame. But we do want this when there's only audio because it will give
18047665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // NuPlayer a chance to switch from non-offload mode to offload mode.
18057665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // So we only set doNotReconnect when there's no video.
18067665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        const bool doNotReconnect = !hasVideo;
1807202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
18083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
18093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
18103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
18113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
1812179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
1813a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1814a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? this : NULL,
1815faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    (audio_output_flags_t)pcmFlags,
1816faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    NULL,
18177665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                    doNotReconnect,
1818179652ee2a508361df1aa18e99000373886f0816Andy Hung                    frameCount);
18193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
18203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            err = mAudioSink->setPlaybackRate(mPlaybackSettings);
18213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1822202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
1823202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
18244d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia            mAudioSink->close();
1825f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1826202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
1827202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
1828f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        mCurrentPcmInfo = info;
1829005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        if (!mPaused) { // for preview mode, don't start if paused
1830005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            mAudioSink->start();
1831005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        }
18323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
18333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
18343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
18353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
1836faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = false;
1837202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
18383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
18393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
18413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
18423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1843f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
18443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
18453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
1846f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
1847f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1848