Home | History | Annotate | Download | only in mpeg2ts
      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 "MPEG2TSExtractor"
     19 #include <utils/Log.h>
     20 
     21 #include "include/MPEG2TSExtractor.h"
     22 #include "include/LiveSession.h"
     23 #include "include/NuCachedSource2.h"
     24 
     25 #include <media/stagefright/DataSource.h>
     26 #include <media/stagefright/MediaDebug.h>
     27 #include <media/stagefright/MediaDefs.h>
     28 #include <media/stagefright/MediaErrors.h>
     29 #include <media/stagefright/MediaSource.h>
     30 #include <media/stagefright/MetaData.h>
     31 #include <utils/String8.h>
     32 
     33 #include "AnotherPacketSource.h"
     34 #include "ATSParser.h"
     35 
     36 namespace android {
     37 
     38 static const size_t kTSPacketSize = 188;
     39 
     40 struct MPEG2TSSource : public MediaSource {
     41     MPEG2TSSource(
     42             const sp<MPEG2TSExtractor> &extractor,
     43             const sp<AnotherPacketSource> &impl,
     44             bool seekable);
     45 
     46     virtual status_t start(MetaData *params = NULL);
     47     virtual status_t stop();
     48     virtual sp<MetaData> getFormat();
     49 
     50     virtual status_t read(
     51             MediaBuffer **buffer, const ReadOptions *options = NULL);
     52 
     53 private:
     54     sp<MPEG2TSExtractor> mExtractor;
     55     sp<AnotherPacketSource> mImpl;
     56 
     57     // If there are both audio and video streams, only the video stream
     58     // will be seekable, otherwise the single stream will be seekable.
     59     bool mSeekable;
     60 
     61     DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
     62 };
     63 
     64 MPEG2TSSource::MPEG2TSSource(
     65         const sp<MPEG2TSExtractor> &extractor,
     66         const sp<AnotherPacketSource> &impl,
     67         bool seekable)
     68     : mExtractor(extractor),
     69       mImpl(impl),
     70       mSeekable(seekable) {
     71 }
     72 
     73 status_t MPEG2TSSource::start(MetaData *params) {
     74     return mImpl->start(params);
     75 }
     76 
     77 status_t MPEG2TSSource::stop() {
     78     return mImpl->stop();
     79 }
     80 
     81 sp<MetaData> MPEG2TSSource::getFormat() {
     82     sp<MetaData> meta = mImpl->getFormat();
     83 
     84     int64_t durationUs;
     85     if (mExtractor->mLiveSession != NULL
     86             && mExtractor->mLiveSession->getDuration(&durationUs) == OK) {
     87         meta->setInt64(kKeyDuration, durationUs);
     88     }
     89 
     90     return meta;
     91 }
     92 
     93 status_t MPEG2TSSource::read(
     94         MediaBuffer **out, const ReadOptions *options) {
     95     *out = NULL;
     96 
     97     int64_t seekTimeUs;
     98     ReadOptions::SeekMode seekMode;
     99     if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
    100         mExtractor->seekTo(seekTimeUs);
    101     }
    102 
    103     status_t finalResult;
    104     while (!mImpl->hasBufferAvailable(&finalResult)) {
    105         if (finalResult != OK) {
    106             return ERROR_END_OF_STREAM;
    107         }
    108 
    109         status_t err = mExtractor->feedMore();
    110         if (err != OK) {
    111             mImpl->signalEOS(err);
    112         }
    113     }
    114 
    115     return mImpl->read(out, options);
    116 }
    117 
    118 ////////////////////////////////////////////////////////////////////////////////
    119 
    120 MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
    121     : mDataSource(source),
    122       mParser(new ATSParser),
    123       mOffset(0) {
    124     init();
    125 }
    126 
    127 size_t MPEG2TSExtractor::countTracks() {
    128     return mSourceImpls.size();
    129 }
    130 
    131 sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
    132     if (index >= mSourceImpls.size()) {
    133         return NULL;
    134     }
    135 
    136     bool seekable = true;
    137     if (mSourceImpls.size() > 1) {
    138         CHECK_EQ(mSourceImpls.size(), 2u);
    139 
    140         sp<MetaData> meta = mSourceImpls.editItemAt(index)->getFormat();
    141         const char *mime;
    142         CHECK(meta->findCString(kKeyMIMEType, &mime));
    143 
    144         if (!strncasecmp("audio/", mime, 6)) {
    145             seekable = false;
    146         }
    147     }
    148 
    149     return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), seekable);
    150 }
    151 
    152 sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
    153         size_t index, uint32_t flags) {
    154     return index < mSourceImpls.size()
    155         ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
    156 }
    157 
    158 sp<MetaData> MPEG2TSExtractor::getMetaData() {
    159     sp<MetaData> meta = new MetaData;
    160     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
    161 
    162     return meta;
    163 }
    164 
    165 void MPEG2TSExtractor::init() {
    166     bool haveAudio = false;
    167     bool haveVideo = false;
    168     int numPacketsParsed = 0;
    169 
    170     while (feedMore() == OK) {
    171         ATSParser::SourceType type;
    172         if (haveAudio && haveVideo) {
    173             break;
    174         }
    175         if (!haveVideo) {
    176             sp<AnotherPacketSource> impl =
    177                 (AnotherPacketSource *)mParser->getSource(
    178                         ATSParser::VIDEO).get();
    179 
    180             if (impl != NULL) {
    181                 haveVideo = true;
    182                 mSourceImpls.push(impl);
    183             }
    184         }
    185 
    186         if (!haveAudio) {
    187             sp<AnotherPacketSource> impl =
    188                 (AnotherPacketSource *)mParser->getSource(
    189                         ATSParser::AUDIO).get();
    190 
    191             if (impl != NULL) {
    192                 haveAudio = true;
    193                 mSourceImpls.push(impl);
    194             }
    195         }
    196 
    197         if (++numPacketsParsed > 10000) {
    198             break;
    199         }
    200     }
    201 
    202     LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
    203 }
    204 
    205 status_t MPEG2TSExtractor::feedMore() {
    206     Mutex::Autolock autoLock(mLock);
    207 
    208     uint8_t packet[kTSPacketSize];
    209     ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
    210 
    211     if (n < (ssize_t)kTSPacketSize) {
    212         return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
    213     }
    214 
    215     mOffset += n;
    216     return mParser->feedTSPacket(packet, kTSPacketSize);
    217 }
    218 
    219 void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) {
    220     Mutex::Autolock autoLock(mLock);
    221 
    222     mLiveSession = liveSession;
    223 }
    224 
    225 void MPEG2TSExtractor::seekTo(int64_t seekTimeUs) {
    226     Mutex::Autolock autoLock(mLock);
    227 
    228     if (mLiveSession == NULL) {
    229         return;
    230     }
    231 
    232     mLiveSession->seekTo(seekTimeUs);
    233 }
    234 
    235 uint32_t MPEG2TSExtractor::flags() const {
    236     Mutex::Autolock autoLock(mLock);
    237 
    238     uint32_t flags = CAN_PAUSE;
    239 
    240     if (mLiveSession != NULL && mLiveSession->isSeekable()) {
    241         flags |= CAN_SEEK_FORWARD | CAN_SEEK_BACKWARD | CAN_SEEK;
    242     }
    243 
    244     return flags;
    245 }
    246 
    247 ////////////////////////////////////////////////////////////////////////////////
    248 
    249 bool SniffMPEG2TS(
    250         const sp<DataSource> &source, String8 *mimeType, float *confidence,
    251         sp<AMessage> *) {
    252     for (int i = 0; i < 5; ++i) {
    253         char header;
    254         if (source->readAt(kTSPacketSize * i, &header, 1) != 1
    255                 || header != 0x47) {
    256             return false;
    257         }
    258     }
    259 
    260     *confidence = 0.1f;
    261     mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
    262 
    263     return true;
    264 }
    265 
    266 }  // namespace android
    267