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 #include "AnotherPacketSource.h"
     18 
     19 #include <media/stagefright/foundation/ABuffer.h>
     20 #include <media/stagefright/foundation/ADebug.h>
     21 #include <media/stagefright/foundation/AMessage.h>
     22 #include <media/stagefright/foundation/AString.h>
     23 #include <media/stagefright/foundation/hexdump.h>
     24 #include <media/stagefright/MediaBuffer.h>
     25 #include <media/stagefright/MediaDefs.h>
     26 #include <media/stagefright/MetaData.h>
     27 #include <utils/Vector.h>
     28 
     29 namespace android {
     30 
     31 const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
     32 
     33 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
     34     : mIsAudio(false),
     35       mFormat(NULL),
     36       mLastQueuedTimeUs(0),
     37       mEOSResult(OK),
     38       mLatestEnqueuedMeta(NULL) {
     39     setFormat(meta);
     40 }
     41 
     42 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
     43     CHECK(mFormat == NULL);
     44 
     45     mIsAudio = false;
     46 
     47     if (meta == NULL) {
     48         return;
     49     }
     50 
     51     mFormat = meta;
     52     const char *mime;
     53     CHECK(meta->findCString(kKeyMIMEType, &mime));
     54 
     55     if (!strncasecmp("audio/", mime, 6)) {
     56         mIsAudio = true;
     57     } else {
     58         CHECK(!strncasecmp("video/", mime, 6));
     59     }
     60 }
     61 
     62 AnotherPacketSource::~AnotherPacketSource() {
     63 }
     64 
     65 status_t AnotherPacketSource::start(MetaData *params) {
     66     return OK;
     67 }
     68 
     69 status_t AnotherPacketSource::stop() {
     70     return OK;
     71 }
     72 
     73 sp<MetaData> AnotherPacketSource::getFormat() {
     74     Mutex::Autolock autoLock(mLock);
     75     if (mFormat != NULL) {
     76         return mFormat;
     77     }
     78 
     79     List<sp<ABuffer> >::iterator it = mBuffers.begin();
     80     while (it != mBuffers.end()) {
     81         sp<ABuffer> buffer = *it;
     82         int32_t discontinuity;
     83         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
     84             break;
     85         }
     86 
     87         sp<RefBase> object;
     88         if (buffer->meta()->findObject("format", &object)) {
     89             return static_cast<MetaData*>(object.get());
     90         }
     91 
     92         ++it;
     93     }
     94     return NULL;
     95 }
     96 
     97 status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) {
     98     buffer->clear();
     99 
    100     Mutex::Autolock autoLock(mLock);
    101     while (mEOSResult == OK && mBuffers.empty()) {
    102         mCondition.wait(mLock);
    103     }
    104 
    105     if (!mBuffers.empty()) {
    106         *buffer = *mBuffers.begin();
    107         mBuffers.erase(mBuffers.begin());
    108 
    109         int32_t discontinuity;
    110         if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
    111             if (wasFormatChange(discontinuity)) {
    112                 mFormat.clear();
    113             }
    114 
    115             return INFO_DISCONTINUITY;
    116         }
    117 
    118         sp<RefBase> object;
    119         if ((*buffer)->meta()->findObject("format", &object)) {
    120             mFormat = static_cast<MetaData*>(object.get());
    121         }
    122 
    123         return OK;
    124     }
    125 
    126     return mEOSResult;
    127 }
    128 
    129 status_t AnotherPacketSource::read(
    130         MediaBuffer **out, const ReadOptions *) {
    131     *out = NULL;
    132 
    133     Mutex::Autolock autoLock(mLock);
    134     while (mEOSResult == OK && mBuffers.empty()) {
    135         mCondition.wait(mLock);
    136     }
    137 
    138     if (!mBuffers.empty()) {
    139         const sp<ABuffer> buffer = *mBuffers.begin();
    140         mBuffers.erase(mBuffers.begin());
    141 
    142         int32_t discontinuity;
    143         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    144             if (wasFormatChange(discontinuity)) {
    145                 mFormat.clear();
    146             }
    147 
    148             return INFO_DISCONTINUITY;
    149         }
    150 
    151         sp<RefBase> object;
    152         if (buffer->meta()->findObject("format", &object)) {
    153             mFormat = static_cast<MetaData*>(object.get());
    154         }
    155 
    156         int64_t timeUs;
    157         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
    158 
    159         MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
    160 
    161         mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
    162 
    163         *out = mediaBuffer;
    164         return OK;
    165     }
    166 
    167     return mEOSResult;
    168 }
    169 
    170 bool AnotherPacketSource::wasFormatChange(
    171         int32_t discontinuityType) const {
    172     if (mIsAudio) {
    173         return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
    174     }
    175 
    176     return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
    177 }
    178 
    179 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
    180     int32_t damaged;
    181     if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
    182         // LOG(VERBOSE) << "discarding damaged AU";
    183         return;
    184     }
    185 
    186     int64_t lastQueuedTimeUs;
    187     CHECK(buffer->meta()->findInt64("timeUs", &lastQueuedTimeUs));
    188     mLastQueuedTimeUs = lastQueuedTimeUs;
    189     ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", mLastQueuedTimeUs, mLastQueuedTimeUs / 1E6);
    190 
    191     Mutex::Autolock autoLock(mLock);
    192     mBuffers.push_back(buffer);
    193     mCondition.signal();
    194 
    195     if (!mLatestEnqueuedMeta.get()) {
    196         mLatestEnqueuedMeta = buffer->meta();
    197     } else {
    198         int64_t latestTimeUs = 0;
    199         CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs));
    200         if (lastQueuedTimeUs > latestTimeUs) {
    201             mLatestEnqueuedMeta = buffer->meta();
    202         }
    203     }
    204 }
    205 
    206 void AnotherPacketSource::clear() {
    207     Mutex::Autolock autoLock(mLock);
    208 
    209     mBuffers.clear();
    210     mEOSResult = OK;
    211 
    212     mFormat = NULL;
    213     mLatestEnqueuedMeta = NULL;
    214 }
    215 
    216 void AnotherPacketSource::queueDiscontinuity(
    217         ATSParser::DiscontinuityType type,
    218         const sp<AMessage> &extra) {
    219     Mutex::Autolock autoLock(mLock);
    220 
    221     // Leave only discontinuities in the queue.
    222     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    223     while (it != mBuffers.end()) {
    224         sp<ABuffer> oldBuffer = *it;
    225 
    226         int32_t oldDiscontinuityType;
    227         if (!oldBuffer->meta()->findInt32(
    228                     "discontinuity", &oldDiscontinuityType)) {
    229             it = mBuffers.erase(it);
    230             continue;
    231         }
    232 
    233         ++it;
    234     }
    235 
    236     mEOSResult = OK;
    237     mLastQueuedTimeUs = 0;
    238     mLatestEnqueuedMeta = NULL;
    239 
    240     sp<ABuffer> buffer = new ABuffer(0);
    241     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
    242     buffer->meta()->setMessage("extra", extra);
    243 
    244     mBuffers.push_back(buffer);
    245     mCondition.signal();
    246 }
    247 
    248 void AnotherPacketSource::signalEOS(status_t result) {
    249     CHECK(result != OK);
    250 
    251     Mutex::Autolock autoLock(mLock);
    252     mEOSResult = result;
    253     mCondition.signal();
    254 }
    255 
    256 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
    257     Mutex::Autolock autoLock(mLock);
    258     if (!mBuffers.empty()) {
    259         return true;
    260     }
    261 
    262     *finalResult = mEOSResult;
    263     return false;
    264 }
    265 
    266 int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) {
    267     Mutex::Autolock autoLock(mLock);
    268 
    269     *finalResult = mEOSResult;
    270 
    271     if (mBuffers.empty()) {
    272         return 0;
    273     }
    274 
    275     int64_t time1 = -1;
    276     int64_t time2 = -1;
    277 
    278     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    279     while (it != mBuffers.end()) {
    280         const sp<ABuffer> &buffer = *it;
    281 
    282         int64_t timeUs;
    283         if (buffer->meta()->findInt64("timeUs", &timeUs)) {
    284             if (time1 < 0) {
    285                 time1 = timeUs;
    286             }
    287 
    288             time2 = timeUs;
    289         } else {
    290             // This is a discontinuity, reset everything.
    291             time1 = time2 = -1;
    292         }
    293 
    294         ++it;
    295     }
    296 
    297     return time2 - time1;
    298 }
    299 
    300 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
    301     *timeUs = 0;
    302 
    303     Mutex::Autolock autoLock(mLock);
    304 
    305     if (mBuffers.empty()) {
    306         return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
    307     }
    308 
    309     sp<ABuffer> buffer = *mBuffers.begin();
    310     CHECK(buffer->meta()->findInt64("timeUs", timeUs));
    311 
    312     return OK;
    313 }
    314 
    315 bool AnotherPacketSource::isFinished(int64_t duration) const {
    316     if (duration > 0) {
    317         int64_t diff = duration - mLastQueuedTimeUs;
    318         if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) {
    319             ALOGV("Detecting EOS due to near end");
    320             return true;
    321         }
    322     }
    323     return (mEOSResult != OK);
    324 }
    325 
    326 sp<AMessage> AnotherPacketSource::getLatestMeta() {
    327     Mutex::Autolock autoLock(mLock);
    328     return mLatestEnqueuedMeta;
    329 }
    330 
    331 }  // namespace android
    332