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