1a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber/*
2a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber *
4a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * you may not use this file except in compliance with the License.
6a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * You may obtain a copy of the License at
7a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber *
8a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber *
10a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * Unless required by applicable law or agreed to in writing, software
11a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * See the License for the specific language governing permissions and
14a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber * limitations under the License.
15a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber */
16a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
17a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber//#define LOG_NDEBUG 0
18a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#define LOG_TAG "MPEG2TSExtractor"
19a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <utils/Log.h>
20a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
21a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include "include/MPEG2TSExtractor.h"
22b5590846c035a28399818451201aaf1256913ec3Andreas Huber#include "include/LiveSession.h"
2354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber#include "include/NuCachedSource2.h"
24a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
25a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <media/stagefright/DataSource.h>
2654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber#include <media/stagefright/MediaDebug.h>
27a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <media/stagefright/MediaDefs.h>
28a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <media/stagefright/MediaErrors.h>
29a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <media/stagefright/MediaSource.h>
30a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <media/stagefright/MetaData.h>
31a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include <utils/String8.h>
32a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
33a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include "AnotherPacketSource.h"
34a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber#include "ATSParser.h"
35a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
36a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubernamespace android {
37a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
38c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huberstatic const size_t kTSPacketSize = 188;
39c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber
40a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberstruct MPEG2TSSource : public MediaSource {
41a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    MPEG2TSSource(
42a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber            const sp<MPEG2TSExtractor> &extractor,
4354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber            const sp<AnotherPacketSource> &impl,
4454d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber            bool seekable);
45a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
46a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    virtual status_t start(MetaData *params = NULL);
47a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    virtual status_t stop();
48a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    virtual sp<MetaData> getFormat();
49a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
50a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    virtual status_t read(
51a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
52a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
53a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberprivate:
54a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    sp<MPEG2TSExtractor> mExtractor;
55a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    sp<AnotherPacketSource> mImpl;
56a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
5754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    // If there are both audio and video streams, only the video stream
5854d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    // will be seekable, otherwise the single stream will be seekable.
5954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    bool mSeekable;
6054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
61a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
62a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber};
63a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
64a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas HuberMPEG2TSSource::MPEG2TSSource(
65a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        const sp<MPEG2TSExtractor> &extractor,
6654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        const sp<AnotherPacketSource> &impl,
6754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        bool seekable)
68a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    : mExtractor(extractor),
6954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber      mImpl(impl),
7054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber      mSeekable(seekable) {
71a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
72a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
73a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberstatus_t MPEG2TSSource::start(MetaData *params) {
74a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return mImpl->start(params);
75a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
76a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
77a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberstatus_t MPEG2TSSource::stop() {
78a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return mImpl->stop();
79a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
80a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
81a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubersp<MetaData> MPEG2TSSource::getFormat() {
8254d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    sp<MetaData> meta = mImpl->getFormat();
8354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
8454d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    int64_t durationUs;
85b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mExtractor->mLiveSession != NULL
86b5590846c035a28399818451201aaf1256913ec3Andreas Huber            && mExtractor->mLiveSession->getDuration(&durationUs) == OK) {
8754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        meta->setInt64(kKeyDuration, durationUs);
8854d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    }
8954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
9054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    return meta;
91a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
92a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
93a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberstatus_t MPEG2TSSource::read(
94a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
95a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    *out = NULL;
96a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
9754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    int64_t seekTimeUs;
9854d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    ReadOptions::SeekMode seekMode;
9954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
10054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        mExtractor->seekTo(seekTimeUs);
10154d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    }
10254d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
103a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    status_t finalResult;
104a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    while (!mImpl->hasBufferAvailable(&finalResult)) {
105a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        if (finalResult != OK) {
106a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber            return ERROR_END_OF_STREAM;
107a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        }
108a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
109a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        status_t err = mExtractor->feedMore();
110a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        if (err != OK) {
111a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber            mImpl->signalEOS(err);
112a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        }
113a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    }
114a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
115a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return mImpl->read(out, options);
116a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
117a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
118a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber////////////////////////////////////////////////////////////////////////////////
119a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
120a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas HuberMPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
121a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    : mDataSource(source),
122a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber      mParser(new ATSParser),
123a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber      mOffset(0) {
124a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    init();
125a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
126a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
127a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubersize_t MPEG2TSExtractor::countTracks() {
128a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return mSourceImpls.size();
129a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
130a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
131a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubersp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
132a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    if (index >= mSourceImpls.size()) {
133a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        return NULL;
134a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    }
135a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
13654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    bool seekable = true;
13754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    if (mSourceImpls.size() > 1) {
13854d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        CHECK_EQ(mSourceImpls.size(), 2u);
13954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
14054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        sp<MetaData> meta = mSourceImpls.editItemAt(index)->getFormat();
14154d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        const char *mime;
14254d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
14354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
14454d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        if (!strncasecmp("audio/", mime, 6)) {
14554d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber            seekable = false;
14654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        }
14754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    }
14854d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
14954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), seekable);
150a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
151a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
152a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubersp<MetaData> MPEG2TSExtractor::getTrackMetaData(
153a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        size_t index, uint32_t flags) {
154a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return index < mSourceImpls.size()
155a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
156a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
157a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
158a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubersp<MetaData> MPEG2TSExtractor::getMetaData() {
159a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    sp<MetaData> meta = new MetaData;
160a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
161a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
162a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return meta;
163a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
164a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
165a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Hubervoid MPEG2TSExtractor::init() {
166a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    bool haveAudio = false;
167a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    bool haveVideo = false;
168c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber    int numPacketsParsed = 0;
169a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
170a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    while (feedMore() == OK) {
171a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        ATSParser::SourceType type;
172a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        if (haveAudio && haveVideo) {
173a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber            break;
174a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        }
175c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber        if (!haveVideo) {
176c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            sp<AnotherPacketSource> impl =
177c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber                (AnotherPacketSource *)mParser->getSource(
178eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber                        ATSParser::VIDEO).get();
179c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber
180c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            if (impl != NULL) {
181c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber                haveVideo = true;
182c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber                mSourceImpls.push(impl);
183c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            }
184a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        }
185a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
186c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber        if (!haveAudio) {
187c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            sp<AnotherPacketSource> impl =
188c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber                (AnotherPacketSource *)mParser->getSource(
189eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber                        ATSParser::AUDIO).get();
190c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber
191c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            if (impl != NULL) {
192a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber                haveAudio = true;
193c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber                mSourceImpls.push(impl);
194a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber            }
195c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber        }
196c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber
197eb2f9c193d74c005a0c78e6dbed874809d55fc81Andreas Huber        if (++numPacketsParsed > 10000) {
198c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            break;
199a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        }
200a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    }
201a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
202a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
203a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
204a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
205a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberstatus_t MPEG2TSExtractor::feedMore() {
206a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    Mutex::Autolock autoLock(mLock);
207a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
208a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    uint8_t packet[kTSPacketSize];
209a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
210a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
211d6c421f1a0ae556d315159dff8a76e4a0e62e700Andreas Huber    if (n < (ssize_t)kTSPacketSize) {
212a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber        return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
213a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    }
214a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
2154c19bf9833f59f58a9aaea566f0eb98a7fb7e2eaAndreas Huber    mOffset += n;
216eeddb0e504abf3575b71624d9453f4acfdc1d318Andreas Huber    return mParser->feedTSPacket(packet, kTSPacketSize);
217a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
218a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
219b5590846c035a28399818451201aaf1256913ec3Andreas Hubervoid MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) {
22054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    Mutex::Autolock autoLock(mLock);
22154d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
222b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mLiveSession = liveSession;
22354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber}
22454d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
22554d09724e3ea2af4e08dff47d7ade92a95784127Andreas Hubervoid MPEG2TSExtractor::seekTo(int64_t seekTimeUs) {
22654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    Mutex::Autolock autoLock(mLock);
22754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
228b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mLiveSession == NULL) {
22954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        return;
23054d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    }
23154d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
232b5590846c035a28399818451201aaf1256913ec3Andreas Huber    mLiveSession->seekTo(seekTimeUs);
23354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber}
23454d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
23554d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huberuint32_t MPEG2TSExtractor::flags() const {
23654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    Mutex::Autolock autoLock(mLock);
23754d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
23854d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    uint32_t flags = CAN_PAUSE;
23954d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
240b5590846c035a28399818451201aaf1256913ec3Andreas Huber    if (mLiveSession != NULL && mLiveSession->isSeekable()) {
24154d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber        flags |= CAN_SEEK_FORWARD | CAN_SEEK_BACKWARD | CAN_SEEK;
24254d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    }
24354d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
24454d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber    return flags;
24554d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber}
24654d09724e3ea2af4e08dff47d7ade92a95784127Andreas Huber
247a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber////////////////////////////////////////////////////////////////////////////////
248a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
249a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huberbool SniffMPEG2TS(
250efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
251efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber        sp<AMessage> *) {
252c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber    for (int i = 0; i < 5; ++i) {
253c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber        char header;
254c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber        if (source->readAt(kTSPacketSize * i, &header, 1) != 1
255c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber                || header != 0x47) {
256c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber            return false;
257c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber        }
258a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    }
259a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
260c751eccad38cf46d7478eca85beefecd2c2b4c3bAndreas Huber    *confidence = 0.1f;
261a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
262a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
263a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber    return true;
264a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}
265a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber
266a557b24ac4dd568d86b08753f7c0361d04f80d46Andreas Huber}  // namespace android
267