NuPlayerRenderer.cpp revision 238e1247a1fde2c7857ec243563126de72346a89
1f933441648ef6a71dee783d733aac17b9508b452Andreas Huber/* 2f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * 4f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * you may not use this file except in compliance with the License. 6f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * You may obtain a copy of the License at 7f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * 8f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * 10f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * Unless required by applicable law or agreed to in writing, software 11f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * See the License for the specific language governing permissions and 14f933441648ef6a71dee783d733aac17b9508b452Andreas Huber * limitations under the License. 15f933441648ef6a71dee783d733aac17b9508b452Andreas Huber */ 16f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 17f933441648ef6a71dee783d733aac17b9508b452Andreas Huber//#define LOG_NDEBUG 0 18f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#define LOG_TAG "NuPlayerRenderer" 19f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <utils/Log.h> 20f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 21f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include "NuPlayerRenderer.h" 22f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung#include <algorithm> 23a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung#include <cutils/properties.h> 24f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 25f933441648ef6a71dee783d733aac17b9508b452Andreas Huber#include <media/stagefright/foundation/ADebug.h> 265bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/AMessage.h> 27a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu#include <media/stagefright/foundation/AUtils.h> 2835d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang#include <media/stagefright/foundation/AWakeLock.h> 295833b6aad2c46ba516bdc8262f4fc4667e8018edWei Jia#include <media/stagefright/MediaClock.h> 30bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MediaErrors.h> 31bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia#include <media/stagefright/MetaData.h> 323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang#include <media/stagefright/Utils.h> 33a3725d7b0cb79ddb49f81cba00a0164d8e645acdLajos Molnar#include <media/stagefright/VideoFrameScheduler.h> 34dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 35095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar#include <inttypes.h> 36095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar 37f933441648ef6a71dee783d733aac17b9508b452Andreas Hubernamespace android { 38f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 39a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung/* 40a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung * Example of common configuration settings in shell script form 41a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 42a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung #Turn offload audio off (use PCM for Play Music) -- AudioPolicyManager 43a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung adb shell setprop audio.offload.disable 1 44a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 45a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung #Allow offload audio with video (requires offloading to be enabled) -- AudioPolicyManager 46a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung adb shell setprop audio.offload.video 1 47a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 48a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung #Use audio callbacks for PCM data 49a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung adb shell setprop media.stagefright.audio.cbk 1 50a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 51288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung #Use deep buffer for PCM data with video (it is generally enabled for audio-only) 52288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung adb shell setprop media.stagefright.audio.deep 1 53288da02b1f074f9f3c191f1838f135d4633b3d34Andy Hung 54179652ee2a508361df1aa18e99000373886f0816Andy Hung #Set size of buffers for pcm audio sink in msec (example: 1000 msec) 55179652ee2a508361df1aa18e99000373886f0816Andy Hung adb shell setprop media.stagefright.audio.sink 1000 56179652ee2a508361df1aa18e99000373886f0816Andy Hung 57a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung * These configurations take effect for the next track played (not the current track). 58a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung */ 59a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 60a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hungstatic inline bool getUseAudioCallbackSetting() { 61a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung return property_get_bool("media.stagefright.audio.cbk", false /* default_value */); 62a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung} 63a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 64179652ee2a508361df1aa18e99000373886f0816Andy Hungstatic inline int32_t getAudioSinkPcmMsSetting() { 65179652ee2a508361df1aa18e99000373886f0816Andy Hung return property_get_int32( 66179652ee2a508361df1aa18e99000373886f0816Andy Hung "media.stagefright.audio.sink", 500 /* default_value */); 67179652ee2a508361df1aa18e99000373886f0816Andy Hung} 68179652ee2a508361df1aa18e99000373886f0816Andy Hung 69f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// Maximum time in paused state when offloading audio decompression. When elapsed, the AudioSink 70f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu// is closed to allow the audio DSP to power down. 71a5d316fd802cfc92954527f27e6f32206a896113Eric Laurentstatic const int64_t kOffloadPauseMaxUs = 10000000ll; 72f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu 7312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia// Maximum allowed delay from AudioSink, 1.5 seconds. 7412b6265f1d4be368957f91104d5210cf604ac4ccWei Jiastatic const int64_t kMaxAllowedAudioSinkDelayUs = 1500000ll; 7512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia 76528c8403ad2ede53054a706a20c00b710fa08166Andy Hungstatic const int64_t kMinimumAudioClockUpdatePeriodUs = 20 /* msec */ * 1000; 77528c8403ad2ede53054a706a20c00b710fa08166Andy Hung 78714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber// static 79f0e83644637bd05852c244df481f21a0d435ff66Andy Hungconst NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = { 80f0e83644637bd05852c244df481f21a0d435ff66Andy Hung AUDIO_CHANNEL_NONE, 81f0e83644637bd05852c244df481f21a0d435ff66Andy Hung AUDIO_OUTPUT_FLAG_NONE, 82f0e83644637bd05852c244df481f21a0d435ff66Andy Hung AUDIO_FORMAT_INVALID, 83f0e83644637bd05852c244df481f21a0d435ff66Andy Hung 0, // mNumChannels 84f0e83644637bd05852c244df481f21a0d435ff66Andy Hung 0 // mSampleRate 85f0e83644637bd05852c244df481f21a0d435ff66Andy Hung}; 86f0e83644637bd05852c244df481f21a0d435ff66Andy Hung 87f0e83644637bd05852c244df481f21a0d435ff66Andy Hung// static 88714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huberconst int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll; 89714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber 90f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::Renderer( 91f933441648ef6a71dee783d733aac17b9508b452Andreas Huber const sp<MediaPlayerBase::AudioSink> &sink, 92d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber const sp<AMessage> ¬ify, 93d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber uint32_t flags) 94f933441648ef6a71dee783d733aac17b9508b452Andreas Huber : mAudioSink(sink), 95d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia mUseVirtualAudioSink(false), 96f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mNotify(notify), 97d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber mFlags(flags), 98f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mNumFramesWritten(0), 99f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainAudioQueuePending(false), 100f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainVideoQueuePending(false), 101f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mAudioQueueGeneration(0), 102f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mVideoQueueGeneration(0), 1037b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAudioDrainGeneration(0), 1047b15cb33847e6282ea8352c98894683b796127f3Wei Jia mVideoDrainGeneration(0), 1057c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia mAudioEOSGeneration(0), 1063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT), 107a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu mAudioFirstAnchorTimeMediaUs(-1), 108eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu mAnchorTimeMediaUs(-1), 109f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar mAnchorNumFramesWritten(-1), 110a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu mVideoLateByUs(0ll), 111bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber mHasAudio(false), 112bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber mHasVideo(false), 1137137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mNotifyCompleteAudio(false), 1147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mNotifyCompleteVideo(false), 115bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber mSyncQueues(false), 116714aa7b7c52ce07d5fb44870c0853b4d8e5a758eAndreas Huber mPaused(false), 117b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung mPauseDrainAudioAllowedUs(0), 11809e0c3646362d29c78bc26c8b23b7a753c412e6cAndy Hung mVideoSampleReceived(false), 119f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong mVideoRenderingStarted(false), 120cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar mVideoRenderingStartGeneration(0), 121cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar mAudioRenderingStartGeneration(0), 122b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung mRenderingDataDelivered(false), 123528c8403ad2ede53054a706a20c00b710fa08166Andy Hung mNextAudioClockUpdateTimeUs(-1), 1242995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia mLastAudioMediaTimeUs(-1), 125f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu mAudioOffloadPauseTimeoutGeneration(0), 126faeb0f291330134dc4468359a36e099aae508449Ronghua Wu mAudioTornDown(false), 127d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), 128f0e83644637bd05852c244df481f21a0d435ff66Andy Hung mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER), 129d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar mTotalBuffersQueued(0), 13035d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang mLastAudioBufferDrained(0), 131a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mUseAudioCallback(false), 13235d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang mWakeLock(new AWakeLock()) { 1337b15cb33847e6282ea8352c98894683b796127f3Wei Jia mMediaClock = new MediaClock; 1343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mPlaybackRate = mPlaybackSettings.mSpeed; 1353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mMediaClock->setPlaybackRate(mPlaybackRate); 136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 138f933441648ef6a71dee783d733aac17b9508b452Andreas HuberNuPlayer::Renderer::~Renderer() { 139bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (offloadingAudio()) { 140bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioSink->stop(); 141bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioSink->flush(); 142bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioSink->close(); 143bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 1444c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia 1454c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia // Try to avoid racing condition in case callback is still on. 1464c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia Mutex::Autolock autoLock(mLock); 1474c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia mUseAudioCallback = false; 1484c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia flushQueue(&mAudioQueue); 1494c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia flushQueue(&mVideoQueue); 1504c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia mWakeLock.clear(); 1514c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia mMediaClock.clear(); 1524c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia mVideoScheduler.clear(); 1534c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia mNotify.clear(); 1544c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia mAudioSink.clear(); 155f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 156f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 157f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueBuffer( 158f933441648ef6a71dee783d733aac17b9508b452Andreas Huber bool audio, 159f933441648ef6a71dee783d733aac17b9508b452Andreas Huber const sp<ABuffer> &buffer, 160f933441648ef6a71dee783d733aac17b9508b452Andreas Huber const sp<AMessage> ¬ifyConsumed) { 1611d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this); 1627b15cb33847e6282ea8352c98894683b796127f3Wei Jia msg->setInt32("queueGeneration", getQueueGeneration(audio)); 163f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->setInt32("audio", static_cast<int32_t>(audio)); 1642d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("buffer", buffer); 165f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->setMessage("notifyConsumed", notifyConsumed); 166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->post(); 167f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 168f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 169f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) { 170f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK_NE(finalResult, (status_t)OK); 171f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1721d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatQueueEOS, this); 1737b15cb33847e6282ea8352c98894683b796127f3Wei Jia msg->setInt32("queueGeneration", getQueueGeneration(audio)); 174f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->setInt32("audio", static_cast<int32_t>(audio)); 175f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->setInt32("finalResult", finalResult); 176f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->post(); 177f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 178f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setPlaybackSettings(const AudioPlaybackRate &rate) { 1803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this); 1813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar writeToAMessage(msg, rate); 1823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response; 1833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = msg->postAndAwaitResponse(&response); 1843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK && response != NULL) { 1853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(response->findInt32("err", &err)); 1863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 1873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return err; 1883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 1893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 1903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigPlayback(const AudioPlaybackRate &rate /* sanitized */) { 1913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (rate.mSpeed == 0.f) { 1923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar onPause(); 1933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // don't call audiosink's setPlaybackRate if pausing, as pitch does not 1943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // have to correspond to the any non-0 speed (e.g old speed). Keep 1953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // settings nonetheless, using the old speed, in case audiosink changes. 1963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar AudioPlaybackRate newRate = rate; 1973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar newRate.mSpeed = mPlaybackSettings.mSpeed; 1983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mPlaybackSettings = newRate; 1993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return OK; 2003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 20227ea08e3811dc8057685258af52a7d40474eba16Wei Jia if (mAudioSink != NULL && mAudioSink->ready()) { 2033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = mAudioSink->setPlaybackRate(rate); 2043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err != OK) { 2053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return err; 2063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mPlaybackSettings = rate; 2093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mPlaybackRate = rate.mSpeed; 2103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mMediaClock->setPlaybackRate(mPlaybackRate); 2113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return OK; 2123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 2133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 2143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) { 2153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this); 2163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response; 2173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = msg->postAndAwaitResponse(&response); 2183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK && response != NULL) { 2193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(response->findInt32("err", &err)); 2203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK) { 2213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar readFromAMessage(response, rate); 2223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return err; 2253a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 2263a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 2273a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) { 22827ea08e3811dc8057685258af52a7d40474eba16Wei Jia if (mAudioSink != NULL && mAudioSink->ready()) { 2293a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = mAudioSink->getPlaybackRate(rate); 2303a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK) { 2313a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) { 2323a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar ALOGW("correcting mismatch in internal/external playback rate"); 2333a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2343a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // get playback settings used by audiosink, as it may be 2353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // slightly off due to audiosink not taking small changes. 2363a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mPlaybackSettings = *rate; 2373a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (mPaused) { 2383a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar rate->mSpeed = 0.f; 2393a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2403a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2413a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return err; 2423a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2433a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar *rate = mPlaybackSettings; 2443a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return OK; 2453a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 2463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 2473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) { 2483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> msg = new AMessage(kWhatConfigSync, this); 2493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar writeToAMessage(msg, sync, videoFpsHint); 2503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response; 2513a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = msg->postAndAwaitResponse(&response); 2523a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK && response != NULL) { 2533a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(response->findInt32("err", &err)); 2543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return err; 2563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 2573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 2583a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onConfigSync(const AVSyncSettings &sync, float videoFpsHint __unused) { 2593a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (sync.mSource != AVSYNC_SOURCE_DEFAULT) { 2603a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return BAD_VALUE; 2613a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2623a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // TODO: support sync sources 2633a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return INVALID_OPERATION; 2643a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 2653a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 2663a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::getSyncSettings(AVSyncSettings *sync, float *videoFps) { 2673a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this); 2683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response; 2693a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = msg->postAndAwaitResponse(&response); 2703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK && response != NULL) { 2713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(response->findInt32("err", &err)); 2723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK) { 2733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar readFromAMessage(response, sync, videoFps); 2743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 2763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return err; 2773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar} 2783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 2793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnarstatus_t NuPlayer::Renderer::onGetSyncSettings( 2803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) { 2813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar *sync = mSyncSettings; 2823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar *videoFps = -1.f; 2833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar return OK; 2849816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia} 2859816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia 2867137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::Renderer::flush(bool audio, bool notifyComplete) { 287f933441648ef6a71dee783d733aac17b9508b452Andreas Huber { 2887b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 289f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (audio) { 2907137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mNotifyCompleteAudio |= notifyComplete; 2913b0cd26dbb0ce37d220db9ff0fa8172a7ef1c5cbWei Jia clearAudioFirstAnchorTime_l(); 2927b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mAudioQueueGeneration; 2937b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mAudioDrainGeneration; 294f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } else { 2957137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mNotifyCompleteVideo |= notifyComplete; 2967b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mVideoQueueGeneration; 2977b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mVideoDrainGeneration; 298f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 2997b15cb33847e6282ea8352c98894683b796127f3Wei Jia 3007b15cb33847e6282ea8352c98894683b796127f3Wei Jia clearAnchorTime_l(); 3017b15cb33847e6282ea8352c98894683b796127f3Wei Jia mVideoLateByUs = 0; 3027b15cb33847e6282ea8352c98894683b796127f3Wei Jia mSyncQueues = false; 303f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 304f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 3051d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatFlush, this); 306f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->setInt32("audio", static_cast<int32_t>(audio)); 307f933441648ef6a71dee783d733aac17b9508b452Andreas Huber msg->post(); 308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 309f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 310f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::signalTimeDiscontinuity() { 31128a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia} 31228a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia 31328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jiavoid NuPlayer::Renderer::signalDisableOffloadAudio() { 3141d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatDisableOffloadAudio, this))->post(); 31528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia} 31628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia 317a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::signalEnableOffloadAudio() { 3181d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatEnableOffloadAudio, this))->post(); 319a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu} 320a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu 321b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::pause() { 3221d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatPause, this))->post(); 323b408222bd9479c291874b607acae1425d6154fe7Andreas Huber} 324b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 325b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::resume() { 3261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatResume, this))->post(); 327b408222bd9479c291874b607acae1425d6154fe7Andreas Huber} 328b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 329c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::setVideoFrameRate(float fps) { 3301d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this); 331c851b5de495169d7e9528644c2592746021bd968Lajos Molnar msg->setFloat("frame-rate", fps); 332c851b5de495169d7e9528644c2592746021bd968Lajos Molnar msg->post(); 333c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 334c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 3354ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia// Called on any threads without mLock acquired. 3367b15cb33847e6282ea8352c98894683b796127f3Wei Jiastatus_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) { 3374ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia status_t result = mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs); 3384ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia if (result == OK) { 3394ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia return result; 3404ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia } 3414ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia 3424ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia // MediaClock has not started yet. Try to start it if possible. 3434ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia { 3444ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia Mutex::Autolock autoLock(mLock); 3454ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia if (mAudioFirstAnchorTimeMediaUs == -1) { 3464ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia return result; 3474ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia } 3484ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia 3494ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia AudioTimestamp ts; 3504ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia status_t res = mAudioSink->getTimestamp(ts); 3514ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia if (res != OK) { 3524ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia return result; 3534ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia } 3544ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia 3554ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia // AudioSink has rendered some frames. 3564ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia int64_t nowUs = ALooper::GetNowUs(); 357d855a738735a3df8863b486f5d3b5e404cef15c1Wei Jia int64_t nowMediaUs = mAudioSink->getPlayedOutDurationUs(nowUs) 3584ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia + mAudioFirstAnchorTimeMediaUs; 3594ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia mMediaClock->updateAnchor(nowMediaUs, nowUs, -1); 3604ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia } 3614ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia 3629816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs); 363a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 3657b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAudioFirstAnchorTime_l() { 3667b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAudioFirstAnchorTimeMediaUs = -1; 3677b15cb33847e6282ea8352c98894683b796127f3Wei Jia mMediaClock->setStartingTimeMedia(-1); 368a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 369a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 3707b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) { 371a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu if (mAudioFirstAnchorTimeMediaUs == -1) { 372a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu mAudioFirstAnchorTimeMediaUs = mediaUs; 3737b15cb33847e6282ea8352c98894683b796127f3Wei Jia mMediaClock->setStartingTimeMedia(mediaUs); 374a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu } 375a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 376a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 3777b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::clearAnchorTime_l() { 3787b15cb33847e6282ea8352c98894683b796127f3Wei Jia mMediaClock->clearAnchor(); 3797b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAnchorTimeMediaUs = -1; 3807b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAnchorNumFramesWritten = -1; 381a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 382a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 383a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuvoid NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) { 3847b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 385a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu mVideoLateByUs = lateUs; 386a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 387a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 388a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getVideoLateByUs() { 3897b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 390a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu return mVideoLateByUs; 391a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 392a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 393202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::openAudioSink( 3943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang const sp<AMessage> &format, 3953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang bool offloadOnly, 3963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang bool hasVideo, 397202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung uint32_t flags, 398202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung bool *isOffloaded) { 3991d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this); 4003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang msg->setMessage("format", format); 4013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang msg->setInt32("offload-only", offloadOnly); 4023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang msg->setInt32("has-video", hasVideo); 4033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang msg->setInt32("flags", flags); 4043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sp<AMessage> response; 4063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang msg->postAndAwaitResponse(&response); 4073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 408202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung int32_t err; 409202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung if (!response->findInt32("err", &err)) { 410202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung err = INVALID_OPERATION; 411202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung } else if (err == OK && isOffloaded != NULL) { 412202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung int32_t offload; 413202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung CHECK(response->findInt32("offload", &offload)); 414202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung *isOffloaded = (offload != 0); 415202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung } 416202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung return err; 4173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang} 4183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::closeAudioSink() { 4201d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this); 4213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sp<AMessage> response; 4233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang msg->postAndAwaitResponse(&response); 4243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang} 4253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 426f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) { 427f933441648ef6a71dee783d733aac17b9508b452Andreas Huber switch (msg->what()) { 4283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang case kWhatOpenAudioSink: 4293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang { 4303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sp<AMessage> format; 4313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(msg->findMessage("format", &format)); 4323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4333b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int32_t offloadOnly; 4343b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(msg->findInt32("offload-only", &offloadOnly)); 4353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4363b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int32_t hasVideo; 4373b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(msg->findInt32("has-video", &hasVideo)); 4383b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang uint32_t flags; 4403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(msg->findInt32("flags", (int32_t *)&flags)); 4413b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 442202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags); 4433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sp<AMessage> response = new AMessage; 445202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung response->setInt32("err", err); 446202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung response->setInt32("offload", offloadingAudio()); 4473b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4483f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 4493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 4503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang response->postReply(replyID); 4513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang break; 4533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 4543b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4553b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang case kWhatCloseAudioSink: 4563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang { 4573f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar sp<AReplyToken> replyID; 4583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(msg->senderAwaitsResponse(&replyID)); 4593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang onCloseAudioSink(); 4613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 4623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sp<AMessage> response = new AMessage; 4633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang response->postReply(replyID); 4643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang break; 4653b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 4663b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 467bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia case kWhatStopAudioSink: 468bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia { 469bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioSink->stop(); 470bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia break; 471bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 472bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 473f933441648ef6a71dee783d733aac17b9508b452Andreas Huber case kWhatDrainAudioQueue: 474f933441648ef6a71dee783d733aac17b9508b452Andreas Huber { 4753ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia mDrainAudioQueuePending = false; 4763ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia 477f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int32_t generation; 4787b15cb33847e6282ea8352c98894683b796127f3Wei Jia CHECK(msg->findInt32("drainGeneration", &generation)); 4797b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (generation != getDrainGeneration(true /* audio */)) { 480f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 481f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 483078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber if (onDrainAudioQueue()) { 484078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber uint32_t numFramesPlayed; 485078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), 486078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber (status_t)OK); 487078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber 488078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber uint32_t numFramesPendingPlayout = 489078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber mNumFramesWritten - numFramesPlayed; 490078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber 491078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber // This is how long the audio sink will have data to 492078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber // play back. 493078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber int64_t delayUs = 494078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber mAudioSink->msecsPerFrame() 495078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber * numFramesPendingPlayout * 1000ll; 496d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia if (mPlaybackRate > 1.0f) { 497d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia delayUs /= mPlaybackRate; 498d9c2e9c81a6f75c4dd6818a3d5075a875d25a2d4Wei Jia } 499078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber 500078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber // Let's give it more data after about half that time 501078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber // has elapsed. 502f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung delayUs /= 2; 503f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung // check the buffer size to estimate maximum delay permitted. 504f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung const int64_t maxDrainDelayUs = std::max( 505f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung mAudioSink->getBufferDurationInUs(), (int64_t)500000 /* half second */); 506f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung ALOGD_IF(delayUs > maxDrainDelayUs, "postDrainAudioQueue long delay: %lld > %lld", 507f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung (long long)delayUs, (long long)maxDrainDelayUs); 5087b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 509f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung postDrainAudioQueue_l(delayUs); 510078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber } 511f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 512f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 513f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 514f933441648ef6a71dee783d733aac17b9508b452Andreas Huber case kWhatDrainVideoQueue: 515f933441648ef6a71dee783d733aac17b9508b452Andreas Huber { 516f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int32_t generation; 5177b15cb33847e6282ea8352c98894683b796127f3Wei Jia CHECK(msg->findInt32("drainGeneration", &generation)); 5187b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (generation != getDrainGeneration(false /* audio */)) { 519f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 520f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 522f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainVideoQueuePending = false; 523f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 524f933441648ef6a71dee783d733aac17b9508b452Andreas Huber onDrainVideoQueue(); 525f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 5267b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainVideoQueue(); 527f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 528f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 529f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 530d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar case kWhatPostDrainVideoQueue: 531d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar { 532d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar int32_t generation; 5337b15cb33847e6282ea8352c98894683b796127f3Wei Jia CHECK(msg->findInt32("drainGeneration", &generation)); 5347b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (generation != getDrainGeneration(false /* audio */)) { 535d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar break; 536d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar } 537d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar 538d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar mDrainVideoQueuePending = false; 5397b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainVideoQueue(); 540d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar break; 541d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar } 542d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar 543f933441648ef6a71dee783d733aac17b9508b452Andreas Huber case kWhatQueueBuffer: 544f933441648ef6a71dee783d733aac17b9508b452Andreas Huber { 545f933441648ef6a71dee783d733aac17b9508b452Andreas Huber onQueueBuffer(msg); 546f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 547f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 548f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 549f933441648ef6a71dee783d733aac17b9508b452Andreas Huber case kWhatQueueEOS: 550f933441648ef6a71dee783d733aac17b9508b452Andreas Huber { 551f933441648ef6a71dee783d733aac17b9508b452Andreas Huber onQueueEOS(msg); 552f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 553f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 554f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 5557c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia case kWhatEOS: 5567c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia { 5577c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia int32_t generation; 5587c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia CHECK(msg->findInt32("audioEOSGeneration", &generation)); 5597c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia if (generation != mAudioEOSGeneration) { 5607c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia break; 5617c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia } 5627c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia status_t finalResult; 5637c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia CHECK(msg->findInt32("finalResult", &finalResult)); 5647c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia notifyEOS(true /* audio */, finalResult); 5657c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia break; 5667c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia } 5677c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia 5683a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar case kWhatConfigPlayback: 5699816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia { 5703a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AReplyToken> replyID; 5713a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(msg->senderAwaitsResponse(&replyID)); 5723a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar AudioPlaybackRate rate; 5733a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar readFromAMessage(msg, &rate); 5743a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = onConfigPlayback(rate); 5753a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response = new AMessage; 5763a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->setInt32("err", err); 5773a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->postReply(replyID); 5783a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar break; 5793a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 5803a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 5813a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar case kWhatGetPlaybackSettings: 5823a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar { 5833a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AReplyToken> replyID; 5843a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(msg->senderAwaitsResponse(&replyID)); 5853a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar AudioPlaybackRate rate = AUDIO_PLAYBACK_RATE_DEFAULT; 5863a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = onGetPlaybackSettings(&rate); 5873a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response = new AMessage; 5883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK) { 5893a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar writeToAMessage(response, rate); 5903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 5913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->setInt32("err", err); 5923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->postReply(replyID); 5933a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar break; 5943a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 5953a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 5963a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar case kWhatConfigSync: 5973a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar { 5983a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AReplyToken> replyID; 5993a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(msg->senderAwaitsResponse(&replyID)); 6003a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar AVSyncSettings sync; 6013a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar float videoFpsHint; 6023a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar readFromAMessage(msg, &sync, &videoFpsHint); 6033a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = onConfigSync(sync, videoFpsHint); 6043a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response = new AMessage; 6053a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->setInt32("err", err); 6063a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->postReply(replyID); 6073a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar break; 6083a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 6093a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 6103a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar case kWhatGetSyncSettings: 6113a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar { 6123a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AReplyToken> replyID; 6133a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar CHECK(msg->senderAwaitsResponse(&replyID)); 6143a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 6153a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar ALOGV("kWhatGetSyncSettings"); 6163a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar AVSyncSettings sync; 6173a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar float videoFps = -1.f; 6183a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar status_t err = onGetSyncSettings(&sync, &videoFps); 6193a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar sp<AMessage> response = new AMessage; 6203a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK) { 6213a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar writeToAMessage(response, sync, videoFps); 6223a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 6233a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->setInt32("err", err); 6243a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar response->postReply(replyID); 6259816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia break; 6269816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia } 6279816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia 628f933441648ef6a71dee783d733aac17b9508b452Andreas Huber case kWhatFlush: 629f933441648ef6a71dee783d733aac17b9508b452Andreas Huber { 630f933441648ef6a71dee783d733aac17b9508b452Andreas Huber onFlush(msg); 631f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 632f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 633f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 634bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia case kWhatDisableOffloadAudio: 635bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia { 636bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia onDisableOffloadAudio(); 637bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia break; 638bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 639bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 640a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu case kWhatEnableOffloadAudio: 641a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu { 642a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu onEnableOffloadAudio(); 643a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu break; 644a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu } 645a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu 646b408222bd9479c291874b607acae1425d6154fe7Andreas Huber case kWhatPause: 647b408222bd9479c291874b607acae1425d6154fe7Andreas Huber { 648b408222bd9479c291874b607acae1425d6154fe7Andreas Huber onPause(); 649b408222bd9479c291874b607acae1425d6154fe7Andreas Huber break; 650b408222bd9479c291874b607acae1425d6154fe7Andreas Huber } 651b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 652b408222bd9479c291874b607acae1425d6154fe7Andreas Huber case kWhatResume: 653b408222bd9479c291874b607acae1425d6154fe7Andreas Huber { 654b408222bd9479c291874b607acae1425d6154fe7Andreas Huber onResume(); 655b408222bd9479c291874b607acae1425d6154fe7Andreas Huber break; 656b408222bd9479c291874b607acae1425d6154fe7Andreas Huber } 657b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 658c851b5de495169d7e9528644c2592746021bd968Lajos Molnar case kWhatSetVideoFrameRate: 659c851b5de495169d7e9528644c2592746021bd968Lajos Molnar { 660c851b5de495169d7e9528644c2592746021bd968Lajos Molnar float fps; 661c851b5de495169d7e9528644c2592746021bd968Lajos Molnar CHECK(msg->findFloat("frame-rate", &fps)); 662c851b5de495169d7e9528644c2592746021bd968Lajos Molnar onSetVideoFrameRate(fps); 663c851b5de495169d7e9528644c2592746021bd968Lajos Molnar break; 664c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 665c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 666faeb0f291330134dc4468359a36e099aae508449Ronghua Wu case kWhatAudioTearDown: 6673a2956d148d81194e297408179e84a47a309ef48Wei Jia { 668a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia int32_t reason; 669a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia CHECK(msg->findInt32("reason", &reason)); 670a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia 671a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia onAudioTearDown((AudioTearDownReason)reason); 6723a2956d148d81194e297408179e84a47a309ef48Wei Jia break; 6733a2956d148d81194e297408179e84a47a309ef48Wei Jia } 6743a2956d148d81194e297408179e84a47a309ef48Wei Jia 675f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu case kWhatAudioOffloadPauseTimeout: 676f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu { 677f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu int32_t generation; 6787b15cb33847e6282ea8352c98894683b796127f3Wei Jia CHECK(msg->findInt32("drainGeneration", &generation)); 679f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu if (generation != mAudioOffloadPauseTimeoutGeneration) { 680f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu break; 681f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu } 6820852917279f79a94907e9906d0533ae409a30f6aRonghua Wu ALOGV("Audio Offload tear down due to pause timeout."); 683faeb0f291330134dc4468359a36e099aae508449Ronghua Wu onAudioTearDown(kDueToTimeout); 68435d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang mWakeLock->release(); 685f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu break; 686f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu } 687f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu 688f933441648ef6a71dee783d733aac17b9508b452Andreas Huber default: 689f933441648ef6a71dee783d733aac17b9508b452Andreas Huber TRESPASS(); 690f933441648ef6a71dee783d733aac17b9508b452Andreas Huber break; 691f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 692f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 693f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 694bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) { 695005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung if (mDrainAudioQueuePending || mSyncQueues || mUseAudioCallback) { 696f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 697f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 698f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 699f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (mAudioQueue.empty()) { 700f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 701f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 702f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 703b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data. 704b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung if (mPaused) { 705b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs(); 706b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung if (diffUs > delayUs) { 707b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung delayUs = diffUs; 708b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung } 709b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung } 710b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung 711f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainAudioQueuePending = true; 7121d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this); 7137b15cb33847e6282ea8352c98894683b796127f3Wei Jia msg->setInt32("drainGeneration", mAudioDrainGeneration); 714078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber msg->post(delayUs); 715f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 716f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 7177b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::prepareForMediaRenderingStart_l() { 7187b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAudioRenderingStartGeneration = mAudioDrainGeneration; 7197b15cb33847e6282ea8352c98894683b796127f3Wei Jia mVideoRenderingStartGeneration = mVideoDrainGeneration; 720b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung mRenderingDataDelivered = false; 721cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar} 722cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 7237b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() { 7247b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (mVideoRenderingStartGeneration == mVideoDrainGeneration && 7257b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAudioRenderingStartGeneration == mAudioDrainGeneration) { 726b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung mRenderingDataDelivered = true; 727b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung if (mPaused) { 728b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung return; 729b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung } 730cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar mVideoRenderingStartGeneration = -1; 731cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar mAudioRenderingStartGeneration = -1; 732cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 733cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar sp<AMessage> notify = mNotify->dup(); 734cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar notify->setInt32("what", kWhatMediaRenderingStart); 735cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar notify->post(); 736cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar } 737cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar} 738cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 739bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia// static 740bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::AudioSinkCallback( 741bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia MediaPlayerBase::AudioSink * /* audioSink */, 742bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia void *buffer, 743bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia size_t size, 744bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia void *cookie, 745bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia MediaPlayerBase::AudioSink::cb_event_t event) { 746bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia NuPlayer::Renderer *me = (NuPlayer::Renderer *)cookie; 747bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 748bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia switch (event) { 749bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia case MediaPlayerBase::AudioSink::CB_EVENT_FILL_BUFFER: 750bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia { 751bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia return me->fillAudioBuffer(buffer, size); 752bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia break; 753bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 754bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 755bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END: 756bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia { 757a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung ALOGV("AudioSink::CB_EVENT_STREAM_END"); 7584c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia me->notifyEOSCallback(); 759bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia break; 760bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 761bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 762bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN: 763bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia { 764a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung ALOGV("AudioSink::CB_EVENT_TEAR_DOWN"); 765a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia me->notifyAudioTearDown(kDueToError); 766bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia break; 767bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 768bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 769bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 770bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia return 0; 771bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia} 772bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 7734c74fde2ef5b582196b296a8263cd39143e7abcaWei Jiavoid NuPlayer::Renderer::notifyEOSCallback() { 7744c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia Mutex::Autolock autoLock(mLock); 7754c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia 7764c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia if (!mUseAudioCallback) { 7774c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia return; 7784c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia } 7794c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia 7804c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia notifyEOS(true /* audio */, ERROR_END_OF_STREAM); 7814c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia} 7824c74fde2ef5b582196b296a8263cd39143e7abcaWei Jia 783bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiasize_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) { 784bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia Mutex::Autolock autoLock(mLock); 785bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 78685e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung if (!mUseAudioCallback) { 787bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia return 0; 788bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 789bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 790bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia bool hasEOS = false; 791bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 792bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia size_t sizeCopied = 0; 7933e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu bool firstEntry = true; 794a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung QueueEntry *entry; // will be valid after while loop if hasEOS is set. 795bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia while (sizeCopied < size && !mAudioQueue.empty()) { 796a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung entry = &*mAudioQueue.begin(); 797bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 798bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (entry->mBuffer == NULL) { // EOS 799bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia hasEOS = true; 800bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioQueue.erase(mAudioQueue.begin()); 801bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia break; 802bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 803bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 8043e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu if (firstEntry && entry->mOffset == 0) { 8053e5efb37308aa1f54c2a72cd8a7a73d2d7921a90Ronghua Wu firstEntry = false; 806bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia int64_t mediaTimeUs; 807bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); 808a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung ALOGV("fillAudioBuffer: rendering audio at media time %.2f secs", mediaTimeUs / 1E6); 8097b15cb33847e6282ea8352c98894683b796127f3Wei Jia setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs); 810bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 811bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 812bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia size_t copy = entry->mBuffer->size() - entry->mOffset; 813bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia size_t sizeRemaining = size - sizeCopied; 814bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (copy > sizeRemaining) { 815bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia copy = sizeRemaining; 816bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 817bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 818bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia memcpy((char *)buffer + sizeCopied, 819bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia entry->mBuffer->data() + entry->mOffset, 820bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia copy); 821bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 822bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia entry->mOffset += copy; 823bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (entry->mOffset == entry->mBuffer->size()) { 824bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia entry->mNotifyConsumed->post(); 825bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioQueue.erase(mAudioQueue.begin()); 826bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia entry = NULL; 827bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 828bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia sizeCopied += copy; 8297b15cb33847e6282ea8352c98894683b796127f3Wei Jia 8307b15cb33847e6282ea8352c98894683b796127f3Wei Jia notifyIfMediaRenderingStarted_l(); 831bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 832bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 833f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar if (mAudioFirstAnchorTimeMediaUs >= 0) { 834f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar int64_t nowUs = ALooper::GetNowUs(); 8359816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia int64_t nowMediaUs = 836c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia mAudioFirstAnchorTimeMediaUs + mAudioSink->getPlayedOutDurationUs(nowUs); 8377b15cb33847e6282ea8352c98894683b796127f3Wei Jia // we don't know how much data we are queueing for offloaded tracks. 8389816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX); 839f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar } 840f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar 841a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // for non-offloaded audio, we need to compute the frames written because 842a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // there is no EVENT_STREAM_END notification. The frames written gives 843a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // an estimate on the pending played out duration. 844a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung if (!offloadingAudio()) { 845a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mNumFramesWritten += sizeCopied / mAudioSink->frameSize(); 846a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung } 847a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 848bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (hasEOS) { 8491d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar (new AMessage(kWhatStopAudioSink, this))->post(); 850a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // As there is currently no EVENT_STREAM_END callback notification for 851a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // non-offloaded audio tracks, we need to post the EOS ourselves. 852a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung if (!offloadingAudio()) { 853a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung int64_t postEOSDelayUs = 0; 854a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung if (mAudioSink->needsTrailingPadding()) { 855a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs()); 856a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung } 857a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung ALOGV("fillAudioBuffer: notifyEOS " 858a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung "mNumFramesWritten:%u finalResult:%d postEOSDelay:%lld", 859a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mNumFramesWritten, entry->mFinalResult, (long long)postEOSDelayUs); 860a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs); 861a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung } 862bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 863bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia return sizeCopied; 864bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia} 865bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 8669da0ce44f228408d73a4dea0be972c785095dcccChong Zhangvoid NuPlayer::Renderer::drainAudioQueueUntilLastEOS() { 8679da0ce44f228408d73a4dea0be972c785095dcccChong Zhang List<QueueEntry>::iterator it = mAudioQueue.begin(), itEOS = it; 8689da0ce44f228408d73a4dea0be972c785095dcccChong Zhang bool foundEOS = false; 8699da0ce44f228408d73a4dea0be972c785095dcccChong Zhang while (it != mAudioQueue.end()) { 8709da0ce44f228408d73a4dea0be972c785095dcccChong Zhang int32_t eos; 8719da0ce44f228408d73a4dea0be972c785095dcccChong Zhang QueueEntry *entry = &*it++; 8729da0ce44f228408d73a4dea0be972c785095dcccChong Zhang if (entry->mBuffer == NULL 8739da0ce44f228408d73a4dea0be972c785095dcccChong Zhang || (entry->mNotifyConsumed->findInt32("eos", &eos) && eos != 0)) { 8749da0ce44f228408d73a4dea0be972c785095dcccChong Zhang itEOS = it; 8759da0ce44f228408d73a4dea0be972c785095dcccChong Zhang foundEOS = true; 8769da0ce44f228408d73a4dea0be972c785095dcccChong Zhang } 8779da0ce44f228408d73a4dea0be972c785095dcccChong Zhang } 8789da0ce44f228408d73a4dea0be972c785095dcccChong Zhang 8799da0ce44f228408d73a4dea0be972c785095dcccChong Zhang if (foundEOS) { 8809da0ce44f228408d73a4dea0be972c785095dcccChong Zhang // post all replies before EOS and drop the samples 8819da0ce44f228408d73a4dea0be972c785095dcccChong Zhang for (it = mAudioQueue.begin(); it != itEOS; it++) { 8829da0ce44f228408d73a4dea0be972c785095dcccChong Zhang if (it->mBuffer == NULL) { 8839da0ce44f228408d73a4dea0be972c785095dcccChong Zhang // delay doesn't matter as we don't even have an AudioTrack 8849da0ce44f228408d73a4dea0be972c785095dcccChong Zhang notifyEOS(true /* audio */, it->mFinalResult); 8859da0ce44f228408d73a4dea0be972c785095dcccChong Zhang } else { 8869da0ce44f228408d73a4dea0be972c785095dcccChong Zhang it->mNotifyConsumed->post(); 8879da0ce44f228408d73a4dea0be972c785095dcccChong Zhang } 8889da0ce44f228408d73a4dea0be972c785095dcccChong Zhang } 8899da0ce44f228408d73a4dea0be972c785095dcccChong Zhang mAudioQueue.erase(mAudioQueue.begin(), itEOS); 8909da0ce44f228408d73a4dea0be972c785095dcccChong Zhang } 8919da0ce44f228408d73a4dea0be972c785095dcccChong Zhang} 8929da0ce44f228408d73a4dea0be972c785095dcccChong Zhang 893078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huberbool NuPlayer::Renderer::onDrainAudioQueue() { 89458d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung // do not drain audio during teardown as queued buffers may be invalid. 89558d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung if (mAudioTornDown) { 89658d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung return false; 89758d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung } 898230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // TODO: This call to getPosition checks if AudioTrack has been created 899230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // in AudioSink before draining audio. If AudioTrack doesn't exist, then 900230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // CHECKs on getPosition will fail. 901230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // We still need to figure out why AudioTrack is not created when 902230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // this function is called. One possible reason could be leftover 903230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // audio. Another possible place is to check whether decoder 904230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // has received INFO_FORMAT_CHANGED as the first buffer since 905230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // AudioSink is opened there, and possible interactions with flush 906230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // immediately after start. Investigate error message 907230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia // "vorbis_dsp_synthesis returned -135", along with RTSP. 908078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber uint32_t numFramesPlayed; 9092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mAudioSink->getPosition(&numFramesPlayed) != OK) { 9109da0ce44f228408d73a4dea0be972c785095dcccChong Zhang // When getPosition fails, renderer will not reschedule the draining 9119da0ce44f228408d73a4dea0be972c785095dcccChong Zhang // unless new samples are queued. 9129da0ce44f228408d73a4dea0be972c785095dcccChong Zhang // If we have pending EOS (or "eos" marker for discontinuities), we need 9139da0ce44f228408d73a4dea0be972c785095dcccChong Zhang // to post these now as NuPlayerDecoder might be waiting for it. 9149da0ce44f228408d73a4dea0be972c785095dcccChong Zhang drainAudioQueueUntilLastEOS(); 9159da0ce44f228408d73a4dea0be972c785095dcccChong Zhang 9169da0ce44f228408d73a4dea0be972c785095dcccChong Zhang ALOGW("onDrainAudioQueue(): audio sink is not ready"); 9172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return false; 9182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 919078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber 920230b188b2c2ed74aa017cb93f847e9a558feba95Wei Jia#if 0 921078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber ssize_t numFramesAvailableToWrite = 922078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed); 923078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber 924078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber if (numFramesAvailableToWrite == mAudioSink->frameCount()) { 925df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("audio sink underrun"); 926078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber } else { 9273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("audio queue has %d frames left to play", 928078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber mAudioSink->frameCount() - numFramesAvailableToWrite); 929078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber } 930078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber#endif 931f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 932005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung uint32_t prevFramesWritten = mNumFramesWritten; 9337d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia while (!mAudioQueue.empty()) { 934f933441648ef6a71dee783d733aac17b9508b452Andreas Huber QueueEntry *entry = &*mAudioQueue.begin(); 935f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 936d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar mLastAudioBufferDrained = entry->mBufferOrdinal; 937d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar 938f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (entry->mBuffer == NULL) { 939f933441648ef6a71dee783d733aac17b9508b452Andreas Huber // EOS 9405095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu int64_t postEOSDelayUs = 0; 9415095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu if (mAudioSink->needsTrailingPadding()) { 94206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar postEOSDelayUs = getPendingAudioPlayoutDurationUs(ALooper::GetNowUs()); 9435095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu } 9445095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu notifyEOS(true /* audio */, entry->mFinalResult, postEOSDelayUs); 9452995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia mLastAudioMediaTimeUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten); 946f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 947f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mAudioQueue.erase(mAudioQueue.begin()); 948f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry = NULL; 9493491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung if (mAudioSink->needsTrailingPadding()) { 9503491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung // If we're not in gapless playback (i.e. through setNextPlayer), we 9513491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung // need to stop the track here, because that will play out the last 9523491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung // little bit at the end of the file. Otherwise short files won't play. 9533491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung mAudioSink->stop(); 9543491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung mNumFramesWritten = 0; 9553491232a7c0d953fa021f6a81baee64c44f364f3Andy Hung } 956078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber return false; 957c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber } 958c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber 95981636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang // ignore 0-sized buffer which could be EOS marker with no data 96081636761bead03f13b4ed9320a7f25ce1354f1aeChong Zhang if (entry->mOffset == 0 && entry->mBuffer->size() > 0) { 961f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int64_t mediaTimeUs; 962f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); 963a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung ALOGV("onDrainAudioQueue: rendering audio at media time %.2f secs", 964a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mediaTimeUs / 1E6); 965eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu onNewAudioMediaTime(mediaTimeUs); 966f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 967f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 968f933441648ef6a71dee783d733aac17b9508b452Andreas Huber size_t copy = entry->mBuffer->size() - entry->mOffset; 969f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 9707d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset, 9717d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia copy, false /* blocking */); 972a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung if (written < 0) { 973202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung // An error in AudioSink write. Perhaps the AudioSink was not properly opened. 9747d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia if (written == WOULD_BLOCK) { 975df809479696725faf5d3424b11fa8a07bd94cb5eWei Jia ALOGV("AudioSink write would block when writing %zu bytes", copy); 9767d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia } else { 9777d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy); 9787665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // This can only happen when AudioSink was opened with doNotReconnect flag set to 9797665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // true, in which case the NuPlayer will handle the reconnect. 980a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia notifyAudioTearDown(kDueToError); 9817d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia } 982202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung break; 983a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung } 984f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 985a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung entry->mOffset += written; 98603cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia size_t remainder = entry->mBuffer->size() - entry->mOffset; 98703cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia if ((ssize_t)remainder < mAudioSink->frameSize()) { 98803cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia if (remainder > 0) { 98903cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia ALOGW("Corrupted audio buffer has fractional frames, discarding %zu bytes.", 99003cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia remainder); 99103cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia entry->mOffset += remainder; 99203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia copy -= remainder; 99303cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia } 99403cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia 995f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry->mNotifyConsumed->post(); 996f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mAudioQueue.erase(mAudioQueue.begin()); 9979b7d950f1f3b0c526712b713dbceb0e22762c015Eric Laurent 998f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry = NULL; 999f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1000f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1001a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung size_t copiedFrames = written / mAudioSink->frameSize(); 1002078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber mNumFramesWritten += copiedFrames; 1003cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 10047b15cb33847e6282ea8352c98894683b796127f3Wei Jia { 10057b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 1006d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia int64_t maxTimeMedia; 1007d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia maxTimeMedia = 1008d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia mAnchorTimeMediaUs + 1009d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL) 1010d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia * 1000LL * mAudioSink->msecsPerFrame()); 1011d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia mMediaClock->updateMaxTimeMedia(maxTimeMedia); 1012d005c5ddb4842369979df7b76f1d0f5f1380fcd9Wei Jia 10137b15cb33847e6282ea8352c98894683b796127f3Wei Jia notifyIfMediaRenderingStarted_l(); 10147b15cb33847e6282ea8352c98894683b796127f3Wei Jia } 101543c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 1016a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung if (written != (ssize_t)copy) { 1017a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // A short count was received from AudioSink::write() 1018a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // 10197d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia // AudioSink write is called in non-blocking mode. 10207d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia // It may return with a short count when: 1021a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // 102203cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia // 1) Size to be copied is not a multiple of the frame size. Fractional frames are 102303cee24b8d54e5b5a94957b9fb7049738ff68765Wei Jia // discarded. 10247d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia // 2) The data to be copied exceeds the available buffer in AudioSink. 10257d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia // 3) An error occurs and data has been partially copied to the buffer in AudioSink. 10267d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded. 1027a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung 1028a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // (Case 1) 1029a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // Must be a multiple of the frame size. If it is not a multiple of a frame size, it 1030a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // needs to fail, as we should not carry over fractional frames between calls. 1031a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung CHECK_EQ(copy % mAudioSink->frameSize(), 0); 1032a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung 10337d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia // (Case 2, 3, 4) 1034a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // Return early to the caller. 1035a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung // Beware of calling immediately again as this may busy-loop if you are not careful. 10367d3f4df0a77e052a7d37de9268aff8c2ed0909ccWei Jia ALOGV("AudioSink write short frame count %zd < %zu", written, copy); 1037a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung break; 1038a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung } 1039a31335a4ec96ba351f25f3b26fa79a78c2723a13Andy Hung } 1040f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar 1041005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung // calculate whether we need to reschedule another write. 1042005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung bool reschedule = !mAudioQueue.empty() 1043005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung && (!mPaused 1044005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung || prevFramesWritten != mNumFramesWritten); // permit pause to fill buffers 1045005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung //ALOGD("reschedule:%d empty:%d mPaused:%d prevFramesWritten:%u mNumFramesWritten:%u", 1046005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung // reschedule, mAudioQueue.empty(), mPaused, prevFramesWritten, mNumFramesWritten); 1047005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung return reschedule; 1048f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1049f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 10509816016afb2a13c6a866cd047d57020566a8b9a9Wei Jiaint64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) { 10519816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia int32_t sampleRate = offloadingAudio() ? 10529816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate; 10534d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia if (sampleRate == 0) { 10544d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload"); 10554d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia return 0; 10564d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia } 10579816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours. 10589816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate); 10599816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia} 10609816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia 10619816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia// Calculate duration of pending samples if played at normal rate (i.e., 1.0). 106206ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnarint64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) { 10639816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten); 1064d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia if (mUseVirtualAudioSink) { 1065d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia int64_t nowUs = ALooper::GetNowUs(); 1066d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia int64_t mediaUs; 1067d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia if (mMediaClock->getMediaTime(nowUs, &mediaUs) != OK) { 1068d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia return 0ll; 1069d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia } else { 1070d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia return writtenAudioDurationUs - (mediaUs - mAudioFirstAnchorTimeMediaUs); 1071d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia } 1072d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia } 1073c4ac8173f911aeac8d5006b19ba48fb51a865115Wei Jia return writtenAudioDurationUs - mAudioSink->getPlayedOutDurationUs(nowUs); 10745095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu} 10755095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu 1076a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wuint64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) { 10779816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia int64_t realUs; 10789816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) { 10797b15cb33847e6282ea8352c98894683b796127f3Wei Jia // If failed to get current position, e.g. due to audio clock is 10807b15cb33847e6282ea8352c98894683b796127f3Wei Jia // not ready, then just play out video immediately without delay. 1081eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu return nowUs; 1082a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu } 10839816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia return realUs; 1084a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu} 1085a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 1086eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wuvoid NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) { 10877b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 1088eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu // TRICKY: vorbis decoder generates multiple frames with the same 1089eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu // timestamp, so only update on the first frame with a given timestamp 1090eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu if (mediaTimeUs == mAnchorTimeMediaUs) { 1091eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu return; 1092eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu } 10937b15cb33847e6282ea8352c98894683b796127f3Wei Jia setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs); 10944ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia 1095528c8403ad2ede53054a706a20c00b710fa08166Andy Hung // mNextAudioClockUpdateTimeUs is -1 if we're waiting for audio sink to start 1096528c8403ad2ede53054a706a20c00b710fa08166Andy Hung if (mNextAudioClockUpdateTimeUs == -1) { 1097528c8403ad2ede53054a706a20c00b710fa08166Andy Hung AudioTimestamp ts; 1098528c8403ad2ede53054a706a20c00b710fa08166Andy Hung if (mAudioSink->getTimestamp(ts) == OK && ts.mPosition > 0) { 1099528c8403ad2ede53054a706a20c00b710fa08166Andy Hung mNextAudioClockUpdateTimeUs = 0; // start our clock updates 1100528c8403ad2ede53054a706a20c00b710fa08166Andy Hung } 1101528c8403ad2ede53054a706a20c00b710fa08166Andy Hung } 110212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia int64_t nowUs = ALooper::GetNowUs(); 1103528c8403ad2ede53054a706a20c00b710fa08166Andy Hung if (mNextAudioClockUpdateTimeUs >= 0) { 1104528c8403ad2ede53054a706a20c00b710fa08166Andy Hung if (nowUs >= mNextAudioClockUpdateTimeUs) { 1105528c8403ad2ede53054a706a20c00b710fa08166Andy Hung int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs); 1106528c8403ad2ede53054a706a20c00b710fa08166Andy Hung mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs); 1107d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia mUseVirtualAudioSink = false; 1108528c8403ad2ede53054a706a20c00b710fa08166Andy Hung mNextAudioClockUpdateTimeUs = nowUs + kMinimumAudioClockUpdatePeriodUs; 1109528c8403ad2ede53054a706a20c00b710fa08166Andy Hung } 111012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia } else { 111112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia int64_t unused; 111212b6265f1d4be368957f91104d5210cf604ac4ccWei Jia if ((mMediaClock->getMediaTime(nowUs, &unused) != OK) 111312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia && (getDurationUsIfPlayedAtSampleRate(mNumFramesWritten) 111412b6265f1d4be368957f91104d5210cf604ac4ccWei Jia > kMaxAllowedAudioSinkDelayUs)) { 111512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // Enough data has been sent to AudioSink, but AudioSink has not rendered 111612b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // any data yet. Something is wrong with AudioSink, e.g., the device is not 111712b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // connected to audio out. 111812b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // Switch to system clock. This essentially creates a virtual AudioSink with 111912b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // initial latenty of getDurationUsIfPlayedAtSampleRate(mNumFramesWritten). 112012b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // This virtual AudioSink renders audio data starting from the very first sample 112112b6265f1d4be368957f91104d5210cf604ac4ccWei Jia // and it's paced by system clock. 112207af6518b7b7eeb730ded9c5fd6fd6fb3a462bc5Wei Jia ALOGW("AudioSink stuck. ARE YOU CONNECTED TO AUDIO OUT? Switching to system clock."); 112312b6265f1d4be368957f91104d5210cf604ac4ccWei Jia mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs, nowUs, mediaTimeUs); 1124d2f35de429c67a156299f662b0783fbcead13cb6Wei Jia mUseVirtualAudioSink = true; 112512b6265f1d4be368957f91104d5210cf604ac4ccWei Jia } 11264ecbea3ae1fcefb082dc419cb663909536138ddbWei Jia } 11278edb3f85f58e8738582e8f9abbc018c85100b712Wei Jia mAnchorNumFramesWritten = mNumFramesWritten; 11287b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAnchorTimeMediaUs = mediaTimeUs; 1129eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu} 1130eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu 11317b15cb33847e6282ea8352c98894683b796127f3Wei Jia// Called without mLock acquired. 11327b15cb33847e6282ea8352c98894683b796127f3Wei Jiavoid NuPlayer::Renderer::postDrainVideoQueue() { 1133fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang if (mDrainVideoQueuePending 11347b15cb33847e6282ea8352c98894683b796127f3Wei Jia || getSyncQueues() 1135fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang || (mPaused && mVideoSampleReceived)) { 1136f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 1137f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1138f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1139f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (mVideoQueue.empty()) { 1140f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 1141f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1142f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1143f933441648ef6a71dee783d733aac17b9508b452Andreas Huber QueueEntry &entry = *mVideoQueue.begin(); 1144f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 11451d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this); 11467b15cb33847e6282ea8352c98894683b796127f3Wei Jia msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */)); 1147f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1148f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (entry.mBuffer == NULL) { 1149f933441648ef6a71dee783d733aac17b9508b452Andreas Huber // EOS doesn't carry a timestamp. 1150dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar msg->post(); 1151dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mDrainVideoQueuePending = true; 1152dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar return; 1153dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 1154dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 115500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih bool needRepostDrainVideoQueue = false; 1156dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar int64_t delayUs; 1157dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar int64_t nowUs = ALooper::GetNowUs(); 1158dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar int64_t realTimeUs; 1159dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mFlags & FLAG_REAL_TIME) { 1160d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber int64_t mediaTimeUs; 1161d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); 1162dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar realTimeUs = mediaTimeUs; 1163f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } else { 1164f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int64_t mediaTimeUs; 1165f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); 1166f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 11677b15cb33847e6282ea8352c98894683b796127f3Wei Jia { 11687b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 11697b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (mAnchorTimeMediaUs < 0) { 11707b15cb33847e6282ea8352c98894683b796127f3Wei Jia mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs); 11717b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAnchorTimeMediaUs = mediaTimeUs; 11727b15cb33847e6282ea8352c98894683b796127f3Wei Jia realTimeUs = nowUs; 117325d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia } else if (!mVideoSampleReceived) { 117425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia // Always render the first video frame. 117525d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia realTimeUs = nowUs; 117600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih } else if (mAudioFirstAnchorTimeMediaUs < 0 117700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih || mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OK) { 11787b15cb33847e6282ea8352c98894683b796127f3Wei Jia realTimeUs = getRealTimeUs(mediaTimeUs, nowUs); 117900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih } else if (mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0) { 118000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih needRepostDrainVideoQueue = true; 118100541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih realTimeUs = nowUs; 118200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih } else { 118300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih realTimeUs = nowUs; 11847b15cb33847e6282ea8352c98894683b796127f3Wei Jia } 1185f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1186f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar if (!mHasAudio) { 11877b15cb33847e6282ea8352c98894683b796127f3Wei Jia // smooth out videos >= 10fps 11887b15cb33847e6282ea8352c98894683b796127f3Wei Jia mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000); 1189f592671336be0a061799033e47ceeacb648ed3bfLajos Molnar } 1190d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar 1191d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar // Heuristics to handle situation when media time changed without a 1192d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar // discontinuity. If we have not drained an audio buffer that was 1193d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar // received after this buffer, repost in 10 msec. Otherwise repost 1194d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar // in 500 msec. 1195d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar delayUs = realTimeUs - nowUs; 119600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih int64_t postDelayUs = -1; 1197d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar if (delayUs > 500000) { 119800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih postDelayUs = 500000; 1199d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) { 1200d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar postDelayUs = 10000; 1201d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar } 120200541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih } else if (needRepostDrainVideoQueue) { 120300541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih // CHECK(mPlaybackRate > 0); 120400541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih // CHECK(mAudioFirstAnchorTimeMediaUs >= 0); 120500541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih // CHECK(mediaTimeUs - mAudioFirstAnchorTimeMediaUs >= 0); 120600541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih postDelayUs = mediaTimeUs - mAudioFirstAnchorTimeMediaUs; 120700541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih postDelayUs /= mPlaybackRate; 120800541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih } 120900541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih 121000541e293c250ea9e31b6ab2dc134802e34fe843Robert Shih if (postDelayUs >= 0) { 1211d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar msg->setWhat(kWhatPostDrainVideoQueue); 1212d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar msg->post(postDelayUs); 1213d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar mVideoScheduler->restart(); 1214238e1247a1fde2c7857ec243563126de72346a89Wei Jia ALOGI("possible video time jump of %dms (%lld : %lld) or uninitialized media clock," 1215238e1247a1fde2c7857ec243563126de72346a89Wei Jia " retrying in %dms", 1216238e1247a1fde2c7857ec243563126de72346a89Wei Jia (int)(delayUs / 1000), (long long)mediaTimeUs, 1217238e1247a1fde2c7857ec243563126de72346a89Wei Jia (long long)mAudioFirstAnchorTimeMediaUs, (int)(postDelayUs / 1000)); 1218d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar mDrainVideoQueuePending = true; 1219d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar return; 1220d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar } 1221f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1222f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1223dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000; 1224dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar int64_t twoVsyncsUs = 2 * (mVideoScheduler->getVsyncPeriod() / 1000); 1225dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 1226dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar delayUs = realTimeUs - nowUs; 1227dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar 1228095248375e29adde961ec2a44989ecb3a6dda6a2Lajos Molnar ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs); 1229dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar // post 2 display refreshes before rendering is due 1230dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0); 1231f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1232f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainVideoQueuePending = true; 1233f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1234f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1235f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onDrainVideoQueue() { 1236f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (mVideoQueue.empty()) { 1237f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 1238f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1239f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1240f933441648ef6a71dee783d733aac17b9508b452Andreas Huber QueueEntry *entry = &*mVideoQueue.begin(); 1241f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1242f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (entry->mBuffer == NULL) { 1243f933441648ef6a71dee783d733aac17b9508b452Andreas Huber // EOS 1244f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1245c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber notifyEOS(false /* audio */, entry->mFinalResult); 1246f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1247f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mVideoQueue.erase(mVideoQueue.begin()); 1248f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry = NULL; 12493fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber 1250a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu setVideoLateByUs(0); 1251f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 1252f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1253f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 125425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia int64_t nowUs = ALooper::GetNowUs(); 1255d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber int64_t realTimeUs; 12562995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia int64_t mediaTimeUs = -1; 1257d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber if (mFlags & FLAG_REAL_TIME) { 1258d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs)); 1259d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber } else { 1260d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); 1261d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber 1262a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu realTimeUs = getRealTimeUs(mediaTimeUs, nowUs); 1263d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber } 1264f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1265fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang bool tooLate = false; 12663fe62150fa3dd6d25cb84aad80bc9e27ddd16c45Andreas Huber 1267fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang if (!mPaused) { 1268a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu setVideoLateByUs(nowUs - realTimeUs); 1269fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang tooLate = (mVideoLateByUs > 40000); 1270fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang 1271fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang if (tooLate) { 1272fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang ALOGV("video late by %lld us (%.2f secs)", 12736d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar (long long)mVideoLateByUs, mVideoLateByUs / 1E6); 1274fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang } else { 12759816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia int64_t mediaUs = 0; 12769816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia mMediaClock->getMediaTime(realTimeUs, &mediaUs); 1277fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang ALOGV("rendering video at media time %.2f secs", 1278fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang (mFlags & FLAG_REAL_TIME ? realTimeUs : 12799816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia mediaUs) / 1E6); 12802995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia 12812995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia if (!(mFlags & FLAG_REAL_TIME) 12822995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia && mLastAudioMediaTimeUs != -1 12832995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia && mediaTimeUs > mLastAudioMediaTimeUs) { 12842995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia // If audio ends before video, video continues to drive media clock. 12852995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia // Also smooth out videos >= 10fps. 12862995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000); 12872995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia } 1288fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang } 1289078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber } else { 1290a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu setVideoLateByUs(0); 1291eecb7805bbbb712925d4372c505f8c7f5c4fb5edRonghua Wu if (!mVideoSampleReceived && !mHasAudio) { 1292a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu // This will ensure that the first frame after a flush won't be used as anchor 1293a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu // when renderer is in paused state, because resume can happen any time after seek. 12947b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 12957b15cb33847e6282ea8352c98894683b796127f3Wei Jia clearAnchorTime_l(); 129649966fff32b27f8821ebe280f25688b3c4f5f73fWei Jia } 1297078cfcf7cce9185ec7559910d08b0bc02bfc88a3Andreas Huber } 1298f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 129925d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia // Always render the first video frame while keeping stats on A/V sync. 130025d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia if (!mVideoSampleReceived) { 130125d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia realTimeUs = nowUs; 130225d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia tooLate = false; 130325d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia } 130425d696f31bfcbb24459f5d68c2288101bb5f7875Wei Jia 1305dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar entry->mNotifyConsumed->setInt64("timestampNs", realTimeUs * 1000ll); 1306683525b61bc1b58b4fd9e1b3ef9ed3b0c3bf34aeGlenn Kasten entry->mNotifyConsumed->setInt32("render", !tooLate); 1307f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry->mNotifyConsumed->post(); 1308f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mVideoQueue.erase(mVideoQueue.begin()); 1309f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry = NULL; 131043c3e6ce02215ca99d506458f596cb1211639f29Andreas Huber 1311fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang mVideoSampleReceived = true; 1312f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong 1313fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang if (!mPaused) { 1314fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang if (!mVideoRenderingStarted) { 1315fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang mVideoRenderingStarted = true; 1316fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang notifyVideoRenderingStart(); 1317fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang } 13187b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 13197b15cb33847e6282ea8352c98894683b796127f3Wei Jia notifyIfMediaRenderingStarted_l(); 1320fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang } 1321f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1322f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1323f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dongvoid NuPlayer::Renderer::notifyVideoRenderingStart() { 1324f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong sp<AMessage> notify = mNotify->dup(); 1325f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong notify->setInt32("what", kWhatVideoRenderingStart); 1326f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong notify->post(); 1327f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong} 1328f57b4ea3e409537b1d5f9aaea93d356b1cebbc6aJames Dong 13295095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wuvoid NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) { 13307c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia if (audio && delayUs > 0) { 13317c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia sp<AMessage> msg = new AMessage(kWhatEOS, this); 13327c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia msg->setInt32("audioEOSGeneration", mAudioEOSGeneration); 13337c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia msg->setInt32("finalResult", finalResult); 13347c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia msg->post(delayUs); 13357c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia return; 13367c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia } 1337f933441648ef6a71dee783d733aac17b9508b452Andreas Huber sp<AMessage> notify = mNotify->dup(); 1338f933441648ef6a71dee783d733aac17b9508b452Andreas Huber notify->setInt32("what", kWhatEOS); 1339f933441648ef6a71dee783d733aac17b9508b452Andreas Huber notify->setInt32("audio", static_cast<int32_t>(audio)); 1340c92fd24c10a6bf80b346d7e261325434d9c6964bAndreas Huber notify->setInt32("finalResult", finalResult); 13415095d7091874cb9e9c95ecc4fe762076ed05e624Ronghua Wu notify->post(delayUs); 1342f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1343f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1344a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jiavoid NuPlayer::Renderer::notifyAudioTearDown(AudioTearDownReason reason) { 1345a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia sp<AMessage> msg = new AMessage(kWhatAudioTearDown, this); 1346a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia msg->setInt32("reason", reason); 1347a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia msg->post(); 13483a2956d148d81194e297408179e84a47a309ef48Wei Jia} 13493a2956d148d81194e297408179e84a47a309ef48Wei Jia 1350f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) { 1351f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int32_t audio; 1352f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(msg->findInt32("audio", &audio)); 1353f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 13547b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (dropBufferIfStale(audio, msg)) { 13557b15cb33847e6282ea8352c98894683b796127f3Wei Jia return; 13567b15cb33847e6282ea8352c98894683b796127f3Wei Jia } 13577b15cb33847e6282ea8352c98894683b796127f3Wei Jia 13587b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (audio) { 13597b15cb33847e6282ea8352c98894683b796127f3Wei Jia mHasAudio = true; 13607b15cb33847e6282ea8352c98894683b796127f3Wei Jia } else { 13617b15cb33847e6282ea8352c98894683b796127f3Wei Jia mHasVideo = true; 13627b15cb33847e6282ea8352c98894683b796127f3Wei Jia } 1363a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu 1364a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu if (mHasVideo) { 1365dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar if (mVideoScheduler == NULL) { 1366dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVideoScheduler = new VideoFrameScheduler(); 1367dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar mVideoScheduler->init(); 1368dc43dfa1294470a4413c37e863ef3b621da8681fLajos Molnar } 1369bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber } 1370bc7f5b2e56107cfeaeeab13cf8979379e3c2f139Andreas Huber 13712d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber sp<ABuffer> buffer; 13722d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber CHECK(msg->findBuffer("buffer", &buffer)); 1373f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1374f933441648ef6a71dee783d733aac17b9508b452Andreas Huber sp<AMessage> notifyConsumed; 1375f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(msg->findMessage("notifyConsumed", ¬ifyConsumed)); 1376f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1377f933441648ef6a71dee783d733aac17b9508b452Andreas Huber QueueEntry entry; 1378f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry.mBuffer = buffer; 1379f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry.mNotifyConsumed = notifyConsumed; 1380f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry.mOffset = 0; 1381f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry.mFinalResult = OK; 1382d5923409bbcbb22954a92c2b497ef4492d7cb6a5Lajos Molnar entry.mBufferOrdinal = ++mTotalBuffersQueued; 1383f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1384f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (audio) { 13857b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 1386f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mAudioQueue.push_back(entry); 1387bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia postDrainAudioQueue_l(); 1388f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } else { 1389f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mVideoQueue.push_back(entry); 13907b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainVideoQueue(); 1391f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1392f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 13937b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 1394cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) { 1395cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber return; 1396cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber } 1397f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1398cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer; 1399cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer; 1400f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1401cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) { 1402cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber // EOS signalled on either queue. 1403bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia syncQueuesDone_l(); 1404cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber return; 1405cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber } 1406f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1407cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber int64_t firstAudioTimeUs; 1408cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber int64_t firstVideoTimeUs; 1409cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber CHECK(firstAudioBuffer->meta() 1410cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber ->findInt64("timeUs", &firstAudioTimeUs)); 1411cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber CHECK(firstVideoBuffer->meta() 1412cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber ->findInt64("timeUs", &firstVideoTimeUs)); 1413f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1414cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber int64_t diff = firstVideoTimeUs - firstAudioTimeUs; 1415f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 14163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("queueDiff = %.2f secs", diff / 1E6); 1417cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber 1418cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber if (diff > 100000ll) { 1419cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber // Audio data starts More than 0.1 secs before video. 1420cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber // Drop some audio. 1421cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber 1422cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber (*mAudioQueue.begin()).mNotifyConsumed->post(); 1423cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber mAudioQueue.erase(mAudioQueue.begin()); 1424cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber return; 1425f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1426cb67cd1b51ff9ab221e3124cf7e546515fef3c87Andreas Huber 1427bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia syncQueuesDone_l(); 1428f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1429f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1430bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::syncQueuesDone_l() { 1431f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (!mSyncQueues) { 1432f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 1433f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1434f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1435f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mSyncQueues = false; 1436f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1437f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (!mAudioQueue.empty()) { 1438bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia postDrainAudioQueue_l(); 1439f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1440f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1441f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (!mVideoQueue.empty()) { 14427b15cb33847e6282ea8352c98894683b796127f3Wei Jia mLock.unlock(); 14437b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainVideoQueue(); 14447b15cb33847e6282ea8352c98894683b796127f3Wei Jia mLock.lock(); 1445f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1446f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1447f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1448f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) { 1449f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int32_t audio; 1450f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(msg->findInt32("audio", &audio)); 1451f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 14527b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (dropBufferIfStale(audio, msg)) { 1453f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return; 1454f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1455f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1456f933441648ef6a71dee783d733aac17b9508b452Andreas Huber int32_t finalResult; 1457f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(msg->findInt32("finalResult", &finalResult)); 1458f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1459f933441648ef6a71dee783d733aac17b9508b452Andreas Huber QueueEntry entry; 1460f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry.mOffset = 0; 1461f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry.mFinalResult = finalResult; 1462f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1463f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (audio) { 14647b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 1465b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson if (mAudioQueue.empty() && mSyncQueues) { 1466bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia syncQueuesDone_l(); 1467b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson } 1468f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mAudioQueue.push_back(entry); 1469bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia postDrainAudioQueue_l(); 1470f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } else { 14717b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (mVideoQueue.empty() && getSyncQueues()) { 14727b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 1473bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia syncQueuesDone_l(); 1474b50e83eca302a12f0fced6e7bab1b8617d63deaaRoger Jönsson } 1475f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mVideoQueue.push_back(entry); 14767b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainVideoQueue(); 1477f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1478f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1479f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1480f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) { 14817137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang int32_t audio, notifyComplete; 1482f933441648ef6a71dee783d733aac17b9508b452Andreas Huber CHECK(msg->findInt32("audio", &audio)); 1483f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 148428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia { 14857b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 148628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia if (audio) { 14877137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang notifyComplete = mNotifyCompleteAudio; 14887137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mNotifyCompleteAudio = false; 14892995dc7afc23e42478969bf567aa3435f4d3b54dWei Jia mLastAudioMediaTimeUs = -1; 149028a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia } else { 14917137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang notifyComplete = mNotifyCompleteVideo; 14927137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mNotifyCompleteVideo = false; 149328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia } 149428a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia 14957b15cb33847e6282ea8352c98894683b796127f3Wei Jia // If we're currently syncing the queues, i.e. dropping audio while 14967b15cb33847e6282ea8352c98894683b796127f3Wei Jia // aligning the first audio/video buffer times and only one of the 14977b15cb33847e6282ea8352c98894683b796127f3Wei Jia // two queues has data, we may starve that queue by not requesting 14987b15cb33847e6282ea8352c98894683b796127f3Wei Jia // more buffers from the decoder. If the other source then encounters 14997b15cb33847e6282ea8352c98894683b796127f3Wei Jia // a discontinuity that leads to flushing, we'll never find the 15007b15cb33847e6282ea8352c98894683b796127f3Wei Jia // corresponding discontinuity on the other queue. 15017b15cb33847e6282ea8352c98894683b796127f3Wei Jia // Therefore we'll stop syncing the queues if at least one of them 15027b15cb33847e6282ea8352c98894683b796127f3Wei Jia // is flushed. 15037b15cb33847e6282ea8352c98894683b796127f3Wei Jia syncQueuesDone_l(); 15047b15cb33847e6282ea8352c98894683b796127f3Wei Jia clearAnchorTime_l(); 1505bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 1506f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1507cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar ALOGV("flushing %s", audio ? "audio" : "video"); 1508f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (audio) { 1509bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia { 1510bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia Mutex::Autolock autoLock(mLock); 1511bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia flushQueue(&mAudioQueue); 1512f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 15137b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mAudioDrainGeneration; 15147c8d0e0a896eb736ca4cec7fb796704a3c14ab66Wei Jia ++mAudioEOSGeneration; 15157b15cb33847e6282ea8352c98894683b796127f3Wei Jia prepareForMediaRenderingStart_l(); 151628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia 1517a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // the frame count will be reset after flush. 1518a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung clearAudioFirstAnchorTime_l(); 151928a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia } 1520f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1521f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainAudioQueuePending = false; 1522cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 1523bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (offloadingAudio()) { 1524bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioSink->pause(); 1525bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mAudioSink->flush(); 152685e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung if (!mPaused) { 152785e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung mAudioSink->start(); 152885e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung } 15299e7ed3315298b42db485963b182a572e9ab42f9fWei Jia } else { 15309e7ed3315298b42db485963b182a572e9ab42f9fWei Jia mAudioSink->pause(); 15319e7ed3315298b42db485963b182a572e9ab42f9fWei Jia mAudioSink->flush(); 15329e7ed3315298b42db485963b182a572e9ab42f9fWei Jia // Call stop() to signal to the AudioSink to completely fill the 15339e7ed3315298b42db485963b182a572e9ab42f9fWei Jia // internal buffer before resuming playback. 1534b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung // FIXME: this is ignored after flush(). 15359e7ed3315298b42db485963b182a572e9ab42f9fWei Jia mAudioSink->stop(); 1536b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung if (mPaused) { 1537b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung // Race condition: if renderer is paused and audio sink is stopped, 1538b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung // we need to make sure that the audio track buffer fully drains 1539b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung // before delivering data. 1540b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung // FIXME: remove this if we can detect if stop() is complete. 1541b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms) 1542b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs; 1543b03dcb34cd44d77e5fe1559e72323e03c59931dbAndy Hung } else { 15449e7ed3315298b42db485963b182a572e9ab42f9fWei Jia mAudioSink->start(); 15459e7ed3315298b42db485963b182a572e9ab42f9fWei Jia } 15469e7ed3315298b42db485963b182a572e9ab42f9fWei Jia mNumFramesWritten = 0; 1547bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 1548528c8403ad2ede53054a706a20c00b710fa08166Andy Hung mNextAudioClockUpdateTimeUs = -1; 1549f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } else { 1550f933441648ef6a71dee783d733aac17b9508b452Andreas Huber flushQueue(&mVideoQueue); 1551f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1552f933441648ef6a71dee783d733aac17b9508b452Andreas Huber mDrainVideoQueuePending = false; 1553cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 1554c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (mVideoScheduler != NULL) { 1555c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mVideoScheduler->restart(); 1556c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 1557c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 15587b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 15597b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mVideoDrainGeneration; 15607b15cb33847e6282ea8352c98894683b796127f3Wei Jia prepareForMediaRenderingStart_l(); 1561f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1562f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1563fbe8bef8bcf7aed97f0332908a817b0e6d91b9baChong Zhang mVideoSampleReceived = false; 15647137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 15657137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (notifyComplete) { 15667137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang notifyFlushComplete(audio); 15677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1568f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1569f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1570f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) { 1571f933441648ef6a71dee783d733aac17b9508b452Andreas Huber while (!queue->empty()) { 1572f933441648ef6a71dee783d733aac17b9508b452Andreas Huber QueueEntry *entry = &*queue->begin(); 1573f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1574f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (entry->mBuffer != NULL) { 1575f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry->mNotifyConsumed->post(); 1576f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1577f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1578f933441648ef6a71dee783d733aac17b9508b452Andreas Huber queue->erase(queue->begin()); 1579f933441648ef6a71dee783d733aac17b9508b452Andreas Huber entry = NULL; 1580f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1581f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1582f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1583f933441648ef6a71dee783d733aac17b9508b452Andreas Hubervoid NuPlayer::Renderer::notifyFlushComplete(bool audio) { 1584f933441648ef6a71dee783d733aac17b9508b452Andreas Huber sp<AMessage> notify = mNotify->dup(); 1585f933441648ef6a71dee783d733aac17b9508b452Andreas Huber notify->setInt32("what", kWhatFlushComplete); 1586f933441648ef6a71dee783d733aac17b9508b452Andreas Huber notify->setInt32("audio", static_cast<int32_t>(audio)); 1587f933441648ef6a71dee783d733aac17b9508b452Andreas Huber notify->post(); 1588f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1589f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 15907b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::dropBufferIfStale( 1591f933441648ef6a71dee783d733aac17b9508b452Andreas Huber bool audio, const sp<AMessage> &msg) { 15927b15cb33847e6282ea8352c98894683b796127f3Wei Jia int32_t queueGeneration; 15937b15cb33847e6282ea8352c98894683b796127f3Wei Jia CHECK(msg->findInt32("queueGeneration", &queueGeneration)); 1594f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 15957b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (queueGeneration == getQueueGeneration(audio)) { 1596f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return false; 1597f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1598f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1599f933441648ef6a71dee783d733aac17b9508b452Andreas Huber sp<AMessage> notifyConsumed; 1600f933441648ef6a71dee783d733aac17b9508b452Andreas Huber if (msg->findMessage("notifyConsumed", ¬ifyConsumed)) { 1601f933441648ef6a71dee783d733aac17b9508b452Andreas Huber notifyConsumed->post(); 1602f933441648ef6a71dee783d733aac17b9508b452Andreas Huber } 1603f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1604f933441648ef6a71dee783d733aac17b9508b452Andreas Huber return true; 1605f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} 1606f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 16073831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Hubervoid NuPlayer::Renderer::onAudioSinkChanged() { 1608bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia if (offloadingAudio()) { 1609bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia return; 1610bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia } 16113831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber CHECK(!mDrainAudioQueuePending); 16123831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber mNumFramesWritten = 0; 16137b15cb33847e6282ea8352c98894683b796127f3Wei Jia { 16147b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 16157b15cb33847e6282ea8352c98894683b796127f3Wei Jia mAnchorNumFramesWritten = -1; 16167b15cb33847e6282ea8352c98894683b796127f3Wei Jia } 16174110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen uint32_t written; 16184110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen if (mAudioSink->getFramesWritten(&written) == OK) { 16194110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen mNumFramesWritten = written; 16204110c101c3d0dd8dbc44c8d2d0edd3e2e7d6652fMarco Nelissen } 16213831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber} 16223831a066bcf1019864a94d2bc7b4c9241efc5c22Andreas Huber 1623bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jiavoid NuPlayer::Renderer::onDisableOffloadAudio() { 1624bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia Mutex::Autolock autoLock(mLock); 1625bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia mFlags &= ~FLAG_OFFLOAD_AUDIO; 16267b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mAudioDrainGeneration; 1627e1d701902765c710398133025cfeee3ea8b6d280Robert Shih if (mAudioRenderingStartGeneration != -1) { 1628e1d701902765c710398133025cfeee3ea8b6d280Robert Shih prepareForMediaRenderingStart_l(); 1629e1d701902765c710398133025cfeee3ea8b6d280Robert Shih } 1630bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia} 1631bc2fb720bbd0acd122bacc67e844e982d068f6f9Wei Jia 1632a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wuvoid NuPlayer::Renderer::onEnableOffloadAudio() { 1633a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu Mutex::Autolock autoLock(mLock); 1634a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu mFlags |= FLAG_OFFLOAD_AUDIO; 16357b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mAudioDrainGeneration; 1636e1d701902765c710398133025cfeee3ea8b6d280Robert Shih if (mAudioRenderingStartGeneration != -1) { 1637e1d701902765c710398133025cfeee3ea8b6d280Robert Shih prepareForMediaRenderingStart_l(); 1638e1d701902765c710398133025cfeee3ea8b6d280Robert Shih } 1639a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu} 1640a10fd23bb9fcf16e778c639ea5638e2917dacd89Ronghua Wu 1641b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onPause() { 16428592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad if (mPaused) { 16438592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad return; 16448592dbbdf5339890db2b14f83bcd6da2ffb023d2Rachad } 16456d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar 164628a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia { 164728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia Mutex::Autolock autoLock(mLock); 1648005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung // we do not increment audio drain generation so that we fill audio buffer during pause. 16497b15cb33847e6282ea8352c98894683b796127f3Wei Jia ++mVideoDrainGeneration; 16507b15cb33847e6282ea8352c98894683b796127f3Wei Jia prepareForMediaRenderingStart_l(); 165173ddd210ea572375198cac1d4960df793745fb4bWei Jia mPaused = true; 16529816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia mMediaClock->setPlaybackRate(0.0); 165328a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia } 1654b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 165528a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia mDrainAudioQueuePending = false; 1656b408222bd9479c291874b607acae1425d6154fe7Andreas Huber mDrainVideoQueuePending = false; 1657cbaffcffee6418d678806e63097c19fe26d48fe0Lajos Molnar 16588420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung // Note: audio data may not have been decoded, and the AudioSink may not be opened. 16598420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung mAudioSink->pause(); 16608420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung startAudioOffloadPauseTimeout(); 1661b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 16626d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar ALOGV("now paused audio queue has %zu entries, video has %zu entries", 1663ea9d51bd710e6739077a3700f27a1c37767a2f6dAndreas Huber mAudioQueue.size(), mVideoQueue.size()); 1664b408222bd9479c291874b607acae1425d6154fe7Andreas Huber} 1665b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 1666b408222bd9479c291874b607acae1425d6154fe7Andreas Hubervoid NuPlayer::Renderer::onResume() { 1667b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber if (!mPaused) { 1668b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber return; 1669b58ce9f5e8d0696f9571a94ba5fc05f4500f663fAndreas Huber } 1670b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 16718420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung // Note: audio data may not have been decoded, and the AudioSink may not be opened. 16728420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung cancelAudioOffloadPauseTimeout(); 16738420073fda0f6f6c68c952e030b0dbc184112e42Andy Hung if (mAudioSink->ready()) { 167497c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent status_t err = mAudioSink->start(); 167597c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent if (err != OK) { 167658d315cae745aae2c87eb3e7cac2da5e25a57d4cAndy Hung ALOGE("cannot start AudioSink err %d", err); 1677a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia notifyAudioTearDown(kDueToError); 167897c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent } 1679b408222bd9479c291874b607acae1425d6154fe7Andreas Huber } 1680b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 16817b15cb33847e6282ea8352c98894683b796127f3Wei Jia { 16827b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 16837b15cb33847e6282ea8352c98894683b796127f3Wei Jia mPaused = false; 1684b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung // rendering started message may have been delayed if we were paused. 1685b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung if (mRenderingDataDelivered) { 1686b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung notifyIfMediaRenderingStarted_l(); 1687b12ea0bbda453769584efcea69054b41d9b4c4c7Andy Hung } 16883a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar // configure audiosink as we did not do it when pausing 168927ea08e3811dc8057685258af52a7d40474eba16Wei Jia if (mAudioSink != NULL && mAudioSink->ready()) { 16903a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar mAudioSink->setPlaybackRate(mPlaybackSettings); 16913a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 16923a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 16939816016afb2a13c6a866cd047d57020566a8b9a9Wei Jia mMediaClock->setPlaybackRate(mPlaybackRate); 1694b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 16957b15cb33847e6282ea8352c98894683b796127f3Wei Jia if (!mAudioQueue.empty()) { 16967b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainAudioQueue_l(); 16977b15cb33847e6282ea8352c98894683b796127f3Wei Jia } 1698b408222bd9479c291874b607acae1425d6154fe7Andreas Huber } 1699b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 1700b408222bd9479c291874b607acae1425d6154fe7Andreas Huber if (!mVideoQueue.empty()) { 17017b15cb33847e6282ea8352c98894683b796127f3Wei Jia postDrainVideoQueue(); 1702b408222bd9479c291874b607acae1425d6154fe7Andreas Huber } 1703b408222bd9479c291874b607acae1425d6154fe7Andreas Huber} 1704b408222bd9479c291874b607acae1425d6154fe7Andreas Huber 1705c851b5de495169d7e9528644c2592746021bd968Lajos Molnarvoid NuPlayer::Renderer::onSetVideoFrameRate(float fps) { 1706c851b5de495169d7e9528644c2592746021bd968Lajos Molnar if (mVideoScheduler == NULL) { 1707c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mVideoScheduler = new VideoFrameScheduler(); 1708c851b5de495169d7e9528644c2592746021bd968Lajos Molnar } 1709c851b5de495169d7e9528644c2592746021bd968Lajos Molnar mVideoScheduler->init(fps); 1710c851b5de495169d7e9528644c2592746021bd968Lajos Molnar} 1711c851b5de495169d7e9528644c2592746021bd968Lajos Molnar 17127b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getQueueGeneration(bool audio) { 17137b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 17147b15cb33847e6282ea8352c98894683b796127f3Wei Jia return (audio ? mAudioQueueGeneration : mVideoQueueGeneration); 17157b15cb33847e6282ea8352c98894683b796127f3Wei Jia} 17167b15cb33847e6282ea8352c98894683b796127f3Wei Jia 17177b15cb33847e6282ea8352c98894683b796127f3Wei Jiaint32_t NuPlayer::Renderer::getDrainGeneration(bool audio) { 17187b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 17197b15cb33847e6282ea8352c98894683b796127f3Wei Jia return (audio ? mAudioDrainGeneration : mVideoDrainGeneration); 17207b15cb33847e6282ea8352c98894683b796127f3Wei Jia} 17217b15cb33847e6282ea8352c98894683b796127f3Wei Jia 17227b15cb33847e6282ea8352c98894683b796127f3Wei Jiabool NuPlayer::Renderer::getSyncQueues() { 17237b15cb33847e6282ea8352c98894683b796127f3Wei Jia Mutex::Autolock autoLock(mLock); 17247b15cb33847e6282ea8352c98894683b796127f3Wei Jia return mSyncQueues; 17257b15cb33847e6282ea8352c98894683b796127f3Wei Jia} 17267b15cb33847e6282ea8352c98894683b796127f3Wei Jia 1727faeb0f291330134dc4468359a36e099aae508449Ronghua Wuvoid NuPlayer::Renderer::onAudioTearDown(AudioTearDownReason reason) { 1728faeb0f291330134dc4468359a36e099aae508449Ronghua Wu if (mAudioTornDown) { 1729f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu return; 1730f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu } 1731faeb0f291330134dc4468359a36e099aae508449Ronghua Wu mAudioTornDown = true; 1732f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu 1733a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57Ronghua Wu int64_t currentPositionUs; 17341a5c859016e743779e4db25855390b3ce523cd48Robert Shih sp<AMessage> notify = mNotify->dup(); 17351a5c859016e743779e4db25855390b3ce523cd48Robert Shih if (getCurrentPosition(¤tPositionUs) == OK) { 17361a5c859016e743779e4db25855390b3ce523cd48Robert Shih notify->setInt64("positionUs", currentPositionUs); 173728a8a9ff2a2bfd5edbdbbadde50c6d804335ffdcWei Jia } 173806ad1528e6dd4c866c085d3cad9235d2752eb3edLajos Molnar 17393a2956d148d81194e297408179e84a47a309ef48Wei Jia mAudioSink->stop(); 17403a2956d148d81194e297408179e84a47a309ef48Wei Jia mAudioSink->flush(); 17413a2956d148d81194e297408179e84a47a309ef48Wei Jia 1742faeb0f291330134dc4468359a36e099aae508449Ronghua Wu notify->setInt32("what", kWhatAudioTearDown); 17430852917279f79a94907e9906d0533ae409a30f6aRonghua Wu notify->setInt32("reason", reason); 17443a2956d148d81194e297408179e84a47a309ef48Wei Jia notify->post(); 17453a2956d148d81194e297408179e84a47a309ef48Wei Jia} 17463a2956d148d81194e297408179e84a47a309ef48Wei Jia 1747f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::startAudioOffloadPauseTimeout() { 1748f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu if (offloadingAudio()) { 174935d5af131c9d4962e935082f204ccd6a2130861cWeiyin Jiang mWakeLock->acquire(); 17501d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this); 17517b15cb33847e6282ea8352c98894683b796127f3Wei Jia msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration); 1752f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu msg->post(kOffloadPauseMaxUs); 1753f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu } 1754f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu} 1755f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu 1756f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wuvoid NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() { 175721afe805580c1fdf394415648fba8e1c482def60Andy Hung // We may have called startAudioOffloadPauseTimeout() without 175821afe805580c1fdf394415648fba8e1c482def60Andy Hung // the AudioSink open and with offloadingAudio enabled. 175921afe805580c1fdf394415648fba8e1c482def60Andy Hung // 176021afe805580c1fdf394415648fba8e1c482def60Andy Hung // When we cancel, it may be that offloadingAudio is subsequently disabled, so regardless 176121afe805580c1fdf394415648fba8e1c482def60Andy Hung // we always release the wakelock and increment the pause timeout generation. 176221afe805580c1fdf394415648fba8e1c482def60Andy Hung // 176321afe805580c1fdf394415648fba8e1c482def60Andy Hung // Note: The acquired wakelock prevents the device from suspending 176421afe805580c1fdf394415648fba8e1c482def60Andy Hung // immediately after offload pause (in case a resume happens shortly thereafter). 176521afe805580c1fdf394415648fba8e1c482def60Andy Hung mWakeLock->release(true); 176621afe805580c1fdf394415648fba8e1c482def60Andy Hung ++mAudioOffloadPauseTimeoutGeneration; 1767f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu} 1768f5b1db11734358d979a23a1ac4903872186ef60bRonghua Wu 1769202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hungstatus_t NuPlayer::Renderer::onOpenAudioSink( 17703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang const sp<AMessage> &format, 17713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang bool offloadOnly, 17723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang bool hasVideo, 17733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang uint32_t flags) { 17743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)", 17753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadOnly, offloadingAudio()); 17763b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang bool audioSinkChanged = false; 17773b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 17783b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int32_t numChannels; 17793b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(format->findInt32("channel-count", &numChannels)); 17803b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 17813b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int32_t channelMask; 17823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (!format->findInt32("channel-mask", &channelMask)) { 17833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // signal to the AudioSink to derive the mask from count. 17843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; 17853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 17863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 17873b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int32_t sampleRate; 17883b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(format->findInt32("sample-rate", &sampleRate)); 17893b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 17903b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (offloadingAudio()) { 17913b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; 17923b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang AString mime; 17933b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang CHECK(format->findString("mime", &mime)); 17943b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); 17953b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 17963b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (err != OK) { 17973b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGE("Couldn't map mime \"%s\" to a valid " 17983b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang "audio_format", mime.c_str()); 17993b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang onDisableOffloadAudio(); 18003b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } else { 18013b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV("Mime \"%s\" mapped to audio_format 0x%x", 18023b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mime.c_str(), audioFormat); 18033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 18043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int avgBitRate = -1; 180546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar format->findInt32("bitrate", &avgBitRate); 18063b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 18073b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang int32_t aacProfile = -1; 18083b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (audioFormat == AUDIO_FORMAT_AAC 18093b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang && format->findInt32("aac-profile", &aacProfile)) { 18103b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // Redefine AAC format as per aac profile 18113b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mapAACProfileToAudioFormat( 18123b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang audioFormat, 18133b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang aacProfile); 18143b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 18153b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 18163b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; 18173b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.duration_us = -1; 18183b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang format->findInt64( 18193b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang "durationUs", &offloadInfo.duration_us); 18203b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.sample_rate = sampleRate; 18213b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.channel_mask = channelMask; 18223b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.format = audioFormat; 18233b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.stream_type = AUDIO_STREAM_MUSIC; 18243b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.bit_rate = avgBitRate; 18253b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.has_video = hasVideo; 18263b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang offloadInfo.is_streaming = true; 18273b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 18283b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) { 18293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV("openAudioSink: no change in offload mode"); 18303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // no change from previous configuration, everything ok. 1831202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung return OK; 18323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 1833f0e83644637bd05852c244df481f21a0d435ff66Andy Hung mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER; 1834f0e83644637bd05852c244df481f21a0d435ff66Andy Hung 18353b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV("openAudioSink: try to open AudioSink in offload mode"); 1836d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent uint32_t offloadFlags = flags; 1837d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; 1838d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 18393b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang audioSinkChanged = true; 18403b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mAudioSink->close(); 1841a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung 18423b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang err = mAudioSink->open( 18433b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sampleRate, 18443b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang numChannels, 18453b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang (audio_channel_mask_t)channelMask, 18463b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang audioFormat, 1847179652ee2a508361df1aa18e99000373886f0816Andy Hung 0 /* bufferCount - unused */, 18483b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang &NuPlayer::Renderer::AudioSinkCallback, 18493b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang this, 1850d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent (audio_output_flags_t)offloadFlags, 18513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang &offloadInfo); 18523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 18533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (err == OK) { 18543a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar err = mAudioSink->setPlaybackRate(mPlaybackSettings); 18553a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar } 18563a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar 18573a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar if (err == OK) { 18583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // If the playback is offloaded to h/w, we pass 18593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // the HAL some metadata information. 18603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // We don't want to do this for PCM because it 18613b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // will be going through the AudioFlinger mixer 18623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // before reaching the hardware. 18633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // TODO 18643b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mCurrentOffloadInfo = offloadInfo; 186585e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung if (!mPaused) { // for preview mode, don't start if paused 186685e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung err = mAudioSink->start(); 186785e48142f726770d3b65caa1f29d8b98f8d5db6bAndy Hung } 18683b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV_IF(err == OK, "openAudioSink: offload succeeded"); 18693b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 18703b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (err != OK) { 18713b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang // Clean up, fall back to non offload mode. 18723b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mAudioSink->close(); 18733b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang onDisableOffloadAudio(); 18743b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; 18753b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV("openAudioSink: offload failed"); 1876a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia if (offloadOnly) { 1877a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia notifyAudioTearDown(kForceNonOffload); 1878a05f1e3a8eb80a0a9f19456aea357d6d8e405794Wei Jia } 18793ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia } else { 18803ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia mUseAudioCallback = true; // offload mode transfers data through callback 18813ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message. 18823b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 18833b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 18843b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 18853b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (!offloadOnly && !offloadingAudio()) { 18863b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang ALOGV("openAudioSink: open AudioSink in NON-offload mode"); 1887d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent uint32_t pcmFlags = flags; 1888d88c3cafb439367f2a245b625e0a74bcd785f099Eric Laurent pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; 1889f0e83644637bd05852c244df481f21a0d435ff66Andy Hung 1890f0e83644637bd05852c244df481f21a0d435ff66Andy Hung const PcmInfo info = { 1891f0e83644637bd05852c244df481f21a0d435ff66Andy Hung (audio_channel_mask_t)channelMask, 1892f0e83644637bd05852c244df481f21a0d435ff66Andy Hung (audio_output_flags_t)pcmFlags, 1893f0e83644637bd05852c244df481f21a0d435ff66Andy Hung AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat 1894f0e83644637bd05852c244df481f21a0d435ff66Andy Hung numChannels, 1895f0e83644637bd05852c244df481f21a0d435ff66Andy Hung sampleRate 1896f0e83644637bd05852c244df481f21a0d435ff66Andy Hung }; 1897f0e83644637bd05852c244df481f21a0d435ff66Andy Hung if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) { 1898f0e83644637bd05852c244df481f21a0d435ff66Andy Hung ALOGV("openAudioSink: no change in pcm mode"); 1899f0e83644637bd05852c244df481f21a0d435ff66Andy Hung // no change from previous configuration, everything ok. 1900f0e83644637bd05852c244df481f21a0d435ff66Andy Hung return OK; 1901f0e83644637bd05852c244df481f21a0d435ff66Andy Hung } 1902f0e83644637bd05852c244df481f21a0d435ff66Andy Hung 19033b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang audioSinkChanged = true; 19043b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mAudioSink->close(); 19053b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; 1906a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // Note: It is possible to set up the callback, but not use it to send audio data. 1907a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung // This requires a fix in AudioSink to explicitly specify the transfer mode. 1908a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mUseAudioCallback = getUseAudioCallbackSetting(); 19093ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia if (mUseAudioCallback) { 19103ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message. 19113ab25457385dceb07205fc8ead86d7fb9e307588Wei Jia } 1912179652ee2a508361df1aa18e99000373886f0816Andy Hung 1913179652ee2a508361df1aa18e99000373886f0816Andy Hung // Compute the desired buffer size. 1914179652ee2a508361df1aa18e99000373886f0816Andy Hung // For callback mode, the amount of time before wakeup is about half the buffer size. 1915179652ee2a508361df1aa18e99000373886f0816Andy Hung const uint32_t frameCount = 1916179652ee2a508361df1aa18e99000373886f0816Andy Hung (unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000; 1917179652ee2a508361df1aa18e99000373886f0816Andy Hung 19187665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct 19197665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // AudioSink. We don't want this when there's video because it will cause a video seek to 19207665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // the previous I frame. But we do want this when there's only audio because it will give 19217665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // NuPlayer a chance to switch from non-offload mode to offload mode. 19227665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu // So we only set doNotReconnect when there's no video. 19237665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu const bool doNotReconnect = !hasVideo; 1924ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung 1925ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung // We should always be able to set our playback settings if the sink is closed. 1926ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung LOG_ALWAYS_FATAL_IF(mAudioSink->setPlaybackRate(mPlaybackSettings) != OK, 1927ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung "onOpenAudioSink: can't set playback rate on closed sink"); 1928202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung status_t err = mAudioSink->open( 19293b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang sampleRate, 19303b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang numChannels, 19313b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang (audio_channel_mask_t)channelMask, 19323b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang AUDIO_FORMAT_PCM_16_BIT, 1933179652ee2a508361df1aa18e99000373886f0816Andy Hung 0 /* bufferCount - unused */, 1934a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL, 1935a0b397133bfce8a62198dfac9a2b970c8b20bcc5Andy Hung mUseAudioCallback ? this : NULL, 1936faeb0f291330134dc4468359a36e099aae508449Ronghua Wu (audio_output_flags_t)pcmFlags, 1937faeb0f291330134dc4468359a36e099aae508449Ronghua Wu NULL, 19387665f5886093e1aee07a5266b8c384e5d1186f34Ronghua Wu doNotReconnect, 1939179652ee2a508361df1aa18e99000373886f0816Andy Hung frameCount); 1940202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung if (err != OK) { 1941202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung ALOGW("openAudioSink: non offloaded open failed status: %d", err); 19424d7ac854c5a45d0e3af3d0af78b5a8c9807cbec6Wei Jia mAudioSink->close(); 1943f0e83644637bd05852c244df481f21a0d435ff66Andy Hung mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER; 1944202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung return err; 1945202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung } 1946f0e83644637bd05852c244df481f21a0d435ff66Andy Hung mCurrentPcmInfo = info; 1947005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung if (!mPaused) { // for preview mode, don't start if paused 1948005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung mAudioSink->start(); 1949005e9d0300fc326a076ec17b7fa6dd4f51568f55Andy Hung } 19503b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 19513b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang if (audioSinkChanged) { 19523b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang onAudioSinkChanged(); 19533b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang } 1954faeb0f291330134dc4468359a36e099aae508449Ronghua Wu mAudioTornDown = false; 1955202bce11a7f66f27e6dbb6d154ddc123aa62513dAndy Hung return OK; 19563b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang} 19573b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 19583b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhangvoid NuPlayer::Renderer::onCloseAudioSink() { 19593b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mAudioSink->close(); 19603b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; 1961f0e83644637bd05852c244df481f21a0d435ff66Andy Hung mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER; 19623b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang} 19633b9eb1f8629c6264d924ab7043f80d824cdd39e2Chong Zhang 1964f933441648ef6a71dee783d733aac17b9508b452Andreas Huber} // namespace android 1965f933441648ef6a71dee783d733aac17b9508b452Andreas Huber 1966