void AMPEG4AudioAssembler::submitAccessUnit() { CHECK(!mPackets.empty()); #if VERBOSE LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)"; #endif sp<ABuffer> accessUnit = MakeCompoundFromPackets(mPackets); accessUnit = removeLATMFraming(accessUnit); 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->setBuffer("access-unit", accessUnit); msg->post(); }
bool AH263Assembler::submitAccessUnit() { MOZ_ASSERT(!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; totalSize += unit->size(); ++it; } sp<ABuffer> accessUnit = new ABuffer(totalSize); size_t offset = 0; it = mPackets.begin(); while (it != mPackets.end()) { const sp<ABuffer> &unit = *it; memcpy((uint8_t *)accessUnit->data() + offset, unit->data(), unit->size()); offset += unit->size(); ++it; } if (!CopyTimes(accessUnit, *mPackets.begin())) { return false; } #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(); return true; }
void AMPEG4ElementaryAssembler::submitAccessUnit() { CHECK(!mPackets.empty()); LOGV("Access unit complete (%d nal units)", mPackets.size()); size_t totalSize = 0; for (List<sp<ABuffer> >::iterator it = mPackets.begin(); it != mPackets.end(); ++it) { totalSize += (*it)->size(); } sp<ABuffer> accessUnit = new ABuffer(totalSize); size_t offset = 0; for (List<sp<ABuffer> >::iterator it = mPackets.begin(); it != mPackets.end(); ++it) { sp<ABuffer> nal = *it; memcpy(accessUnit->data() + offset, nal->data(), nal->size()); offset += nal->size(); } 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 AMPEG4ElementaryAssembler::submitAccessUnit() { CHECK(!mPackets.empty()); LOGV("Access unit complete (%d nal units)", mPackets.size()); for (List<sp<ABuffer> >::iterator it = mPackets.begin(); it != mPackets.end(); ++it) { sp<ABuffer> accessUnit = new ABuffer((*it)->size()); sp<ABuffer> nal = *it; memcpy(accessUnit->data(), nal->data(), nal->size()); CopyTimes(accessUnit, nal); if (mAccessUnitDamaged) { accessUnit->meta()->setInt32("damaged", true); } sp<AMessage> msg = mNotifyMsg->dup(); msg->setObject("access-unit", accessUnit); msg->post(); } mPackets.clear(); mAccessUnitDamaged = false; }
ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::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) { LOGV("Not the sequence number I expected"); 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; if (!mIsGeneric) { mPackets.push_back(buffer); } else { // hexdump(buffer->data(), buffer->size()); CHECK_GE(buffer->size(), 2u); unsigned AU_headers_length = U16_AT(buffer->data()); // in bits CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8); List<AUHeader> headers; ABitReader bits(buffer->data() + 2, buffer->size() - 2); unsigned numBitsLeft = AU_headers_length; unsigned AU_serial = 0; for (;;) { if (numBitsLeft < mSizeLength) { break; } unsigned AU_size = bits.getBits(mSizeLength); numBitsLeft -= mSizeLength; size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength; if (numBitsLeft < n) { break; } unsigned AU_index = bits.getBits(n); numBitsLeft -= n; if (headers.empty()) { AU_serial = AU_index; } else { AU_serial += 1 + AU_index; } if (mCTSDeltaLength > 0) { if (numBitsLeft < 1) { break; } --numBitsLeft; if (bits.getBits(1)) { if (numBitsLeft < mCTSDeltaLength) { break; } bits.skipBits(mCTSDeltaLength); numBitsLeft -= mCTSDeltaLength; } } if (mDTSDeltaLength > 0) { if (numBitsLeft < 1) { break; } --numBitsLeft; if (bits.getBits(1)) { if (numBitsLeft < mDTSDeltaLength) { break; } bits.skipBits(mDTSDeltaLength); numBitsLeft -= mDTSDeltaLength; } } if (mRandomAccessIndication) { if (numBitsLeft < 1) { break; } bits.skipBits(1); --numBitsLeft; } if (mStreamStateIndication > 0) { if (numBitsLeft < mStreamStateIndication) { break; } bits.skipBits(mStreamStateIndication); } AUHeader header; header.mSize = AU_size; header.mSerial = AU_serial; headers.push_back(header); } size_t offset = 2 + (AU_headers_length + 7) / 8; if (mAuxiliaryDataSizeLength > 0) { ABitReader bits(buffer->data() + offset, buffer->size() - offset); unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength); offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8; } for (List<AUHeader>::iterator it = headers.begin(); it != headers.end(); ++it) { const AUHeader &header = *it; CHECK_LE(offset + header.mSize, buffer->size()); sp<ABuffer> accessUnit = new ABuffer(header.mSize); memcpy(accessUnit->data(), buffer->data() + offset, header.mSize); offset += header.mSize; CopyTimes(accessUnit, buffer); mPackets.push_back(accessUnit); } CHECK_EQ(offset, buffer->size()); } queue->erase(queue->begin()); ++mNextExpectedSeqNo; return OK; }
ARTPAssembler::AssemblyStatus AAMRAssembler::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) { LOGV("Not the sequence number I expected"); return WRONG_SEQUENCE_NUMBER; } // hexdump(buffer->data(), buffer->size()); if (buffer->size() < 1) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; LOGW("AMR packet too short."); return MALFORMED_PACKET; } unsigned payloadHeader = buffer->data()[0]; if (payloadHeader & 0x0f != 0u) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; LOGW("Wrong payload header"); return MALFORMED_PACKET; } Vector<uint8_t> tableOfContents; size_t offset = 1; size_t totalSize = 0; for (;;) { if (offset >= buffer->size()) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; LOGW("Unable to parse TOC."); return MALFORMED_PACKET; } uint8_t toc = buffer->data()[offset++]; unsigned FT = (toc >> 3) & 0x0f; if ((toc & 3) != 0 || (mIsWide && FT > 9 && FT != 15) || (!mIsWide && FT > 8 && FT != 15)) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; LOGW("Illegal TOC entry."); return MALFORMED_PACKET; } totalSize += getFrameSize(mIsWide, (toc >> 3) & 0x0f); tableOfContents.push(toc); if (0 == (toc & 0x80)) { break; } } sp<ABuffer> accessUnit = new ABuffer(totalSize); if (!CopyTimes(accessUnit, buffer)) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; return MALFORMED_PACKET; } size_t dstOffset = 0; for (size_t i = 0; i < tableOfContents.size(); ++i) { uint8_t toc = tableOfContents[i]; size_t frameSize = getFrameSize(mIsWide, (toc >> 3) & 0x0f); if (offset + frameSize - 1 > buffer->size()) { queue->erase(queue->begin()); ++mNextExpectedSeqNo; LOGW("AMR packet too short."); return MALFORMED_PACKET; } accessUnit->data()[dstOffset++] = toc; memcpy(accessUnit->data() + dstOffset, buffer->data() + offset, frameSize - 1); offset += frameSize - 1; dstOffset += frameSize - 1; } sp<AMessage> msg = mNotifyMsg->dup(); msg->setObject("access-unit", accessUnit); msg->post(); queue->erase(queue->begin()); ++mNextExpectedSeqNo; return OK; }
bool AMPEG4ElementaryAssembler::submitAccessUnit() { MOZ_ASSERT(mPackets.empty()); LOGV("Access unit complete (%d nal units)", mPackets.size()); if (mIsGeneric) { /* * Bug 877116. * In order to remedy a latency problem caused by hardware decoder for * mpeg4-generic audios, we artificially divide AUs into more smaller * AUs before feeding them to decoder. * * TODO: However, we are not sure this solution is appropriate to video * or not. Need more investigation on this. Refer to RFC 3640. */ for (List<sp<ABuffer> >::iterator it = mPackets.begin(); it != mPackets.end(); ++it) { sp<ABuffer> accessUnit = new ABuffer((*it)->size()); sp<ABuffer> nal = *it; memcpy(accessUnit->data(), nal->data(), nal->size()); if (!CopyTimes(accessUnit, nal)) { return false; } if (mAccessUnitDamaged) { accessUnit->meta()->setInt32("damaged", true); } sp<AMessage> msg = mNotifyMsg->dup(); msg->setObject("access-unit", accessUnit); msg->post(); } } else { /* * For MP4V-ES (MPEG-4 Visual Elementary Streams), NAL units with the * same RTP timestamp are assembled into an AU, which results in one * decoded picture (RFC 6416). */ size_t totalSize = 0; for (List<sp<ABuffer> >::iterator it = mPackets.begin(); it != mPackets.end(); ++it) { totalSize += (*it)->size(); } sp<ABuffer> accessUnit = new ABuffer(totalSize); size_t offset = 0; for (List<sp<ABuffer> >::iterator it = mPackets.begin(); it != mPackets.end(); ++it) { sp<ABuffer> nal = *it; memcpy(accessUnit->data() + offset, nal->data(), nal->size()); offset += nal->size(); } if (!CopyTimes(accessUnit, *mPackets.begin())) { return false; } if (mAccessUnitDamaged) { accessUnit->meta()->setInt32("damaged", true); } sp<AMessage> msg = mNotifyMsg->dup(); msg->setObject("access-unit", accessUnit); msg->post(); } mPackets.clear(); mAccessUnitDamaged = false; return true; }