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 "AAVCAssembler"
     19 #include <utils/Log.h>
     20 
     21 #include "AAVCAssembler.h"
     22 
     23 #include "ARTPSource.h"
     24 
     25 #include <media/stagefright/foundation/ABuffer.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/AMessage.h>
     28 #include <media/stagefright/foundation/hexdump.h>
     29 
     30 #include <stdint.h>
     31 
     32 namespace android {
     33 
     34 // static
     35 AAVCAssembler::AAVCAssembler(const sp<AMessage> &notify)
     36     : mNotifyMsg(notify),
     37       mAccessUnitRTPTime(0),
     38       mNextExpectedSeqNoValid(false),
     39       mNextExpectedSeqNo(0),
     40       mAccessUnitDamaged(false) {
     41 }
     42 
     43 AAVCAssembler::~AAVCAssembler() {
     44 }
     45 
     46 ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
     47         const sp<ARTPSource> &source) {
     48     List<sp<ABuffer> > *queue = source->queue();
     49 
     50     if (queue->empty()) {
     51         return NOT_ENOUGH_DATA;
     52     }
     53 
     54     if (mNextExpectedSeqNoValid) {
     55         List<sp<ABuffer> >::iterator it = queue->begin();
     56         while (it != queue->end()) {
     57             if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
     58                 break;
     59             }
     60 
     61             it = queue->erase(it);
     62         }
     63 
     64         if (queue->empty()) {
     65             return NOT_ENOUGH_DATA;
     66         }
     67     }
     68 
     69     sp<ABuffer> buffer = *queue->begin();
     70 
     71     if (!mNextExpectedSeqNoValid) {
     72         mNextExpectedSeqNoValid = true;
     73         mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
     74     } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
     75         ALOGV("Not the sequence number I expected");
     76 
     77         return WRONG_SEQUENCE_NUMBER;
     78     }
     79 
     80     const uint8_t *data = buffer->data();
     81     size_t size = buffer->size();
     82 
     83     if (size < 1 || (data[0] & 0x80)) {
     84         // Corrupt.
     85 
     86         ALOGV("Ignoring corrupt buffer.");
     87         queue->erase(queue->begin());
     88 
     89         ++mNextExpectedSeqNo;
     90         return MALFORMED_PACKET;
     91     }
     92 
     93     unsigned nalType = data[0] & 0x1f;
     94     if (nalType >= 1 && nalType <= 23) {
     95         addSingleNALUnit(buffer);
     96         queue->erase(queue->begin());
     97         ++mNextExpectedSeqNo;
     98         return OK;
     99     } else if (nalType == 28) {
    100         // FU-A
    101         return addFragmentedNALUnit(queue);
    102     } else if (nalType == 24) {
    103         // STAP-A
    104         bool success = addSingleTimeAggregationPacket(buffer);
    105         queue->erase(queue->begin());
    106         ++mNextExpectedSeqNo;
    107 
    108         return success ? OK : MALFORMED_PACKET;
    109     } else if (nalType == 0) {
    110         ALOGV("Ignoring undefined nal type.");
    111 
    112         queue->erase(queue->begin());
    113         ++mNextExpectedSeqNo;
    114 
    115         return OK;
    116     } else {
    117         ALOGV("Ignoring unsupported buffer (nalType=%d)", nalType);
    118 
    119         queue->erase(queue->begin());
    120         ++mNextExpectedSeqNo;
    121 
    122         return MALFORMED_PACKET;
    123     }
    124 }
    125 
    126 void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
    127     ALOGV("addSingleNALUnit of size %d", buffer->size());
    128 #if !LOG_NDEBUG
    129     hexdump(buffer->data(), buffer->size());
    130 #endif
    131 
    132     uint32_t rtpTime;
    133     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
    134 
    135     if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
    136         submitAccessUnit();
    137     }
    138     mAccessUnitRTPTime = rtpTime;
    139 
    140     mNALUnits.push_back(buffer);
    141 }
    142 
    143 bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
    144     const uint8_t *data = buffer->data();
    145     size_t size = buffer->size();
    146 
    147     if (size < 3) {
    148         ALOGV("Discarding too small STAP-A packet.");
    149         return false;
    150     }
    151 
    152     ++data;
    153     --size;
    154     while (size >= 2) {
    155         size_t nalSize = (data[0] << 8) | data[1];
    156 
    157         if (size < nalSize + 2) {
    158             ALOGV("Discarding malformed STAP-A packet.");
    159             return false;
    160         }
    161 
    162         sp<ABuffer> unit = new ABuffer(nalSize);
    163         memcpy(unit->data(), &data[2], nalSize);
    164 
    165         CopyTimes(unit, buffer);
    166 
    167         addSingleNALUnit(unit);
    168 
    169         data += 2 + nalSize;
    170         size -= 2 + nalSize;
    171     }
    172 
    173     if (size != 0) {
    174         ALOGV("Unexpected padding at end of STAP-A packet.");
    175     }
    176 
    177     return true;
    178 }
    179 
    180 ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
    181         List<sp<ABuffer> > *queue) {
    182     CHECK(!queue->empty());
    183 
    184     sp<ABuffer> buffer = *queue->begin();
    185     const uint8_t *data = buffer->data();
    186     size_t size = buffer->size();
    187 
    188     CHECK(size > 0);
    189     unsigned indicator = data[0];
    190 
    191     CHECK((indicator & 0x1f) == 28);
    192 
    193     if (size < 2) {
    194         ALOGV("Ignoring malformed FU buffer (size = %d)", size);
    195 
    196         queue->erase(queue->begin());
    197         ++mNextExpectedSeqNo;
    198         return MALFORMED_PACKET;
    199     }
    200 
    201     if (!(data[1] & 0x80)) {
    202         // Start bit not set on the first buffer.
    203 
    204         ALOGV("Start bit not set on first buffer");
    205 
    206         queue->erase(queue->begin());
    207         ++mNextExpectedSeqNo;
    208         return MALFORMED_PACKET;
    209     }
    210 
    211     uint32_t nalType = data[1] & 0x1f;
    212     uint32_t nri = (data[0] >> 5) & 3;
    213 
    214     uint32_t expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
    215     size_t totalSize = size - 2;
    216     size_t totalCount = 1;
    217     bool complete = false;
    218 
    219     if (data[1] & 0x40) {
    220         // Huh? End bit also set on the first buffer.
    221 
    222         ALOGV("Grrr. This isn't fragmented at all.");
    223 
    224         complete = true;
    225     } else {
    226         List<sp<ABuffer> >::iterator it = ++queue->begin();
    227         while (it != queue->end()) {
    228             ALOGV("sequence length %d", totalCount);
    229 
    230             const sp<ABuffer> &buffer = *it;
    231 
    232             const uint8_t *data = buffer->data();
    233             size_t size = buffer->size();
    234 
    235             if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
    236                 ALOGV("sequence not complete, expected seqNo %d, got %d",
    237                      expectedSeqNo, (uint32_t)buffer->int32Data());
    238 
    239                 return WRONG_SEQUENCE_NUMBER;
    240             }
    241 
    242             if (size < 2
    243                     || data[0] != indicator
    244                     || (data[1] & 0x1f) != nalType
    245                     || (data[1] & 0x80)) {
    246                 ALOGV("Ignoring malformed FU buffer.");
    247 
    248                 // Delete the whole start of the FU.
    249 
    250                 it = queue->begin();
    251                 for (size_t i = 0; i <= totalCount; ++i) {
    252                     it = queue->erase(it);
    253                 }
    254 
    255                 mNextExpectedSeqNo = expectedSeqNo + 1;
    256 
    257                 return MALFORMED_PACKET;
    258             }
    259 
    260             totalSize += size - 2;
    261             ++totalCount;
    262 
    263             expectedSeqNo = expectedSeqNo + 1;
    264 
    265             if (data[1] & 0x40) {
    266                 // This is the last fragment.
    267                 complete = true;
    268                 break;
    269             }
    270 
    271             ++it;
    272         }
    273     }
    274 
    275     if (!complete) {
    276         return NOT_ENOUGH_DATA;
    277     }
    278 
    279     mNextExpectedSeqNo = expectedSeqNo;
    280 
    281     // We found all the fragments that make up the complete NAL unit.
    282 
    283     // Leave room for the header. So far totalSize did not include the
    284     // header byte.
    285     ++totalSize;
    286 
    287     sp<ABuffer> unit = new ABuffer(totalSize);
    288     CopyTimes(unit, *queue->begin());
    289 
    290     unit->data()[0] = (nri << 5) | nalType;
    291 
    292     size_t offset = 1;
    293     List<sp<ABuffer> >::iterator it = queue->begin();
    294     for (size_t i = 0; i < totalCount; ++i) {
    295         const sp<ABuffer> &buffer = *it;
    296 
    297         ALOGV("piece #%d/%d", i + 1, totalCount);
    298 #if !LOG_NDEBUG
    299         hexdump(buffer->data(), buffer->size());
    300 #endif
    301 
    302         memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
    303         offset += buffer->size() - 2;
    304 
    305         it = queue->erase(it);
    306     }
    307 
    308     unit->setRange(0, totalSize);
    309 
    310     addSingleNALUnit(unit);
    311 
    312     ALOGV("successfully assembled a NAL unit from fragments.");
    313 
    314     return OK;
    315 }
    316 
    317 void AAVCAssembler::submitAccessUnit() {
    318     CHECK(!mNALUnits.empty());
    319 
    320     ALOGV("Access unit complete (%d nal units)", mNALUnits.size());
    321 
    322     size_t totalSize = 0;
    323     for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
    324          it != mNALUnits.end(); ++it) {
    325         totalSize += 4 + (*it)->size();
    326     }
    327 
    328     sp<ABuffer> accessUnit = new ABuffer(totalSize);
    329     size_t offset = 0;
    330     for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
    331          it != mNALUnits.end(); ++it) {
    332         memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
    333         offset += 4;
    334 
    335         sp<ABuffer> nal = *it;
    336         memcpy(accessUnit->data() + offset, nal->data(), nal->size());
    337         offset += nal->size();
    338     }
    339 
    340     CopyTimes(accessUnit, *mNALUnits.begin());
    341 
    342 #if 0
    343     printf(mAccessUnitDamaged ? "X" : ".");
    344     fflush(stdout);
    345 #endif
    346 
    347     if (mAccessUnitDamaged) {
    348         accessUnit->meta()->setInt32("damaged", true);
    349     }
    350 
    351     mNALUnits.clear();
    352     mAccessUnitDamaged = false;
    353 
    354     sp<AMessage> msg = mNotifyMsg->dup();
    355     msg->setBuffer("access-unit", accessUnit);
    356     msg->post();
    357 }
    358 
    359 ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
    360         const sp<ARTPSource> &source) {
    361     AssemblyStatus status = addNALUnit(source);
    362     if (status == MALFORMED_PACKET) {
    363         mAccessUnitDamaged = true;
    364     }
    365     return status;
    366 }
    367 
    368 void AAVCAssembler::packetLost() {
    369     CHECK(mNextExpectedSeqNoValid);
    370     ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
    371 
    372     ++mNextExpectedSeqNo;
    373 
    374     mAccessUnitDamaged = true;
    375 }
    376 
    377 void AAVCAssembler::onByeReceived() {
    378     sp<AMessage> msg = mNotifyMsg->dup();
    379     msg->setInt32("eos", true);
    380     msg->post();
    381 }
    382 
    383 }  // namespace android
    384