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 AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
     32     : mIsAudio(false),
     33       mFormat(meta),
     34       mEOSResult(OK) {
     35     const char *mime;
     36     CHECK(meta->findCString(kKeyMIMEType, &mime));
     37 
     38     if (!strncasecmp("audio/", mime, 6)) {
     39         mIsAudio = true;
     40     } else {
     41         CHECK(!strncasecmp("video/", mime, 6));
     42     }
     43 }
     44 
     45 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
     46     CHECK(mFormat == NULL);
     47     mFormat = meta;
     48 }
     49 
     50 AnotherPacketSource::~AnotherPacketSource() {
     51 }
     52 
     53 status_t AnotherPacketSource::start(MetaData *params) {
     54     return OK;
     55 }
     56 
     57 status_t AnotherPacketSource::stop() {
     58     return OK;
     59 }
     60 
     61 sp<MetaData> AnotherPacketSource::getFormat() {
     62     return mFormat;
     63 }
     64 
     65 status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) {
     66     buffer->clear();
     67 
     68     Mutex::Autolock autoLock(mLock);
     69     while (mEOSResult == OK && mBuffers.empty()) {
     70         mCondition.wait(mLock);
     71     }
     72 
     73     if (!mBuffers.empty()) {
     74         *buffer = *mBuffers.begin();
     75         mBuffers.erase(mBuffers.begin());
     76 
     77         int32_t discontinuity;
     78         if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
     79             if (wasFormatChange(discontinuity)) {
     80                 mFormat.clear();
     81             }
     82 
     83             return INFO_DISCONTINUITY;
     84         }
     85 
     86         return OK;
     87     }
     88 
     89     return mEOSResult;
     90 }
     91 
     92 status_t AnotherPacketSource::read(
     93         MediaBuffer **out, const ReadOptions *) {
     94     *out = NULL;
     95 
     96     Mutex::Autolock autoLock(mLock);
     97     while (mEOSResult == OK && mBuffers.empty()) {
     98         mCondition.wait(mLock);
     99     }
    100 
    101     if (!mBuffers.empty()) {
    102         const sp<ABuffer> buffer = *mBuffers.begin();
    103         mBuffers.erase(mBuffers.begin());
    104 
    105         int32_t discontinuity;
    106         if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
    107             if (wasFormatChange(discontinuity)) {
    108                 mFormat.clear();
    109             }
    110 
    111             return INFO_DISCONTINUITY;
    112         } else {
    113             int64_t timeUs;
    114             CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
    115 
    116             MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
    117 
    118             mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
    119 
    120             *out = mediaBuffer;
    121             return OK;
    122         }
    123     }
    124 
    125     return mEOSResult;
    126 }
    127 
    128 bool AnotherPacketSource::wasFormatChange(
    129         int32_t discontinuityType) const {
    130     if (mIsAudio) {
    131         return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
    132     }
    133 
    134     return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
    135 }
    136 
    137 void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
    138     int32_t damaged;
    139     if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
    140         // LOG(VERBOSE) << "discarding damaged AU";
    141         return;
    142     }
    143 
    144     int64_t timeUs;
    145     CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
    146     ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6);
    147 
    148     Mutex::Autolock autoLock(mLock);
    149     mBuffers.push_back(buffer);
    150     mCondition.signal();
    151 }
    152 
    153 void AnotherPacketSource::queueDiscontinuity(
    154         ATSParser::DiscontinuityType type,
    155         const sp<AMessage> &extra) {
    156     Mutex::Autolock autoLock(mLock);
    157 
    158     // Leave only discontinuities in the queue.
    159     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    160     while (it != mBuffers.end()) {
    161         sp<ABuffer> oldBuffer = *it;
    162 
    163         int32_t oldDiscontinuityType;
    164         if (!oldBuffer->meta()->findInt32(
    165                     "discontinuity", &oldDiscontinuityType)) {
    166             it = mBuffers.erase(it);
    167             continue;
    168         }
    169 
    170         ++it;
    171     }
    172 
    173     mEOSResult = OK;
    174 
    175     sp<ABuffer> buffer = new ABuffer(0);
    176     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
    177     buffer->meta()->setMessage("extra", extra);
    178 
    179     mBuffers.push_back(buffer);
    180     mCondition.signal();
    181 }
    182 
    183 void AnotherPacketSource::signalEOS(status_t result) {
    184     CHECK(result != OK);
    185 
    186     Mutex::Autolock autoLock(mLock);
    187     mEOSResult = result;
    188     mCondition.signal();
    189 }
    190 
    191 bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
    192     Mutex::Autolock autoLock(mLock);
    193     if (!mBuffers.empty()) {
    194         return true;
    195     }
    196 
    197     *finalResult = mEOSResult;
    198     return false;
    199 }
    200 
    201 int64_t AnotherPacketSource::getBufferedDurationUs(status_t *finalResult) {
    202     Mutex::Autolock autoLock(mLock);
    203 
    204     *finalResult = mEOSResult;
    205 
    206     if (mBuffers.empty()) {
    207         return 0;
    208     }
    209 
    210     int64_t time1 = -1;
    211     int64_t time2 = -1;
    212 
    213     List<sp<ABuffer> >::iterator it = mBuffers.begin();
    214     while (it != mBuffers.end()) {
    215         const sp<ABuffer> &buffer = *it;
    216 
    217         int64_t timeUs;
    218         if (buffer->meta()->findInt64("timeUs", &timeUs)) {
    219             if (time1 < 0) {
    220                 time1 = timeUs;
    221             }
    222 
    223             time2 = timeUs;
    224         } else {
    225             // This is a discontinuity, reset everything.
    226             time1 = time2 = -1;
    227         }
    228 
    229         ++it;
    230     }
    231 
    232     return time2 - time1;
    233 }
    234 
    235 status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
    236     *timeUs = 0;
    237 
    238     Mutex::Autolock autoLock(mLock);
    239 
    240     if (mBuffers.empty()) {
    241         return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
    242     }
    243 
    244     sp<ABuffer> buffer = *mBuffers.begin();
    245     CHECK(buffer->meta()->findInt64("timeUs", timeUs));
    246 
    247     return OK;
    248 }
    249 
    250 }  // namespace android
    251