Home | History | Annotate | Download | only in rtsp
      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 "AMPEG4ElementaryAssembler"
     19 #include <utils/Log.h>
     20 
     21 #include "AMPEG4ElementaryAssembler.h"
     22 
     23 #include "ARTPSource.h"
     24 #include "ASessionDescription.h"
     25 
     26 #include <media/stagefright/foundation/ABitReader.h>
     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/foundation/hexdump.h>
     31 #include <media/stagefright/Utils.h>
     32 
     33 #include <ctype.h>
     34 #include <stdint.h>
     35 
     36 namespace android {
     37 
     38 static bool GetAttribute(const char *s, const char *key, AString *value) {
     39     value->clear();
     40 
     41     size_t keyLen = strlen(key);
     42 
     43     for (;;) {
     44         while (isspace(*s)) {
     45             ++s;
     46         }
     47 
     48         const char *colonPos = strchr(s, ';');
     49 
     50         size_t len =
     51             (colonPos == NULL) ? strlen(s) : colonPos - s;
     52 
     53         if (len >= keyLen + 1 && s[keyLen] == '='
     54                 && !strncasecmp(s, key, keyLen)) {
     55             value->setTo(&s[keyLen + 1], len - keyLen - 1);
     56             return true;
     57         }
     58 
     59         if (colonPos == NULL) {
     60             return false;
     61         }
     62 
     63         s = colonPos + 1;
     64     }
     65 }
     66 
     67 static bool GetIntegerAttribute(
     68         const char *s, const char *key, unsigned *x) {
     69     *x = 0;
     70 
     71     AString val;
     72     if (!GetAttribute(s, key, &val)) {
     73         return false;
     74     }
     75 
     76     s = val.c_str();
     77     char *end;
     78     unsigned y = strtoul(s, &end, 10);
     79 
     80     if (end == s || *end != '\0') {
     81         return false;
     82     }
     83 
     84     *x = y;
     85 
     86     return true;
     87 }
     88 
     89 static bool GetSampleRateIndex(int32_t sampleRate, size_t *tableIndex) {
     90     static const int32_t kSampleRateTable[] = {
     91         96000, 88200, 64000, 48000, 44100, 32000,
     92         24000, 22050, 16000, 12000, 11025, 8000
     93     };
     94     const size_t kNumSampleRates =
     95         sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
     96 
     97     *tableIndex = 0;
     98     for (size_t index = 0; index < kNumSampleRates; ++index) {
     99         if (sampleRate == kSampleRateTable[index]) {
    100             *tableIndex = index;
    101             return true;
    102         }
    103     }
    104 
    105     return false;
    106 }
    107 
    108 // static
    109 AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
    110         const sp<AMessage> &notify, const AString &desc, const AString &params)
    111     : mNotifyMsg(notify),
    112       mIsGeneric(false),
    113       mParams(params),
    114       mSizeLength(0),
    115       mIndexLength(0),
    116       mIndexDeltaLength(0),
    117       mCTSDeltaLength(0),
    118       mDTSDeltaLength(0),
    119       mRandomAccessIndication(false),
    120       mStreamStateIndication(0),
    121       mAuxiliaryDataSizeLength(0),
    122       mHasAUHeader(false),
    123       mChannelConfig(0),
    124       mSampleRateIndex(0),
    125       mAccessUnitRTPTime(0),
    126       mNextExpectedSeqNoValid(false),
    127       mNextExpectedSeqNo(0),
    128       mAccessUnitDamaged(false) {
    129     mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
    130 
    131     if (mIsGeneric) {
    132         AString value;
    133         CHECK(GetAttribute(params.c_str(), "mode", &value));
    134 
    135         if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) {
    136             mSizeLength = 0;
    137         }
    138 
    139         if (!GetIntegerAttribute(
    140                     params.c_str(), "indexLength", &mIndexLength)) {
    141             mIndexLength = 0;
    142         }
    143 
    144         if (!GetIntegerAttribute(
    145                     params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) {
    146             mIndexDeltaLength = 0;
    147         }
    148 
    149         if (!GetIntegerAttribute(
    150                     params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) {
    151             mCTSDeltaLength = 0;
    152         }
    153 
    154         if (!GetIntegerAttribute(
    155                     params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) {
    156             mDTSDeltaLength = 0;
    157         }
    158 
    159         unsigned x;
    160         if (!GetIntegerAttribute(
    161                     params.c_str(), "randomAccessIndication", &x)) {
    162             mRandomAccessIndication = false;
    163         } else {
    164             CHECK(x == 0 || x == 1);
    165             mRandomAccessIndication = (x != 0);
    166         }
    167 
    168         if (!GetIntegerAttribute(
    169                     params.c_str(), "streamStateIndication",
    170                     &mStreamStateIndication)) {
    171             mStreamStateIndication = 0;
    172         }
    173 
    174         if (!GetIntegerAttribute(
    175                     params.c_str(), "auxiliaryDataSizeLength",
    176                     &mAuxiliaryDataSizeLength)) {
    177             mAuxiliaryDataSizeLength = 0;
    178         }
    179 
    180         mHasAUHeader =
    181             mSizeLength > 0
    182             || mIndexLength > 0
    183             || mIndexDeltaLength > 0
    184             || mCTSDeltaLength > 0
    185             || mDTSDeltaLength > 0
    186             || mRandomAccessIndication
    187             || mStreamStateIndication > 0;
    188 
    189         int32_t sampleRate, numChannels;
    190         ASessionDescription::ParseFormatDesc(
    191                 desc.c_str(), &sampleRate, &numChannels);
    192 
    193         mChannelConfig = numChannels;
    194         CHECK(GetSampleRateIndex(sampleRate, &mSampleRateIndex));
    195     }
    196 }
    197 
    198 AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
    199 }
    200 
    201 struct AUHeader {
    202     unsigned mSize;
    203     unsigned mSerial;
    204 };
    205 
    206 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
    207         const sp<ARTPSource> &source) {
    208     List<sp<ABuffer> > *queue = source->queue();
    209 
    210     if (queue->empty()) {
    211         return NOT_ENOUGH_DATA;
    212     }
    213 
    214     if (mNextExpectedSeqNoValid) {
    215         List<sp<ABuffer> >::iterator it = queue->begin();
    216         while (it != queue->end()) {
    217             if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
    218                 break;
    219             }
    220 
    221             it = queue->erase(it);
    222         }
    223 
    224         if (queue->empty()) {
    225             return NOT_ENOUGH_DATA;
    226         }
    227     }
    228 
    229     sp<ABuffer> buffer = *queue->begin();
    230 
    231     if (!mNextExpectedSeqNoValid) {
    232         mNextExpectedSeqNoValid = true;
    233         mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
    234     } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
    235         ALOGV("Not the sequence number I expected");
    236 
    237         return WRONG_SEQUENCE_NUMBER;
    238     }
    239 
    240     uint32_t rtpTime;
    241     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
    242 
    243     if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
    244         submitAccessUnit();
    245     }
    246     mAccessUnitRTPTime = rtpTime;
    247 
    248     if (!mIsGeneric) {
    249         mPackets.push_back(buffer);
    250     } else {
    251         // hexdump(buffer->data(), buffer->size());
    252 
    253         CHECK_GE(buffer->size(), 2u);
    254         unsigned AU_headers_length = U16_AT(buffer->data());  // in bits
    255 
    256         CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8);
    257 
    258         List<AUHeader> headers;
    259 
    260         ABitReader bits(buffer->data() + 2, buffer->size() - 2);
    261         unsigned numBitsLeft = AU_headers_length;
    262 
    263         unsigned AU_serial = 0;
    264         for (;;) {
    265             if (numBitsLeft < mSizeLength) { break; }
    266 
    267             unsigned AU_size = bits.getBits(mSizeLength);
    268             numBitsLeft -= mSizeLength;
    269 
    270             size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
    271             if (numBitsLeft < n) { break; }
    272 
    273             unsigned AU_index = bits.getBits(n);
    274             numBitsLeft -= n;
    275 
    276             if (headers.empty()) {
    277                 AU_serial = AU_index;
    278             } else {
    279                 AU_serial += 1 + AU_index;
    280             }
    281 
    282             if (mCTSDeltaLength > 0) {
    283                 if (numBitsLeft < 1) {
    284                     break;
    285                 }
    286                 --numBitsLeft;
    287                 if (bits.getBits(1)) {
    288                     if (numBitsLeft < mCTSDeltaLength) {
    289                         break;
    290                     }
    291                     bits.skipBits(mCTSDeltaLength);
    292                     numBitsLeft -= mCTSDeltaLength;
    293                 }
    294             }
    295 
    296             if (mDTSDeltaLength > 0) {
    297                 if (numBitsLeft < 1) {
    298                     break;
    299                 }
    300                 --numBitsLeft;
    301                 if (bits.getBits(1)) {
    302                     if (numBitsLeft < mDTSDeltaLength) {
    303                         break;
    304                     }
    305                     bits.skipBits(mDTSDeltaLength);
    306                     numBitsLeft -= mDTSDeltaLength;
    307                 }
    308             }
    309 
    310             if (mRandomAccessIndication) {
    311                 if (numBitsLeft < 1) {
    312                     break;
    313                 }
    314                 bits.skipBits(1);
    315                 --numBitsLeft;
    316             }
    317 
    318             if (mStreamStateIndication > 0) {
    319                 if (numBitsLeft < mStreamStateIndication) {
    320                     break;
    321                 }
    322                 bits.skipBits(mStreamStateIndication);
    323             }
    324 
    325             AUHeader header;
    326             header.mSize = AU_size;
    327             header.mSerial = AU_serial;
    328             headers.push_back(header);
    329         }
    330 
    331         size_t offset = 2 + (AU_headers_length + 7) / 8;
    332 
    333         if (mAuxiliaryDataSizeLength > 0) {
    334             ABitReader bits(buffer->data() + offset, buffer->size() - offset);
    335 
    336             unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
    337 
    338             offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
    339         }
    340 
    341         for (List<AUHeader>::iterator it = headers.begin();
    342              it != headers.end(); ++it) {
    343             const AUHeader &header = *it;
    344 
    345             CHECK_LE(offset + header.mSize, buffer->size());
    346 
    347             sp<ABuffer> accessUnit = new ABuffer(header.mSize);
    348             memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
    349 
    350             offset += header.mSize;
    351 
    352             CopyTimes(accessUnit, buffer);
    353             mPackets.push_back(accessUnit);
    354         }
    355 
    356         CHECK_EQ(offset, buffer->size());
    357     }
    358 
    359     queue->erase(queue->begin());
    360     ++mNextExpectedSeqNo;
    361 
    362     return OK;
    363 }
    364 
    365 void AMPEG4ElementaryAssembler::submitAccessUnit() {
    366     CHECK(!mPackets.empty());
    367 
    368     ALOGV("Access unit complete (%d nal units)", mPackets.size());
    369 
    370     sp<ABuffer> accessUnit;
    371 
    372     if (mIsGeneric) {
    373         accessUnit = MakeADTSCompoundFromAACFrames(
    374                 OMX_AUDIO_AACObjectLC - 1,
    375                 mSampleRateIndex,
    376                 mChannelConfig,
    377                 mPackets);
    378     } else {
    379         accessUnit = MakeCompoundFromPackets(mPackets);
    380     }
    381 
    382 #if 0
    383     printf(mAccessUnitDamaged ? "X" : ".");
    384     fflush(stdout);
    385 #endif
    386 
    387     if (mAccessUnitDamaged) {
    388         accessUnit->meta()->setInt32("damaged", true);
    389     }
    390 
    391     mPackets.clear();
    392     mAccessUnitDamaged = false;
    393 
    394     sp<AMessage> msg = mNotifyMsg->dup();
    395     msg->setBuffer("access-unit", accessUnit);
    396     msg->post();
    397 }
    398 
    399 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
    400         const sp<ARTPSource> &source) {
    401     AssemblyStatus status = addPacket(source);
    402     if (status == MALFORMED_PACKET) {
    403         mAccessUnitDamaged = true;
    404     }
    405     return status;
    406 }
    407 
    408 void AMPEG4ElementaryAssembler::packetLost() {
    409     CHECK(mNextExpectedSeqNoValid);
    410     ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
    411 
    412     ++mNextExpectedSeqNo;
    413 
    414     mAccessUnitDamaged = true;
    415 }
    416 
    417 void AMPEG4ElementaryAssembler::onByeReceived() {
    418     sp<AMessage> msg = mNotifyMsg->dup();
    419     msg->setInt32("eos", true);
    420     msg->post();
    421 }
    422 
    423 }  // namespace android
    424