1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "ARTSPController.h" 18 19 #include "MyHandler.h" 20 21 #include <media/stagefright/foundation/ADebug.h> 22 #include <media/stagefright/MediaErrors.h> 23 #include <media/stagefright/MediaSource.h> 24 #include <media/stagefright/MetaData.h> 25 26 namespace android { 27 28 ARTSPController::ARTSPController(const sp<ALooper> &looper) 29 : mState(DISCONNECTED), 30 mLooper(looper), 31 mUIDValid(false), 32 mSeekDoneCb(NULL), 33 mSeekDoneCookie(NULL), 34 mLastSeekCompletedTimeUs(-1) { 35 mReflector = new AHandlerReflector<ARTSPController>(this); 36 looper->registerHandler(mReflector); 37 } 38 39 ARTSPController::~ARTSPController() { 40 CHECK_EQ((int)mState, (int)DISCONNECTED); 41 mLooper->unregisterHandler(mReflector->id()); 42 } 43 44 void ARTSPController::setUID(uid_t uid) { 45 mUIDValid = true; 46 mUID = uid; 47 } 48 49 status_t ARTSPController::connect(const char *url) { 50 Mutex::Autolock autoLock(mLock); 51 52 if (mState != DISCONNECTED) { 53 return ERROR_ALREADY_CONNECTED; 54 } 55 56 sp<AMessage> msg = new AMessage(kWhatConnectDone, mReflector->id()); 57 58 mHandler = new MyHandler(url, mLooper, mUIDValid, mUID); 59 60 mState = CONNECTING; 61 62 mHandler->connect(msg); 63 64 while (mState == CONNECTING) { 65 mCondition.wait(mLock); 66 } 67 68 if (mState != CONNECTED) { 69 mHandler.clear(); 70 } 71 72 return mConnectionResult; 73 } 74 75 void ARTSPController::disconnect() { 76 Mutex::Autolock autoLock(mLock); 77 78 if (mState == CONNECTING) { 79 mState = DISCONNECTED; 80 mConnectionResult = ERROR_IO; 81 mCondition.broadcast(); 82 83 mHandler.clear(); 84 return; 85 } else if (mState != CONNECTED) { 86 return; 87 } 88 89 sp<AMessage> msg = new AMessage(kWhatDisconnectDone, mReflector->id()); 90 mHandler->disconnect(msg); 91 92 while (mState == CONNECTED) { 93 mCondition.wait(mLock); 94 } 95 96 mHandler.clear(); 97 } 98 99 void ARTSPController::seekAsync( 100 int64_t timeUs, 101 void (*seekDoneCb)(void *), void *cookie) { 102 Mutex::Autolock autoLock(mLock); 103 104 CHECK(seekDoneCb != NULL); 105 CHECK(mSeekDoneCb == NULL); 106 107 // Ignore seek requests that are too soon after the previous one has 108 // completed, we don't want to swamp the server. 109 110 bool tooEarly = 111 mLastSeekCompletedTimeUs >= 0 112 && ALooper::GetNowUs() < mLastSeekCompletedTimeUs + 500000ll; 113 114 if (mState != CONNECTED || tooEarly) { 115 (*seekDoneCb)(cookie); 116 return; 117 } 118 119 mSeekDoneCb = seekDoneCb; 120 mSeekDoneCookie = cookie; 121 122 sp<AMessage> msg = new AMessage(kWhatSeekDone, mReflector->id()); 123 mHandler->seek(timeUs, msg); 124 } 125 126 size_t ARTSPController::countTracks() { 127 if (mHandler == NULL) { 128 return 0; 129 } 130 131 return mHandler->countTracks(); 132 } 133 134 sp<MediaSource> ARTSPController::getTrack(size_t index) { 135 CHECK(mHandler != NULL); 136 137 return mHandler->getPacketSource(index); 138 } 139 140 sp<MetaData> ARTSPController::getTrackMetaData( 141 size_t index, uint32_t flags) { 142 CHECK(mHandler != NULL); 143 144 return mHandler->getPacketSource(index)->getFormat(); 145 } 146 147 void ARTSPController::onMessageReceived(const sp<AMessage> &msg) { 148 switch (msg->what()) { 149 case kWhatConnectDone: 150 { 151 Mutex::Autolock autoLock(mLock); 152 153 CHECK(msg->findInt32("result", &mConnectionResult)); 154 mState = (mConnectionResult == OK) ? CONNECTED : DISCONNECTED; 155 156 mCondition.signal(); 157 break; 158 } 159 160 case kWhatDisconnectDone: 161 { 162 Mutex::Autolock autoLock(mLock); 163 mState = DISCONNECTED; 164 mCondition.signal(); 165 break; 166 } 167 168 case kWhatSeekDone: 169 { 170 LOGI("seek done"); 171 172 mLastSeekCompletedTimeUs = ALooper::GetNowUs(); 173 174 void (*seekDoneCb)(void *) = mSeekDoneCb; 175 mSeekDoneCb = NULL; 176 177 (*seekDoneCb)(mSeekDoneCookie); 178 break; 179 } 180 181 default: 182 TRESPASS(); 183 break; 184 } 185 } 186 187 int64_t ARTSPController::getNormalPlayTimeUs() { 188 CHECK(mHandler != NULL); 189 return mHandler->getNormalPlayTimeUs(); 190 } 191 192 int64_t ARTSPController::getQueueDurationUs(bool *eos) { 193 *eos = true; 194 195 int64_t minQueuedDurationUs = 0; 196 for (size_t i = 0; i < mHandler->countTracks(); ++i) { 197 sp<APacketSource> source = mHandler->getPacketSource(i); 198 199 bool newEOS; 200 int64_t queuedDurationUs = source->getQueueDurationUs(&newEOS); 201 202 if (!newEOS) { 203 *eos = false; 204 } 205 206 if (i == 0 || queuedDurationUs < minQueuedDurationUs) { 207 minQueuedDurationUs = queuedDurationUs; 208 } 209 } 210 211 return minQueuedDurationUs; 212 } 213 214 } // namespace android 215