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()->dup();
    222     } else {
    223         int64_t latestTimeUs = 0;
    224         int64_t frameDeltaUs = 0;
    225         CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs));
    226         if (lastQueuedTimeUs > latestTimeUs) {
    227             mLatestEnqueuedMeta = buffer->meta()->dup();
    228             frameDeltaUs = lastQueuedTimeUs - latestTimeUs;
    229             mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
    230         } else if (!mLatestEnqueuedMeta->findInt64("durationUs", &frameDeltaUs)) {
    231             // For B frames
    232             frameDeltaUs = latestTimeUs - lastQueuedTimeUs;
    233             mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
    234         }
    235     }
    236 }
    237 
    238 void AnotherPacketSource::clear() {
    239     Mutex::Autolock autoLock(mLock);
    240 
    241     mBuffers.clear();
    242     mEOSResult = OK;
    243     mQueuedDiscontinuityCount = 0;
    244 
    245     mFormat = NULL;
    246     mLatestEnqueuedMeta = NULL;
    247 }
    248 
    249 void AnotherPacketSource::queueDiscontinuity(
    250         ATSParser::DiscontinuityType type,
    251         const sp<AMessage> &extra,
    252         bool discard) {
    253     Mutex::Autolock autoLock(mLock);
    254 
    255     if (discard) {
    256         // Leave only discontinuities in the queue.
    257         List<sp<ABuffer> >::iterator it = mBuffers.begin();
    258         while (it != mBuffers.end()) {
    259             sp<ABuffer> oldBuffer = *it;
    260 
    261             int32_t oldDiscontinuityType;
    262             if (!oldBuffer->meta()->findInt32(
    263                         "discontinuity", &oldDiscontinuityType)) {
    264                 it = mBuffers.erase(it);
    265                 continue;
    266             }
    267 
    268             ++it;
    269         }
    270     }
    271 
    272     mEOSResult = OK;
    273     mLastQueuedTimeUs = 0;
    274     mLatestEnqueuedMeta = NULL;
    275 
    276     if (type == ATSParser::DISCONTINUITY_NONE) {
    277         return;
    278     }
    279 
    280     ++mQueuedDiscontinuityCount;
    281     sp<ABuffer> buffer = new ABuffer(0);
    282     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
    283     buffer->meta()->setMessage("extra", extra);
    284 
    285     mBuffers.push_back(buffer);
    286     mCondition.signal();
    287 }
    288 
    289 void AnotherPacketSource::signalEOS(status_t result) {
    290     CHECK(result != OK);
    291 
    292     Mutex::Autolock autoLock(mLock);
    293     mEOSResult = result;
    294     mCondition.signal();
    295 }
    296 
    297 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
    298     Mutex::Autolock autoLock(mLock);
    299     if (!mBuffers.empty()) {
    300         return true;
    301     }
    302 
    303     *finalResult = mEOSResult;
    304     return false;
    305 }
    306 
    307 int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) {
    308     Mutex::Autolock autoLock(mLock);
    309     return getBufferedDurationUs_l(finalResult);
    310 }
    311 
    312 int64_t AnotherPacketSource::getBufferedDurationUs_l(status_t *finalResult) {
    313     *finalResult = mEOSResult;
    314 
    315     if (mBuffers.empty()) {
    316         return 0;
    317     }
    318 
    319     int64_t time1 = -1;
    320     int64_t time2 = -1;
    321     int64_t durationUs = 0;
    322 
    323     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    324     while (it != mBuffers.end()) {
    325         const sp<ABuffer> &buffer = *it;
    326 
    327         int64_t timeUs;
    328         if (buffer->meta()->findInt64("timeUs", &timeUs)) {
    329             if (time1 < 0 || timeUs < time1) {
    330                 time1 = timeUs;
    331             }
    332 
    333             if (time2 < 0 || timeUs > time2) {
    334                 time2 = timeUs;
    335             }
    336         } else {
    337             // This is a discontinuity, reset everything.
    338             durationUs += time2 - time1;
    339             time1 = time2 = -1;
    340         }
    341 
    342         ++it;
    343     }
    344 
    345     return durationUs + (time2 - time1);
    346 }
    347 
    348 // A cheaper but less precise version of getBufferedDurationUs that we would like to use in
    349 // LiveSession::dequeueAccessUnit to trigger downwards adaptation.
    350 int64_t AnotherPacketSource::getEstimatedDurationUs() {
    351     Mutex::Autolock autoLock(mLock);
    352     if (mBuffers.empty()) {
    353         return 0;
    354     }
    355 
    356     if (mQueuedDiscontinuityCount > 0) {
    357         status_t finalResult;
    358         return getBufferedDurationUs_l(&finalResult);
    359     }
    360 
    361     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    362     sp<ABuffer> buffer = *it;
    363 
    364     int64_t startTimeUs;
    365     buffer->meta()->findInt64("timeUs", &startTimeUs);
    366     if (startTimeUs < 0) {
    367         return 0;
    368     }
    369 
    370     it = mBuffers.end();
    371     --it;
    372     buffer = *it;
    373 
    374     int64_t endTimeUs;
    375     buffer->meta()->findInt64("timeUs", &endTimeUs);
    376     if (endTimeUs < 0) {
    377         return 0;
    378     }
    379 
    380     int64_t diffUs;
    381     if (endTimeUs > startTimeUs) {
    382         diffUs = endTimeUs - startTimeUs;
    383     } else {
    384         diffUs = startTimeUs - endTimeUs;
    385     }
    386     return diffUs;
    387 }
    388 
    389 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
    390     *timeUs = 0;
    391 
    392     Mutex::Autolock autoLock(mLock);
    393 
    394     if (mBuffers.empty()) {
    395         return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
    396     }
    397 
    398     sp<ABuffer> buffer = *mBuffers.begin();
    399     CHECK(buffer->meta()->findInt64("timeUs", timeUs));
    400 
    401     return OK;
    402 }
    403 
    404 bool AnotherPacketSource::isFinished(int64_t duration) const {
    405     if (duration > 0) {
    406         int64_t diff = duration - mLastQueuedTimeUs;
    407         if (diff < kNearEOSMarkUs && diff > -kNearEOSMarkUs) {
    408             ALOGV("Detecting EOS due to near end");
    409             return true;
    410         }
    411     }
    412     return (mEOSResult != OK);
    413 }
    414 
    415 sp<AMessage> AnotherPacketSource::getLatestEnqueuedMeta() {
    416     Mutex::Autolock autoLock(mLock);
    417     return mLatestEnqueuedMeta;
    418 }
    419 
    420 sp<AMessage> AnotherPacketSource::getLatestDequeuedMeta() {
    421     Mutex::Autolock autoLock(mLock);
    422     return mLatestDequeuedMeta;
    423 }
    424 
    425 }  // namespace android
    426