1cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber/*
2cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *
4cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * you may not use this file except in compliance with the License.
6cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * You may obtain a copy of the License at
7cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *
8cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *
10cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * Unless required by applicable law or agreed to in writing, software
11cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * See the License for the specific language governing permissions and
14cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * limitations under the License.
15cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber */
16cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
17cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//#define LOG_NDEBUG 0
18cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#define LOG_TAG "MPEG2TSExtractor"
19cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/Log.h>
20cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
21cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "include/MPEG2TSExtractor.h"
22bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber#include "include/NuCachedSource2.h"
23cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
24f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
25cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/DataSource.h>
26cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaDefs.h>
27cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaErrors.h>
28cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaSource.h>
29cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MetaData.h>
30cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/String8.h>
31cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
32cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "AnotherPacketSource.h"
33cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "ATSParser.h"
34cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
35cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubernamespace android {
36cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberstatic const size_t kTSPacketSize = 188;
380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
39cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstruct MPEG2TSSource : public MediaSource {
40cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    MPEG2TSSource(
41cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber            const sp<MPEG2TSExtractor> &extractor,
42bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber            const sp<AnotherPacketSource> &impl,
43bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber            bool seekable);
44cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
45cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    virtual status_t start(MetaData *params = NULL);
46cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    virtual status_t stop();
47cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    virtual sp<MetaData> getFormat();
48cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
49cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    virtual status_t read(
50cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
51cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
52cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberprivate:
53cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    sp<MPEG2TSExtractor> mExtractor;
54cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    sp<AnotherPacketSource> mImpl;
55cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
56bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    // If there are both audio and video streams, only the video stream
57bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    // will be seekable, otherwise the single stream will be seekable.
58bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    bool mSeekable;
59bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber
60cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
61cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber};
62cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
63cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSSource::MPEG2TSSource(
64cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        const sp<MPEG2TSExtractor> &extractor,
65bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        const sp<AnotherPacketSource> &impl,
66bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        bool seekable)
67cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    : mExtractor(extractor),
68bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber      mImpl(impl),
69bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber      mSeekable(seekable) {
70cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
71cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
72cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::start(MetaData *params) {
73cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return mImpl->start(params);
74cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
75cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
76cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::stop() {
77cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return mImpl->stop();
78cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
79cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
80cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSSource::getFormat() {
8114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return mImpl->getFormat();
82cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
83cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
84cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::read(
85cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
86cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    *out = NULL;
87cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
88bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    int64_t seekTimeUs;
89bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    ReadOptions::SeekMode seekMode;
90bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
9114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return ERROR_UNSUPPORTED;
92bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    }
93bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber
94cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    status_t finalResult;
95cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    while (!mImpl->hasBufferAvailable(&finalResult)) {
96cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        if (finalResult != OK) {
97cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber            return ERROR_END_OF_STREAM;
98cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        }
99cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
100cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        status_t err = mExtractor->feedMore();
101cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        if (err != OK) {
102cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber            mImpl->signalEOS(err);
103cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        }
104cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    }
105cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
106cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return mImpl->read(out, options);
107cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
108cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
109cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber////////////////////////////////////////////////////////////////////////////////
110cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
111cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
112cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    : mDataSource(source),
113cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber      mParser(new ATSParser),
114cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber      mOffset(0) {
115cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    init();
116cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
117cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
118cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersize_t MPEG2TSExtractor::countTracks() {
119cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return mSourceImpls.size();
120cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
121cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
122cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
123cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    if (index >= mSourceImpls.size()) {
124cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        return NULL;
125cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    }
126cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
127bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    bool seekable = true;
128bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    if (mSourceImpls.size() > 1) {
129bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        CHECK_EQ(mSourceImpls.size(), 2u);
130bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber
131bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        sp<MetaData> meta = mSourceImpls.editItemAt(index)->getFormat();
132bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        const char *mime;
133bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
134bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber
135bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        if (!strncasecmp("audio/", mime, 6)) {
136bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber            seekable = false;
137bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber        }
138bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    }
139bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber
140bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber    return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), seekable);
141cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
142cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
143cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSExtractor::getTrackMetaData(
14484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        size_t index, uint32_t /* flags */) {
145cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return index < mSourceImpls.size()
146cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
147cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
148cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
149cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSExtractor::getMetaData() {
150cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    sp<MetaData> meta = new MetaData;
151cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
152cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
153cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return meta;
154cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
155cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
156cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubervoid MPEG2TSExtractor::init() {
157cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    bool haveAudio = false;
158cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    bool haveVideo = false;
1590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    int numPacketsParsed = 0;
160cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
161cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    while (feedMore() == OK) {
162cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        ATSParser::SourceType type;
163cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        if (haveAudio && haveVideo) {
164cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber            break;
165cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        }
1660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        if (!haveVideo) {
1670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            sp<AnotherPacketSource> impl =
1680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                (AnotherPacketSource *)mParser->getSource(
169386d609dc513e838c7e7c4c46c604493ccd560beAndreas Huber                        ATSParser::VIDEO).get();
1700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            if (impl != NULL) {
1720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                haveVideo = true;
1730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                mSourceImpls.push(impl);
1740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            }
175cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        }
176cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
1770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        if (!haveAudio) {
1780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            sp<AnotherPacketSource> impl =
1790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                (AnotherPacketSource *)mParser->getSource(
180386d609dc513e838c7e7c4c46c604493ccd560beAndreas Huber                        ATSParser::AUDIO).get();
1810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            if (impl != NULL) {
183cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber                haveAudio = true;
1840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                mSourceImpls.push(impl);
185cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber            }
1860da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        }
1870da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
188386d609dc513e838c7e7c4c46c604493ccd560beAndreas Huber        if (++numPacketsParsed > 10000) {
1890da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            break;
190cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        }
191cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    }
192cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
193df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
194cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
195cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
196cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSExtractor::feedMore() {
197cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    Mutex::Autolock autoLock(mLock);
198cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
199cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    uint8_t packet[kTSPacketSize];
200cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
201cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
202ed8d14f6a934072cd012992c4ef16990a54baa9aAndreas Huber    if (n < (ssize_t)kTSPacketSize) {
203cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber        return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
204cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    }
205cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
2062a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber    mOffset += n;
20706528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber    return mParser->feedTSPacket(packet, kTSPacketSize);
208cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
209cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
210bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huberuint32_t MPEG2TSExtractor::flags() const {
21114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    return CAN_PAUSE;
212bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber}
213bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber
214cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber////////////////////////////////////////////////////////////////////////////////
215cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
216cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberbool SniffMPEG2TS(
2175a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
2185a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
2190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    for (int i = 0; i < 5; ++i) {
2200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        char header;
2210da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        if (source->readAt(kTSPacketSize * i, &header, 1) != 1
2220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                || header != 0x47) {
2230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            return false;
2240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        }
225cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    }
226cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
2270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *confidence = 0.1f;
228cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
229cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
230cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    return true;
231cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}
232cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber
233cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}  // namespace android
234