예제 #1
1
ARTPAssembler::AssemblyStatus AH263Assembler::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;

    // 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;
}
예제 #2
0
/**
 * UTF16toUTF8: converts UTF-16 (host byte order) to UTF-8
 *
 * @param src UTF-16 bytes sequence, aligned on a 16-bits boundary
 * @param len number of uint16_t to convert
 */
static char *
UTF16toUTF8( const uint16_t *in, size_t len, size_t *newlen )
{
    char *res, *out;

    /* allocate memory */
    out = res = (char *)malloc( 3 * len );
    if( res == NULL )
        return NULL;

    while( len > 0 )
    {
        uint32_t uv = *in;

        in++;
        len--;

        if( uv < 0x80 )
        {
            *out++ = uv;
            continue;
        }
        if( uv < 0x800 )
        {
            *out++ = (( uv >>  6)         | 0xc0);
            *out++ = (( uv        & 0x3f) | 0x80);
            continue;
        }
        if( (uv >= 0xd800) && (uv < 0xdbff) )
        {   /* surrogates */
            uint16_t low = U16_AT( in );
            in++;
            len--;

            if( (low < 0xdc00) || (low >= 0xdfff) )
            {
                *out++ = '?'; /* Malformed surrogate */
                continue;
            }
            else
                uv = ((uv - 0xd800) << 10) + (low - 0xdc00) + 0x10000;
        }
        if( uv < 0x10000 )
        {
            *out++ = (( uv >> 12)         | 0xe0);
            *out++ = (((uv >>  6) & 0x3f) | 0x80);
            *out++ = (( uv        & 0x3f) | 0x80);
            continue;
        }
예제 #3
0
파일: araw.c 프로젝트: chouquette/vlc
static void DAT12Decode( void *outp, const uint8_t *in, unsigned samples )
{
    int32_t *out = outp;

    while( samples >= 2 )
    {
        *(out++) = dat12tos16(U16_AT(in) >> 4);
        *(out++) = dat12tos16(U16_AT(in + 1) & ~0xF000);
        in += 3;
        samples -= 2;
    }

    if( samples )
        *(out++) = dat12tos16(U16_AT(in) >> 4);
}
예제 #4
0
파일: araw.c 프로젝트: chouquette/vlc
static void S20BDecode( void *outp, const uint8_t *in, unsigned samples )
{
    int32_t *out = outp;

    while( samples >= 2 )
    {
        uint32_t dw = U32_AT(in);
        in += 4;
        *(out++) = dw & ~0xFFF;
        *(out++) = (dw << 20) | (*in << 12);
        in++;
        samples -= 2;
    }

    /* No U32_AT() for the last odd sample: avoid off-by-one overflow! */
    if( samples )
        *(out++) = (U16_AT(in) << 16) | ((in[2] & 0xF0) << 8);
}
size_t AH263Assembler::getOffsetOfHeader(const sp<ABuffer> buffer) {
    //the final right offset should be 0 or 2, it is
    //initialized to 1 for checking whether errors happen
    size_t offset = 1;

    if (buffer->size() < 2) {
        ALOGW("Packet size is less than 2 bytes");
        return offset;
    }

    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) {
        ALOGW("Packet discarded due to VRC (V != 0)");
        return offset;
    }

    // PLEN=0
    if (PLEN != 0u) {
        ALOGW("Packet discarded (PLEN != 0)");
        return offset;
    }

    // PEBIT=0
    if (PEBIT != 0u) {
        ALOGW("Packet discarded (PEBIT != 0)");
        return offset;
    }
    offset = V + PLEN + (P ? 0 : 2);
    return offset;
}
예제 #6
0
파일: ID3.cpp 프로젝트: Andrel322/gecko-dev
bool ID3::parseV2(const sp<DataSource> &source) {
struct id3_header {
    char id[3];
    uint8_t version_major;
    uint8_t version_minor;
    uint8_t flags;
    uint8_t enc_size[4];
    };

    id3_header header;
    if (source->readAt(
                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
        return false;
    }

    if (memcmp(header.id, "ID3", 3)) {
        return false;
    }

    if (header.version_major == 0xff || header.version_minor == 0xff) {
        return false;
    }

    if (header.version_major == 2) {
        if (header.flags & 0x3f) {
            // We only support the 2 high bits, if any of the lower bits are
            // set, we cannot guarantee to understand the tag format.
            return false;
        }

        if (header.flags & 0x40) {
            // No compression scheme has been decided yet, ignore the
            // tag if compression is indicated.

            return false;
        }
    } else if (header.version_major == 3) {
        if (header.flags & 0x1f) {
            // We only support the 3 high bits, if any of the lower bits are
            // set, we cannot guarantee to understand the tag format.
            return false;
        }
    } else if (header.version_major == 4) {
        if (header.flags & 0x0f) {
            // The lower 4 bits are undefined in this spec.
            return false;
        }
    } else {
        return false;
    }

    size_t size;
    if (!ParseSyncsafeInteger(header.enc_size, &size)) {
        return false;
    }

    if (size > kMaxMetadataSize) {
        ALOGE("skipping huge ID3 metadata of size %d", size);
        return false;
    }

    mData = (uint8_t *)malloc(size);

    if (mData == NULL) {
        return false;
    }

    mSize = size;
    mRawSize = mSize + sizeof(header);

    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
        free(mData);
        mData = NULL;

        return false;
    }

    if (header.version_major == 4) {
        void *copy = malloc(size);
        memcpy(copy, mData, size);

        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
        if (!success) {
            memcpy(mData, copy, size);
            mSize = size;

            success = removeUnsynchronizationV2_4(true /* iTunesHack */);

            if (success) {
                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
            }
        }

        free(copy);
        copy = NULL;

        if (!success) {
            free(mData);
            mData = NULL;

            return false;
        }
    } else if (header.flags & 0x80) {
        ALOGV("removing unsynchronization");

        removeUnsynchronization();
    }

    mFirstFrameOffset = 0;
    if (header.version_major == 3 && (header.flags & 0x40)) {
        // Version 2.3 has an optional extended header.

        if (mSize < 4) {
            free(mData);
            mData = NULL;

            return false;
        }

        size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;

        if (extendedHeaderSize > mSize) {
            free(mData);
            mData = NULL;

            return false;
        }

        mFirstFrameOffset = extendedHeaderSize;

        uint16_t extendedFlags = 0;
        if (extendedHeaderSize >= 6) {
            extendedFlags = U16_AT(&mData[4]);

            if (extendedHeaderSize >= 10) {
                size_t paddingSize = U32_AT(&mData[6]);

                if (mFirstFrameOffset + paddingSize > mSize) {
                    free(mData);
                    mData = NULL;

                    return false;
                }

                mSize -= paddingSize;
            }

            if (extendedFlags & 0x8000) {
                ALOGV("have crc");
            }
        }
    } else if (header.version_major == 4 && (header.flags & 0x40)) {
        // Version 2.4 has an optional extended header, that's different
        // from Version 2.3's...

        if (mSize < 4) {
            free(mData);
            mData = NULL;

            return false;
        }

        size_t ext_size;
        if (!ParseSyncsafeInteger(mData, &ext_size)) {
            free(mData);
            mData = NULL;

            return false;
        }

        if (ext_size < 6 || ext_size > mSize) {
            free(mData);
            mData = NULL;

            return false;
        }

        mFirstFrameOffset = ext_size;
    }

    if (header.version_major == 2) {
        mVersion = ID3_V2_2;
    } else if (header.version_major == 3) {
        mVersion = ID3_V2_3;
    } else {
        CHECK_EQ(header.version_major, 4);
        mVersion = ID3_V2_4;
    }

    return true;
}
예제 #7
0
ARTPAssembler::AssemblyStatus AH263Assembler::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;
    if (!buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)) {
        queue->erase(queue->begin());
        ++mNextExpectedSeqNo;

        LOGW("Cannot find rtp-time. Malformed packet.");

        return MALFORMED_PACKET;
    }

    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
        if (!submitAccessUnit()) {
            queue->erase(queue->begin());
            ++mNextExpectedSeqNo;

            LOGW("Cannot find rtp-time. Malformed packet.");

            return MALFORMED_PACKET;
        }
    }
    mAccessUnitRTPTime = rtpTime;

    // hexdump(buffer->data(), buffer->size());

    if (buffer->size() < 2) {
        queue->erase(queue->begin());
        ++mNextExpectedSeqNo;

        return MALFORMED_PACKET;
    }

    // RFC 4629, Sec. 5.1 General H.263+ Payload Header.
    // The H.263+ payload header is structured as follows:
    //  0                   1
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    // |   RR    |P|V|   PLEN    |PEBIT|
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //
    // RR: 5 bits
    //     Reserved bits. It SHALL be zero and MUST be ignored by receivers.
    // P: 1 bit
    //     Indicates the picture start or a picture segment (GOB/Slice) start or
    //     a video sequence end (EOS or EOSBS). Two bytes of zero bits then have
    //     to be prefixed to the payload of such a packet to compose a complete
    //     picture/GOB/slice/EOS/EOSBS start code. This bit allows the omission
    //     of the two first bytes of the start code, thus improving the
    //     compression ratio.
    // V: 1 bit
    //     Indicates the presence of an 8-bit field containing information for
    //     Video Redundancy Coding (VRC), which follows immediately after the
    //     initial 16 bits of the payload header.
    // PLEN: 6 bits
    //     Length, in bytes, of the extra picture header. If no extra picture
    //     header is attached, PLEN is 0. If PLEN>0, the extra picture header is
    //     attached immediately following the rest of the payload header. Note
    //     that the length reflects the omission of the first two bytes of the
    //     picture start code (PSC).
    // PEBIT: 3 bits
    //     Indicates the number of bits that shall be ignored in the last byte
    //     of the picture header. If PLEN is not zero, the ignored bits shall be
    //     the least significant bits of the byte. If PLEN is zero, then PEBIT
    //     shall also be zero.

    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
    // We do not support VRC header extension for now, so just discard it if
    // present.
    if (V != 0u) {
        queue->erase(queue->begin());
        ++mNextExpectedSeqNo;
        LOGW("Packet discarded due to VRC (V != 0)");
        return MALFORMED_PACKET;
    }

    // If PLEN is zero, then PEBIT shall also be zero.
    if (PLEN == 0u && PEBIT != 0u) {
        queue->erase(queue->begin());
        ++mNextExpectedSeqNo;
        LOGW("Packet discarded (PEBIT != 0)");
        return MALFORMED_PACKET;
    }

    size_t skip = 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;
}
예제 #8
0
파일: stream.c 프로젝트: 02002love/vlc
char *stream_ReadLine( stream_t *s )
{
    stream_priv_t *priv = (stream_priv_t *)s;
    char *p_line = NULL;
    int i_line = 0, i_read = 0;

    /* Let's fail quickly if this is a readdir access */
    if( s->pf_read == NULL )
        return NULL;

    for( ;; )
    {
        char *psz_eol;
        const uint8_t *p_data;
        int i_data;
        int64_t i_pos;

        /* Probe new data */
        i_data = stream_Peek( s, &p_data, STREAM_PROBE_LINE );
        if( i_data <= 0 ) break; /* No more data */

        /* BOM detection */
        i_pos = stream_Tell( s );
        if( i_pos == 0 && i_data >= 2 )
        {
            const char *psz_encoding = NULL;

            if( !memcmp( p_data, "\xFF\xFE", 2 ) )
            {
                psz_encoding = "UTF-16LE";
                priv->text.little_endian = true;
            }
            else if( !memcmp( p_data, "\xFE\xFF", 2 ) )
            {
                psz_encoding = "UTF-16BE";
            }

            /* Open the converter if we need it */
            if( psz_encoding != NULL )
            {
                msg_Dbg( s, "UTF-16 BOM detected" );
                priv->text.char_width = 2;
                priv->text.conv = vlc_iconv_open( "UTF-8", psz_encoding );
                if( priv->text.conv == (vlc_iconv_t)-1 )
                    msg_Err( s, "iconv_open failed" );
            }
        }

        if( i_data % priv->text.char_width )
        {
            /* keep i_char_width boundary */
            i_data = i_data - ( i_data % priv->text.char_width );
            msg_Warn( s, "the read is not i_char_width compatible");
        }

        if( i_data == 0 )
            break;

        /* Check if there is an EOL */
        if( priv->text.char_width == 1 )
        {
            /* UTF-8: 0A <LF> */
            psz_eol = memchr( p_data, '\n', i_data );
            if( psz_eol == NULL )
                /* UTF-8: 0D <CR> */
                psz_eol = memchr( p_data, '\r', i_data );
        }
        else
        {
            const uint8_t *p_last = p_data + i_data - priv->text.char_width;
            uint16_t eol = priv->text.little_endian ? 0x0A00 : 0x00A0;

            assert( priv->text.char_width == 2 );
            psz_eol = NULL;
            /* UTF-16: 000A <LF> */
            for( const uint8_t *p = p_data; p <= p_last; p += 2 )
            {
                if( U16_AT( p ) == eol )
                {
                     psz_eol = (char *)p + 1;
                     break;
                }
            }

            if( psz_eol == NULL )
            {   /* UTF-16: 000D <CR> */
                eol = priv->text.little_endian ? 0x0D00 : 0x00D0;
                for( const uint8_t *p = p_data; p <= p_last; p += 2 )
                {
                    if( U16_AT( p ) == eol )
                    {
                        psz_eol = (char *)p + 1;
                        break;
                    }
                }
            }
        }

        if( psz_eol )
        {
            i_data = (psz_eol - (char *)p_data) + 1;
            p_line = realloc_or_free( p_line,
                        i_line + i_data + priv->text.char_width ); /* add \0 */
            if( !p_line )
                goto error;
            i_data = stream_Read( s, &p_line[i_line], i_data );
            if( i_data <= 0 ) break; /* Hmmm */
            i_line += i_data - priv->text.char_width; /* skip \n */;
            i_read += i_data;

            /* We have our line */
            break;
        }

        /* Read data (+1 for easy \0 append) */
        p_line = realloc_or_free( p_line,
                          i_line + STREAM_PROBE_LINE + priv->text.char_width );
        if( !p_line )
            goto error;
        i_data = stream_Read( s, &p_line[i_line], STREAM_PROBE_LINE );
        if( i_data <= 0 ) break; /* Hmmm */
        i_line += i_data;
        i_read += i_data;

        if( i_read >= STREAM_LINE_MAX )
            goto error; /* line too long */
    }

    if( i_read > 0 )
    {
        memset(p_line + i_line, 0, priv->text.char_width);
        i_line += priv->text.char_width; /* the added \0 */

        if( priv->text.char_width > 1 )
        {
            int i_new_line = 0;
            size_t i_in = 0, i_out = 0;
            const char * p_in = NULL;
            char * p_out = NULL;
            char * psz_new_line = NULL;

            /* iconv */
            /* UTF-8 needs at most 150% of the buffer as many as UTF-16 */
            i_new_line = i_line * 3 / 2;
            psz_new_line = malloc( i_new_line );
            if( psz_new_line == NULL )
                goto error;
            i_in = (size_t)i_line;
            i_out = (size_t)i_new_line;
            p_in = p_line;
            p_out = psz_new_line;

            if( vlc_iconv( priv->text.conv, &p_in, &i_in, &p_out, &i_out ) == (size_t)-1 )
            {
                msg_Err( s, "iconv failed" );
                msg_Dbg( s, "original: %d, in %d, out %d", i_line, (int)i_in, (int)i_out );
            }
            free( p_line );
            p_line = psz_new_line;
            i_line = (size_t)i_new_line - i_out; /* does not include \0 */
        }

        /* Remove trailing LF/CR */
        while( i_line >= 2 && ( p_line[i_line-2] == '\r' ||
            p_line[i_line-2] == '\n') ) i_line--;

        /* Make sure the \0 is there */
        p_line[i_line-1] = '\0';

        return p_line;
    }

error:
    /* We failed to read any data, probably EOF */
    free( p_line );

    /* */
    if( priv->text.conv != (vlc_iconv_t)(-1) )
    {
        vlc_iconv_close( priv->text.conv );
        priv->text.conv = (vlc_iconv_t)(-1);
    }
    return NULL;
}
status_t MatroskaSource::read(
        MediaBuffer **out, const ReadOptions *options) {
    *out = NULL;

    int64_t targetSampleTimeUs = -1ll;

    int64_t seekTimeUs;
    ReadOptions::SeekMode mode;
    if (options && options->getSeekTo(&seekTimeUs, &mode)
            && !mExtractor->isLiveStreaming()) {
        clearPendingFrames();

        // The audio we want is located by using the Cues to seek the video
        // stream to find the target Cluster then iterating to finalize for
        // audio.
        int64_t actualFrameTimeUs;
        mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);

        if (mode == ReadOptions::SEEK_CLOSEST) {
            targetSampleTimeUs = actualFrameTimeUs;
        }
    }

    while (mPendingFrames.empty()) {
        status_t err = readBlock();

        if (err != OK) {
            clearPendingFrames();

            return err;
        }
    }

    MediaBuffer *frame = *mPendingFrames.begin();
    mPendingFrames.erase(mPendingFrames.begin());

    if (mType != AVC || mNALSizeLen == 0) {
        if (targetSampleTimeUs >= 0ll) {
            frame->meta_data()->setInt64(
                    kKeyTargetTime, targetSampleTimeUs);
        }

        *out = frame;

        return OK;
    }

    // Each input frame contains one or more NAL fragments, each fragment
    // is prefixed by mNALSizeLen bytes giving the fragment length,
    // followed by a corresponding number of bytes containing the fragment.
    // We output all these fragments into a single large buffer separated
    // by startcodes (0x00 0x00 0x00 0x01).
    //
    // When mNALSizeLen is 0, we assume the data is already in the format
    // desired.

    const uint8_t *srcPtr =
        (const uint8_t *)frame->data() + frame->range_offset();

    size_t srcSize = frame->range_length();

    size_t dstSize = 0;
    MediaBuffer *buffer = NULL;
    uint8_t *dstPtr = NULL;

    for (int32_t pass = 0; pass < 2; ++pass) {
        size_t srcOffset = 0;
        size_t dstOffset = 0;
        while (srcOffset + mNALSizeLen <= srcSize) {
            size_t NALsize;
            switch (mNALSizeLen) {
                case 1: NALsize = srcPtr[srcOffset]; break;
                case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
                case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
                case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
                default:
                    TRESPASS();
            }

            if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
                frame->release();
                frame = NULL;

                return ERROR_MALFORMED;
            } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
                break;
            }

            if (pass == 1) {
                memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);

                if (frame != buffer) {
                    memcpy(&dstPtr[dstOffset + 4],
                           &srcPtr[srcOffset + mNALSizeLen],
                           NALsize);
                }
            }

            dstOffset += 4;  // 0x00 00 00 01
            dstOffset += NALsize;

            srcOffset += mNALSizeLen + NALsize;
        }

        if (srcOffset < srcSize) {
            // There were trailing bytes or not enough data to complete
            // a fragment.

            frame->release();
            frame = NULL;

            return ERROR_MALFORMED;
        }

        if (pass == 0) {
            dstSize = dstOffset;

            if (dstSize == srcSize && mNALSizeLen == 4) {
                // In this special case we can re-use the input buffer by substituting
                // each 4-byte nal size with a 4-byte start code
                buffer = frame;
            } else {
                buffer = new MediaBuffer(dstSize);
            }

            int64_t timeUs;
            CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
            int32_t isSync;
            CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));

            buffer->meta_data()->setInt64(kKeyTime, timeUs);
            buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);

            dstPtr = (uint8_t *)buffer->data();
        }
    }

    if (frame != buffer) {
        frame->release();
        frame = NULL;
    }

    if (targetSampleTimeUs >= 0ll) {
        buffer->meta_data()->setInt64(
                kKeyTargetTime, targetSampleTimeUs);
    }

    *out = buffer;

    return OK;
}
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;
    if (!buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)) {
        LOGW("Cannot find rtp-time. Malformed packet.");

        return MALFORMED_PACKET;
    }

    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
        if (!submitAccessUnit()) {
            LOGW("Cannot find rtp-time. Malformed packet.");

            return MALFORMED_PACKET;
        }
    }

    // If constantDuration and CTSDelta are not present. We should assume the
    // stream has fixed duration and calculate the mConstantDuration.
    if (!mConstantDuration && !mCTSDeltaLength && mPreviousAUCount
        && rtpTime > mAccessUnitRTPTime) {
        mConstantDuration = (rtpTime - mAccessUnitRTPTime) / mPreviousAUCount;
    }

    mAccessUnitRTPTime = rtpTime;

    if (!mIsGeneric) {
        mPackets.push_back(buffer);
    } else {
        // hexdump(buffer->data(), buffer->size());

        if (buffer->size() < 2u) {
            LOGW("Payload format error. Malformed packet.");

            return MALFORMED_PACKET;
        }
        unsigned AU_headers_length = U16_AT(buffer->data());  // in bits

        if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
            LOGW("Payload format error. Malformed packet.");

            return MALFORMED_PACKET;
        }

        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;
        }

        mPreviousAUCount = 0;
        for (List<AUHeader>::iterator it = headers.begin();
             it != headers.end(); ++it) {
            mPreviousAUCount++;
            const AUHeader &header = *it;
            const AUHeader &first = *headers.begin();
            if (offset + header.mSize > buffer->size()) {
                LOGW("Payload format error. Malformed packet.");

                return MALFORMED_PACKET;
            }

            sp<ABuffer> accessUnit = new ABuffer(header.mSize);
            memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);

            offset += header.mSize;

            int rtpTime = mAccessUnitRTPTime +
                          mConstantDuration * (header.mSerial - first.mSerial);
            accessUnit->meta()->setInt32("rtp-time", rtpTime);
            accessUnit->setInt32Data(buffer->int32Data());

            mPackets.push_back(accessUnit);
        }

        if (offset != buffer->size()) {
            LOGW("Payload format error. Malformed packet.");

            return MALFORMED_PACKET;
        }
    }

    queue->erase(queue->begin());
    ++mNextExpectedSeqNo;

    return OK;
}
// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
status_t TextDescriptions::extract3GPPGlobalDescriptions(
        const uint8_t *data, ssize_t size, Parcel *parcel, int depth) {

    ssize_t chunkSize = U32_AT(data);
    uint32_t chunkType = U32_AT(data + 4);
    const uint8_t *tmpData = data;
    tmpData += 8;

    if (size < chunkSize) {
        return OK;
    }

    if (depth == 0) {
        parcel->writeInt32(KEY_GLOBAL_SETTING);
    }
    switch(chunkType) {
        case FOURCC('t', 'x', '3', 'g'):
        {
            tmpData += 8; // skip the first 8 bytes
            parcel->writeInt32(KEY_DISPLAY_FLAGS);
            parcel->writeInt32(U32_AT(tmpData));

            parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
            parcel->writeInt32(tmpData[4]);
            parcel->writeInt32(tmpData[5]);

            parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
            uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
                | *(tmpData + 8) << 8 | *(tmpData + 9);
            parcel->writeInt32(rgba);

            tmpData += 10;
            parcel->writeInt32(KEY_STRUCT_TEXT_POS);
            parcel->writeInt32(U16_AT(tmpData));
            parcel->writeInt32(U16_AT(tmpData + 2));
            parcel->writeInt32(U16_AT(tmpData + 4));
            parcel->writeInt32(U16_AT(tmpData + 6));

            tmpData += 8;
            parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
            parcel->writeInt32(KEY_START_CHAR);
            parcel->writeInt32(U16_AT(tmpData));

            parcel->writeInt32(KEY_END_CHAR);
            parcel->writeInt32(U16_AT(tmpData + 2));

            parcel->writeInt32(KEY_FONT_ID);
            parcel->writeInt32(U16_AT(tmpData + 4));

            parcel->writeInt32(KEY_STYLE_FLAGS);
            parcel->writeInt32(*(tmpData + 6));

            parcel->writeInt32(KEY_FONT_SIZE);
            parcel->writeInt32(*(tmpData + 7));

            parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
            rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
                | *(tmpData + 10) << 8 | *(tmpData + 11);
            parcel->writeInt32(rgba);

            tmpData += 12;
            parcel->writeInt32(KEY_STRUCT_FONT_LIST);
            uint16_t count = U16_AT(tmpData);
            parcel->writeInt32(count);

            tmpData += 2;
            for (int i = 0; i < count; i++) {
                // font ID
                parcel->writeInt32(U16_AT(tmpData));

                // font name length
                parcel->writeInt32(*(tmpData + 2));

                int len = *(tmpData + 2);

                parcel->write(tmpData + 3, len);
                tmpData += 3 + len;
            }

            break;
        }
        default:
        {
            break;
        }
    }

    data += chunkSize;
    size -= chunkSize;

    if (size > 0) {
        // continue to extract next 'tx3g'
        return extract3GPPGlobalDescriptions(data, size, parcel, 1);
    }

    return OK;
}
status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
    Mutex::Autolock autoLock(mDRMLock);
    status_t err;
    if ((err = mOriginalMediaSource->read(buffer, options)) != OK) {
        return err;
    }

    size_t len = (*buffer)->range_length();

    char *src = (char *)(*buffer)->data() + (*buffer)->range_offset();

    DrmBuffer encryptedDrmBuffer(src, len);
    DrmBuffer decryptedDrmBuffer;
    decryptedDrmBuffer.length = len;
    decryptedDrmBuffer.data = new char[len];
    DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;

    if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
            &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {

        if (decryptedDrmBuffer.data) {
            delete [] decryptedDrmBuffer.data;
            decryptedDrmBuffer.data = NULL;
        }

        return err;
    }
    CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer);

    const char *mime;
    CHECK(getFormat()->findCString(kKeyMIMEType, &mime));

    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) && !mWantsNALFragments) {
        uint8_t *dstData = (uint8_t*)src;
        size_t srcOffset = 0;
        size_t dstOffset = 0;

        len = decryptedDrmBuffer.length;
        while (srcOffset < len) {
            CHECK(srcOffset + mNALLengthSize <= len);
            size_t nalLength = 0;
            const uint8_t* data = (const uint8_t*)(&decryptedDrmBuffer.data[srcOffset]);

            switch (mNALLengthSize) {
                case 1:
                    nalLength = *data;
                    break;
                case 2:
                    nalLength = U16_AT(data);
                    break;
                case 3:
                    nalLength = ((size_t)data[0] << 16) | U16_AT(&data[1]);
                    break;
                case 4:
                    nalLength = U32_AT(data);
                    break;
                default:
                    CHECK(!"Should not be here.");
                    break;
            }

            srcOffset += mNALLengthSize;

            if (srcOffset + nalLength > len) {
                if (decryptedDrmBuffer.data) {
                    delete [] decryptedDrmBuffer.data;
                    decryptedDrmBuffer.data = NULL;
                }

                return ERROR_MALFORMED;
            }

            if (nalLength == 0) {
                continue;
            }

            CHECK(dstOffset + 4 <= (*buffer)->size());

            dstData[dstOffset++] = 0;
            dstData[dstOffset++] = 0;
            dstData[dstOffset++] = 0;
            dstData[dstOffset++] = 1;
            memcpy(&dstData[dstOffset], &decryptedDrmBuffer.data[srcOffset], nalLength);
            srcOffset += nalLength;
            dstOffset += nalLength;
        }

        CHECK_EQ(srcOffset, len);
        (*buffer)->set_range((*buffer)->range_offset(), dstOffset);

    } else {
        memcpy(src, decryptedDrmBuffer.data, decryptedDrmBuffer.length);
        (*buffer)->set_range((*buffer)->range_offset(), decryptedDrmBuffer.length);
    }

    if (decryptedDrmBuffer.data) {
        delete [] decryptedDrmBuffer.data;
        decryptedDrmBuffer.data = NULL;
    }

    return OK;
}
// Extract the local 3GPP display descriptions. 3GPP local descriptions
// are appended to the text sample if any. The descriptions could include
// information such as text styles, highlights, karaoke and so on. They
// are contained in different boxes, such as 'styl' box contains text
// styles, and 'krok' box contains karaoke timing and positions.
status_t TextDescriptions::extract3GPPLocalDescriptions(
        const uint8_t *data, ssize_t size,
        int timeMs, Parcel *parcel) {

    parcel->writeInt32(KEY_LOCAL_SETTING);

    // write start time to display this text sample
    parcel->writeInt32(KEY_START_TIME);
    parcel->writeInt32(timeMs);

    if (size < 2) {
        return OK;
    }
    ssize_t textLen = (*data) << 8 | (*(data + 1));

    if (size < textLen + 2) {
        return OK;
    }

    // write text sample length and text sample itself
    parcel->writeInt32(KEY_STRUCT_TEXT);
    parcel->writeInt32(textLen);
    parcel->writeInt32(textLen);
    parcel->write(data + 2, textLen);

    if (size > textLen + 2) {
        data += (textLen + 2);
        size -= (textLen + 2);
    } else {
        return OK;
    }

    while (size >= 8) {
        const uint8_t *tmpData = data;
        ssize_t chunkSize = U32_AT(tmpData);      // size includes size and type
        uint32_t chunkType = U32_AT(tmpData + 4);

        if (chunkSize <= 8 || chunkSize > size) {
            return OK;
        }

        size_t remaining = chunkSize - 8;

        tmpData += 8;

        switch(chunkType) {
            // 'styl' box specifies the style of the text.
            case FOURCC('s', 't', 'y', 'l'):
            {
                if (remaining < 2) {
                    return OK;
                }
                size_t dataPos = parcel->dataPosition();
                uint16_t count = U16_AT(tmpData);

                tmpData += 2;
                remaining -= 2;

                for (int i = 0; i < count; i++) {
                    if (remaining < 12) {
                        // roll back
                        parcel->setDataPosition(dataPos);
                        return OK;
                    }
                    parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
                    parcel->writeInt32(KEY_START_CHAR);
                    parcel->writeInt32(U16_AT(tmpData));

                    parcel->writeInt32(KEY_END_CHAR);
                    parcel->writeInt32(U16_AT(tmpData + 2));

                    parcel->writeInt32(KEY_FONT_ID);
                    parcel->writeInt32(U16_AT(tmpData + 4));

                    parcel->writeInt32(KEY_STYLE_FLAGS);
                    parcel->writeInt32(*(tmpData + 6));

                    parcel->writeInt32(KEY_FONT_SIZE);
                    parcel->writeInt32(*(tmpData + 7));

                    parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
                    uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
                        | *(tmpData + 10) << 8 | *(tmpData + 11);
                    parcel->writeInt32(rgba);

                    tmpData += 12;
                    remaining -= 12;
                }

                break;
            }
            // 'krok' box. The number of highlight events is specified, and each
            // event is specified by a starting and ending char offset and an end
            // time for the event.
            case FOURCC('k', 'r', 'o', 'k'):
            {
                if (remaining < 6) {
                    return OK;
                }
                size_t dataPos = parcel->dataPosition();

                parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);

                int startTime = U32_AT(tmpData);
                uint16_t count = U16_AT(tmpData + 4);
                parcel->writeInt32(count);

                tmpData += 6;
                remaining -= 6;
                int lastEndTime = 0;

                for (int i = 0; i < count; i++) {
                    if (remaining < 8) {
                        // roll back
                        parcel->setDataPosition(dataPos);
                        return OK;
                    }
                    parcel->writeInt32(startTime + lastEndTime);

                    lastEndTime = U32_AT(tmpData);
                    parcel->writeInt32(lastEndTime);

                    parcel->writeInt32(U16_AT(tmpData + 4));
                    parcel->writeInt32(U16_AT(tmpData + 6));

                    tmpData += 8;
                    remaining -= 8;
                }

                break;
            }
            // 'hlit' box specifies highlighted text
            case FOURCC('h', 'l', 'i', 't'):
            {
                if (remaining < 4) {
                    return OK;
                }

                parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);

                // the start char offset to highlight
                parcel->writeInt32(U16_AT(tmpData));
                // the last char offset to highlight
                parcel->writeInt32(U16_AT(tmpData + 2));

                tmpData += 4;
                remaining -= 4;
                break;
            }
            // 'hclr' box specifies the RGBA color: 8 bits each of
            // red, green, blue, and an alpha(transparency) value
            case FOURCC('h', 'c', 'l', 'r'):
            {
                if (remaining < 4) {
                    return OK;
                }
                parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);

                uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
                    | *(tmpData + 2) << 8 | *(tmpData + 3);
                parcel->writeInt32(rgba);

                tmpData += 4;
                remaining -= 4;
                break;
            }
            // 'dlay' box specifies a delay after a scroll in and/or
            // before scroll out.
            case FOURCC('d', 'l', 'a', 'y'):
            {
                if (remaining < 4) {
                    return OK;
                }
                parcel->writeInt32(KEY_SCROLL_DELAY);

                uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
                    | *(tmpData + 2) << 8 | *(tmpData + 3);
                parcel->writeInt32(delay);

                tmpData += 4;
                remaining -= 4;
                break;
            }
            // 'href' box for hyper text link
            case FOURCC('h', 'r', 'e', 'f'):
            {
                if (remaining < 5) {
                    return OK;
                }

                size_t dataPos = parcel->dataPosition();

                parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);

                // the start offset of the text to be linked
                parcel->writeInt32(U16_AT(tmpData));
                // the end offset of the text
                parcel->writeInt32(U16_AT(tmpData + 2));

                // the number of bytes in the following URL
                size_t len = *(tmpData + 4);
                parcel->writeInt32(len);

                remaining -= 5;

                if (remaining  < len) {
                    parcel->setDataPosition(dataPos);
                    return OK;
                }
                // the linked-to URL
                parcel->writeInt32(len);
                parcel->write(tmpData + 5, len);

                tmpData += (5 + len);
                remaining -= len;

                if (remaining  < 1) {
                    parcel->setDataPosition(dataPos);
                    return OK;
                }

                // the number of bytes in the following "alt" string
                len = *tmpData;
                parcel->writeInt32(len);

                tmpData += 1;
                remaining -= 1;
                if (remaining  < len) {
                    parcel->setDataPosition(dataPos);
                    return OK;
                }

                // an "alt" string for user display
                parcel->writeInt32(len);
                parcel->write(tmpData, len);

                tmpData += 1;
                remaining -= 1;
                break;
            }
            // 'tbox' box to indicate the position of the text with values
            // of top, left, bottom and right
            case FOURCC('t', 'b', 'o', 'x'):
            {
                if (remaining < 8) {
                    return OK;
                }
                parcel->writeInt32(KEY_STRUCT_TEXT_POS);
                parcel->writeInt32(U16_AT(tmpData));
                parcel->writeInt32(U16_AT(tmpData + 2));
                parcel->writeInt32(U16_AT(tmpData + 4));
                parcel->writeInt32(U16_AT(tmpData + 6));

                tmpData += 8;
                remaining -= 8;
                break;
            }
            // 'blnk' to specify the char range to be blinked
            case FOURCC('b', 'l', 'n', 'k'):
            {
                if (remaining < 4) {
                    return OK;
                }

                parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);

                // start char offset
                parcel->writeInt32(U16_AT(tmpData));
                // end char offset
                parcel->writeInt32(U16_AT(tmpData + 2));

                tmpData += 4;
                remaining -= 4;
                break;
            }
            // 'twrp' box specifies text wrap behavior. If the value if 0x00,
            // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
            // 0x02-0xff are reserved.
            case FOURCC('t', 'w', 'r', 'p'):
            {
                if (remaining < 1) {
                    return OK;
                }
                parcel->writeInt32(KEY_WRAP_TEXT);
                parcel->writeInt32(*tmpData);

                tmpData += 1;
                remaining -= 1;
                break;
            }
            default:
            {
                break;
            }
        }

        data += chunkSize;
        size -= chunkSize;
    }

    return OK;
}
// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
status_t TextDescriptions::extract3GPPGlobalDescriptions(
        const uint8_t *data, ssize_t size, Parcel *parcel) {

    parcel->writeInt32(KEY_GLOBAL_SETTING);

    while (size >= 8) {
        ssize_t chunkSize = U32_AT(data);
        uint32_t chunkType = U32_AT(data + 4);
        const uint8_t *tmpData = data;
        tmpData += 8;
        size_t remaining = size - 8;

        if (size < chunkSize) {
            return OK;
        }
        switch(chunkType) {
            case FOURCC('t', 'x', '3', 'g'):
            {
                if (remaining < 18) { // 8 just below, and another 10 a little further down
                    return OK;
                }
                tmpData += 8; // skip the first 8 bytes
                remaining -=8;
                parcel->writeInt32(KEY_DISPLAY_FLAGS);
                parcel->writeInt32(U32_AT(tmpData));

                parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
                parcel->writeInt32(tmpData[4]);
                parcel->writeInt32(tmpData[5]);

                parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
                uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
                    | *(tmpData + 8) << 8 | *(tmpData + 9);
                parcel->writeInt32(rgba);

                tmpData += 10;
                remaining -= 10;

                if (remaining < 8) {
                    return OK;
                }
                parcel->writeInt32(KEY_STRUCT_TEXT_POS);
                parcel->writeInt32(U16_AT(tmpData));
                parcel->writeInt32(U16_AT(tmpData + 2));
                parcel->writeInt32(U16_AT(tmpData + 4));
                parcel->writeInt32(U16_AT(tmpData + 6));

                tmpData += 8;
                remaining -= 8;

                if (remaining < 12) {
                    return OK;
                }
                parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
                parcel->writeInt32(KEY_START_CHAR);
                parcel->writeInt32(U16_AT(tmpData));

                parcel->writeInt32(KEY_END_CHAR);
                parcel->writeInt32(U16_AT(tmpData + 2));

                parcel->writeInt32(KEY_FONT_ID);
                parcel->writeInt32(U16_AT(tmpData + 4));

                parcel->writeInt32(KEY_STYLE_FLAGS);
                parcel->writeInt32(*(tmpData + 6));

                parcel->writeInt32(KEY_FONT_SIZE);
                parcel->writeInt32(*(tmpData + 7));

                parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
                rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
                    | *(tmpData + 10) << 8 | *(tmpData + 11);
                parcel->writeInt32(rgba);

                tmpData += 12;
                remaining -= 12;

                if (remaining < 2) {
                    return OK;
                }

                size_t dataPos = parcel->dataPosition();

                parcel->writeInt32(KEY_STRUCT_FONT_LIST);
                uint16_t count = U16_AT(tmpData);
                parcel->writeInt32(count);

                tmpData += 2;
                remaining -= 2;

                for (int i = 0; i < count; i++) {
                    if (remaining < 3) {
                        // roll back
                        parcel->setDataPosition(dataPos);
                        return OK;
                    }
                    // font ID
                    parcel->writeInt32(U16_AT(tmpData));

                    // font name length
                    parcel->writeInt32(*(tmpData + 2));

                    size_t len = *(tmpData + 2);

                    tmpData += 3;
                    remaining -= 3;

                    if (remaining < len) {
                        // roll back
                        parcel->setDataPosition(dataPos);
                        return OK;
                    }

                    parcel->write(tmpData, len);
                    tmpData += len;
                    remaining -= len;
                }

                // there is a "DisparityBox" after this according to the spec, but we ignore it
                break;
            }
            default:
            {
                break;
            }
        }

        data += chunkSize;
        size -= chunkSize;
    }

    return OK;
}
예제 #15
0
status_t SampleTable::setSampleDescParams(uint32_t count, off64_t offset, size_t size)
{
    // avcC atom will start after 78 bytes in avC1 atom
    const uint32_t avcC_offset = 78;

    for(uint32_t i = 0; i < count; ++i) {
        uint32_t hdr[2];
        if (mDataSource->readAt(offset, hdr, 8) < 8) {
            return ERROR_IO;
        }
        uint64_t avc1_chunk_size = ntohl(hdr[0]);
        uint32_t avc1_chunk_type = ntohl(hdr[1]);
        off64_t avc1_data_offset = offset + 8;

        if(avc1_chunk_size == 0)
            return ERROR_MALFORMED;

        if (avc1_chunk_size == 1) {
            if (mDataSource->readAt(offset + 8, &avc1_chunk_size, 8) < 8) {
                return ERROR_IO;
            }
            avc1_chunk_size = ntoh64(avc1_chunk_size);
            if (avc1_chunk_size == 0)
                return ERROR_MALFORMED;
            avc1_data_offset += 8;

            if (avc1_chunk_size < 16) {
                // The smallest valid chunk is 16 bytes long in this case.
                return ERROR_MALFORMED;
            }
        } else if (avc1_chunk_size < 8) {
            // The smallest valid chunk is 8 bytes long.
            return ERROR_MALFORMED;
        }

        off64_t avc1_chunk_data_size = offset + avc1_chunk_size - avc1_data_offset;
        LOGV("parsing chunk %c%c%c%c", ((char *)&avc1_chunk_type)[3],
                                                   ((char *)&avc1_chunk_type)[2],
                                                   ((char *)&avc1_chunk_type)[1],
                                                   ((char *)&avc1_chunk_type)[0]);

        if (avc1_chunk_type != FOURCC('a', 'v', 'c', '1')) {
            LOGE("Multiple Non AVC Sample Entries are not supported");
            return ERROR_MALFORMED;
        }

        uint8_t *buffer = new uint8_t[(ssize_t)avc1_chunk_data_size];
        if (mDataSource->readAt(avc1_data_offset, buffer, (ssize_t)avc1_chunk_data_size) < (ssize_t)avc1_chunk_data_size) {
              return ERROR_IO;
        }
        uint16_t data_ref_index = U16_AT(&buffer[6]);
        uint16_t width = U16_AT(&buffer[6 + 18]);
        uint16_t height = U16_AT(&buffer[6 + 20]);
        LOGE("data_ref_index : %d width : %d height: %d", data_ref_index, width, height);

        /* parse AVCC atom */
        uint64_t avcc_chunk_size = U32_AT(&buffer[avcC_offset]);
        uint32_t avcc_chunk_type = U32_AT(&buffer[avcC_offset+4]);;
        if((avcc_chunk_size == 0)|| (avcc_chunk_size == 1)) {
            LOGE("chunk size error while reading avCC atom");
            return ERROR_MALFORMED;
        }

        LOGV("parsing chunk %c%c%c%c",
               ((char *)&avcc_chunk_type)[3],
               ((char *)&avcc_chunk_type)[2],
               ((char *)&avcc_chunk_type)[1],
               ((char *)&avcc_chunk_type)[0]);

        if (avcc_chunk_type != FOURCC('a', 'v', 'c', 'C')) {
            LOGE("'avcC' atom expected, but not found");
            return ERROR_MALFORMED;
        }

        off64_t avcc_chunk_data_size = avc1_chunk_data_size - avcC_offset - 8;
        SampleDescAtom *sda = new SampleDescAtom;
        uint8_t *avccBuffer = new uint8_t[avcc_chunk_data_size];
        memcpy(avccBuffer, buffer+avcC_offset+8,avcc_chunk_data_size);
        sda->ptr = avccBuffer;
        sda->size =  avcc_chunk_data_size;
        mSampleDescAtoms.push_back(sda);

        delete[] buffer;

        offset += avc1_chunk_size;
    }
    return OK;
}
예제 #16
0
파일: ID3.cpp 프로젝트: Andrel322/gecko-dev
bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
    size_t oldSize = mSize;

    size_t offset = 0;
    while (offset + 10 <= mSize) {
        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
            break;
        }

        size_t dataSize;
        if (iTunesHack) {
            dataSize = U32_AT(&mData[offset + 4]);
        } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
            return false;
        }

        if (offset + dataSize + 10 > mSize) {
            return false;
        }

        uint16_t flags = U16_AT(&mData[offset + 8]);
        uint16_t prevFlags = flags;

        if (flags & 1) {
            // Strip data length indicator

            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
            mSize -= 4;
            dataSize -= 4;

            flags &= ~1;
        }

        if (flags & 2) {
            // This file has "unsynchronization", so we have to replace occurrences
            // of 0xff 0x00 with just 0xff in order to get the real data.

            size_t readOffset = offset + 11;
            size_t writeOffset = offset + 11;
            for (size_t i = 0; i + 1 < dataSize; ++i) {
                if (mData[readOffset - 1] == 0xff
                        && mData[readOffset] == 0x00) {
                    ++readOffset;
                    --mSize;
                    --dataSize;
                }
                mData[writeOffset++] = mData[readOffset++];
            }
            // move the remaining data following this frame
            memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);

            flags &= ~2;
        }

        if (flags != prevFlags || iTunesHack) {
            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
            mData[offset + 8] = flags >> 8;
            mData[offset + 9] = flags & 0xff;
        }

        offset += 10 + dataSize;
    }
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;
}
예제 #18
0
// static
sp<VBRISeeker> VBRISeeker::CreateFromSource(
        const sp<DataSource> &source, off64_t post_id3_pos) {
    off64_t pos = post_id3_pos;

    uint8_t header[4];
    ssize_t n = source->readAt(pos, header, sizeof(header));
    if (n < (ssize_t)sizeof(header)) {
        return NULL;
    }

    uint32_t tmp = U32_AT(&header[0]);
    size_t frameSize;
    int sampleRate;
    if (!GetMPEGAudioFrameSize(tmp, &frameSize, &sampleRate)) {
        return NULL;
    }

    // VBRI header follows 32 bytes after the header _ends_.
    pos += sizeof(header) + 32;

    uint8_t vbriHeader[26];
    n = source->readAt(pos, vbriHeader, sizeof(vbriHeader));
    if (n < (ssize_t)sizeof(vbriHeader)) {
        return NULL;
    }

    if (memcmp(vbriHeader, "VBRI", 4)) {
        return NULL;
    }

    size_t numFrames = U32_AT(&vbriHeader[14]);

    int64_t durationUs =
        numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;

    ALOGV("duration = %.2f secs", durationUs / 1E6);

    size_t numEntries = U16_AT(&vbriHeader[18]);
    size_t entrySize = U16_AT(&vbriHeader[22]);
    size_t scale = U16_AT(&vbriHeader[20]);

    ALOGV("%zu entries, scale=%zu, size_per_entry=%zu",
         numEntries,
         scale,
         entrySize);

    size_t totalEntrySize = numEntries * entrySize;
    uint8_t *buffer = new uint8_t[totalEntrySize];

    n = source->readAt(pos + sizeof(vbriHeader), buffer, totalEntrySize);
    if (n < (ssize_t)totalEntrySize) {
        delete[] buffer;
        buffer = NULL;

        return NULL;
    }

    sp<VBRISeeker> seeker = new VBRISeeker;
    seeker->mBasePos = post_id3_pos + frameSize;
    // only update mDurationUs if the calculated duration is valid (non zero)
    // otherwise, leave duration at -1 so that getDuration() and getOffsetForTime()
    // return false when called, to indicate that this vbri tag does not have the
    // requested information
    if (durationUs) {
        seeker->mDurationUs = durationUs;
    }

    off64_t offset = post_id3_pos;
    for (size_t i = 0; i < numEntries; ++i) {
        uint32_t numBytes;
        switch (entrySize) {
            case 1: numBytes = buffer[i]; break;
            case 2: numBytes = U16_AT(buffer + 2 * i); break;
            case 3: numBytes = U24_AT(buffer + 3 * i); break;
            default:
            {
                CHECK_EQ(entrySize, 4u);
                numBytes = U32_AT(buffer + 4 * i); break;
            }
        }

        numBytes *= scale;

        seeker->mSegments.push(numBytes);

        ALOGV("entry #%zu: %u offset 0x%016llx", i, numBytes, offset);
        offset += numBytes;
    }

    delete[] buffer;
    buffer = NULL;

    ALOGI("Found VBRI header.");

    return seeker;
}