HTTPLiveSource.cpp revision dcb89b3b505522efde173c105a851c412f947178
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 "AnotherPacketSource.h"
24#include "LiveDataSource.h"
25#include "LiveSession.h"
26
27#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/MediaErrors.h>
31#include <media/stagefright/MetaData.h>
32
33namespace android {
34
35NuPlayer::HTTPLiveSource::HTTPLiveSource(
36        const sp<AMessage> &notify,
37        const char *url,
38        const KeyedVector<String8, String8> *headers,
39        bool uidValid, uid_t uid)
40    : Source(notify),
41      mURL(url),
42      mUIDValid(uidValid),
43      mUID(uid),
44      mFlags(0),
45      mFinalResult(OK),
46      mOffset(0),
47      mFetchSubtitleDataGeneration(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
62NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
63    if (mLiveSession != NULL) {
64        mLiveSession->disconnect();
65        mLiveSession.clear();
66
67        mLiveLooper->stop();
68        mLiveLooper.clear();
69    }
70}
71
72void NuPlayer::HTTPLiveSource::prepareAsync() {
73    mLiveLooper = new ALooper;
74    mLiveLooper->setName("http live");
75    mLiveLooper->start();
76
77    sp<AMessage> notify = new AMessage(kWhatSessionNotify, id());
78
79    mLiveSession = new LiveSession(
80            notify,
81            (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
82            mUIDValid,
83            mUID);
84
85    mLiveLooper->registerHandler(mLiveSession);
86
87    mLiveSession->connectAsync(
88            mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
89}
90
91void NuPlayer::HTTPLiveSource::start() {
92}
93
94sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
95    sp<AMessage> format;
96    status_t err = mLiveSession->getStreamFormat(
97            audio ? LiveSession::STREAMTYPE_AUDIO
98                  : LiveSession::STREAMTYPE_VIDEO,
99            &format);
100
101    if (err != OK) {
102        return NULL;
103    }
104
105    return format;
106}
107
108status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
109    return OK;
110}
111
112status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
113        bool audio, sp<ABuffer> *accessUnit) {
114    return mLiveSession->dequeueAccessUnit(
115            audio ? LiveSession::STREAMTYPE_AUDIO
116                  : LiveSession::STREAMTYPE_VIDEO,
117            accessUnit);
118}
119
120status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
121    return mLiveSession->getDuration(durationUs);
122}
123
124status_t NuPlayer::HTTPLiveSource::getTrackInfo(Parcel *reply) const {
125    return mLiveSession->getTrackInfo(reply);
126}
127
128status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select) {
129    status_t err = mLiveSession->selectTrack(trackIndex, select);
130
131    if (err == OK) {
132        mFetchSubtitleDataGeneration++;
133        if (select) {
134            sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
135            msg->setInt32("generation", mFetchSubtitleDataGeneration);
136            msg->post();
137        }
138    }
139
140    // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
141    // selected track, or unselecting a non-selected track. In this case it's an
142    // no-op so we return OK.
143    return (err == OK || err == BAD_VALUE) ? OK : err;
144}
145
146status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
147    return mLiveSession->seekTo(seekTimeUs);
148}
149
150void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
151    switch (msg->what()) {
152        case kWhatSessionNotify:
153        {
154            onSessionNotify(msg);
155            break;
156        }
157
158        case kWhatFetchSubtitleData:
159        {
160            int32_t generation;
161            CHECK(msg->findInt32("generation", &generation));
162
163            if (generation != mFetchSubtitleDataGeneration) {
164                // stale
165                break;
166            }
167
168            sp<ABuffer> buffer;
169            if (mLiveSession->dequeueAccessUnit(
170                    LiveSession::STREAMTYPE_SUBTITLES, &buffer) == OK) {
171                sp<AMessage> notify = dupNotify();
172                notify->setInt32("what", kWhatSubtitleData);
173                notify->setBuffer("buffer", buffer);
174                notify->post();
175
176                int64_t timeUs, baseUs, durationUs, delayUs;
177                CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
178                CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
179                CHECK(buffer->meta()->findInt64("durationUs", &durationUs));
180                delayUs = baseUs + timeUs - ALooper::GetNowUs();
181
182                msg->post(delayUs > 0ll ? delayUs : 0ll);
183            } else {
184                // try again in 1 second
185                msg->post(1000000ll);
186            }
187
188            break;
189        }
190
191        default:
192            Source::onMessageReceived(msg);
193            break;
194    }
195}
196
197void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
198    int32_t what;
199    CHECK(msg->findInt32("what", &what));
200
201    switch (what) {
202        case LiveSession::kWhatPrepared:
203        {
204            notifyVideoSizeChanged(0, 0);
205
206            uint32_t flags = FLAG_CAN_PAUSE;
207            if (mLiveSession->isSeekable()) {
208                flags |= FLAG_CAN_SEEK;
209                flags |= FLAG_CAN_SEEK_BACKWARD;
210                flags |= FLAG_CAN_SEEK_FORWARD;
211            }
212
213            if (mLiveSession->hasDynamicDuration()) {
214                flags |= FLAG_DYNAMIC_DURATION;
215            }
216
217            notifyFlagsChanged(flags);
218
219            notifyPrepared();
220            break;
221        }
222
223        case LiveSession::kWhatPreparationFailed:
224        {
225            status_t err;
226            CHECK(msg->findInt32("err", &err));
227
228            notifyPrepared(err);
229            break;
230        }
231
232        case LiveSession::kWhatStreamsChanged:
233        {
234            uint32_t changedMask;
235            CHECK(msg->findInt32(
236                        "changedMask", (int32_t *)&changedMask));
237
238            bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
239            bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
240
241            sp<AMessage> reply;
242            CHECK(msg->findMessage("reply", &reply));
243
244            sp<AMessage> notify = dupNotify();
245            notify->setInt32("what", kWhatQueueDecoderShutdown);
246            notify->setInt32("audio", audio);
247            notify->setInt32("video", video);
248            notify->setMessage("reply", reply);
249            notify->post();
250            break;
251        }
252
253        case LiveSession::kWhatError:
254        {
255            break;
256        }
257
258        default:
259            TRESPASS();
260    }
261}
262
263}  // namespace android
264
265