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 mSeekDoneCb(NULL), 32 mSeekDoneCookie(NULL), 33 mLastSeekCompletedTimeUs(-1) { 34 mReflector = new AHandlerReflector<ARTSPController>(this); 35 looper->registerHandler(mReflector); 36 } 37 38 ARTSPController::~ARTSPController() { 39 CHECK_EQ((int)mState, (int)DISCONNECTED); 40 mLooper->unregisterHandler(mReflector->id()); 41 } 42 43 status_t ARTSPController::connect(const char *url) { 44 Mutex::Autolock autoLock(mLock); 45 46 if (mState != DISCONNECTED) { 47 return ERROR_ALREADY_CONNECTED; 48 } 49 50 sp<AMessage> msg = new AMessage(kWhatConnectDone, mReflector->id()); 51 52 mHandler = new MyHandler(url, mLooper); 53 54 mState = CONNECTING; 55 56 mHandler->connect(msg); 57 58 while (mState == CONNECTING) { 59 mCondition.wait(mLock); 60 } 61 62 if (mState != CONNECTED) { 63 mHandler.clear(); 64 } 65 66 return mConnectionResult; 67 } 68 69 void ARTSPController::disconnect() { 70 Mutex::Autolock autoLock(mLock); 71 72 if (mState != CONNECTED) { 73 return; 74 } 75 76 sp<AMessage> msg = new AMessage(kWhatDisconnectDone, mReflector->id()); 77 mHandler->disconnect(msg); 78 79 while (mState == CONNECTED) { 80 mCondition.wait(mLock); 81 } 82 83 mHandler.clear(); 84 } 85 86 void ARTSPController::seekAsync( 87 int64_t timeUs, 88 void (*seekDoneCb)(void *), void *cookie) { 89 Mutex::Autolock autoLock(mLock); 90 91 CHECK(seekDoneCb != NULL); 92 CHECK(mSeekDoneCb == NULL); 93 94 // Ignore seek requests that are too soon after the previous one has 95 // completed, we don't want to swamp the server. 96 97 bool tooEarly = 98 mLastSeekCompletedTimeUs >= 0 99 && ALooper::GetNowUs() < mLastSeekCompletedTimeUs + 500000ll; 100 101 if (mState != CONNECTED || tooEarly) { 102 (*seekDoneCb)(cookie); 103 return; 104 } 105 106 mSeekDoneCb = seekDoneCb; 107 mSeekDoneCookie = cookie; 108 109 sp<AMessage> msg = new AMessage(kWhatSeekDone, mReflector->id()); 110 mHandler->seek(timeUs, msg); 111 } 112 113 size_t ARTSPController::countTracks() { 114 if (mHandler == NULL) { 115 return 0; 116 } 117 118 return mHandler->countTracks(); 119 } 120 121 sp<MediaSource> ARTSPController::getTrack(size_t index) { 122 CHECK(mHandler != NULL); 123 124 return mHandler->getPacketSource(index); 125 } 126 127 sp<MetaData> ARTSPController::getTrackMetaData( 128 size_t index, uint32_t flags) { 129 CHECK(mHandler != NULL); 130 131 return mHandler->getPacketSource(index)->getFormat(); 132 } 133 134 void ARTSPController::onMessageReceived(const sp<AMessage> &msg) { 135 switch (msg->what()) { 136 case kWhatConnectDone: 137 { 138 Mutex::Autolock autoLock(mLock); 139 140 CHECK(msg->findInt32("result", &mConnectionResult)); 141 mState = (mConnectionResult == OK) ? CONNECTED : DISCONNECTED; 142 143 mCondition.signal(); 144 break; 145 } 146 147 case kWhatDisconnectDone: 148 { 149 Mutex::Autolock autoLock(mLock); 150 mState = DISCONNECTED; 151 mCondition.signal(); 152 break; 153 } 154 155 case kWhatSeekDone: 156 { 157 LOGI("seek done"); 158 159 mLastSeekCompletedTimeUs = ALooper::GetNowUs(); 160 161 void (*seekDoneCb)(void *) = mSeekDoneCb; 162 mSeekDoneCb = NULL; 163 164 (*seekDoneCb)(mSeekDoneCookie); 165 break; 166 } 167 168 default: 169 TRESPASS(); 170 break; 171 } 172 } 173 174 int64_t ARTSPController::getNormalPlayTimeUs() { 175 CHECK(mHandler != NULL); 176 return mHandler->getNormalPlayTimeUs(); 177 } 178 179 int64_t ARTSPController::getQueueDurationUs(bool *eos) { 180 *eos = true; 181 182 int64_t minQueuedDurationUs = 0; 183 for (size_t i = 0; i < mHandler->countTracks(); ++i) { 184 sp<APacketSource> source = mHandler->getPacketSource(i); 185 186 bool newEOS; 187 int64_t queuedDurationUs = source->getQueueDurationUs(&newEOS); 188 189 if (!newEOS) { 190 *eos = false; 191 } 192 193 if (i == 0 || queuedDurationUs < minQueuedDurationUs) { 194 minQueuedDurationUs = queuedDurationUs; 195 } 196 } 197 198 return minQueuedDurationUs; 199 } 200 201 } // namespace android 202