• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "HTTPLiveSource"
19 #include <utils/Log.h>
20 
21 #include "HTTPLiveSource.h"
22 
23 #include "ATSParser.h"
24 #include "AnotherPacketSource.h"
25 #include "LiveDataSource.h"
26 #include "LiveSession.h"
27 
28 #include <media/stagefright/foundation/ABuffer.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/AMessage.h>
31 #include <media/stagefright/MediaErrors.h>
32 #include <media/stagefright/MetaData.h>
33 
34 namespace android {
35 
HTTPLiveSource(const sp<AMessage> & notify,const char * url,const KeyedVector<String8,String8> * headers,bool uidValid,uid_t uid)36 NuPlayer::HTTPLiveSource::HTTPLiveSource(
37         const sp<AMessage> &notify,
38         const char *url,
39         const KeyedVector<String8, String8> *headers,
40         bool uidValid, uid_t uid)
41     : Source(notify),
42       mURL(url),
43       mUIDValid(uidValid),
44       mUID(uid),
45       mFlags(0),
46       mFinalResult(OK),
47       mOffset(0) {
48     if (headers) {
49         mExtraHeaders = *headers;
50 
51         ssize_t index =
52             mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
53 
54         if (index >= 0) {
55             mFlags |= kFlagIncognito;
56 
57             mExtraHeaders.removeItemsAt(index);
58         }
59     }
60 }
61 
~HTTPLiveSource()62 NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
63     if (mLiveSession != NULL) {
64         mLiveSession->disconnect();
65         mLiveLooper->stop();
66     }
67 }
68 
prepareAsync()69 void NuPlayer::HTTPLiveSource::prepareAsync() {
70     mLiveLooper = new ALooper;
71     mLiveLooper->setName("http live");
72     mLiveLooper->start();
73 
74     sp<AMessage> notify = new AMessage(kWhatSessionNotify, id());
75 
76     mLiveSession = new LiveSession(
77             notify,
78             (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
79             mUIDValid, mUID);
80 
81     mLiveLooper->registerHandler(mLiveSession);
82 
83     mLiveSession->connect(
84             mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
85 
86     mTSParser = new ATSParser;
87 }
88 
start()89 void NuPlayer::HTTPLiveSource::start() {
90 }
91 
getFormatMeta(bool audio)92 sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
93     ATSParser::SourceType type =
94         audio ? ATSParser::AUDIO : ATSParser::VIDEO;
95 
96     sp<AnotherPacketSource> source =
97         static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
98 
99     if (source == NULL) {
100         return NULL;
101     }
102 
103     return source->getFormat();
104 }
105 
feedMoreTSData()106 status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
107     if (mFinalResult != OK) {
108         return mFinalResult;
109     }
110 
111     sp<LiveDataSource> source =
112         static_cast<LiveDataSource *>(mLiveSession->getDataSource().get());
113 
114     for (int32_t i = 0; i < 50; ++i) {
115         char buffer[188];
116         ssize_t n = source->readAtNonBlocking(mOffset, buffer, sizeof(buffer));
117 
118         if (n == -EWOULDBLOCK) {
119             break;
120         } else if (n < 0) {
121             if (n != ERROR_END_OF_STREAM) {
122                 ALOGI("input data EOS reached, error %ld", n);
123             } else {
124                 ALOGI("input data EOS reached.");
125             }
126             mTSParser->signalEOS(n);
127             mFinalResult = n;
128             break;
129         } else {
130             if (buffer[0] == 0x00) {
131                 // XXX legacy
132 
133                 uint8_t type = buffer[1];
134 
135                 sp<AMessage> extra = new AMessage;
136 
137                 if (type & 2) {
138                     int64_t mediaTimeUs;
139                     memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
140 
141                     extra->setInt64(IStreamListener::kKeyMediaTimeUs, mediaTimeUs);
142                 }
143 
144                 mTSParser->signalDiscontinuity(
145                         ((type & 1) == 0)
146                             ? ATSParser::DISCONTINUITY_SEEK
147                             : ATSParser::DISCONTINUITY_FORMATCHANGE,
148                         extra);
149             } else {
150                 status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
151 
152                 if (err != OK) {
153                     ALOGE("TS Parser returned error %d", err);
154                     mTSParser->signalEOS(err);
155                     mFinalResult = err;
156                     break;
157                 }
158             }
159 
160             mOffset += n;
161         }
162     }
163 
164     return OK;
165 }
166 
dequeueAccessUnit(bool audio,sp<ABuffer> * accessUnit)167 status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
168         bool audio, sp<ABuffer> *accessUnit) {
169     ATSParser::SourceType type =
170         audio ? ATSParser::AUDIO : ATSParser::VIDEO;
171 
172     sp<AnotherPacketSource> source =
173         static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
174 
175     if (source == NULL) {
176         return -EWOULDBLOCK;
177     }
178 
179     status_t finalResult;
180     if (!source->hasBufferAvailable(&finalResult)) {
181         return finalResult == OK ? -EWOULDBLOCK : finalResult;
182     }
183 
184     return source->dequeueAccessUnit(accessUnit);
185 }
186 
getDuration(int64_t * durationUs)187 status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
188     return mLiveSession->getDuration(durationUs);
189 }
190 
seekTo(int64_t seekTimeUs)191 status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
192     // We need to make sure we're not seeking until we have seen the very first
193     // PTS timestamp in the whole stream (from the beginning of the stream).
194     while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData() == OK) {
195         usleep(100000);
196     }
197 
198     mLiveSession->seekTo(seekTimeUs);
199 
200     return OK;
201 }
202 
onMessageReceived(const sp<AMessage> & msg)203 void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
204     switch (msg->what()) {
205         case kWhatSessionNotify:
206         {
207             onSessionNotify(msg);
208             break;
209         }
210 
211         default:
212             Source::onMessageReceived(msg);
213             break;
214     }
215 }
216 
onSessionNotify(const sp<AMessage> & msg)217 void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
218     int32_t what;
219     CHECK(msg->findInt32("what", &what));
220 
221     switch (what) {
222         case LiveSession::kWhatPrepared:
223         {
224             notifyVideoSizeChanged(0, 0);
225 
226             uint32_t flags = FLAG_CAN_PAUSE;
227             if (mLiveSession->isSeekable()) {
228                 flags |= FLAG_CAN_SEEK;
229                 flags |= FLAG_CAN_SEEK_BACKWARD;
230                 flags |= FLAG_CAN_SEEK_FORWARD;
231             }
232 
233             if (mLiveSession->hasDynamicDuration()) {
234                 flags |= FLAG_DYNAMIC_DURATION;
235             }
236 
237             notifyFlagsChanged(flags);
238 
239             notifyPrepared();
240             break;
241         }
242 
243         case LiveSession::kWhatPreparationFailed:
244         {
245             status_t err;
246             CHECK(msg->findInt32("err", &err));
247 
248             notifyPrepared(err);
249             break;
250         }
251 
252         default:
253             TRESPASS();
254     }
255 }
256 
257 }  // namespace android
258 
259