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;
}
Exemple #6
0
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;
}