Home | History | Annotate | Download | only in nuplayer
      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 "StreamingSource"
     19 #include <utils/Log.h>
     20 
     21 #include "StreamingSource.h"
     22 
     23 #include "ATSParser.h"
     24 #include "AnotherPacketSource.h"
     25 #include "NuPlayerStreamListener.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/MediaSource.h>
     31 #include <media/stagefright/MetaData.h>
     32 
     33 namespace android {
     34 
     35 NuPlayer::StreamingSource::StreamingSource(
     36         const sp<AMessage> &notify,
     37         const sp<IStreamSource> &source)
     38     : Source(notify),
     39       mSource(source),
     40       mFinalResult(OK) {
     41 }
     42 
     43 NuPlayer::StreamingSource::~StreamingSource() {
     44 }
     45 
     46 void NuPlayer::StreamingSource::prepareAsync() {
     47     notifyVideoSizeChanged();
     48     notifyFlagsChanged(0);
     49     notifyPrepared();
     50 }
     51 
     52 void NuPlayer::StreamingSource::start() {
     53     mStreamListener = new NuPlayerStreamListener(mSource, 0);
     54 
     55     uint32_t sourceFlags = mSource->flags();
     56 
     57     uint32_t parserFlags = ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE;
     58     if (sourceFlags & IStreamSource::kFlagAlignedVideoData) {
     59         parserFlags |= ATSParser::ALIGNED_VIDEO_DATA;
     60     }
     61 
     62     mTSParser = new ATSParser(parserFlags);
     63 
     64     mStreamListener->start();
     65 }
     66 
     67 status_t NuPlayer::StreamingSource::feedMoreTSData() {
     68     if (mFinalResult != OK) {
     69         return mFinalResult;
     70     }
     71 
     72     for (int32_t i = 0; i < 50; ++i) {
     73         char buffer[188];
     74         sp<AMessage> extra;
     75         ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
     76 
     77         if (n == 0) {
     78             ALOGI("input data EOS reached.");
     79             mTSParser->signalEOS(ERROR_END_OF_STREAM);
     80             mFinalResult = ERROR_END_OF_STREAM;
     81             break;
     82         } else if (n == INFO_DISCONTINUITY) {
     83             int32_t type = ATSParser::DISCONTINUITY_SEEK;
     84 
     85             int32_t mask;
     86             if (extra != NULL
     87                     && extra->findInt32(
     88                         IStreamListener::kKeyDiscontinuityMask, &mask)) {
     89                 if (mask == 0) {
     90                     ALOGE("Client specified an illegal discontinuity type.");
     91                     return ERROR_UNSUPPORTED;
     92                 }
     93 
     94                 type = mask;
     95             }
     96 
     97             mTSParser->signalDiscontinuity(
     98                     (ATSParser::DiscontinuityType)type, extra);
     99         } else if (n < 0) {
    100             CHECK_EQ(n, -EWOULDBLOCK);
    101             break;
    102         } else {
    103             if (buffer[0] == 0x00) {
    104                 // XXX legacy
    105 
    106                 if (extra == NULL) {
    107                     extra = new AMessage;
    108                 }
    109 
    110                 uint8_t type = buffer[1];
    111 
    112                 if (type & 2) {
    113                     int64_t mediaTimeUs;
    114                     memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
    115 
    116                     extra->setInt64(IStreamListener::kKeyMediaTimeUs, mediaTimeUs);
    117                 }
    118 
    119                 mTSParser->signalDiscontinuity(
    120                         ((type & 1) == 0)
    121                             ? ATSParser::DISCONTINUITY_SEEK
    122                             : ATSParser::DISCONTINUITY_FORMATCHANGE,
    123                         extra);
    124             } else {
    125                 status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
    126 
    127                 if (err != OK) {
    128                     ALOGE("TS Parser returned error %d", err);
    129 
    130                     mTSParser->signalEOS(err);
    131                     mFinalResult = err;
    132                     break;
    133                 }
    134             }
    135         }
    136     }
    137 
    138     return OK;
    139 }
    140 
    141 sp<MetaData> NuPlayer::StreamingSource::getFormatMeta(bool audio) {
    142     ATSParser::SourceType type =
    143         audio ? ATSParser::AUDIO : ATSParser::VIDEO;
    144 
    145     sp<AnotherPacketSource> source =
    146         static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
    147 
    148     if (source == NULL) {
    149         return NULL;
    150     }
    151 
    152     return source->getFormat();
    153 }
    154 
    155 status_t NuPlayer::StreamingSource::dequeueAccessUnit(
    156         bool audio, sp<ABuffer> *accessUnit) {
    157     ATSParser::SourceType type =
    158         audio ? ATSParser::AUDIO : ATSParser::VIDEO;
    159 
    160     sp<AnotherPacketSource> source =
    161         static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
    162 
    163     if (source == NULL) {
    164         return -EWOULDBLOCK;
    165     }
    166 
    167     status_t finalResult;
    168     if (!source->hasBufferAvailable(&finalResult)) {
    169         return finalResult == OK ? -EWOULDBLOCK : finalResult;
    170     }
    171 
    172     status_t err = source->dequeueAccessUnit(accessUnit);
    173 
    174 #if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
    175     if (err == OK) {
    176         int64_t timeUs;
    177         CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
    178         ALOGV("dequeueAccessUnit timeUs=%lld us", timeUs);
    179     }
    180 #endif
    181 
    182     return err;
    183 }
    184 
    185 bool NuPlayer::StreamingSource::isRealTime() const {
    186     return mSource->flags() & IStreamSource::kFlagIsRealTimeData;
    187 }
    188 
    189 }  // namespace android
    190 
    191