blob: 1328d2ec595cab7ead048159a520291a25f43495 [file] [log] [blame]
Andreas Huber7a747b82010-06-07 15:19:40 -07001/*
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
26namespace android {
27
28ARTSPController::ARTSPController(const sp<ALooper> &looper)
Andreas Huber8370be12010-08-23 11:28:34 -070029 : mState(DISCONNECTED),
Andreas Huber0c46b692010-10-08 15:21:08 -070030 mLooper(looper),
31 mSeekDoneCb(NULL),
32 mSeekDoneCookie(NULL),
33 mLastSeekCompletedTimeUs(-1) {
Andreas Huber8370be12010-08-23 11:28:34 -070034 mReflector = new AHandlerReflector<ARTSPController>(this);
35 looper->registerHandler(mReflector);
Andreas Huber7a747b82010-06-07 15:19:40 -070036}
37
38ARTSPController::~ARTSPController() {
Andreas Hubere0dd7d32010-08-24 14:33:58 -070039 CHECK_EQ((int)mState, (int)DISCONNECTED);
Andreas Huber8370be12010-08-23 11:28:34 -070040 mLooper->unregisterHandler(mReflector->id());
Andreas Huber7a747b82010-06-07 15:19:40 -070041}
42
43status_t ARTSPController::connect(const char *url) {
Andreas Huber8370be12010-08-23 11:28:34 -070044 Mutex::Autolock autoLock(mLock);
45
46 if (mState != DISCONNECTED) {
Andreas Huber7a747b82010-06-07 15:19:40 -070047 return ERROR_ALREADY_CONNECTED;
48 }
49
Andreas Huber8370be12010-08-23 11:28:34 -070050 sp<AMessage> msg = new AMessage(kWhatConnectDone, mReflector->id());
51
Andreas Huber7a747b82010-06-07 15:19:40 -070052 mHandler = new MyHandler(url, mLooper);
Andreas Huber4e4173b2010-07-22 09:20:13 -070053
Andreas Huber8370be12010-08-23 11:28:34 -070054 mState = CONNECTING;
Andreas Huber7a747b82010-06-07 15:19:40 -070055
Andreas Huber8370be12010-08-23 11:28:34 -070056 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;
Andreas Huber7a747b82010-06-07 15:19:40 -070067}
68
69void ARTSPController::disconnect() {
Andreas Huber8370be12010-08-23 11:28:34 -070070 Mutex::Autolock autoLock(mLock);
71
Andreas Hubercb218792011-02-14 14:14:23 -080072 if (mState == CONNECTING) {
73 mState = DISCONNECTED;
74 mConnectionResult = ERROR_IO;
75 mCondition.broadcast();
76
77 mHandler.clear();
78 return;
79 } else if (mState != CONNECTED) {
Andreas Huber7a747b82010-06-07 15:19:40 -070080 return;
81 }
82
Andreas Huber8370be12010-08-23 11:28:34 -070083 sp<AMessage> msg = new AMessage(kWhatDisconnectDone, mReflector->id());
84 mHandler->disconnect(msg);
85
86 while (mState == CONNECTED) {
87 mCondition.wait(mLock);
88 }
89
Andreas Huber7a747b82010-06-07 15:19:40 -070090 mHandler.clear();
91}
92
Andreas Huber0c46b692010-10-08 15:21:08 -070093void ARTSPController::seekAsync(
94 int64_t timeUs,
95 void (*seekDoneCb)(void *), void *cookie) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -070096 Mutex::Autolock autoLock(mLock);
97
Andreas Huber0c46b692010-10-08 15:21:08 -070098 CHECK(seekDoneCb != NULL);
99 CHECK(mSeekDoneCb == NULL);
100
101 // Ignore seek requests that are too soon after the previous one has
102 // completed, we don't want to swamp the server.
103
104 bool tooEarly =
105 mLastSeekCompletedTimeUs >= 0
106 && ALooper::GetNowUs() < mLastSeekCompletedTimeUs + 500000ll;
107
108 if (mState != CONNECTED || tooEarly) {
109 (*seekDoneCb)(cookie);
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700110 return;
111 }
112
Andreas Huber0c46b692010-10-08 15:21:08 -0700113 mSeekDoneCb = seekDoneCb;
114 mSeekDoneCookie = cookie;
115
116 sp<AMessage> msg = new AMessage(kWhatSeekDone, mReflector->id());
117 mHandler->seek(timeUs, msg);
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700118}
119
Andreas Huber7a747b82010-06-07 15:19:40 -0700120size_t ARTSPController::countTracks() {
121 if (mHandler == NULL) {
122 return 0;
123 }
124
125 return mHandler->countTracks();
126}
127
128sp<MediaSource> ARTSPController::getTrack(size_t index) {
129 CHECK(mHandler != NULL);
130
131 return mHandler->getPacketSource(index);
132}
133
134sp<MetaData> ARTSPController::getTrackMetaData(
135 size_t index, uint32_t flags) {
136 CHECK(mHandler != NULL);
137
138 return mHandler->getPacketSource(index)->getFormat();
139}
140
Andreas Huber8370be12010-08-23 11:28:34 -0700141void ARTSPController::onMessageReceived(const sp<AMessage> &msg) {
142 switch (msg->what()) {
143 case kWhatConnectDone:
144 {
145 Mutex::Autolock autoLock(mLock);
146
147 CHECK(msg->findInt32("result", &mConnectionResult));
148 mState = (mConnectionResult == OK) ? CONNECTED : DISCONNECTED;
149
150 mCondition.signal();
151 break;
152 }
153
154 case kWhatDisconnectDone:
155 {
156 Mutex::Autolock autoLock(mLock);
157 mState = DISCONNECTED;
158 mCondition.signal();
159 break;
160 }
161
Andreas Huber0c46b692010-10-08 15:21:08 -0700162 case kWhatSeekDone:
163 {
164 LOGI("seek done");
165
166 mLastSeekCompletedTimeUs = ALooper::GetNowUs();
167
168 void (*seekDoneCb)(void *) = mSeekDoneCb;
169 mSeekDoneCb = NULL;
170
171 (*seekDoneCb)(mSeekDoneCookie);
172 break;
173 }
174
Andreas Huber8370be12010-08-23 11:28:34 -0700175 default:
176 TRESPASS();
177 break;
178 }
179}
180
Andreas Hubereeb97d92010-08-27 13:29:08 -0700181int64_t ARTSPController::getNormalPlayTimeUs() {
182 CHECK(mHandler != NULL);
183 return mHandler->getNormalPlayTimeUs();
184}
185
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700186int64_t ARTSPController::getQueueDurationUs(bool *eos) {
187 *eos = true;
188
189 int64_t minQueuedDurationUs = 0;
190 for (size_t i = 0; i < mHandler->countTracks(); ++i) {
191 sp<APacketSource> source = mHandler->getPacketSource(i);
192
193 bool newEOS;
194 int64_t queuedDurationUs = source->getQueueDurationUs(&newEOS);
195
196 if (!newEOS) {
197 *eos = false;
198 }
199
200 if (i == 0 || queuedDurationUs < minQueuedDurationUs) {
201 minQueuedDurationUs = queuedDurationUs;
202 }
203 }
204
205 return minQueuedDurationUs;
206}
207
Andreas Huber7a747b82010-06-07 15:19:40 -0700208} // namespace android