| /* |
| * 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. |
| */ |
| |
| #include "AMPEG4AudioAssembler.h" |
| |
| #include "ARTPSource.h" |
| |
| #include <media/stagefright/foundation/ABuffer.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <media/stagefright/foundation/AMessage.h> |
| |
| namespace android { |
| |
| AMPEG4AudioAssembler::AMPEG4AudioAssembler(const sp<AMessage> ¬ify) |
| : mNotifyMsg(notify), |
| mAccessUnitRTPTime(0), |
| mNextExpectedSeqNoValid(false), |
| mNextExpectedSeqNo(0), |
| mAccessUnitDamaged(false) { |
| } |
| |
| AMPEG4AudioAssembler::~AMPEG4AudioAssembler() { |
| } |
| |
| ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::assembleMore( |
| const sp<ARTPSource> &source) { |
| AssemblyStatus status = addPacket(source); |
| if (status == MALFORMED_PACKET) { |
| mAccessUnitDamaged = true; |
| } |
| return status; |
| } |
| |
| ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket( |
| const sp<ARTPSource> &source) { |
| List<sp<ABuffer> > *queue = source->queue(); |
| |
| if (queue->empty()) { |
| return NOT_ENOUGH_DATA; |
| } |
| |
| if (mNextExpectedSeqNoValid) { |
| List<sp<ABuffer> >::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<ABuffer> 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; |
| |
| mPackets.push_back(buffer); |
| |
| queue->erase(queue->begin()); |
| ++mNextExpectedSeqNo; |
| |
| return OK; |
| } |
| |
| void AMPEG4AudioAssembler::submitAccessUnit() { |
| CHECK(!mPackets.empty()); |
| |
| #if VERBOSE |
| LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)"; |
| #endif |
| |
| size_t totalSize = 0; |
| List<sp<ABuffer> >::iterator it = mPackets.begin(); |
| while (it != mPackets.end()) { |
| const sp<ABuffer> &unit = *it; |
| |
| size_t n = 0; |
| while (unit->data()[n] == 0xff) { |
| ++n; |
| } |
| ++n; |
| |
| totalSize += unit->size() - n; |
| ++it; |
| } |
| |
| sp<ABuffer> accessUnit = new ABuffer(totalSize); |
| size_t offset = 0; |
| it = mPackets.begin(); |
| while (it != mPackets.end()) { |
| const sp<ABuffer> &unit = *it; |
| |
| size_t n = 0; |
| while (unit->data()[n] == 0xff) { |
| ++n; |
| } |
| ++n; |
| |
| memcpy((uint8_t *)accessUnit->data() + offset, |
| unit->data() + n, unit->size() - n); |
| |
| offset += unit->size() - n; |
| |
| ++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<AMessage> msg = mNotifyMsg->dup(); |
| msg->setObject("access-unit", accessUnit); |
| msg->post(); |
| } |
| |
| void AMPEG4AudioAssembler::packetLost() { |
| CHECK(mNextExpectedSeqNoValid); |
| ++mNextExpectedSeqNo; |
| |
| mAccessUnitDamaged = true; |
| } |
| |
| void AMPEG4AudioAssembler::onByeReceived() { |
| sp<AMessage> msg = mNotifyMsg->dup(); |
| msg->setInt32("eos", true); |
| msg->post(); |
| } |
| |
| } // namespace android |