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