/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "AH263Assembler" #include #include "AH263Assembler.h" #include "ARTPSource.h" #include #include #include #include #include namespace android { AH263Assembler::AH263Assembler(const sp ¬ify) : mNotifyMsg(notify), mAccessUnitRTPTime(0), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0), mAccessUnitDamaged(false) { } AH263Assembler::~AH263Assembler() { } ARTPAssembler::AssemblyStatus AH263Assembler::assembleMore( const sp &source) { AssemblyStatus status = addPacket(source); if (status == MALFORMED_PACKET) { mAccessUnitDamaged = true; } return status; } ARTPAssembler::AssemblyStatus AH263Assembler::addPacket( const sp &source) { List > *queue = source->queue(); if (queue->empty()) { return NOT_ENOUGH_DATA; } if (mNextExpectedSeqNoValid) { List >::iterator it = queue->begin(); while (it != queue->end()) { if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) { break; } it = queue->erase(it); } if (queue->empty()) { return NOT_ENOUGH_DATA; } } sp buffer = *queue->begin(); if (!mNextExpectedSeqNoValid) { mNextExpectedSeqNoValid = true; mNextExpectedSeqNo = (uint32_t)buffer->int32Data(); } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) { #if VERBOSE LOG(VERBOSE) << "Not the sequence number I expected"; #endif return WRONG_SEQUENCE_NUMBER; } uint32_t rtpTime; CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)); if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) { submitAccessUnit(); } mAccessUnitRTPTime = rtpTime; // hexdump(buffer->data(), buffer->size()); if (buffer->size() < 2) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; return MALFORMED_PACKET; } unsigned payloadHeader = U16_AT(buffer->data()); unsigned P = (payloadHeader >> 10) & 1; unsigned V = (payloadHeader >> 9) & 1; unsigned PLEN = (payloadHeader >> 3) & 0x3f; unsigned PEBIT = payloadHeader & 7; // V=0 if (V != 0u) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; ALOGW("Packet discarded due to VRC (V != 0)"); return MALFORMED_PACKET; } // PLEN=0 if (PLEN != 0u) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; ALOGW("Packet discarded (PLEN != 0)"); return MALFORMED_PACKET; } // PEBIT=0 if (PEBIT != 0u) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; ALOGW("Packet discarded (PEBIT != 0)"); return MALFORMED_PACKET; } size_t skip = V + PLEN + (P ? 0 : 2); buffer->setRange(buffer->offset() + skip, buffer->size() - skip); if (P) { buffer->data()[0] = 0x00; buffer->data()[1] = 0x00; } mPackets.push_back(buffer); queue->erase(queue->begin()); ++mNextExpectedSeqNo; return OK; } void AH263Assembler::submitAccessUnit() { CHECK(!mPackets.empty()); #if VERBOSE LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)"; #endif size_t totalSize = 0; List >::iterator it = mPackets.begin(); while (it != mPackets.end()) { const sp &unit = *it; totalSize += unit->size(); ++it; } sp accessUnit = new ABuffer(totalSize); size_t offset = 0; it = mPackets.begin(); while (it != mPackets.end()) { const sp &unit = *it; memcpy((uint8_t *)accessUnit->data() + offset, unit->data(), unit->size()); offset += unit->size(); ++it; } CopyTimes(accessUnit, *mPackets.begin()); #if 0 printf(mAccessUnitDamaged ? "X" : "."); fflush(stdout); #endif if (mAccessUnitDamaged) { accessUnit->meta()->setInt32("damaged", true); } mPackets.clear(); mAccessUnitDamaged = false; sp msg = mNotifyMsg->dup(); msg->setBuffer("access-unit", accessUnit); msg->post(); } void AH263Assembler::packetLost() { CHECK(mNextExpectedSeqNoValid); ++mNextExpectedSeqNo; mAccessUnitDamaged = true; } void AH263Assembler::onByeReceived() { sp msg = mNotifyMsg->dup(); msg->setInt32("eos", true); msg->post(); } } // namespace android