NuPlayerRenderer.cpp revision 12b6265f1d4be368957f91104d5210cf604ac4cc
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
7212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia// Maximum allowed delay from AudioSink, 1.5 seconds.
7312b6265f1d4be368957f91104d5210cf604ac4ccWei Jiastatic const int64_t kMaxAllowedAudioSinkDelayUs = 1500000ll;
7412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia
75714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber// static
76f0e83644637bd05852c244df481f21a0d435ff66Andy Hungconst NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
77f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_CHANNEL_NONE,
78f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_OUTPUT_FLAG_NONE,
79f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        AUDIO_FORMAT_INVALID,
80f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0, // mNumChannels
81f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        0 // mSampleRate
82f0e83644637bd05852c244df481f21a0d435ff66Andy Hung};
83f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
84f0e83644637bd05852c244df481f21a0d435ff66Andy Hung// static
85714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huberconst int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
86714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber
87f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::Renderer(
88f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<MediaPlayerBase::AudioSink> &sink,
89d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        const sp<AMessage> &notify,
90d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        uint32_t flags)
91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    : mAudioSink(sink),
92f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNotify(notify),
93d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber      mFlags(flags),
94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mNumFramesWritten(0),
95f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainAudioQueuePending(false),
96f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mDrainVideoQueuePending(false),
97f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mAudioQueueGeneration(0),
98f933441648ef6a71dee783d733aac17b9508b452Andreas Huber      mVideoQueueGeneration(0),
997b15cb33847e6282ea8352c98894683b796127f3Wei Jia      mAudioDrainGeneration(0),
1007b15cb33847e6282ea8352c98894683b796127f3Wei Jia      mVideoDrainGeneration(0),
1017c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia      mAudioEOSGeneration(0),
1023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar      mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
103a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mAudioFirstAnchorTimeMediaUs(-1),
104eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu      mAnchorTimeMediaUs(-1),
105f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar      mAnchorNumFramesWritten(-1),
106a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu      mVideoLateByUs(0ll),
107bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasAudio(false),
108bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mHasVideo(false),
1097137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteAudio(false),
1107137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang      mNotifyCompleteVideo(false),
111bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber      mSyncQueues(false),
112714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber      mPaused(false),
113b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung      mPauseDrainAudioAllowedUs(0),
11409e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung      mVideoSampleReceived(false),
115f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong      mVideoRenderingStarted(false),
116cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mVideoRenderingStartGeneration(0),
117cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar      mAudioRenderingStartGeneration(0),
118b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung      mRenderingDataDelivered(false),
1192995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia      mLastAudioMediaTimeUs(-1),
120f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu      mAudioOffloadPauseTimeoutGeneration(0),
121faeb0f291330134dc4468359a36e099aae508449Ronghua Wu      mAudioTornDown(false),
122d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
123f0e83644637bd05852c244df481f21a0d435ff66Andy Hung      mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
124d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar      mTotalBuffersQueued(0),
12535d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mLastAudioBufferDrained(0),
126a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung      mUseAudioCallback(false),
12735d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang      mWakeLock(new AWakeLock()) {
1287b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock = new MediaClock;
1293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = mPlaybackSettings.mSpeed;
1303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
131f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
132f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
133f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::~Renderer() {
134bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
135bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->stop();
136bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->flush();
137bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        mAudioSink->close();
138bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
141f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer(
142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio,
143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<ABuffer> &buffer,
144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        const sp<AMessage> &notifyConsumed) {
1451d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
1467b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
1482d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setMessage("notifyConsumed", notifyConsumed);
150f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
151f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
152f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
153f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
154f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK_NE(finalResult, (status_t)OK);
155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1561d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
1577b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("queueGeneration", getQueueGeneration(audio));
158f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("finalResult", finalResult);
160f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
161f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
162f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) {
1643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
1653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, rate);
1663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
1673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
1683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
1693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
1703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
1723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) {
1753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (rate.mSpeed == 0.f) {
1763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        onPause();
1773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // don't call audiosink's setPlaybackRate if pausing, as pitch does not
1783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // have to correspond to the any non-0 speed (e.g old speed). Keep
1793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // settings nonetheless, using the old speed, in case audiosink changes.
1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AudioPlaybackRate newRate = rate;
1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        newRate.mSpeed = mPlaybackSettings.mSpeed;
1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        mPlaybackSettings = newRate;
1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return OK;
1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
18627ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->setPlaybackRate(rate);
1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err != OK) {
1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            return err;
1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackSettings = rate;
1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mPlaybackRate = rate.mSpeed;
1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mMediaClock->setPlaybackRate(mPlaybackRate);
1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, rate);
2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
21227ea08e3811dc8057685258af52a7d40474eba16Wei Jia    if (mAudioSink != NULL && mAudioSink->ready()) {
2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        status_t err = mAudioSink->getPlaybackRate(rate);
2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                ALOGW("correcting mismatch in internal/external playback rate");
2173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // get playback settings used by audiosink, as it may be
2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            // slightly off due to audiosink not taking small changes.
2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mPlaybackSettings = *rate;
2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (mPaused) {
2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                rate->mSpeed = 0.f;
2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return err;
2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *rate = mPlaybackSettings;
2283a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    writeToAMessage(msg, sync, videoFpsHint);
2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) {
2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (sync.mSource != AVSYNC_SOURCE_DEFAULT) {
2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        return BAD_VALUE;
2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    // TODO: support sync sources
2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return INVALID_OPERATION;
2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) {
2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    sp<AMessage> response;
2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    status_t err = msg->postAndAwaitResponse(&response);
2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    if (err == OK && response != NULL) {
2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        CHECK(response->findInt32("err", &err));
2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(response, sync, videoFps);
2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    }
2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return err;
2613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar}
2623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
2633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetSyncSettings(
2643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
2653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *sync = mSyncSettings;
2663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    *videoFps = -1.f;
2673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    return OK;
2689816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
2699816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
2707137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
271f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    {
2727b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
273f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (audio) {
2747137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio |= notifyComplete;
2753b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia            clearAudioFirstAnchorTime_l();
2767b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioQueueGeneration;
2777b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
278f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        } else {
2797137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo |= notifyComplete;
2807b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoQueueGeneration;
2817b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mVideoDrainGeneration;
282f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
2837b15cb33847e6282ea8352c98894683b796127f3Wei Jia
2847b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
2857b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mVideoLateByUs = 0;
2867b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mSyncQueues = false;
287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
288f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
2891d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatFlush, this);
290f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->setInt32("audio", static_cast<int32_t>(audio));
291f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    msg->post();
292f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
293f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
294f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() {
29528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
29628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
29728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() {
2981d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatDisableOffloadAudio, this))->post();
29928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia}
30028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
301a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() {
3021d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatEnableOffloadAudio, this))->post();
303a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
304a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
305b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() {
3061d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
307b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
308b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
309b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() {
3101d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
311b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
312b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
313c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) {
3141d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
315c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->setFloat("frame-rate", fps);
316c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    msg->post();
317c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
318c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
3194ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia// Called on any threads without mLock acquired.
3207b15cb33847e6282ea8352c98894683b796127f3Wei Jiastatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
3214ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
3224ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (result == OK) {
3234ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        return result;
3244ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3254ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3264ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    // MediaClock has not started yet. Try to start it if possible.
3274ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    {
3284ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        Mutex::Autolock autoLock(mLock);
3294ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (mAudioFirstAnchorTimeMediaUs == -1) {
3304ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3314ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3324ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3334ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        AudioTimestamp ts;
3344ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        status_t res = mAudioSink->getTimestamp(ts);
3354ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        if (res != OK) {
3364ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia            return result;
3374ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        }
3384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        // AudioSink has rendered some frames.
3404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowUs = ALooper::GetNowUs();
341d855a738735a3df8863b486f5d3b5e404cef15c1Wei Jia        int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs)
3424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia                + mAudioFirstAnchorTimeMediaUs;
3434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, -1);
3444ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
3454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
3469816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
347a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
348a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3497b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
3507b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioFirstAnchorTimeMediaUs = -1;
3517b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->setStartingTimeMedia(-1);
352a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
353a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3547b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
355a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mAudioFirstAnchorTimeMediaUs == -1) {
356a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        mAudioFirstAnchorTimeMediaUs = mediaUs;
3577b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mMediaClock->setStartingTimeMedia(mediaUs);
358a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
359a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
360a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
3617b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAnchorTime_l() {
3627b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mMediaClock->clearAnchor();
3637b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = -1;
3647b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorNumFramesWritten = -1;
365a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
366a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
367a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
3687b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
369a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    mVideoLateByUs = lateUs;
370a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
371a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() {
3737b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
374a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    return mVideoLateByUs;
375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
376a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
377202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink(
3783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
3793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
3803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
381202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        uint32_t flags,
382202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        bool *isOffloaded) {
3831d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
3843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setMessage("format", format);
3853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("offload-only", offloadOnly);
3863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("has-video", hasVideo);
3873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->setInt32("flags", flags);
3883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
3893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
3903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
3913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
392202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    int32_t err;
393202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    if (!response->findInt32("err", &err)) {
394202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        err = INVALID_OPERATION;
395202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    } else if (err == OK && isOffloaded != NULL) {
396202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        int32_t offload;
397202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        CHECK(response->findInt32("offload", &offload));
398202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        *isOffloaded = (offload != 0);
399202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    }
400202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return err;
4013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() {
4041d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
4053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    sp<AMessage> response;
4073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    msg->postAndAwaitResponse(&response);
4083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
4093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
410f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
411f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    switch (msg->what()) {
4123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatOpenAudioSink:
4133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> format;
4153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findMessage("format", &format));
4163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t offloadOnly;
4183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("offload-only", &offloadOnly));
4193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t hasVideo;
4213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("has-video", &hasVideo));
4223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            uint32_t flags;
4243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
4253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
426202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
4273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
429202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("err", err);
430202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            response->setInt32("offload", offloadingAudio());
4313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4323f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        case kWhatCloseAudioSink:
4403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        {
4413f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
4423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
4433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onCloseAudioSink();
4453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
4463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            sp<AMessage> response = new AMessage;
4473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            response->postReply(replyID);
4483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            break;
4493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
4503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
451bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatStopAudioSink:
452bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
453bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->stop();
454bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
455bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
456bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
457f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainAudioQueue:
458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
4593ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            mDrainAudioQueuePending = false;
4603ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia
461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
4627b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
4637b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(true /* audio */)) {
464f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
465f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
466f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
467078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            if (onDrainAudioQueue()) {
468078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPlayed;
469078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
470078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                         (status_t)OK);
471078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
472078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                uint32_t numFramesPendingPlayout =
473078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mNumFramesWritten - numFramesPlayed;
474078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
475078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // This is how long the audio sink will have data to
476078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // play back.
477078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                int64_t delayUs =
478078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                    mAudioSink->msecsPerFrame()
479078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                        * numFramesPendingPlayout * 1000ll;
480d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                if (mPlaybackRate > 1.0f) {
481d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                    delayUs /= mPlaybackRate;
482d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia                }
483078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
484078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // Let's give it more data after about half that time
485078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber                // has elapsed.
4867b15cb33847e6282ea8352c98894683b796127f3Wei Jia                Mutex::Autolock autoLock(mLock);
487bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia                postDrainAudioQueue_l(delayUs / 2);
488078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            }
489f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
490f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
491f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
492f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatDrainVideoQueue:
493f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
494f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int32_t generation;
4957b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
4967b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
497f933441648ef6a71dee783d733aac17b9508b452Andreas Huber                break;
498f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            }
499f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
500f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mDrainVideoQueuePending = false;
501f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
502f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onDrainVideoQueue();
503f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5047b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
505f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
506f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
507f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
508d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        case kWhatPostDrainVideoQueue:
509d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        {
510d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            int32_t generation;
5117b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
5127b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (generation != getDrainGeneration(false /* audio */)) {
513d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                break;
514d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
515d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
516d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = false;
5177b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainVideoQueue();
518d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            break;
519d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
520d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueBuffer:
522f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
523f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueBuffer(msg);
524f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
525f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
526f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatQueueEOS:
528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onQueueEOS(msg);
530f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
531f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
532f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
5337c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        case kWhatEOS:
5347c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        {
5357c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            int32_t generation;
5367c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("audioEOSGeneration", &generation));
5377c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            if (generation != mAudioEOSGeneration) {
5387c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia                break;
5397c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            }
5407c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            status_t finalResult;
5417c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            CHECK(msg->findInt32("finalResult", &finalResult));
5427c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            notifyEOS(true /* audio */, finalResult);
5437c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            break;
5447c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        }
5457c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia
5463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigPlayback:
5479816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        {
5483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate;
5513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &rate);
5523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigPlayback(rate);
5533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetPlaybackSettings:
5603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT;
5643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetPlaybackSettings(&rate);
5653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
5673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, rate);
5683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
5693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatConfigSync:
5753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
5793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFpsHint;
5803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            readFromAMessage(msg, &sync, &videoFpsHint);
5813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onConfigSync(sync, videoFpsHint);
5823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
5843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
5853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            break;
5863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
5873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        case kWhatGetSyncSettings:
5893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        {
5903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AReplyToken> replyID;
5913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
5923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
5933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGV("kWhatGetSyncSettings");
5943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            AVSyncSettings sync;
5953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            float videoFps = -1.f;
5963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            status_t err = onGetSyncSettings(&sync, &videoFps);
5973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            sp<AMessage> response = new AMessage;
5983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
5993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                writeToAMessage(response, sync, videoFps);
6003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
6013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->setInt32("err", err);
6023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            response->postReply(replyID);
6039816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            break;
6049816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        }
6059816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
606f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        case kWhatFlush:
607f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        {
608f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            onFlush(msg);
609f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
610f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
611f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
612bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case kWhatDisableOffloadAudio:
613bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
614bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            onDisableOffloadAudio();
615bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
616bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
617bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
618a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        case kWhatEnableOffloadAudio:
619a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        {
620a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            onEnableOffloadAudio();
621a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu            break;
622a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu        }
623a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
624b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatPause:
625b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
626b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onPause();
627b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
628b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
629b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
630b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        case kWhatResume:
631b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        {
632b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            onResume();
633b408222bd9479c291874b607acae1425d6154fe7Andreas Huber            break;
634b408222bd9479c291874b607acae1425d6154fe7Andreas Huber        }
635b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
636c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        case kWhatSetVideoFrameRate:
637c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        {
638c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            float fps;
639c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            CHECK(msg->findFloat("frame-rate", &fps));
640c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            onSetVideoFrameRate(fps);
641c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            break;
642c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
643c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
644faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        case kWhatAudioTearDown:
6453a2956d148d81194e297408179e84a47a309ef48Wei Jia        {
646faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToError);
6473a2956d148d81194e297408179e84a47a309ef48Wei Jia            break;
6483a2956d148d81194e297408179e84a47a309ef48Wei Jia        }
6493a2956d148d81194e297408179e84a47a309ef48Wei Jia
650f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        case kWhatAudioOffloadPauseTimeout:
651f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        {
652f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            int32_t generation;
6537b15cb33847e6282ea8352c98894683b796127f3Wei Jia            CHECK(msg->findInt32("drainGeneration", &generation));
654f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            if (generation != mAudioOffloadPauseTimeoutGeneration) {
655f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu                break;
656f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            }
6570852917279f79a94907e9906d0533ae409a30f6aRonghua Wu            ALOGV("Audio Offload tear down due to pause timeout.");
658faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            onAudioTearDown(kDueToTimeout);
65935d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang            mWakeLock->release();
660f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu            break;
661f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        }
662f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
663f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        default:
664f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            TRESPASS();
665f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            break;
666f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
667f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
668f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
669bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
670005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) {
671f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
672f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
673f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
674f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mAudioQueue.empty()) {
675f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
676f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
677f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
678b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
679b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    if (mPaused) {
680b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
681b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        if (diffUs > delayUs) {
682b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            delayUs = diffUs;
683b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung        }
684b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung    }
685b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung
686f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainAudioQueuePending = true;
6871d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
6887b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", mAudioDrainGeneration);
689078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    msg->post(delayUs);
690f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
691f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
6927b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
6937b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAudioRenderingStartGeneration = mAudioDrainGeneration;
6947b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mVideoRenderingStartGeneration = mVideoDrainGeneration;
695b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung    mRenderingDataDelivered = false;
696cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
697cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
6987b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
6997b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
7007b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
701b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        mRenderingDataDelivered = true;
702b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mPaused) {
703b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            return;
704b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
705cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mVideoRenderingStartGeneration = -1;
706cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        mAudioRenderingStartGeneration = -1;
707cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
708cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        sp<AMessage> notify = mNotify->dup();
709cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->setInt32("what", kWhatMediaRenderingStart);
710cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar        notify->post();
711cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    }
712cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar}
713cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
714bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static
715bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback(
716bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink * /* audioSink */,
717bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *buffer,
718bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t size,
719bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        void *cookie,
720bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        MediaPlayerBase::AudioSink::cb_event_t event) {
721bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie;
722bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
723bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    switch (event) {
724bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER:
725bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
726bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            return me->fillAudioBuffer(buffer, size);
727bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
728bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
729bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
730bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
731bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
732a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_STREAM_END");
733bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            me->notifyEOS(true /* audio */, ERROR_END_OF_STREAM);
734bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
735bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
736bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
737bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
738bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
739a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("AudioSink::CB_EVENT_TEAR_DOWN");
740faeb0f291330134dc4468359a36e099aae508449Ronghua Wu            me->notifyAudioTearDown();
741bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
742bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
743bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
744bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
745bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return 0;
746bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
747bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
748bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
749bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
750bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
75185e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung    if (!mUseAudioCallback) {
752bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return 0;
753bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
754bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
755bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    bool hasEOS = false;
756bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
757bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    size_t sizeCopied = 0;
7583e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu    bool firstEntry = true;
759a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    QueueEntry *entry;  // will be valid after while loop if hasEOS is set.
760bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    while (sizeCopied < size && !mAudioQueue.empty()) {
761a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        entry = &*mAudioQueue.begin();
762bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
763bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mBuffer == NULL) { // EOS
764bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            hasEOS = true;
765bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
766bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            break;
767bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
768bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
7693e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu        if (firstEntry && entry->mOffset == 0) {
7703e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu            firstEntry = false;
771bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            int64_t mediaTimeUs;
772bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
773a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
7747b15cb33847e6282ea8352c98894683b796127f3Wei Jia            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
775bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
776bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
777bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t copy = entry->mBuffer->size() - entry->mOffset;
778bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        size_t sizeRemaining = size - sizeCopied;
779bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (copy > sizeRemaining) {
780bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            copy = sizeRemaining;
781bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
782bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
783bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        memcpy((char *)buffer + sizeCopied,
784bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               entry->mBuffer->data() + entry->mOffset,
785bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia               copy);
786bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
787bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        entry->mOffset += copy;
788bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (entry->mOffset == entry->mBuffer->size()) {
789bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry->mNotifyConsumed->post();
790bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioQueue.erase(mAudioQueue.begin());
791bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            entry = NULL;
792bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
793bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        sizeCopied += copy;
7947b15cb33847e6282ea8352c98894683b796127f3Wei Jia
7957b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
796bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
797bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
798f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    if (mAudioFirstAnchorTimeMediaUs >= 0) {
799f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        int64_t nowUs = ALooper::GetNowUs();
8009816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        int64_t nowMediaUs =
801c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia            mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs);
8027b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // we don't know how much data we are queueing for offloaded tracks.
8039816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
804f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar    }
805f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
806a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // for non-offloaded audio, we need to compute the frames written because
807a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // there is no EVENT_STREAM_END notification. The frames written gives
808a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    // an estimate on the pending played out duration.
809a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    if (!offloadingAudio()) {
810a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mNumFramesWritten += sizeCopied / mAudioSink->frameSize();
811a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung    }
812a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
813bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (hasEOS) {
8141d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        (new AMessage(kWhatStopAudioSink, this))->post();
815a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // As there is currently no EVENT_STREAM_END callback notification for
816a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // non-offloaded audio tracks, we need to post the EOS ourselves.
817a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        if (!offloadingAudio()) {
818a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            int64_t postEOSDelayUs = 0;
819a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            if (mAudioSink->needsTrailingPadding()) {
820a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
821a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            }
822a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("fillAudioBuffer: notifyEOS "
823a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    "mNumFramesWritten:%u  finalResult:%d  postEOSDelay:%lld",
824a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs);
825a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
826a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        }
827bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
828bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    return sizeCopied;
829bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
830bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
8319da0ce44f228408d73a4dea0be972c785095dcccChong Zhangvoid NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
8329da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it;
8339da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    bool foundEOS = false;
8349da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    while (it != mAudioQueue.end()) {
8359da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        int32_t eos;
8369da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        QueueEntry *entry = &*it++;
8379da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        if (entry->mBuffer == NULL
8389da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) {
8399da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            itEOS = it;
8409da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            foundEOS = true;
8419da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8429da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8439da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8449da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    if (foundEOS) {
8459da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // post all replies before EOS and drop the samples
8469da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        for (it = mAudioQueue.begin(); it != itEOS; it++) {
8479da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            if (it->mBuffer == NULL) {
8489da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                // delay doesn't matter as we don't even have an AudioTrack
8499da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                notifyEOS(true /* audio */, it->mFinalResult);
8509da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            } else {
8519da0ce44f228408d73a4dea0be972c785095dcccChong Zhang                it->mNotifyConsumed->post();
8529da0ce44f228408d73a4dea0be972c785095dcccChong Zhang            }
8539da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        }
8549da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        mAudioQueue.erase(mAudioQueue.begin(), itEOS);
8559da0ce44f228408d73a4dea0be972c785095dcccChong Zhang    }
8569da0ce44f228408d73a4dea0be972c785095dcccChong Zhang}
8579da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
858078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() {
85958d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    // do not drain audio during teardown as queued buffers may be invalid.
86058d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    if (mAudioTornDown) {
86158d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung        return false;
86258d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung    }
863230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // TODO: This call to getPosition checks if AudioTrack has been created
864230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
865230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // CHECKs on getPosition will fail.
866230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // We still need to figure out why AudioTrack is not created when
867230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // this function is called. One possible reason could be leftover
868230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // audio. Another possible place is to check whether decoder
869230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // has received INFO_FORMAT_CHANGED as the first buffer since
870230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // AudioSink is opened there, and possible interactions with flush
871230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // immediately after start. Investigate error message
872230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia    // "vorbis_dsp_synthesis returned -135", along with RTSP.
873078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    uint32_t numFramesPlayed;
8742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
8759da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // When getPosition fails, renderer will not reschedule the draining
8769da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // unless new samples are queued.
8779da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // If we have pending EOS (or "eos" marker for discontinuities), we need
8789da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        // to post these now as NuPlayerDecoder might be waiting for it.
8799da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        drainAudioQueueUntilLastEOS();
8809da0ce44f228408d73a4dea0be972c785095dcccChong Zhang
8819da0ce44f228408d73a4dea0be972c785095dcccChong Zhang        ALOGW("onDrainAudioQueue(): audio sink is not ready");
8822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return false;
8832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
884078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
885230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia#if 0
886078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    ssize_t numFramesAvailableToWrite =
887078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
888078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber
889078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
890df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("audio sink underrun");
891078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
8923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("audio queue has %d frames left to play",
893078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber             mAudioSink->frameCount() - numFramesAvailableToWrite);
894078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
895078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif
896f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
897005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    uint32_t prevFramesWritten = mNumFramesWritten;
8987d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia    while (!mAudioQueue.empty()) {
899f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*mAudioQueue.begin();
900f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
901d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        mLastAudioBufferDrained = entry->mBufferOrdinal;
902d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
903f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer == NULL) {
904f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            // EOS
9055095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            int64_t postEOSDelayUs = 0;
9065095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            if (mAudioSink->needsTrailingPadding()) {
90706ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar                postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs());
9085095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            }
9095095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu            notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs);
9102995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
911f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
912f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
913f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
9143491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            if (mAudioSink->needsTrailingPadding()) {
9153491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // If we're not in gapless playback (i.e. through setNextPlayer), we
9163491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // need to stop the track here, because that will play out the last
9173491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                // little bit at the end of the file. Otherwise short files won't play.
9183491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mAudioSink->stop();
9193491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung                mNumFramesWritten = 0;
9203491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung            }
921078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber            return false;
922c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        }
923c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber
92481636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        // ignore 0-sized buffer which could be EOS marker with no data
92581636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang        if (entry->mOffset == 0 && entry->mBuffer->size() > 0) {
926f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            int64_t mediaTimeUs;
927f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
928a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs",
929a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mediaTimeUs / 1E6);
930eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu            onNewAudioMediaTime(mediaTimeUs);
931f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
932f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
933f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        size_t copy = entry->mBuffer->size() - entry->mOffset;
934f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
9357d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
9367d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                                            copy, false /* blocking */);
937a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written < 0) {
938202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
9397d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            if (written == WOULD_BLOCK) {
940df809479696725faf5d3424b11fa8a07bd94cb5eWei Jia                ALOGV("AudioSink write would block when writing %zu bytes", copy);
9417d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            } else {
9427d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
9437665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // This can only happen when AudioSink was opened with doNotReconnect flag set to
9447665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                // true, in which case the NuPlayer will handle the reconnect.
945faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                notifyAudioTearDown();
9467d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            }
947202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            break;
948a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
949f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
950a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        entry->mOffset += written;
951f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mOffset == entry->mBuffer->size()) {
952f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
953f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            mAudioQueue.erase(mAudioQueue.begin());
9549b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent
955f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry = NULL;
956f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
957f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
958a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        size_t copiedFrames = written / mAudioSink->frameSize();
959078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber        mNumFramesWritten += copiedFrames;
960cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
9617b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
9627b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
963d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            int64_t maxTimeMedia;
964d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            maxTimeMedia =
965d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                mAnchorTimeMediaUs +
966d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                        (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
967d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia                                * 1000LL * mAudioSink->msecsPerFrame());
968d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia            mMediaClock->updateMaxTimeMedia(maxTimeMedia);
969d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia
9707b15cb33847e6282ea8352c98894683b796127f3Wei Jia            notifyIfMediaRenderingStarted_l();
9717b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
97243c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
973a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        if (written != (ssize_t)copy) {
974a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // A short count was received from AudioSink::write()
975a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
9767d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // AudioSink write is called in non-blocking mode.
9777d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // It may return with a short count when:
978a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            //
979a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
9807d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 2) The data to be copied exceeds the available buffer in AudioSink.
9817d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
9827d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
983a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
984a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // (Case 1)
985a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
986a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // needs to fail, as we should not carry over fractional frames between calls.
987a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            CHECK_EQ(copy % mAudioSink->frameSize(), 0);
988a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung
9897d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            // (Case 2, 3, 4)
990a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Return early to the caller.
991a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            // Beware of calling immediately again as this may busy-loop if you are not careful.
9927d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
993a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung            break;
994a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung        }
995a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung    }
996f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar
997005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    // calculate whether we need to reschedule another write.
998005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    bool reschedule = !mAudioQueue.empty()
999005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            && (!mPaused
1000005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung                || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers
1001005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //ALOGD("reschedule:%d  empty:%d  mPaused:%d  prevFramesWritten:%u  mNumFramesWritten:%u",
1002005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    //        reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten);
1003005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung    return reschedule;
1004f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1005f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10069816016afb2a13c6a866cd047d57020566a8b9a9Wei Jiaint64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
10079816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int32_t sampleRate = offloadingAudio() ?
10089816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
10094d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    if (sampleRate == 0) {
10104d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
10114d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia        return 0;
10124d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia    }
10139816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
10149816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
10159816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia}
10169816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia
10179816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
101806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
10199816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
1020c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia    return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs);
10215095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu}
10225095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu
1023a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
10249816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    int64_t realUs;
10259816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
10267b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If failed to get current position, e.g. due to audio clock is
10277b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // not ready, then just play out video immediately without delay.
1028eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return nowUs;
1029a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    }
10309816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia    return realUs;
1031a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu}
1032a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1033eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
10347b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1035eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // TRICKY: vorbis decoder generates multiple frames with the same
1036eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    // timestamp, so only update on the first frame with a given timestamp
1037eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    if (mediaTimeUs == mAnchorTimeMediaUs) {
1038eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        return;
1039eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu    }
10407b15cb33847e6282ea8352c98894683b796127f3Wei Jia    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
10414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia
10424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    AudioTimestamp ts;
10434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    status_t res = mAudioSink->getTimestamp(ts);
104412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    int64_t nowUs = ALooper::GetNowUs();
10454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    if (res == OK) {
10464ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
10474ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia        mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
104812b6265f1d4be368957f91104d5210cf604ac4ccWei Jia    } else {
104912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        int64_t unused;
105012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        if ((mMediaClock->getMediaTime(nowUs, &unused) != OK)
105112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten)
105212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia                        > kMaxAllowedAudioSinkDelayUs)) {
105312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Enough data has been sent to AudioSink, but AudioSink has not rendered
105412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // any data yet. Something is wrong with AudioSink, e.g., the device is not
105512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // connected to audio out.
105612b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // Switch to system clock. This essentially creates a virtual AudioSink with
105712b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten).
105812b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // This virtual AudioSink renders audio data starting from the very first sample
105912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            // and it's paced by system clock.
106012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            ALOGW(""AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock.");
106112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia            mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs);
106212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia        }
10634ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia    }
10648edb3f85f58e8738582e8f9abbc018c85100b712Wei Jia    mAnchorNumFramesWritten = mNumFramesWritten;
10657b15cb33847e6282ea8352c98894683b796127f3Wei Jia    mAnchorTimeMediaUs = mediaTimeUs;
1066eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu}
1067eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu
10687b15cb33847e6282ea8352c98894683b796127f3Wei Jia// Called without mLock acquired.
10697b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue() {
1070fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (mDrainVideoQueuePending
10717b15cb33847e6282ea8352c98894683b796127f3Wei Jia            || getSyncQueues()
1072fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            || (mPaused && mVideoSampleReceived)) {
1073f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1074f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1075f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1076f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1077f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1078f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1079f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1080f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry &entry = *mVideoQueue.begin();
1081f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
10821d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
10837b15cb33847e6282ea8352c98894683b796127f3Wei Jia    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
1084f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1085f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry.mBuffer == NULL) {
1086f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS doesn't carry a timestamp.
1087dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        msg->post();
1088dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        mDrainVideoQueuePending = true;
1089dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        return;
1090dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    }
1091dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
109200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih    bool needRepostDrainVideoQueue = false;
1093dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t delayUs;
1094dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t nowUs = ALooper::GetNowUs();
1095dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t realTimeUs;
1096dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    if (mFlags & FLAG_REAL_TIME) {
1097d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        int64_t mediaTimeUs;
1098d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1099dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        realTimeUs = mediaTimeUs;
1100f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1101f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        int64_t mediaTimeUs;
1102f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1103f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
11047b15cb33847e6282ea8352c98894683b796127f3Wei Jia        {
11057b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
11067b15cb33847e6282ea8352c98894683b796127f3Wei Jia            if (mAnchorTimeMediaUs < 0) {
11077b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
11087b15cb33847e6282ea8352c98894683b796127f3Wei Jia                mAnchorTimeMediaUs = mediaTimeUs;
11097b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = nowUs;
111025d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia            } else if (!mVideoSampleReceived) {
111125d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                // Always render the first video frame.
111225d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia                realTimeUs = nowUs;
111300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mAudioFirstAnchorTimeMediaUs < 0
111400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) {
11157b15cb33847e6282ea8352c98894683b796127f3Wei Jia                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
111600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) {
111700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                needRepostDrainVideoQueue = true;
111800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
111900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            } else {
112000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih                realTimeUs = nowUs;
11217b15cb33847e6282ea8352c98894683b796127f3Wei Jia            }
1122f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1123f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        if (!mHasAudio) {
11247b15cb33847e6282ea8352c98894683b796127f3Wei Jia            // smooth out videos >= 10fps
11257b15cb33847e6282ea8352c98894683b796127f3Wei Jia            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
1126f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar        }
1127d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar
1128d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // Heuristics to handle situation when media time changed without a
1129d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // discontinuity. If we have not drained an audio buffer that was
1130d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // received after this buffer, repost in 10 msec. Otherwise repost
1131d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        // in 500 msec.
1132d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        delayUs = realTimeUs - nowUs;
113300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        int64_t postDelayUs = -1;
1134d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        if (delayUs > 500000) {
113500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = 500000;
1136d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
1137d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                postDelayUs = 10000;
1138d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            }
113900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        } else if (needRepostDrainVideoQueue) {
114000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mPlaybackRate > 0);
114100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mAudioFirstAnchorTimeMediaUs >= 0);
114200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0);
114300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs;
114400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            postDelayUs /= mPlaybackRate;
114500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        }
114600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih
114700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih        if (postDelayUs >= 0) {
1148d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->setWhat(kWhatPostDrainVideoQueue);
1149d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            msg->post(postDelayUs);
1150d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mVideoScheduler->restart();
115100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih            ALOGI("possible video time jump of %dms or uninitialized media clock, retrying in %dms",
1152d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar                    (int)(delayUs / 1000), (int)(postDelayUs / 1000));
1153d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            mDrainVideoQueuePending = true;
1154d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar            return;
1155d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar        }
1156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1157f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1158dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
1159dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000);
1160dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1161dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    delayUs = realTimeUs - nowUs;
1162dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar
1163095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar    ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
1164dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    // post 2 display refreshes before rendering is due
1165dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
1166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1167f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mDrainVideoQueuePending = true;
1168f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1169f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1170f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() {
1171f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (mVideoQueue.empty()) {
1172f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1173f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1174f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1175f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry *entry = &*mVideoQueue.begin();
1176f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1177f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (entry->mBuffer == NULL) {
1178f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        // EOS
1179f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1180c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber        notifyEOS(false /* audio */, entry->mFinalResult);
1181f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1182f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.erase(mVideoQueue.begin());
1183f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
11843fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1185a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1186f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1187f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1188f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
118925d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    int64_t nowUs = ALooper::GetNowUs();
1190d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    int64_t realTimeUs;
11912995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia    int64_t mediaTimeUs = -1;
1192d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    if (mFlags & FLAG_REAL_TIME) {
1193d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
1194d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    } else {
1195d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber        CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
1196d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
1197a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
1198d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber    }
1199f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1200fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    bool tooLate = false;
12013fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber
1202fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1203a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(nowUs - realTimeUs);
1204fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        tooLate = (mVideoLateByUs > 40000);
1205fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang
1206fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (tooLate) {
1207fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("video late by %lld us (%.2f secs)",
12086d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                 (long long)mVideoLateByUs, mVideoLateByUs / 1E6);
1209fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        } else {
12109816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            int64_t mediaUs = 0;
12119816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
1212fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            ALOGV("rendering video at media time %.2f secs",
1213fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang                    (mFlags & FLAG_REAL_TIME ? realTimeUs :
12149816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia                    mediaUs) / 1E6);
12152995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia
12162995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            if (!(mFlags & FLAG_REAL_TIME)
12172995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mLastAudioMediaTimeUs != -1
12182995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                    && mediaTimeUs > mLastAudioMediaTimeUs) {
12192995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // If audio ends before video, video continues to drive media clock.
12202995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                // Also smooth out videos >= 10fps.
12212995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia                mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
12222995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            }
1223fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
1224078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    } else {
1225a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu        setVideoLateByUs(0);
1226eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu        if (!mVideoSampleReceived && !mHasAudio) {
1227a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // This will ensure that the first frame after a flush won't be used as anchor
1228a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu            // when renderer is in paused state, because resume can happen any time after seek.
12297b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
12307b15cb33847e6282ea8352c98894683b796127f3Wei Jia            clearAnchorTime_l();
123149966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia        }
1232078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber    }
1233f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
123425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    // Always render the first video frame while keeping stats on A/V sync.
123525d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    if (!mVideoSampleReceived) {
123625d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        realTimeUs = nowUs;
123725d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia        tooLate = false;
123825d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia    }
123925d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia
1240dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar    entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll);
1241683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten    entry->mNotifyConsumed->setInt32("render", !tooLate);
1242f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry->mNotifyConsumed->post();
1243f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mVideoQueue.erase(mVideoQueue.begin());
1244f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry = NULL;
124543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber
1246fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = true;
1247f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
1248fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    if (!mPaused) {
1249fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        if (!mVideoRenderingStarted) {
1250fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            mVideoRenderingStarted = true;
1251fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang            notifyVideoRenderingStart();
1252fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang        }
12537b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
12547b15cb33847e6282ea8352c98894683b796127f3Wei Jia        notifyIfMediaRenderingStarted_l();
1255fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    }
1256f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1257f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1258f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() {
1259f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    sp<AMessage> notify = mNotify->dup();
1260f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->setInt32("what", kWhatVideoRenderingStart);
1261f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong    notify->post();
1262f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong}
1263f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong
12645095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
12657c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    if (audio && delayUs > 0) {
12667c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        sp<AMessage> msg = new AMessage(kWhatEOS, this);
12677c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("audioEOSGeneration", mAudioEOSGeneration);
12687c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->setInt32("finalResult", finalResult);
12697c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        msg->post(delayUs);
12707c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia        return;
12717c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia    }
1272f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1273f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatEOS);
1274f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1275c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber    notify->setInt32("finalResult", finalResult);
12765095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu    notify->post(delayUs);
1277f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1278f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1279faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::notifyAudioTearDown() {
1280faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    (new AMessage(kWhatAudioTearDown, this))->post();
12813a2956d148d81194e297408179e84a47a309ef48Wei Jia}
12823a2956d148d81194e297408179e84a47a309ef48Wei Jia
1283f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
1284f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1285f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1286f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
12877b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
12887b15cb33847e6282ea8352c98894683b796127f3Wei Jia        return;
12897b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
12907b15cb33847e6282ea8352c98894683b796127f3Wei Jia
12917b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (audio) {
12927b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasAudio = true;
12937b15cb33847e6282ea8352c98894683b796127f3Wei Jia    } else {
12947b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mHasVideo = true;
12957b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
1296a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu
1297a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    if (mHasVideo) {
1298dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        if (mVideoScheduler == NULL) {
1299dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler = new VideoFrameScheduler();
1300dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar            mVideoScheduler->init();
1301dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar        }
1302bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber    }
1303bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber
13042d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
13052d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
1306f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1307f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
1309f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1310f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1311f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mBuffer = buffer;
1312f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mNotifyConsumed = notifyConsumed;
1313f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1314f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = OK;
1315d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar    entry.mBufferOrdinal = ++mTotalBuffersQueued;
1316f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1317f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
13187b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1319f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1320bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1321f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1322f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
13237b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1324f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1325f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13267b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
1327cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
1328cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1329cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1330f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1331cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
1332cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
1333f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1334cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
1335cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // EOS signalled on either queue.
1336bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        syncQueuesDone_l();
1337cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1338cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    }
1339f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1340cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstAudioTimeUs;
1341cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t firstVideoTimeUs;
1342cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstAudioBuffer->meta()
1343cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstAudioTimeUs));
1344cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    CHECK(firstVideoBuffer->meta()
1345cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber            ->findInt64("timeUs", &firstVideoTimeUs));
1346f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1347cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
1348f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("queueDiff = %.2f secs", diff / 1E6);
1350cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1351cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber    if (diff > 100000ll) {
1352cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Audio data starts More than 0.1 secs before video.
1353cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        // Drop some audio.
1354cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1355cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        (*mAudioQueue.begin()).mNotifyConsumed->post();
1356cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        mAudioQueue.erase(mAudioQueue.begin());
1357cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber        return;
1358f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1359cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber
1360bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    syncQueuesDone_l();
1361f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1362f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1363bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() {
1364f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mSyncQueues) {
1365f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1366f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1367f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1368f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    mSyncQueues = false;
1369f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1370f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mAudioQueue.empty()) {
1371bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1372f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1373f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1374f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (!mVideoQueue.empty()) {
13757b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.unlock();
13767b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
13777b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mLock.lock();
1378f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1379f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1380f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1381f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
1382f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t audio;
1383f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1384f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
13857b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (dropBufferIfStale(audio, msg)) {
1386f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return;
1387f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1388f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1389f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    int32_t finalResult;
1390f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("finalResult", &finalResult));
1391f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1392f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    QueueEntry entry;
1393f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mOffset = 0;
1394f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    entry.mFinalResult = finalResult;
1395f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1396f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
13977b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
1398b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        if (mAudioQueue.empty() && mSyncQueues) {
1399bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1400b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1401f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mAudioQueue.push_back(entry);
1402bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        postDrainAudioQueue_l();
1403f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
14047b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (mVideoQueue.empty() && getSyncQueues()) {
14057b15cb33847e6282ea8352c98894683b796127f3Wei Jia            Mutex::Autolock autoLock(mLock);
1406bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            syncQueuesDone_l();
1407b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson        }
1408f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mVideoQueue.push_back(entry);
14097b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1410f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1411f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1412f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1413f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
14147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    int32_t audio, notifyComplete;
1415f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    CHECK(msg->findInt32("audio", &audio));
1416f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
141728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
14187b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
141928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        if (audio) {
14207137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteAudio;
14217137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteAudio = false;
14222995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia            mLastAudioMediaTimeUs = -1;
142328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        } else {
14247137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            notifyComplete = mNotifyCompleteVideo;
14257137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang            mNotifyCompleteVideo = false;
142628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
142728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
14287b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // If we're currently syncing the queues, i.e. dropping audio while
14297b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // aligning the first audio/video buffer times and only one of the
14307b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // two queues has data, we may starve that queue by not requesting
14317b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // more buffers from the decoder. If the other source then encounters
14327b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // a discontinuity that leads to flushing, we'll never find the
14337b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // corresponding discontinuity on the other queue.
14347b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // Therefore we'll stop syncing the queues if at least one of them
14357b15cb33847e6282ea8352c98894683b796127f3Wei Jia        // is flushed.
14367b15cb33847e6282ea8352c98894683b796127f3Wei Jia        syncQueuesDone_l();
14377b15cb33847e6282ea8352c98894683b796127f3Wei Jia        clearAnchorTime_l();
1438bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
1439f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1440cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar    ALOGV("flushing %s", audio ? "audio" : "video");
1441f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (audio) {
1442bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        {
1443bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            Mutex::Autolock autoLock(mLock);
1444bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            flushQueue(&mAudioQueue);
1445f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
14467b15cb33847e6282ea8352c98894683b796127f3Wei Jia            ++mAudioDrainGeneration;
14477c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia            ++mAudioEOSGeneration;
14487b15cb33847e6282ea8352c98894683b796127f3Wei Jia            prepareForMediaRenderingStart_l();
144928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia
1450a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            // the frame count will be reset after flush.
1451a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung            clearAudioFirstAnchorTime_l();
145228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        }
1453f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainAudioQueuePending = false;
1455cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1456bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        if (offloadingAudio()) {
1457bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->pause();
1458bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia            mAudioSink->flush();
145985e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            if (!mPaused) {
146085e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                mAudioSink->start();
146185e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung            }
14629e7ed3315298b42db485963b182a572e9ab42f9fWei Jia        } else {
14639e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->pause();
14649e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->flush();
14659e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // Call stop() to signal to the AudioSink to completely fill the
14669e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            // internal buffer before resuming playback.
1467b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            // FIXME: this is ignored after flush().
14689e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mAudioSink->stop();
1469b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            if (mPaused) {
1470b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // Race condition: if renderer is paused and audio sink is stopped,
1471b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // we need to make sure that the audio track buffer fully drains
1472b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // before delivering data.
1473b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                // FIXME: remove this if we can detect if stop() is complete.
1474b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
1475b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung                mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
1476b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung            } else {
14779e7ed3315298b42db485963b182a572e9ab42f9fWei Jia                mAudioSink->start();
14789e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            }
14799e7ed3315298b42db485963b182a572e9ab42f9fWei Jia            mNumFramesWritten = 0;
1480bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        }
1481f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    } else {
1482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        flushQueue(&mVideoQueue);
1483f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1484f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        mDrainVideoQueuePending = false;
1485cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
1486c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        if (mVideoScheduler != NULL) {
1487c851b5de495169d7e9528644c2592746021bd968Lajos Molnar            mVideoScheduler->restart();
1488c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        }
1489c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
14907b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
14917b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
14927b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
1493f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1494f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1495fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang    mVideoSampleReceived = false;
14967137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang
14977137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    if (notifyComplete) {
14987137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang        notifyFlushComplete(audio);
14997137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang    }
1500f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1501f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1502f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
1503f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    while (!queue->empty()) {
1504f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        QueueEntry *entry = &*queue->begin();
1505f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1506f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        if (entry->mBuffer != NULL) {
1507f933441648ef6a71dee783d733aac17b9508b452Andreas Huber            entry->mNotifyConsumed->post();
1508f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        }
1509f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1510f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        queue->erase(queue->begin());
1511f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        entry = NULL;
1512f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1513f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1514f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1515f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) {
1516f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notify = mNotify->dup();
1517f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("what", kWhatFlushComplete);
1518f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->setInt32("audio", static_cast<int32_t>(audio));
1519f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    notify->post();
1520f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15227b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::dropBufferIfStale(
1523f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        bool audio, const sp<AMessage> &msg) {
15247b15cb33847e6282ea8352c98894683b796127f3Wei Jia    int32_t queueGeneration;
15257b15cb33847e6282ea8352c98894683b796127f3Wei Jia    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
1526f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15277b15cb33847e6282ea8352c98894683b796127f3Wei Jia    if (queueGeneration == getQueueGeneration(audio)) {
1528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        return false;
1529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1530f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1531f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    sp<AMessage> notifyConsumed;
1532f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
1533f933441648ef6a71dee783d733aac17b9508b452Andreas Huber        notifyConsumed->post();
1534f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    }
1535f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1536f933441648ef6a71dee783d733aac17b9508b452Andreas Huber    return true;
1537f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}
1538f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
15393831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() {
1540bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    if (offloadingAudio()) {
1541bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia        return;
1542bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    }
15433831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    CHECK(!mDrainAudioQueuePending);
15443831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber    mNumFramesWritten = 0;
15457b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
15467b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
15477b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mAnchorNumFramesWritten = -1;
15487b15cb33847e6282ea8352c98894683b796127f3Wei Jia    }
15494110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    uint32_t written;
15504110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    if (mAudioSink->getFramesWritten(&written) == OK) {
15514110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen        mNumFramesWritten = written;
15524110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen    }
15533831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber}
15543831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber
1555bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() {
1556bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    Mutex::Autolock autoLock(mLock);
1557bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia    mFlags &= ~FLAG_OFFLOAD_AUDIO;
15587b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1559e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1560e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1561e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1562bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia}
1563bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia
1564a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() {
1565a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    Mutex::Autolock autoLock(mLock);
1566a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu    mFlags |= FLAG_OFFLOAD_AUDIO;
15677b15cb33847e6282ea8352c98894683b796127f3Wei Jia    ++mAudioDrainGeneration;
1568e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    if (mAudioRenderingStartGeneration != -1) {
1569e1d701902765c710398133025cfeee3ea8b6d280Robert Shih        prepareForMediaRenderingStart_l();
1570e1d701902765c710398133025cfeee3ea8b6d280Robert Shih    }
1571a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu}
1572a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu
1573b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() {
15748592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    if (mPaused) {
15758592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad        return;
15768592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad    }
15776d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar
157828a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    {
157928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia        Mutex::Autolock autoLock(mLock);
1580005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        // we do not increment audio drain generation so that we fill audio buffer during pause.
15817b15cb33847e6282ea8352c98894683b796127f3Wei Jia        ++mVideoDrainGeneration;
15827b15cb33847e6282ea8352c98894683b796127f3Wei Jia        prepareForMediaRenderingStart_l();
158373ddd210ea572375198cac1d4960df793745fb4bWei Jia        mPaused = true;
15849816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(0.0);
158528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
1586b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
158728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    mDrainAudioQueuePending = false;
1588b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    mDrainVideoQueuePending = false;
1589cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar
15908420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
15918420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    mAudioSink->pause();
15928420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    startAudioOffloadPauseTimeout();
1593b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
15946d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar    ALOGV("now paused audio queue has %zu entries, video has %zu entries",
1595ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber          mAudioQueue.size(), mVideoQueue.size());
1596b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1597b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1598b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() {
1599b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    if (!mPaused) {
1600b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber        return;
1601b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber    }
1602b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16038420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    // Note: audio data may not have been decoded, and the AudioSink may not be opened.
16048420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    cancelAudioOffloadPauseTimeout();
16058420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung    if (mAudioSink->ready()) {
160697c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        status_t err = mAudioSink->start();
160797c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        if (err != OK) {
160858d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung            ALOGE("cannot start AudioSink err %d", err);
160997c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent            notifyAudioTearDown();
161097c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent        }
1611b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1612b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16137b15cb33847e6282ea8352c98894683b796127f3Wei Jia    {
16147b15cb33847e6282ea8352c98894683b796127f3Wei Jia        Mutex::Autolock autoLock(mLock);
16157b15cb33847e6282ea8352c98894683b796127f3Wei Jia        mPaused = false;
1616b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        // rendering started message may have been delayed if we were paused.
1617b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        if (mRenderingDataDelivered) {
1618b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung            notifyIfMediaRenderingStarted_l();
1619b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung        }
16203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        // configure audiosink as we did not do it when pausing
162127ea08e3811dc8057685258af52a7d40474eba16Wei Jia        if (mAudioSink != NULL && mAudioSink->ready()) {
16223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            mAudioSink->setPlaybackRate(mPlaybackSettings);
16233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
16243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
16259816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia        mMediaClock->setPlaybackRate(mPlaybackRate);
1626b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
16277b15cb33847e6282ea8352c98894683b796127f3Wei Jia        if (!mAudioQueue.empty()) {
16287b15cb33847e6282ea8352c98894683b796127f3Wei Jia            postDrainAudioQueue_l();
16297b15cb33847e6282ea8352c98894683b796127f3Wei Jia        }
1630b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1631b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1632b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    if (!mVideoQueue.empty()) {
16337b15cb33847e6282ea8352c98894683b796127f3Wei Jia        postDrainVideoQueue();
1634b408222bd9479c291874b607acae1425d6154fe7Andreas Huber    }
1635b408222bd9479c291874b607acae1425d6154fe7Andreas Huber}
1636b408222bd9479c291874b607acae1425d6154fe7Andreas Huber
1637c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
1638c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    if (mVideoScheduler == NULL) {
1639c851b5de495169d7e9528644c2592746021bd968Lajos Molnar        mVideoScheduler = new VideoFrameScheduler();
1640c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    }
1641c851b5de495169d7e9528644c2592746021bd968Lajos Molnar    mVideoScheduler->init(fps);
1642c851b5de495169d7e9528644c2592746021bd968Lajos Molnar}
1643c851b5de495169d7e9528644c2592746021bd968Lajos Molnar
16447b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
16457b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16467b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
16477b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16487b15cb33847e6282ea8352c98894683b796127f3Wei Jia
16497b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
16507b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16517b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
16527b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16537b15cb33847e6282ea8352c98894683b796127f3Wei Jia
16547b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::getSyncQueues() {
16557b15cb33847e6282ea8352c98894683b796127f3Wei Jia    Mutex::Autolock autoLock(mLock);
16567b15cb33847e6282ea8352c98894683b796127f3Wei Jia    return mSyncQueues;
16577b15cb33847e6282ea8352c98894683b796127f3Wei Jia}
16587b15cb33847e6282ea8352c98894683b796127f3Wei Jia
1659faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) {
1660faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    if (mAudioTornDown) {
1661f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        return;
1662f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1663faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = true;
1664f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1665a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu    int64_t currentPositionUs;
16661a5c859016e743779e4db25855390b3ce523cd48Robert Shih    sp<AMessage> notify = mNotify->dup();
16671a5c859016e743779e4db25855390b3ce523cd48Robert Shih    if (getCurrentPosition(&currentPositionUs) == OK) {
16681a5c859016e743779e4db25855390b3ce523cd48Robert Shih        notify->setInt64("positionUs", currentPositionUs);
166928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia    }
167006ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar
16713a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->stop();
16723a2956d148d81194e297408179e84a47a309ef48Wei Jia    mAudioSink->flush();
16733a2956d148d81194e297408179e84a47a309ef48Wei Jia
1674faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    notify->setInt32("what", kWhatAudioTearDown);
16750852917279f79a94907e9906d0533ae409a30f6aRonghua Wu    notify->setInt32("reason", reason);
16763a2956d148d81194e297408179e84a47a309ef48Wei Jia    notify->post();
16773a2956d148d81194e297408179e84a47a309ef48Wei Jia}
16783a2956d148d81194e297408179e84a47a309ef48Wei Jia
1679f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
1680f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
168135d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->acquire();
16821d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
16837b15cb33847e6282ea8352c98894683b796127f3Wei Jia        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
1684f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        msg->post(kOffloadPauseMaxUs);
1685f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1686f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1687f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1688f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
1689f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    if (offloadingAudio()) {
169035d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang        mWakeLock->release(true);
1691f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu        ++mAudioOffloadPauseTimeoutGeneration;
1692f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu    }
1693f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu}
1694f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu
1695202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink(
16963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        const sp<AMessage> &format,
16973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool offloadOnly,
16983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        bool hasVideo,
16993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        uint32_t flags) {
17003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
17013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadOnly, offloadingAudio());
17023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    bool audioSinkChanged = false;
17033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t numChannels;
17053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("channel-count", &numChannels));
17063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t channelMask;
17083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!format->findInt32("channel-mask", &channelMask)) {
17093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        // signal to the AudioSink to derive the mask from count.
17103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
17113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
17123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    int32_t sampleRate;
17143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    CHECK(format->findInt32("sample-rate", &sampleRate));
17153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (offloadingAudio()) {
17173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
17183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        AString mime;
17193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        CHECK(format->findString("mime", &mime));
17203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
17213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        if (err != OK) {
17233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGE("Couldn't map mime \"%s\" to a valid "
17243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "audio_format", mime.c_str());
17253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            onDisableOffloadAudio();
17263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        } else {
17273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
17283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    mime.c_str(), audioFormat);
17293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int avgBitRate = -1;
17313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt32("bit-rate", &avgBitRate);
17323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            int32_t aacProfile = -1;
17343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (audioFormat == AUDIO_FORMAT_AAC
17353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    && format->findInt32("aac-profile", &aacProfile)) {
17363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Redefine AAC format as per aac profile
17373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mapAACProfileToAudioFormat(
17383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        audioFormat,
17393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                        aacProfile);
17403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
17413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
17433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.duration_us = -1;
17443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            format->findInt64(
17453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    "durationUs", &offloadInfo.duration_us);
17463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.sample_rate = sampleRate;
17473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.channel_mask = channelMask;
17483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.format = audioFormat;
17493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
17503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.bit_rate = avgBitRate;
17513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.has_video = hasVideo;
17523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            offloadInfo.is_streaming = true;
17533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
17553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: no change in offload mode");
17563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // no change from previous configuration, everything ok.
1757202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung                return OK;
17583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
1759f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1760f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
17613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            ALOGV("openAudioSink: try to open AudioSink in offload mode");
1762d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            uint32_t offloadFlags = flags;
1763d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1764d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent            offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
17653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            audioSinkChanged = true;
17663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            mAudioSink->close();
1767a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung
17683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            err = mAudioSink->open(
17693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
17703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
17713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
17723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    audioFormat,
1773179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
17743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &NuPlayer::Renderer::AudioSinkCallback,
17753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    this,
1776d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent                    (audio_output_flags_t)offloadFlags,
17773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    &offloadInfo);
17783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
17793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err == OK) {
17803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar                err = mAudioSink->setPlaybackRate(mPlaybackSettings);
17813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            }
17823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
17833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            if (err == OK) {
17843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // If the playback is offloaded to h/w, we pass
17853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // the HAL some metadata information.
17863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // We don't want to do this for PCM because it
17873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // will be going through the AudioFlinger mixer
17883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // before reaching the hardware.
17893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // TODO
17903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = offloadInfo;
179185e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                if (!mPaused) { // for preview mode, don't start if paused
179285e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                    err = mAudioSink->start();
179385e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung                }
17943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV_IF(err == OK, "openAudioSink: offload succeeded");
17953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
17963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            if (err != OK) {
17973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                // Clean up, fall back to non offload mode.
17983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mAudioSink->close();
17993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                onDisableOffloadAudio();
18003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
18013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                ALOGV("openAudioSink: offload failed");
18023ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            } else {
18033ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                mUseAudioCallback = true;  // offload mode transfers data through callback
18043ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia                ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
18053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang            }
18063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        }
18073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
18083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (!offloadOnly && !offloadingAudio()) {
18093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        ALOGV("openAudioSink: open AudioSink in NON-offload mode");
1810d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        uint32_t pcmFlags = flags;
1811d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent        pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
1812f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
1813f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        const PcmInfo info = {
1814f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_channel_mask_t)channelMask,
1815f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                (audio_output_flags_t)pcmFlags,
1816f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
1817f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                numChannels,
1818f0e83644637bd05852c244df481f21a0d435ff66Andy Hung                sampleRate
1819f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        };
1820f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
1821f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            ALOGV("openAudioSink: no change in pcm mode");
1822f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            // no change from previous configuration, everything ok.
1823f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            return OK;
1824f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        }
1825f0e83644637bd05852c244df481f21a0d435ff66Andy Hung
18263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        audioSinkChanged = true;
18273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mAudioSink->close();
18283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1829a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // Note: It is possible to set up the callback, but not use it to send audio data.
1830a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        // This requires a fix in AudioSink to explicitly specify the transfer mode.
1831a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung        mUseAudioCallback = getUseAudioCallbackSetting();
18323ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        if (mUseAudioCallback) {
18333ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia            ++mAudioDrainGeneration;  // discard pending kWhatDrainAudioQueue message.
18343ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia        }
1835179652ee2a508361df1aa18e99000373886f0816Andy Hung
1836179652ee2a508361df1aa18e99000373886f0816Andy Hung        // Compute the desired buffer size.
1837179652ee2a508361df1aa18e99000373886f0816Andy Hung        // For callback mode, the amount of time before wakeup is about half the buffer size.
1838179652ee2a508361df1aa18e99000373886f0816Andy Hung        const uint32_t frameCount =
1839179652ee2a508361df1aa18e99000373886f0816Andy Hung                (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
1840179652ee2a508361df1aa18e99000373886f0816Andy Hung
18417665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
18427665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // AudioSink. We don't want this when there's video because it will cause a video seek to
18437665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // the previous I frame. But we do want this when there's only audio because it will give
18447665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // NuPlayer a chance to switch from non-offload mode to offload mode.
18457665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        // So we only set doNotReconnect when there's no video.
18467665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu        const bool doNotReconnect = !hasVideo;
1847202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        status_t err = mAudioSink->open(
18483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    sampleRate,
18493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    numChannels,
18503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    (audio_channel_mask_t)channelMask,
18513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang                    AUDIO_FORMAT_PCM_16_BIT,
1852179652ee2a508361df1aa18e99000373886f0816Andy Hung                    0 /* bufferCount - unused */,
1853a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
1854a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung                    mUseAudioCallback ? this : NULL,
1855faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    (audio_output_flags_t)pcmFlags,
1856faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                    NULL,
18577665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu                    doNotReconnect,
1858179652ee2a508361df1aa18e99000373886f0816Andy Hung                    frameCount);
18593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (err == OK) {
18603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            err = mAudioSink->setPlaybackRate(mPlaybackSettings);
18613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        }
1862202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        if (err != OK) {
1863202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
18644d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia            mAudioSink->close();
1865f0e83644637bd05852c244df481f21a0d435ff66Andy Hung            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
1866202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung            return err;
1867202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung        }
1868f0e83644637bd05852c244df481f21a0d435ff66Andy Hung        mCurrentPcmInfo = info;
1869005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        if (!mPaused) { // for preview mode, don't start if paused
1870005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung            mAudioSink->start();
1871005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung        }
18723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
18733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    if (audioSinkChanged) {
18743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang        onAudioSinkChanged();
18753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    }
1876faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mAudioTornDown = false;
1877202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung    return OK;
18783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
18793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
18803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() {
18813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mAudioSink->close();
18823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang    mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
1883f0e83644637bd05852c244df481f21a0d435ff66Andy Hung    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
18843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang}
18853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang
1886f933441648ef6a71dee783d733aac17b9508b452Andreas Huber}  // namespace android
1887f933441648ef6a71dee783d733aac17b9508b452Andreas Huber
1888