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