namespace android {

// static
const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
// static
const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
// static
const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
// static
const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');

////////////////////////////////////////////////////////////////////////////////

struct SampleTable::CompositionDeltaLookup {
    CompositionDeltaLookup();

    void setEntries(
            const uint32_t *deltaEntries, size_t numDeltaEntries);

    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);

private:
    Mutex mLock;

    const uint32_t *mDeltaEntries;
    size_t mNumDeltaEntries;

    size_t mCurrentDeltaEntry;
    size_t mCurrentEntrySampleIndex;

    DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
};

SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
    : mDeltaEntries(NULL),
      mNumDeltaEntries(0),
      mCurrentDeltaEntry(0),
      mCurrentEntrySampleIndex(0) {
}

void SampleTable::CompositionDeltaLookup::setEntries(
        const uint32_t *deltaEntries, size_t numDeltaEntries) {
    Mutex::Autolock autolock(mLock);

    mDeltaEntries = deltaEntries;
    mNumDeltaEntries = numDeltaEntries;
    mCurrentDeltaEntry = 0;
    mCurrentEntrySampleIndex = 0;
}

uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
        uint32_t sampleIndex) {
    Mutex::Autolock autolock(mLock);

    if (mDeltaEntries == NULL) {
        return 0;
    }

    if (sampleIndex < mCurrentEntrySampleIndex) {
        mCurrentDeltaEntry = 0;
        mCurrentEntrySampleIndex = 0;
    }

    while (mCurrentDeltaEntry < mNumDeltaEntries) {
        uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
        if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
            return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
        }

        mCurrentEntrySampleIndex += sampleCount;
        ++mCurrentDeltaEntry;
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////////

SampleTable::SampleTable(const sp<DataSource> &source)
    : mDataSource(source),
      mChunkOffsetOffset(-1),
      mChunkOffsetType(0),
      mNumChunkOffsets(0),
      mSampleToChunkOffset(-1),
      mNumSampleToChunkOffsets(0),
      mSampleSizeOffset(-1),
      mSampleSizeFieldSize(0),
      mDefaultSampleSize(0),
      mNumSampleSizes(0),
      mTimeToSampleCount(0),
      mTimeToSample(NULL),
      mSampleTimeEntries(NULL),
      mCompositionTimeDeltaEntries(NULL),
      mNumCompositionTimeDeltaEntries(0),
      mCompositionDeltaLookup(new CompositionDeltaLookup),
      mSyncSampleOffset(-1),
      mNumSyncSamples(0),
      mSyncSamples(NULL),
      mLastSyncSampleIndex(0),
      mSampleToChunkEntries(NULL) {
    mSampleIterator = new SampleIterator(this);
}

SampleTable::~SampleTable() {
    delete[] mSampleToChunkEntries;
    mSampleToChunkEntries = NULL;

    delete[] mSyncSamples;
    mSyncSamples = NULL;

    delete mCompositionDeltaLookup;
    mCompositionDeltaLookup = NULL;

    delete[] mCompositionTimeDeltaEntries;
    mCompositionTimeDeltaEntries = NULL;

    delete[] mSampleTimeEntries;
    mSampleTimeEntries = NULL;

    delete[] mTimeToSample;
    mTimeToSample = NULL;

    delete mSampleIterator;
    mSampleIterator = NULL;
}

bool SampleTable::isValid() const {
    return mChunkOffsetOffset >= 0
        && mSampleToChunkOffset >= 0
        && mSampleSizeOffset >= 0
        && mTimeToSample != NULL;
}

status_t SampleTable::setChunkOffsetParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    if (mChunkOffsetOffset >= 0) {
        return ERROR_MALFORMED;
    }

    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);

    mChunkOffsetOffset = data_offset;
    mChunkOffsetType = type;

    if (data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumChunkOffsets = U32_AT(&header[4]);

    if (mChunkOffsetType == kChunkOffsetType32) {
        if (data_size < 8 + mNumChunkOffsets * 4) {
            return ERROR_MALFORMED;
        }
    } else {
        if (data_size < 8 + mNumChunkOffsets * 8) {
            return ERROR_MALFORMED;
        }
    }

    return OK;
}

status_t SampleTable::setSampleToChunkParams(
        off64_t data_offset, size_t data_size) {
    if (mSampleToChunkOffset >= 0) {
        return ERROR_MALFORMED;
    }

    mSampleToChunkOffset = data_offset;

    if (data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumSampleToChunkOffsets = U32_AT(&header[4]);

    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
        return ERROR_MALFORMED;
    }

    mSampleToChunkEntries =
        new SampleToChunkEntry[mNumSampleToChunkOffsets];

    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
        uint8_t buffer[12];
        if (mDataSource->readAt(
                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
                != (ssize_t)sizeof(buffer)) {
            return ERROR_IO;
        }

        CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.

        // We want the chunk index to be 0-based.
        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
    }

    return OK;
}

status_t SampleTable::setSampleSizeParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    if (mSampleSizeOffset >= 0) {
        return ERROR_MALFORMED;
    }

    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);

    mSampleSizeOffset = data_offset;

    if (data_size < 12) {
        return ERROR_MALFORMED;
    }

    uint8_t header[12];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mDefaultSampleSize = U32_AT(&header[4]);
    mNumSampleSizes = U32_AT(&header[8]);

    if (type == kSampleSizeType32) {
        mSampleSizeFieldSize = 32;

        if (mDefaultSampleSize != 0) {
            return OK;
        }

        if (data_size < 12 + mNumSampleSizes * 4) {
            return ERROR_MALFORMED;
        }
    } else {
        if ((mDefaultSampleSize & 0xffffff00) != 0) {
            // The high 24 bits are reserved and must be 0.
            return ERROR_MALFORMED;
        }

        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
        mDefaultSampleSize = 0;

        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
            && mSampleSizeFieldSize != 16) {
            return ERROR_MALFORMED;
        }

        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
            return ERROR_MALFORMED;
        }
    }

    return OK;
}

status_t SampleTable::setTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    if (mTimeToSample != NULL || data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mTimeToSampleCount = U32_AT(&header[4]);
    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];

    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
    if (mDataSource->readAt(
                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
        return ERROR_IO;
    }

    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
        mTimeToSample[i] = ntohl(mTimeToSample[i]);
    }

    return OK;
}

status_t SampleTable::setCompositionTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    LOGI("There are reordered frames present.");

    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header))
            < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    size_t numEntries = U32_AT(&header[4]);

    if (data_size != (numEntries + 1) * 8) {
        return ERROR_MALFORMED;
    }

    mNumCompositionTimeDeltaEntries = numEntries;
    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];

    if (mDataSource->readAt(
                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
            < (ssize_t)numEntries * 8) {
        delete[] mCompositionTimeDeltaEntries;
        mCompositionTimeDeltaEntries = NULL;

        return ERROR_IO;
    }

    for (size_t i = 0; i < 2 * numEntries; ++i) {
        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
    }

    mCompositionDeltaLookup->setEntries(
            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);

    return OK;
}

status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
    if (mSyncSampleOffset >= 0 || data_size < 8) {
        return ERROR_MALFORMED;
    }

    mSyncSampleOffset = data_offset;

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumSyncSamples = U32_AT(&header[4]);

    if (mNumSyncSamples < 2) {
        ALOGV("Table of sync samples is empty or has only a single entry!");
    }

    mSyncSamples = new uint32_t[mNumSyncSamples];
    size_t size = mNumSyncSamples * sizeof(uint32_t);
    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
            != (ssize_t)size) {
        return ERROR_IO;
    }

    for (size_t i = 0; i < mNumSyncSamples; ++i) {
        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
    }

    return OK;
}

uint32_t SampleTable::countChunkOffsets() const {
    return mNumChunkOffsets;
}

uint32_t SampleTable::countSamples() const {
    return mNumSampleSizes;
}

status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    Mutex::Autolock autoLock(mLock);

    *max_size = 0;

    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
        size_t sample_size;
        status_t err = getSampleSize_l(i, &sample_size);

        if (err != OK) {
            return err;
        }

        if (sample_size > *max_size) {
            *max_size = sample_size;
        }
    }

    return OK;
}

uint32_t abs_difference(uint32_t time1, uint32_t time2) {
    return time1 > time2 ? time1 - time2 : time2 - time1;
}

// static
int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;

    if (a->mCompositionTime < b->mCompositionTime) {
        return -1;
    } else if (a->mCompositionTime > b->mCompositionTime) {
        return 1;
    }

    return 0;
}

void SampleTable::buildSampleEntriesTable() {
    Mutex::Autolock autoLock(mLock);

    if (mSampleTimeEntries != NULL) {
        return;
    }

    mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];

    uint32_t sampleIndex = 0;
    uint32_t sampleTime = 0;

    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
        uint32_t n = mTimeToSample[2 * i];
        uint32_t delta = mTimeToSample[2 * i + 1];

        for (uint32_t j = 0; j < n; ++j) {
            if (sampleIndex < mNumSampleSizes) {
                // Technically this should always be the case if the file
                // is well-formed, but you know... there's (gasp) malformed
                // content out there.

                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;

                uint32_t compTimeDelta =
                    mCompositionDeltaLookup->getCompositionTimeOffset(
                            sampleIndex);

                mSampleTimeEntries[sampleIndex].mCompositionTime =
                    sampleTime + compTimeDelta;
            }

            ++sampleIndex;
            sampleTime += delta;
        }
    }

    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
          CompareIncreasingTime);
}

status_t SampleTable::findSampleAtTime(
        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
    buildSampleEntriesTable();

    uint32_t left = 0;
    uint32_t right = mNumSampleSizes;
    while (left < right) {
        uint32_t center = (left + right) / 2;
        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;

        if (req_time < centerTime) {
            right = center;
        } else if (req_time > centerTime) {
            left = center + 1;
        } else {
            left = center;
            break;
        }
    }

    if (left == mNumSampleSizes) {
        if (flags == kFlagAfter) {
            return ERROR_OUT_OF_RANGE;
        }

        --left;
    }

    uint32_t closestIndex = left;

    switch (flags) {
        case kFlagBefore:
        {
            while (closestIndex > 0
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            > req_time) {
                --closestIndex;
            }
            break;
        }

        case kFlagAfter:
        {
            while (closestIndex + 1 < mNumSampleSizes
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            < req_time) {
                ++closestIndex;
            }
            break;
        }

        default:
        {
            CHECK(flags == kFlagClosest);

            if (closestIndex > 0) {
                // Check left neighbour and pick closest.
                uint32_t absdiff1 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex].mCompositionTime,
                            req_time);

                uint32_t absdiff2 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
                            req_time);

                if (absdiff1 > absdiff2) {
                    closestIndex = closestIndex - 1;
                }
            }

            break;
        }
    }

    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;

    return OK;
}

status_t SampleTable::findSyncSampleNear(
        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
    Mutex::Autolock autoLock(mLock);

    *sample_index = 0;

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = start_sample_index;
        return OK;
    }

    if (mNumSyncSamples == 0) {
        *sample_index = 0;
        return OK;
    }

    uint32_t left = 0;
    while (left < mNumSyncSamples) {
        uint32_t x = mSyncSamples[left];

        if (x >= start_sample_index) {
            break;
        }

        ++left;
    }

    if (left == mNumSyncSamples) {
        if (flags == kFlagAfter) {
            LOGE("tried to find a sync frame after the last one: %d", left);
            return ERROR_OUT_OF_RANGE;
        }
    }

    if (left > 0) {
        --left;
    }

    uint32_t x = mSyncSamples[left];

    if (left + 1 < mNumSyncSamples) {
        uint32_t y = mSyncSamples[left + 1];

        // our sample lies between sync samples x and y.

        status_t err = mSampleIterator->seekTo(start_sample_index);
        if (err != OK) {
            return err;
        }

        uint32_t sample_time = mSampleIterator->getSampleTime();

        err = mSampleIterator->seekTo(x);
        if (err != OK) {
            return err;
        }
        uint32_t x_time = mSampleIterator->getSampleTime();

        err = mSampleIterator->seekTo(y);
        if (err != OK) {
            return err;
        }

        uint32_t y_time = mSampleIterator->getSampleTime();

        if (abs_difference(x_time, sample_time)
                > abs_difference(y_time, sample_time)) {
            // Pick the sync sample closest (timewise) to the start-sample.
            x = y;
            ++left;
        }
    }

    switch (flags) {
        case kFlagBefore:
        {
            if (x > start_sample_index) {
                CHECK(left > 0);

                x = mSyncSamples[left - 1];

                CHECK(x <= start_sample_index);
            }
            break;
        }

        case kFlagAfter:
        {
            if (x < start_sample_index) {
                if (left + 1 >= mNumSyncSamples) {
                    return ERROR_OUT_OF_RANGE;
                }

                x = mSyncSamples[left + 1];

                CHECK(x >= start_sample_index);
            }

            break;
        }

        default:
            break;
    }

    *sample_index = x;

    return OK;
}

status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
    Mutex::Autolock autoLock(mLock);

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = 0;
        return OK;
    }

    uint32_t bestSampleIndex = 0;
    size_t maxSampleSize = 0;

    static const size_t kMaxNumSyncSamplesToScan = 20;

    // Consider the first kMaxNumSyncSamplesToScan sync samples and
    // pick the one with the largest (compressed) size as the thumbnail.

    size_t numSamplesToScan = mNumSyncSamples;
    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
        numSamplesToScan = kMaxNumSyncSamplesToScan;
    }

    for (size_t i = 0; i < numSamplesToScan; ++i) {
        uint32_t x = mSyncSamples[i];

        // Now x is a sample index.
        size_t sampleSize;
        status_t err = getSampleSize_l(x, &sampleSize);
        if (err != OK) {
            return err;
        }

        if (i == 0 || sampleSize > maxSampleSize) {
            bestSampleIndex = x;
            maxSampleSize = sampleSize;
        }
    }

    *sample_index = bestSampleIndex;

    return OK;
}

status_t SampleTable::getSampleSize_l(
        uint32_t sampleIndex, size_t *sampleSize) {
    return mSampleIterator->getSampleSizeDirect(
            sampleIndex, sampleSize);
}

status_t SampleTable::getMetaDataForSample(
        uint32_t sampleIndex,
        off64_t *offset,
        size_t *size,
        uint32_t *compositionTime,
        bool *isSyncSample) {
    Mutex::Autolock autoLock(mLock);

    status_t err;
    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
        return err;
    }

    if (offset) {
        *offset = mSampleIterator->getSampleOffset();
    }

    if (size) {
        *size = mSampleIterator->getSampleSize();
    }

    if (compositionTime) {
        *compositionTime = mSampleIterator->getSampleTime();
    }

    if (isSyncSample) {
        *isSyncSample = false;
        if (mSyncSampleOffset < 0) {
            // Every sample is a sync sample.
            *isSyncSample = true;
        } else {
            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
                ? mLastSyncSampleIndex : 0;

            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
                ++i;
            }

            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
                *isSyncSample = true;
            }

            mLastSyncSampleIndex = i;
        }
    }

    return OK;
}

uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
}

}  // namespace android
// 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;
}
Пример #3
0
// $Version$
// $Revision:$
//   
// DESCRIPTION:   GFX Font Class Member Functions
//   
// (c) Copyright 1995, Dynamix Inc.   All rights reserved.
//
//========================================================================

#include <filstrm.h>
#include "g_font.h"
#include "g_bitmap.h"
#include "g_pal.h"
#include "resManager.h"

IMPLEMENT_PERSISTENT_TAG(GFXFont,         FOURCC('P','F','O','N'));

static void SetMonoBits( GFXBitmap *pBitmap, UInt32 obgc, UInt32 nfgc, UInt32 nbgc, Int32 flags );
#define TRANSLATE_FOREGROUND  (1<<1)
#define TRANSLATE_BACKGROUND  (1<<2)

//========================================================================
//                Definitions and Structure Declerations
//========================================================================

#define DEREF(x,y)  ((y->fi.flags&FONT_UNICODE)? (UInt32 *)x:(char *)x)
#define NEXT(x,y)   ( x += (y->fi.flags&FONT_UNICODE)? 2:1)

struct Header
{
	DWORD ver_nc;
Пример #4
0
bool eZ80AccessorSZX::SetState(xIo::eStreamMemory& is)
{
	ZXSTHEADER header;
	if(is.Read(&header, sizeof(header)) != sizeof(header))
		return false;
	if(header.dwMagic != FOURCC('Z', 'X', 'S', 'T'))
		return false;
	bool model48k = false;
	switch(header.chMachineId)
	{
	case ZXSTMID_16K:
	case ZXSTMID_48K:
	case ZXSTMID_NTSC48K:
		model48k = true;
		break;
	case ZXSTMID_128K:
	case ZXSTMID_PENTAGON128:
		break;
	default:
		return false;
	}
	SetupDevices(model48k);
	ZXSTBLOCK block;
	while(is.Read(&block, sizeof(block)) == sizeof(block))
	{
		switch(block.dwId)
		{
		case FOURCC('Z', '8', '0', 'R'):
			{
				ZXSTZ80REGS regs;
				if(!ReadBlock(is, &regs, block))
					return false;
				af = SwapWord(regs.AF);
				bc = SwapWord(regs.BC);
				de = SwapWord(regs.DE);
				hl = SwapWord(regs.HL);
				alt.af = SwapWord(regs.AF1);
				alt.bc = SwapWord(regs.BC1);
				alt.de = SwapWord(regs.DE1);
				alt.hl = SwapWord(regs.HL1);

				ix = SwapWord(regs.IX);
				iy = SwapWord(regs.IY);
				sp = SwapWord(regs.SP);
				pc = SwapWord(regs.PC);
				i = regs.I;
				r_low = regs.R;
				r_hi = regs.R & 0x80;
				im = regs.IM;
				iff1 = regs.IFF1;
				iff2 = regs.IFF2;
				t = Dword((const byte*)&regs.dwCyclesStart) % frame_tacts;
				if(regs.wMemPtr)
					memptr = SwapWord(regs.wMemPtr);
			}
			break;
		case FOURCC('S', 'P', 'C', 'R'):
			{
				ZXSTSPECREGS regs;
				if(!ReadBlock(is, &regs, block))
					return false;
				devices->IoWrite(0xfe, (regs.chFe&0x18) | regs.chBorder, t);
				devices->IoWrite(0x7ffd, model48k ? 0x30 : regs.ch7ffd, t);
				if(model48k)
					devices->Get<eMemory>()->SetRomPage(eMemory::P_ROM_48);
				else
					devices->Get<eMemory>()->SetRomPage((regs.ch7ffd & 0x10) ? eMemory::P_ROM_128_0 : eMemory::P_ROM_128_1);
			}
			break;
		case FOURCC('R', 'A', 'M', 'P'):
			{
				ZXSTRAMPAGE ram_page;
				if(!ReadBlock(is, &ram_page, block, sizeof(ZXSTRAMPAGE) - sizeof(ZXSTBLOCK) - 1))
					return false;
				byte* buf = new byte[eMemory::PAGE_SIZE];
				bool ok = false;
				if(SwapWord(ram_page.wFlags)&ZXSTRF_COMPRESSED)
				{
#ifdef USE_ZIP
					size_t size = ram_page.blk.dwSize - (sizeof(ZXSTRAMPAGE) - sizeof(ZXSTBLOCK) - 1);
					byte* buf_compr = new byte[size];
					ok = is.Read(buf_compr, size) == size;
					if(ok)
					{
						z_stream zs;
						memset(&zs, 0, sizeof(zs));
						zs.next_in = buf_compr;
						zs.avail_in = size;
						zs.next_out = buf;
						zs.avail_out = eMemory::PAGE_SIZE;
						ok = inflateInit2(&zs, 15) == Z_OK;
						if(ok)
							ok = inflate(&zs, Z_NO_FLUSH) == Z_STREAM_END;
						inflateEnd(&zs);
					}
					SAFE_DELETE_ARRAY(buf_compr);
#endif//USE_ZIP
				}
				else
				{
					size_t size = ram_page.blk.dwSize - (sizeof(ZXSTRAMPAGE) - sizeof(ZXSTBLOCK) - 1);
					ok = size == eMemory::PAGE_SIZE;
					if(ok)
					{
						ok = is.Read(buf, size) == size;
					}
				}
				if(ok && ram_page.chPageNo <= 7)
				{
					memcpy(memory->Get(eMemory::P_RAM0 + ram_page.chPageNo), buf, eMemory::PAGE_SIZE);
				}
				SAFE_DELETE(buf);
				if(!ok)
					return false;
			}
			break;
		case FOURCC('A', 'Y', '\0', '\0'):
			{
				ZXSTAYBLOCK ay_state;
				if(!ReadBlock(is, &ay_state, block))
					return false;
				devices->Get<eAY>()->SetRegs(ay_state.chAyRegs);
				devices->Get<eAY>()->Select(ay_state.chCurrentRegister);
			}
			break;
		default:
			if(is.Seek(block.dwSize, xIo::eStreamMemory::S_CUR) != 0)
				return false;
		}
		if(is.Pos() == is.Size())
			return true;
	}
	return false;
}
Пример #5
0
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "codeclib.h"
#include "codecs/libpcm/support_formats.h"

CODEC_HEADER

#define FOURCC(c1, c2, c3, c4) \
((((uint32_t)c1)<<24)|(((uint32_t)c2)<<16)|(((uint32_t)c3)<<8)|((uint32_t)c4))

/* This codec supports the following AIFC compressionType formats */
enum {
    AIFC_FORMAT_PCM          = FOURCC('N', 'O', 'N', 'E'), /* AIFC PCM Format (big endian) */
    AIFC_FORMAT_ALAW         = FOURCC('a', 'l', 'a', 'w'), /* AIFC ALaw compressed */
    AIFC_FORMAT_MULAW        = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */
    AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */
    AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */
    AIFC_FORMAT_QT_IMA_ADPCM = FOURCC('i', 'm', 'a', '4'), /* AIFC QuickTime IMA ADPCM */
};

static const struct pcm_entry pcm_codecs[] = {
    { AIFC_FORMAT_PCM,          get_linear_pcm_codec      },
    { AIFC_FORMAT_ALAW,         get_itut_g711_alaw_codec  },
    { AIFC_FORMAT_MULAW,        get_itut_g711_mulaw_codec },
    { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec      },
    { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec      },
    { AIFC_FORMAT_QT_IMA_ADPCM, get_qt_ima_adpcm_codec    },
};
Пример #6
0
namespace android {

// static
const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
// static
const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
// static
const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
// static
const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');

////////////////////////////////////////////////////////////////////////////////

struct SampleTable::CompositionDeltaLookup {
    CompositionDeltaLookup();

    void setEntries(
            const uint32_t *deltaEntries, size_t numDeltaEntries);

    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);

private:
    Mutex mLock;

    const uint32_t *mDeltaEntries;
    size_t mNumDeltaEntries;

    size_t mCurrentDeltaEntry;
    size_t mCurrentEntrySampleIndex;

    DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
};

SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
    : mDeltaEntries(NULL),
      mNumDeltaEntries(0),
      mCurrentDeltaEntry(0),
      mCurrentEntrySampleIndex(0) {
}

void SampleTable::CompositionDeltaLookup::setEntries(
        const uint32_t *deltaEntries, size_t numDeltaEntries) {
    Mutex::Autolock autolock(mLock);

    mDeltaEntries = deltaEntries;
    mNumDeltaEntries = numDeltaEntries;
    mCurrentDeltaEntry = 0;
    mCurrentEntrySampleIndex = 0;
}

uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
        uint32_t sampleIndex) {
    Mutex::Autolock autolock(mLock);

    if (mDeltaEntries == NULL) {
        return 0;
    }

    if (sampleIndex < mCurrentEntrySampleIndex) {
        mCurrentDeltaEntry = 0;
        mCurrentEntrySampleIndex = 0;
    }

    while (mCurrentDeltaEntry < mNumDeltaEntries) {
        uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
        if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
            return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
        }

        mCurrentEntrySampleIndex += sampleCount;
        ++mCurrentDeltaEntry;
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////////

SampleTable::SampleTable(const sp<DataSource> &source)
    : mDataSource(source),
      mChunkOffsetOffset(-1),
      mChunkOffsetType(0),
      mNumChunkOffsets(0),
      mSampleToChunkOffset(-1),
      mNumSampleToChunkOffsets(0),
      mSampleSizeOffset(-1),
      mSampleSizeFieldSize(0),
      mDefaultSampleSize(0),
      mNumSampleSizes(0),
      mTimeToSampleCount(0),
      mTimeToSample(NULL),
      mSampleTimeEntries(NULL),
      mCompositionTimeDeltaEntries(NULL),
      mNumCompositionTimeDeltaEntries(0),
      mCompositionDeltaLookup(new CompositionDeltaLookup),
      mSyncSampleOffset(-1),
      mNumSyncSamples(0),
      mSyncSamples(NULL),
      mLastSyncSampleIndex(0),
      mSampleToChunkEntries(NULL) {
    mSampleIterator = new SampleIterator(this);
}

SampleTable::~SampleTable() {
    delete[] mSampleToChunkEntries;
    mSampleToChunkEntries = NULL;

    delete[] mSyncSamples;
    mSyncSamples = NULL;

    delete mCompositionDeltaLookup;
    mCompositionDeltaLookup = NULL;

    delete[] mCompositionTimeDeltaEntries;
    mCompositionTimeDeltaEntries = NULL;

    delete[] mSampleTimeEntries;
    mSampleTimeEntries = NULL;

    delete[] mTimeToSample;
    mTimeToSample = NULL;

    delete mSampleIterator;
    mSampleIterator = NULL;

    while (!mSampleDescAtoms.empty()) {
        List<SampleDescAtom *>::iterator it = mSampleDescAtoms.begin();
        delete (*it)->ptr;
        (*it) = NULL;
         mSampleDescAtoms.erase(it);
    }
    mSampleDescAtoms.clear();
}

bool SampleTable::isValid() const {
    return mChunkOffsetOffset >= 0
        && mSampleToChunkOffset >= 0
        && mSampleSizeOffset >= 0
        && mTimeToSample != NULL;
}

status_t SampleTable::setChunkOffsetParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    if (mChunkOffsetOffset >= 0) {
        return ERROR_MALFORMED;
    }

    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);

    mChunkOffsetOffset = data_offset;
    mChunkOffsetType = type;

    if (data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumChunkOffsets = U32_AT(&header[4]);

    if (mChunkOffsetType == kChunkOffsetType32) {
        if (data_size < 8 + mNumChunkOffsets * 4) {
            return ERROR_MALFORMED;
        }
    } else {
        if (data_size < 8 + mNumChunkOffsets * 8) {
            return ERROR_MALFORMED;
        }
    }

    return OK;
}

status_t SampleTable::setSampleToChunkParams(
        off64_t data_offset, size_t data_size) {
    if (mSampleToChunkOffset >= 0) {
        return ERROR_MALFORMED;
    }

    mSampleToChunkOffset = data_offset;

    if (data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumSampleToChunkOffsets = U32_AT(&header[4]);

    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
        return ERROR_MALFORMED;
    }

    mSampleToChunkEntries =
        new SampleToChunkEntry[mNumSampleToChunkOffsets];

    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
        uint8_t buffer[12];
        if (mDataSource->readAt(
                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
                != (ssize_t)sizeof(buffer)) {
            return ERROR_IO;
        }

        //CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.
        if(U32_AT(buffer) <= 0) {
            LOGE("Non Standard Chunk index\n");
            return ERROR_MALFORMED;
        }
        // We want the chunk index to be 0-based.
        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
    }

    return OK;
}

status_t SampleTable::setSampleSizeParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    if (mSampleSizeOffset >= 0) {
        return ERROR_MALFORMED;
    }

    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);

    mSampleSizeOffset = data_offset;

    if (data_size < 12) {
        return ERROR_MALFORMED;
    }

    uint8_t header[12];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mDefaultSampleSize = U32_AT(&header[4]);
    mNumSampleSizes = U32_AT(&header[8]);

    if (type == kSampleSizeType32) {
        mSampleSizeFieldSize = 32;

        // this needs to be 64 or overflow may occur from the calculation
        uint64_t expectedDataSize = (uint64_t)12 + (uint64_t)mNumSampleSizes * (uint64_t)4;

        // mDefaultSampleSize = 0 means sample table follows the field
        if (((uint64_t)data_size < expectedDataSize) && (mDefaultSampleSize == 0)){
            return ERROR_MALFORMED;
        }

        if (((uint64_t)data_size < expectedDataSize) && ((mDefaultSampleSize & 0xFF000000) != 0) ) {
            return ERROR_MALFORMED;
        }

        if (mDefaultSampleSize != 0) {
            return OK;
        }
    } else {
        if ((mDefaultSampleSize & 0xffffff00) != 0) {
            // The high 24 bits are reserved and must be 0.
            return ERROR_MALFORMED;
        }

        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
        mDefaultSampleSize = 0;

        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
            && mSampleSizeFieldSize != 16) {
            return ERROR_MALFORMED;
        }

        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
            return ERROR_MALFORMED;
        }
    }

    return OK;
}

status_t SampleTable::setTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    if (mTimeToSample != NULL || data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mTimeToSampleCount = U32_AT(&header[4]);
    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];

    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
    if (mDataSource->readAt(
                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
        return ERROR_IO;
    }

    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
        mTimeToSample[i] = ntohl(mTimeToSample[i]);
    }

    return OK;
}

status_t SampleTable::setCompositionTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    LOGI("There are reordered frames present.");

    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header))
            < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0 &&
        U32_AT(header) != 0x00010000) {
        // Expected version = 0 or 1, flags = 0.
        return ERROR_MALFORMED;
    }

    size_t numEntries = U32_AT(&header[4]);

    if (data_size != (numEntries + 1) * 8) {
        return ERROR_MALFORMED;
    }

    mNumCompositionTimeDeltaEntries = numEntries;
    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];

    if (mDataSource->readAt(
                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
            < (ssize_t)numEntries * 8) {
        delete[] mCompositionTimeDeltaEntries;
        mCompositionTimeDeltaEntries = NULL;

        return ERROR_IO;
    }

    for (size_t i = 0; i < 2 * numEntries; ++i) {
        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
    }

    mCompositionDeltaLookup->setEntries(
            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);

    return OK;
}

status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
    if (mSyncSampleOffset >= 0 || data_size < 8) {
        return ERROR_MALFORMED;
    }

    mSyncSampleOffset = data_offset;

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumSyncSamples = U32_AT(&header[4]);

    if (mNumSyncSamples < 2) {
        LOGV("Table of sync samples is empty or has only a single entry!");
    }

    mSyncSamples = new uint32_t[mNumSyncSamples];
    size_t size = mNumSyncSamples * sizeof(uint32_t);
    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
            != (ssize_t)size) {
        return ERROR_IO;
    }

    for (size_t i = 0; i < mNumSyncSamples; ++i) {
        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
    }

    return OK;
}

uint32_t SampleTable::countChunkOffsets() const {
    return mNumChunkOffsets;
}

uint32_t SampleTable::countSamples() const {
    return mNumSampleSizes;
}

status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    Mutex::Autolock autoLock(mLock);

    *max_size = 0;
    if(mDefaultSampleSize > 0){
        *max_size = mDefaultSampleSize;
        return OK;
    }

    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
        size_t sample_size;
        status_t err = getSampleSize_l(i, &sample_size);

        if (err != OK) {
            return err;
        }

        if (sample_size > *max_size) {
            *max_size = sample_size;
        }
    }

    return OK;
}

uint32_t abs_difference(uint32_t time1, uint32_t time2) {
    return time1 > time2 ? time1 - time2 : time2 - time1;
}

// static
int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;

    if (a->mCompositionTime < b->mCompositionTime) {
        return -1;
    } else if (a->mCompositionTime > b->mCompositionTime) {
        return 1;
    }

    return 0;
}

void SampleTable::buildSampleEntriesTable() {
    Mutex::Autolock autoLock(mLock);

    if (mSampleTimeEntries != NULL) {
        return;
    }

    mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];

    uint32_t sampleIndex = 0;
    uint32_t sampleTime = 0;

    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
        uint32_t n = mTimeToSample[2 * i];
        uint32_t delta = mTimeToSample[2 * i + 1];

        for (uint32_t j = 0; j < n; ++j) {
            if (sampleIndex < mNumSampleSizes) {
                // Technically this should always be the case if the file
                // is well-formed, but you know... there's (gasp) malformed
                // content out there.

                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;

                int32_t compTimeDelta = (int32_t)
                    mCompositionDeltaLookup->getCompositionTimeOffset(
                            sampleIndex);

                mSampleTimeEntries[sampleIndex].mCompositionTime =
                    sampleTime + compTimeDelta;
            }

            ++sampleIndex;
            sampleTime += delta;
        }
    }

    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
          CompareIncreasingTime);
}

status_t SampleTable::findSampleAtTime(
        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
    buildSampleEntriesTable();

    uint32_t left = 0;
    uint32_t right = mNumSampleSizes;
    while (left < right) {
        uint32_t center = (left + right) / 2;
        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;

        if (req_time < centerTime) {
            right = center;
        } else if (req_time > centerTime) {
            left = center + 1;
        } else {
            left = center;
            break;
        }
    }

    if (left == mNumSampleSizes) {
        if (flags == kFlagAfter) {
            return ERROR_OUT_OF_RANGE;
        }

        --left;
    }

    uint32_t closestIndex = left;

    switch (flags) {
        case kFlagBefore:
        {
            while (closestIndex > 0
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            > req_time) {
                --closestIndex;
            }
            break;
        }

        case kFlagAfter:
        {
            while (closestIndex + 1 < mNumSampleSizes
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            < req_time) {
                ++closestIndex;
            }
            break;
        }

        default:
        {
            CHECK(flags == kFlagClosest);

            if (closestIndex > 0) {
                // Check left neighbour and pick closest.
                uint32_t absdiff1 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex].mCompositionTime,
                            req_time);

                uint32_t absdiff2 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
                            req_time);

                if (absdiff1 > absdiff2) {
                    closestIndex = closestIndex - 1;
                }
            }

            break;
        }
    }

    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;

    return OK;
}

status_t SampleTable::findSyncSampleNear(
        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
    Mutex::Autolock autoLock(mLock);

    *sample_index = 0;

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = start_sample_index;
        return OK;
    }

    if (mNumSyncSamples == 0) {
        *sample_index = 0;
        return OK;
    }

    uint32_t left = 0;
    while (left < mNumSyncSamples) {
        uint32_t x = mSyncSamples[left];

        if (x >= start_sample_index) {
            break;
        }

        ++left;
    }

    if (left == mNumSyncSamples) {
        if (flags == kFlagAfter) {
            LOGE("tried to find a sync frame after the last one: %d", left);
            return ERROR_OUT_OF_RANGE;
        }
    }

    if (left > 0) {
        --left;
    }

    uint32_t x = mSyncSamples[left];

    if (left + 1 < mNumSyncSamples) {
        uint32_t y = mSyncSamples[left + 1];

        // our sample lies between sync samples x and y.

        status_t err = mSampleIterator->seekTo(start_sample_index);
        if (err != OK) {
            return err;
        }

        uint32_t sample_time = mSampleIterator->getSampleTime();

        err = mSampleIterator->seekTo(x);
        if (err != OK) {
            return err;
        }
        uint32_t x_time = mSampleIterator->getSampleTime();

        err = mSampleIterator->seekTo(y);
        if (err != OK) {
            return err;
        }

        uint32_t y_time = mSampleIterator->getSampleTime();

        if (abs_difference(x_time, sample_time)
                > abs_difference(y_time, sample_time)) {
            // Pick the sync sample closest (timewise) to the start-sample.
            x = y;
            ++left;
        }
    }

    switch (flags) {
        case kFlagBefore:
        {
            if (x > start_sample_index) {
                CHECK(left > 0);

                x = mSyncSamples[left - 1];

                CHECK(x <= start_sample_index);
            }
            break;
        }

        case kFlagAfter:
        {
            if (x < start_sample_index) {
                if (left + 1 >= mNumSyncSamples) {
                    return ERROR_OUT_OF_RANGE;
                }

                x = mSyncSamples[left + 1];

                CHECK(x >= start_sample_index);
            }

            break;
        }

        default:
            break;
    }

    *sample_index = x;

    return OK;
}

status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
    Mutex::Autolock autoLock(mLock);

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = 0;
        return OK;
    }

    uint32_t bestSampleIndex = 0;
    size_t maxSampleSize = 0;

    static const size_t kMaxNumSyncSamplesToScan = 20;

    // Consider the first kMaxNumSyncSamplesToScan sync samples and
    // pick the one with the largest (compressed) size as the thumbnail.

    size_t numSamplesToScan = mNumSyncSamples;
    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
        numSamplesToScan = kMaxNumSyncSamplesToScan;
    }

    for (size_t i = 0; i < numSamplesToScan; ++i) {
        uint32_t x = mSyncSamples[i];

        // Now x is a sample index.
        size_t sampleSize;
        status_t err = getSampleSize_l(x, &sampleSize);
        if (err != OK) {
            return err;
        }

        if (i == 0 || sampleSize > maxSampleSize) {
            bestSampleIndex = x;
            maxSampleSize = sampleSize;
        }
    }

    *sample_index = bestSampleIndex;

    return OK;
}

status_t SampleTable::getSampleSize_l(
        uint32_t sampleIndex, size_t *sampleSize) {
    return mSampleIterator->getSampleSizeDirect(
            sampleIndex, sampleSize);
}

status_t SampleTable::getMetaDataForSample(
        uint32_t sampleIndex,
        off64_t *offset,
        size_t *size,
        uint32_t *compositionTime,
        bool *isSyncSample,
        uint32_t *sampleDescIndex) {
    Mutex::Autolock autoLock(mLock);

    status_t err;
    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
        return err;
    }

    if (offset) {
        *offset = mSampleIterator->getSampleOffset();
    }

    if (size) {
        *size = mSampleIterator->getSampleSize();
    }

    if (compositionTime) {
        *compositionTime = mSampleIterator->getSampleTime();
    }

    if (sampleDescIndex) {
       *sampleDescIndex = mSampleIterator->getDescIndex();
    }

    if (isSyncSample) {
        *isSyncSample = false;
        if (mSyncSampleOffset < 0) {
            // Every sample is a sync sample.
            *isSyncSample = true;
        } else {
            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
                ? mLastSyncSampleIndex : 0;

            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
                ++i;
            }

            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
                *isSyncSample = true;
            }

            mLastSyncSampleIndex = i;
        }
    }

    return OK;
}

uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
}

uint32_t SampleTable::getNumSyncSamples()
{
    return mNumSyncSamples;
}

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

status_t SampleTable::getSampleDescAtIndex(uint32_t index, uint8_t **ptr, uint32_t *size)
{
    uint32_t i = 1;
    for (List<SampleDescAtom *>::iterator it = mSampleDescAtoms.begin();
         it != mSampleDescAtoms.end(); ++it, ++i) {

         if(i == index) {
             SampleDescAtom *sda = *it;
             *ptr = sda->ptr;
             *size = sda->size;
         }
    }
    return OK;
}

status_t SampleTable::getMaxAvccAtomSize(uint32_t *size)
{
    *size = 0;
    for (List<SampleDescAtom *>::iterator it = mSampleDescAtoms.begin();
                it != mSampleDescAtoms.end(); ++it) {
         SampleDescAtom *sda = *it;
         if( *size < sda->size)
             *size = sda->size;
    }
    return OK;
}

}  // namespace android
Пример #7
0
#include "sky.h"
#include "planet.h"
#include "d_caps.h"
#include "g_surfac.h"
#include "simResource.h"
#include "console.h"
#include "gOGLSfc.h"

//--------------------------------------------------------------------------- 

#define DEGRAD (M_PI/180.0)
#define RADDEG (180.0/M_PI)

//--------------------------------------------------------------------------- 

IMPLEMENT_PERSISTENT_TAGS(Planet, FOURCC('T','P','L','A'), PlanetPersTag);

static Point2F textCoord[4];

const float hexPoints[6][2] = { 
   { -1.0f, 0.0f }, { -0.5f, -0.83f }, { 0.5f, -0.83f }, 
   { 1.0f,  0.0f }, { 0.5f,   0.83f }, {-0.5f, 0.83f }
};

//--------------------------------------------------------------------------- 

const char *Planet::LensFlare::filename = "lensFlare.dml";

//--------------------------------------------------------------------------- 

float boxPoints[4][2] = { {-1.0f, -1.0f}, {1.0f, -1.0f}, {1.0f, 1.0f}, {-1.0f, 1.0f} };
Пример #8
0
void
mpeg_ts_reader_c::identify() {
  std::vector<std::string> verbose_info;
  auto mpls_in = dynamic_cast<mm_mpls_multi_file_io_c *>(get_underlying_input_as_multi_file_io());
  if (mpls_in)
    mpls_in->create_verbose_identification_info(verbose_info);

  id_result_container(verbose_info);

  size_t i;
  for (i = 0; i < tracks.size(); i++) {
    mpeg_ts_track_ptr &track = tracks[i];

    if (!track->probed_ok)
      continue;

    const char *fourcc = FOURCC('M', 'P', 'G', '1') == track->fourcc ? "MPEG-1"
                       : FOURCC('M', 'P', 'G', '2') == track->fourcc ? "MPEG-2"
                       : FOURCC('A', 'V', 'C', '1') == track->fourcc ? "AVC/h.264"
                       : FOURCC('W', 'V', 'C', '1') == track->fourcc ? "VC1"
                       : FOURCC('M', 'P', '1', ' ') == track->fourcc ? "MPEG-1 layer 1"
                       : FOURCC('M', 'P', '2', ' ') == track->fourcc ? "MPEG-1 layer 2"
                       : FOURCC('M', 'P', '3', ' ') == track->fourcc ? "MPEG-1 layer 3"
                       : FOURCC('A', 'A', 'C', ' ') == track->fourcc ? "AAC"
                       : FOURCC('A', 'C', '3', ' ') == track->fourcc ? "AC3"
                       : FOURCC('D', 'T', 'S', ' ') == track->fourcc ? "DTS"
                       : FOURCC('T', 'R', 'H', 'D') == track->fourcc ? "TrueHD"
                       : FOURCC('P', 'G', 'S', ' ') == track->fourcc ? "HDMV PGS"
                       // : FOURCC('P', 'C', 'M', ' ') == track->fourcc ? "PCM"
                       // : FOURCC('L', 'P', 'C', 'M') == track->fourcc ? "LPCM"
                       :                                               nullptr;

    if (!fourcc)
      continue;

    verbose_info.clear();
    if (!track->language.empty())
      verbose_info.push_back((boost::format("language:%1%") % escape(track->language)).str());

    verbose_info.push_back((boost::format("ts_pid:%1%") % track->pid).str());

    std::string type = ES_AUDIO_TYPE == track->type ? ID_RESULT_TRACK_AUDIO
                     : ES_VIDEO_TYPE == track->type ? ID_RESULT_TRACK_VIDEO
                     :                                ID_RESULT_TRACK_SUBTITLES;

    id_result_track(i, type, fourcc, verbose_info);
  }

  if (!m_chapter_timecodes.empty())
    id_result_chapters(m_chapter_timecodes.size());
}
Пример #9
0
int
mpeg_ts_reader_c::parse_pmt(unsigned char *pmt) {
  if (!pmt) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Invalid parameters!\n");
    return -1;
  }

  mpeg_ts_pmt_t *pmt_header = (mpeg_ts_pmt_t *)pmt;

  if (pmt_header->table_id != 0x02) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Invalid PMT table_id!\n");
    return -1;
  }

  if (pmt_header->get_section_syntax_indicator() != 1 || pmt_header->get_current_next_indicator() == 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Invalid PMT section_syntax_indicator/current_next_indicator!\n");
    return -1;
  }

  if (pmt_header->section_number != 0 || pmt_header->last_section_number != 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Unsupported multiple section PMT!\n");
    return -1;
  }

  unsigned short pmt_section_length = pmt_header->get_section_length();
  uint32_t elapsed_CRC              = crc_calc_mpeg2(pmt, 3 + pmt_section_length - 4/*CRC32*/);
  uint32_t read_CRC                 = get_uint32_be(pmt + 3 + pmt_section_length - 4);

  if (elapsed_CRC != read_CRC) {
    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: Wrong PMT CRC !!! Elapsed = 0x%|1$08x|, read 0x%|2$08x|\n") % elapsed_CRC % read_CRC);
    return -1;
  }

  if (pmt_section_length < 13 || pmt_section_length > 1021) {
    mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: Wrong PMT section_length (=%1%)\n") % pmt_section_length);
    return -1;
  }

  mpeg_ts_pmt_descriptor_t *pmt_descriptor = (mpeg_ts_pmt_descriptor_t *)(pmt + sizeof(mpeg_ts_pmt_t));
  unsigned short program_info_length       = pmt_header->get_program_info_length();

  while (pmt_descriptor < (mpeg_ts_pmt_descriptor_t *)(pmt + sizeof(mpeg_ts_pmt_t) + program_info_length))
    pmt_descriptor = (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_descriptor + sizeof(mpeg_ts_pmt_descriptor_t) + pmt_descriptor->length);

  mpeg_ts_pmt_pid_info_t *pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)pmt_descriptor;

  // Calculate pids_count
  size_t pids_found = 0;
  while (pmt_pid_info < (mpeg_ts_pmt_pid_info_t *)(pmt + 3 + pmt_section_length - 4/*CRC32*/)) {
    pids_found++;
    pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t) + pmt_pid_info->get_es_info_length());
  }

  mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: program number     (%1%)\n") % pmt_header->get_program_number());
  mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: pcr pid            (%1%)\n") % pmt_header->get_pcr_pid());

  if (pids_found == 0) {
    mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: There's no information about elementary PIDs\n");
    return 0;
  }

  pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)pmt_descriptor;

  // Extract pid_info
  while (pmt_pid_info < (mpeg_ts_pmt_pid_info_t *)(pmt + 3 + pmt_section_length - 4/*CRC32*/)) {
    mpeg_ts_track_ptr track(new mpeg_ts_track_c(*this));
    unsigned short es_info_length = pmt_pid_info->get_es_info_length();
    track->type                   = ES_UNKNOWN;

    track->set_pid(pmt_pid_info->get_pid());

    switch(pmt_pid_info->stream_type) {
      case ISO_11172_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('M', 'P', 'G', '1');
        break;
      case ISO_13818_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('M', 'P', 'G', '2');
        break;
      case ISO_14496_PART2_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('M', 'P', 'G', '4');
        break;
      case ISO_14496_PART10_VIDEO:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('A', 'V', 'C', '1');
        break;
      case STREAM_VIDEO_VC1:
        track->type   = ES_VIDEO_TYPE;
        track->fourcc = FOURCC('W', 'V', 'C', '1');
        break;
      case ISO_11172_AUDIO:
      case ISO_13818_AUDIO:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('M', 'P', '2', ' ');
        break;
      case ISO_13818_PART7_AUDIO:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('A', 'A', 'C', ' ');
        break;
      case ISO_14496_PART3_AUDIO:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('A', 'A', 'C', ' ');
        break;
      case STREAM_AUDIO_AC3:
      case STREAM_AUDIO_AC3_PLUS: // EAC3
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('A', 'C', '3', ' ');
        break;
      case STREAM_AUDIO_AC3_LOSSLESS:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('T', 'R', 'H', 'D');
        break;
      case STREAM_AUDIO_DTS:
      case STREAM_AUDIO_DTS_HD:
      case STREAM_AUDIO_DTS_HD_MA:
        track->type   = ES_AUDIO_TYPE;
        track->fourcc = FOURCC('D', 'T', 'S', ' ');
        break;
      case STREAM_SUBTITLES_HDMV_PGS:
        track->type      = ES_SUBT_TYPE;
        track->fourcc    = FOURCC('P', 'G', 'S', ' ');
        track->probed_ok = true;
        break;
      case ISO_13818_PES_PRIVATE:
        break;
      default:
        mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: Unknown stream type: %1%\n") % (int)pmt_pid_info->stream_type);
        track->type   = ES_UNKNOWN;
        break;
    }

    pmt_descriptor  = (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t));
    bool type_known = false;

    while (pmt_descriptor < (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t) + es_info_length)) {
      mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: PMT descriptor tag 0x%|1$02x| length %2%\n") % static_cast<unsigned int>(pmt_descriptor->tag) % static_cast<unsigned int>(pmt_descriptor->length));

      switch(pmt_descriptor->tag) {
        case 0x56: // Teletext descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_UNKNOWN;
            type_known    = true;
            mxdebug_if(m_debug_pat_pmt, "mpeg_ts:parse_pmt: Teletext found but not handled !!\n");
          }
          break;
        case 0x59: // Subtitles descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_SUBT_TYPE;
            track->fourcc = FOURCC('V', 'S', 'U', 'B');
            type_known    = true;
          }
          break;
        case 0x6A: // AC3 descriptor
        case 0x7A: // EAC3 descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_AUDIO_TYPE;
            track->fourcc = FOURCC('A', 'C', '3', ' ');
            type_known    = true;
          }
          break;
        case 0x7b: // DTS descriptor
          if (pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) { // PES containig private data
            track->type   = ES_AUDIO_TYPE;
            track->fourcc = FOURCC('D', 'T', 'S', ' ');
            type_known    = true;
          }
          break;
        case 0x0a: // ISO 639 language descriptor
          if (3 <= pmt_descriptor->length) {
            int language_idx = map_to_iso639_2_code(std::string(reinterpret_cast<char *>(pmt_descriptor + 1), 3).c_str());
            if (-1 != language_idx)
              track->language = iso639_languages[language_idx].iso639_2_code;
          }
          break;
      }

      pmt_descriptor = (mpeg_ts_pmt_descriptor_t *)((unsigned char *)pmt_descriptor + sizeof(mpeg_ts_pmt_descriptor_t) + pmt_descriptor->length);
    }

    // Default to AC3 if it's a PES private stream type that's missing
    // a known/more concrete descriptor tag.
    if ((pmt_pid_info->stream_type == ISO_13818_PES_PRIVATE) && !type_known) {
      track->type   = ES_AUDIO_TYPE;
      track->fourcc = FOURCC('A', 'C', '3', ' ');
    }

    pmt_pid_info = (mpeg_ts_pmt_pid_info_t *)((unsigned char *)pmt_pid_info + sizeof(mpeg_ts_pmt_pid_info_t) + es_info_length);
    if (track->type != ES_UNKNOWN) {
      PMT_found         = true;
      track->pid        = track->pid;
      track->processed  = false;
      track->data_ready = false;
      tracks.push_back(track);
      es_to_process++;
      uint32_t fourcc = get_uint32_be(&track->fourcc);
      mxdebug_if(m_debug_pat_pmt, boost::format("mpeg_ts:parse_pmt: PID %1% has type: 0x%|2$08x| (%3%)\n") % track->pid % fourcc % std::string(reinterpret_cast<char *>(&fourcc), 4));
    }
  }

  return 0;
}
Пример #10
0
void exec_sendEvent(Chirp *chirp, uint32_t event)
{
    if (chirp)
        CRP_SEND_XDATA(chirp, HTYPE(FOURCC('E','V','T','1')), INT32(event));
}
Пример #11
0
namespace FearGui
{

static int __cdecl nickNameAscend(const void *a,const void *b)
{
   FGIRCNicknames::NickRep **entry_A = (FGIRCNicknames::NickRep **)(a);
   FGIRCNicknames::NickRep **entry_B = (FGIRCNicknames::NickRep **)(b);
   return (stricmp((*entry_A)->nick, (*entry_B)->nick));
}

enum {
   
   NIName = 0,
   NICount
};

static FGArrayCtrl::ColumnInfo gNicknameInfo[NICount] =
{
   { IDSTR_NICKNAMES,          10, 300,   0,   0,    TRUE, 90, nickNameAscend, NULL },
};                                       
static FGArrayCtrl::ColumnInfo *gInfoPtrs[NICount];
                                         
IMPLEMENT_PERSISTENT_TAG(FGIRCNicknames, FOURCC('F','G','i','n'));

bool FGIRCNicknames::onAdd()
{
   if(!Parent::onAdd())
      return false;

   //reset the fonts
   hFont = SimResource::loadByTag(manager, IDFNT_9_STANDARD, true);
   hFontHL = SimResource::loadByTag(manager, IDFNT_9_STATIC, true);
   hFontNA = SimResource::loadByTag(manager, IDFNT_9_DISABLED, true);
   hFontMO = SimResource::loadByTag(manager, IDFNT_9_HILITE, true);
   
   //load the icons
   mAwayBMP = SimResource::get(manager)->load("irc_icon_away.bmp");
   AssertFatal(mAwayBMP, "Unable to load irc_icon_away.bmp");
   mAwayBMP->attribute |= BMA_TRANSPARENT;
   
   mIgnoreBMP = SimResource::get(manager)->load("irc_icon_Ignore.bmp");
   AssertFatal(mIgnoreBMP, "Unable to load irc_icon_Ignore.bmp");
   mIgnoreBMP->attribute |= BMA_TRANSPARENT;
   
   mLockBMP = SimResource::get(manager)->load("irc_icon_Lock.bmp");
   AssertFatal(mLockBMP, "Unable to load irc_icon_Lock.bmp");
   mLockBMP->attribute |= BMA_TRANSPARENT;
   
   mMesgBMP = SimResource::get(manager)->load("irc_icon_Mesg.bmp");
   AssertFatal(mMesgBMP, "Unable to load irc_icon_Mesg.bmp");
   mMesgBMP->attribute |= BMA_TRANSPARENT;
   
   mOperBMP = SimResource::get(manager)->load("irc_icon_Oper.bmp");
   AssertFatal(mOperBMP, "Unable to load irc_icon_Oper.bmp");
   mOperBMP->attribute |= BMA_TRANSPARENT;
   
   mSpecBMP = SimResource::get(manager)->load("irc_icon_Spec.bmp");
   AssertFatal(mSpecBMP, "Unable to load irc_icon_Spec.bmp");
   mSpecBMP->attribute |= BMA_TRANSPARENT;
   
   mSpkrBMP = SimResource::get(manager)->load("irc_icon_Spkr.bmp");
   AssertFatal(mSpkrBMP, "Unable to load irc_icon_Spkr.bmp");
   mSpkrBMP->attribute |= BMA_TRANSPARENT;
   
   //other misc vars
   refresh = TRUE;
	numColumns = NICount;
	columnInfo = gInfoPtrs;
   
   //set the ptrs table
   for (int i = 0; i < NICount; i++)
   {
      gInfoPtrs[i] = &gNicknameInfo[i];
   }
   
   //set the cell dimensions
   int width = 0;
   for (int k = 0; k < NICount; k++)
   {
      width += gInfoPtrs[k]->width;
   }
   cellSize.set(width, hFont->getHeight() + 6);
   
   prevSelected.set(-1, -1);
   
   //find the IRC client
   mIRCClient = ::IRCClient::find(manager);
   AssertFatal(mIRCClient, "IRCChatDelegate: unable to locate IRC client");
   
   return true;
}

void FGIRCNicknames::onWake()
{
   cellSize.set(max(cellSize.x, parent->extent.x), cellSize.y);
   setSize(Point2I( 1, 0));
   refresh = TRUE;
}

void FGIRCNicknames::onPreRender()
{
   // Keep the cell size up to date
   cellSize.set(max(cellSize.x, parent->extent.x), cellSize.y);
   
   // Build up the list of nicknames
   entries.clear();
   entryPtrs.clear();
   
   // Get the current channel
   ::IRCClient::Channel *channel = mIRCClient->findChannel(NULL);

   if (channel)
   {
      // Build up the nickname list
      for (int i = 0; i < channel->members.size(); i ++)
      {
         // Add the client to the list
         NickRep newNick;

         strcpy(newNick.nick, channel->members[i].person->nick);
         newNick.status = 
            (channel->members[i].person->flags | channel->members[i].flags); 
         entries.push_back(newNick);
      }

      setSize(Point2I(1, entries.size()));
   
      // Set up the pointers array
      for (int j = 0; j < entries.size(); j++)
      {
         entryPtrs.push_back(&entries[j]);
      }
   }
   else
   {
      setSize(Point2I(1, 0));
   }
}

void FGIRCNicknames::onRenderCell(GFXSurface *sfc, Point2I offset, Point2I cell, bool sel, bool mouseOver)
{
   IRCClient::Channel *channel = mIRCClient->findChannel(NULL);
   Point2I parentOffset = parent->localToGlobalCoord(Point2I(0, 0));
   
   bool ghosted = FALSE;
   if (root)
   {
      SimGui::Control *topDialog = root->getDialogNumber(1);
      if ((! active) || 
          (topDialog && (topDialog != getTopMostParent()) && (topDialog->findControlWithTag(IDCTG_DIALOG))))
      {
         ghosted = TRUE;
      }
   }
   
   //initialize the font
   GFXFont *font;
   if (ghosted || (! cellSelectable(cell))) font = hFontNA;
   else if (sel) font = hFontHL;
   else if (mouseOver) font = hFontMO;
   else font = hFont;
   
   //initialize the draw offset
   Point2I drawOffset = offset;
   drawOffset.x += 2;
   
   //first draw the icon
   int iconWidth = mOperBMP->getWidth() + 3;
   GFXBitmap *bmp;

   if (entryPtrs[cell.y]->status & IRCClient::PERSON_IGNORE)
   {
      bmp = mIgnoreBMP;
   }
   else
   {
      if (entryPtrs[cell.y]->status & IRCClient::PERSON_AWAY)
      {
         bmp = mAwayBMP;
      }
      else if (entryPtrs[cell.y]->status & IRCClient::PERSON_OPERATOR)
      {
         bmp = mOperBMP;
      }
      else if (entryPtrs[cell.y]->status & IRCClient::PERSON_SPEAKER ||
              (channel && !(channel->flags & IRCClient::CHANNEL_MODERATED)))
      {
         bmp = mSpkrBMP;
      }
      else
      {
         bmp = mSpecBMP;
      }
   }

   if (bmp && (! ghosted))
   {
      sfc->drawBitmap2d(bmp, &Point2I(drawOffset.x, drawOffset.y + 2 + (cellSize.y - bmp->getHeight()) / 2));
   }
   drawOffset.x += iconWidth;
      
   char *entryText = entryPtrs[cell.y]->nick; 
   if (entryText)
   {
      drawInfoText(sfc, font, entryText, Point2I(drawOffset.x, drawOffset.y - 2),
                                         Point2I(columnInfo[0]->width - 4 - iconWidth, cellSize.y), TRUE, FALSE);
   }
   drawOffset.x += columnInfo[0]->width;
}

void FGIRCNicknames::onRender(GFXSurface *sfc, Point2I offset, const Box2I &updateRect)
{
   Grandparent::onRender(sfc, offset, updateRect);
}

static char buffer[256];
char* FGIRCNicknames::getCellText(GFXSurface *, const Point2I &cell, const Point2I &, const Point2I &)
{
   switch (cell.x)
   {
      case NIName:
         //NAME
         return entryPtrs[cell.y]->nick;  
   }
   return NULL;
}

const char *FGIRCNicknames::getSelectedText()
{
   if (selectedCell.y != -1)
   {
      return (entryPtrs[selectedCell.y]->nick);
   }
   return (NULL);
}

void FGIRCNicknames::onRightMouseDown(const Event &event)
{
   onMouseDown(event);
}

void FGIRCNicknames::onMouseDown(const Event &event)
{
   Parent::onMouseDown(event);
   if (event.mouseDownCount > 1)
   {
      if (selectedCell.y == prevSelected.y)
      {
         onMessage(this, IDIRC_MENUOPT_PRIVATE_CHAT);
      }
   }
   prevSelected = selectedCell;
}

void FGIRCNicknames::onRightMouseUp(const Event &event)
{
   bool                   fIsMe;
   IRCClient             *objIRCClient;
   IRCClient::Person     *person;
   IRCClient::PersonInfo *info;
   IRCClient::Channel *channel = mIRCClient->findChannel(NULL);

   //find out in which cell the mouse was released
   Point2I pt = globalToLocalCoord(event.ptMouse);
   if (pt.x < 0 || pt.x >= extent.x) return;
   int cell = pt.y / cellSize.y;
   if (cell < 0 || cell != prevSelected.y) return;
   
   // Get our information
   person  = mIRCClient->getMe();
   
   if (person && channel)
   {
      info = channel->findPerson(person->nick);

      if (info && selectedCell.y != -1)
      {
         FGPopUpMenu *menu = new FGPopUpMenu;

         manager->addObject(menu);
         menu->onWake();
         menu->setPos(event.ptMouse);

         // KICK menu entry is DISABLED if the current user (me) is not
         // an OPERATOR, or if the selected entry is me
         menu->appendMenu(MENU_STRING |
            ((!(info->flags & IRCClient::PERSON_OPERATOR) || 
              !(stricmp(entryPtrs[selectedCell.y]->nick, person->nick))) ? MENU_DISABLED : 0),    
            IDIRC_MENUOPT_KICK,
            SimTagDictionary::getString(manager, IDSTR_KICK_USER));

         // BAN menu entry is DISABLED if the current user (me) is not
         // an OPERATOR, or if the selected entry is me
         menu->appendMenu(MENU_STRING |
            ((!(info->flags & IRCClient::PERSON_OPERATOR) || 
              !(stricmp(entryPtrs[selectedCell.y]->nick, person->nick))) ? MENU_DISABLED : 0),    
            IDIRC_MENUOPT_BAN, 
            SimTagDictionary::getString(manager, IDSTR_BAN_UNBAN_USER));

         // Space the entries
         menu->appendMenu(MENU_SEPARATOR);

         fIsMe = (stricmp(entryPtrs[selectedCell.y]->nick, person->nick) == 0);

         menu->appendMenu(MENU_STRING |
            (fIsMe ? MENU_DISABLED : 0), 
            IDIRC_MENUOPT_PRIVATE_CHAT, 
            SimTagDictionary::getString(manager, IDSTR_PRIVATE_CHAT));
         menu->appendMenu(MENU_STRING |
            (fIsMe ? MENU_DISABLED : 0), 
            IDIRC_MENUOPT_PING_USER, 
            SimTagDictionary::getString(manager, IDSTR_PING_USER));
         menu->appendMenu(MENU_STRING | 
            (fIsMe ? MENU_DISABLED : 0), 
            IDIRC_MENUOPT_WHOIS_USER, 
            SimTagDictionary::getString(manager, IDSTR_WHO_IS_THIS));
         menu->appendMenu(MENU_SEPARATOR);

         menu->appendMenu(MENU_STRING |
            (entryPtrs[selectedCell.y]->status & IRCClient::PERSON_AWAY ? MENU_CHECKED : 0) |
            (fIsMe ? 0 : MENU_DISABLED),
            IDIRC_MENUOPT_AWAY, 
            SimTagDictionary::getString(manager, IDSTR_AWAY_FROM_KEYBOARD));

         // IGNORE menu entry is CHECKED if we are currently ignoring the
         // selected entry
         menu->appendMenu(MENU_STRING | 
            (entryPtrs[selectedCell.y]->status & IRCClient::PERSON_IGNORE ? MENU_CHECKED : 0) |
            (fIsMe ? MENU_DISABLED : 0),
            IDIRC_MENUOPT_IGNORE,
            SimTagDictionary::getString(manager, IDSTR_IGNORE_USER));

         // Space the entries
         menu->appendMenu(MENU_SEPARATOR);

         // HOST menu entry is CHECKED if the selected entry is an OPERATOR, 
         // and is DISABLED if the current user (me) is not an OPERATOR
         menu->appendMenu(MENU_STRING | 
            ((entryPtrs[selectedCell.y]->status & IRCClient::PERSON_OPERATOR) ? MENU_CHECKED : 0) |
            ((info->flags        & IRCClient::PERSON_OPERATOR) ? 0 : MENU_DISABLED), 
            IDIRC_MENUOPT_OPER, 
            SimTagDictionary::getString(manager, IDSTR_OPERATOR));

         // SPEAKER menu entry is CHECKED if the selected entry is NOT an 
         // OPERATOR and is either explicitly set as a SPEAKER or this
         // channel is NOT MODERATED.  It is DISABLED if the current user
         // (me) is not an OPERATOR
         menu->appendMenu(MENU_STRING |
            ((!(entryPtrs[selectedCell.y]->status & IRCClient::PERSON_OPERATOR) && 
              ((entryPtrs[selectedCell.y]->status & IRCClient::PERSON_SPEAKER) || 
             (!(channel->flags     & IRCClient::CHANNEL_MODERATED)))) ? MENU_CHECKED : 0) |
            ((info->flags & IRCClient::PERSON_OPERATOR) ? 0 : MENU_DISABLED), 
            IDIRC_MENUOPT_SPKR, 
            SimTagDictionary::getString(manager, IDSTR_SPEAKER));

         // SPECTATOR menu entry is CHECKED if the selected entry is NOT an
         // OPERATOR and is NOT a SPEAKER and the channel is MODERATED.  It
         // is DISABLED if the current user (me) is not an OPERATOR
         menu->appendMenu(MENU_STRING |
            ((info->flags        & IRCClient::PERSON_OPERATOR) &&
             (channel->flags     & IRCClient::CHANNEL_MODERATED) ? 0 : MENU_DISABLED) |
          ((!(entryPtrs[selectedCell.y]->status & IRCClient::PERSON_OPERATOR) &&
           (!(entryPtrs[selectedCell.y]->status & IRCClient::PERSON_SPEAKER)) && 
             (channel->flags     & IRCClient::CHANNEL_MODERATED)) ? MENU_CHECKED : 0),
             IDIRC_MENUOPT_SPEC, 
             SimTagDictionary::getString(manager, IDSTR_SPECTATOR));

         // Done, display the menu
         root->pushDialogControl(menu);
      }
   }
}
   
};
Пример #12
0
//-----------------------------------------------------------------------------
// _ctmUncompressMesh_MG1() - Uncmpress the mesh from the input stream in the
// CTM context, and store the resulting mesh in the CTM context.
//-----------------------------------------------------------------------------
int _ctmUncompressMesh_MG1(_CTMcontext * self)
{
  CTMuint * indices;
  _CTMfloatmap * map;
  CTMuint i;

  // Allocate memory for the indices
  indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3);
  if(!indices)
  {
    self->mError = CTM_OUT_OF_MEMORY;
    return CTM_FALSE;
  }

  // Read triangle indices
  if(_ctmStreamReadUINT(self) != FOURCC("INDX"))
  {
    self->mError = CTM_BAD_FORMAT;
    free(indices);
    return CTM_FALSE;
  }
  if(!_ctmStreamReadPackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE))
    return CTM_FALSE;

  // Restore indices
  _ctmRestoreIndices(self, indices);
  for(i = 0; i < self->mTriangleCount * 3; ++ i)
    self->mIndices[i] = indices[i];

  // Free temporary resources
  free(indices);

  // Read vertices
  if(_ctmStreamReadUINT(self) != FOURCC("VERT"))
  {
    self->mError = CTM_BAD_FORMAT;
    return CTM_FALSE;
  }
  if(!_ctmStreamReadPackedFloats(self, self->mVertices, self->mVertexCount * 3, 1))
    return CTM_FALSE;

  // Read normals
  if(self->mNormals)
  {
    if(_ctmStreamReadUINT(self) != FOURCC("NORM"))
    {
      self->mError = CTM_BAD_FORMAT;
      return CTM_FALSE;
    }
    if(!_ctmStreamReadPackedFloats(self, self->mNormals, self->mVertexCount, 3))
      return CTM_FALSE;
  }

  // Read UV maps
  map = self->mUVMaps;
  while(map)
  {
    if(_ctmStreamReadUINT(self) != FOURCC("TEXC"))
    {
      self->mError = CTM_BAD_FORMAT;
      return 0;
    }
    _ctmStreamReadSTRING(self, &map->mName);
    _ctmStreamReadSTRING(self, &map->mFileName);
    if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 2))
      return CTM_FALSE;
    map = map->mNext;
  }

  // Read vertex attribute maps
  map = self->mAttribMaps;
  while(map)
  {
    if(_ctmStreamReadUINT(self) != FOURCC("ATTR"))
    {
      self->mError = CTM_BAD_FORMAT;
      return 0;
    }
    _ctmStreamReadSTRING(self, &map->mName);
    if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 4))
      return CTM_FALSE;
    map = map->mNext;
  }

  return CTM_TRUE;
}
Пример #13
0
int Interpreter::call(const QStringList &argv, bool interactive)
{
    QMutexLocker locker(&m_chirp->m_mutex);
    ChirpProc proc;
    ProcInfo info;
    int args[20];
    int i, j, k, n, base, res;
    bool ok;
    uint type;
    ArgList list;

    // not allowed
    if (argv.size()<1)
        return -1;

    // a procedure needs extension info (arg info, etc) in order for us to call...
    if ((proc=m_chirp->getProc(argv[0].toLocal8Bit()))>=0 &&
            m_chirp->getProcInfo(proc, &info)>=0)
    {
        memset(args, 0, sizeof(args)); // zero args
        getArgs(&info, &list);
        n = strlen((char *)info.argTypes);

        // if we have fewer args than required...
        if ((int)list.size()>argv.size()-1)
        {
            // if we're interactive, ask for values
            if (interactive && argv.size()>0)
            {
                QStringList cargv = argv;
                QString pstring, pstring2;
                for (i=cargv.size()-1; i<(int)list.size(); i++)
                {
                    if (info.argTypes[i]==CRP_TYPE_HINT)
                    {
                        if (n>i+4)
                        {
                            type = *(uint *)&info.argTypes[i+1];
                            if (type==FOURCC('R','E','G','1'))
                            {
                                emit videoInput(VideoWidget::REGION);
                                pstring2 = "(select region with mouse)";
                            }
                            if (type==FOURCC('P','N','T','1'))
                            {
                                emit videoInput(VideoWidget::POINT);
                                pstring2 = "(select point with mouse)";
                            }

                            emit enableConsole(false);
                        }

                    }
                    k = i;
                    pstring = printArgType(&info.argTypes[i], i) + " " + list[k].first +
                            (list[k].second=="" ? "?" : " (" + list[k].second + ")?") + " " + pstring2;

                    emit prompt(pstring);
                    m_mutexInput.lock();
                    m_waiting = true;
                    m_waitInput.wait(&m_mutexInput);
                    m_waiting = false;
                    m_mutexInput.unlock();

                    emit enableConsole(true);

                    if (m_key==Qt::Key_Escape)
                        return -1;
                    cargv << m_command.split(QRegExp("\\s+"));
                }
                // call ourselves again, now that we have all the args
                return call(cargv, true);
            }
            else
            {
                emit error("too few arguments.\n");
                return -1;
            }
        }


        augmentProcInfo(&info);
        // if we have all the args we need, parse, put in args array
        for (i=0, j=0; m_argTypes[i]; i++)
        {
            if (argv.size()>i+1)
            {
                if (m_argTypes[i]==CRP_INT8 || m_argTypes[i]==CRP_INT16 || m_argTypes[i]==CRP_INT32)
                {
                    args[j++] = m_argTypes[i];
                    if (argv[i+1].left(2)=="0x")
                        base = 16;
                    else
                        base = 10;
                    args[j++] = argv[i+1].toInt(&ok, base);
                    if (!ok)
                    {
                        emit error("argument didn't parse.\n");
                        return -1;
                    }
                }
#if 0
                else if (m_argTypes[i]==CRP_STRING)
                {
                    args[j++] = m_argTypes[i];
                    // string goes where?  can't cast pointer to int...
                }
#endif
                else
                {
                    // deal with non-integer types
                    return -1;
                }
            }
        }
#if 0
        // print helpful chirp argument string
        if (interactive && argv.size()>1)
        {
            QString callString = "Chirp arguments for " + argv[0] +
                    " (ChirpProc=" + QString::number(proc) + "): ";
            for (i=1; i<argv.size(); i++)
            {
                if (i>1)
                    callString += ", ";
                j = i;
                callString += printArgType(&m_argTypes[i-1], i) + "(" + argv[j] + ")";
            }
            emit textOut(callString + "\n");
        }
#endif

        // make chirp call
        res = m_chirp->callAsync(proc, args[0], args[1], args[2], args[3], args[4], args[5], args[6],
                           args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15],
                           args[16], args[17], args[18], args[19], END_OUT_ARGS);

        // check for cable disconnect
        if (res<0 && !m_notified) //res==LIBUSB_ERROR_PIPE)
        {
            m_notified = true;
            emit connected(PIXY, false);
            return res;
        }
        // get response if we're not programming, save text if we are
        if (m_programming)
            addProgram(argv);
        else
            m_chirp->serviceChirp();
    }
    else
    {
        emit error("procedure unsupported.\n");
        return -1;
    }

    return 0;
}
Пример #14
0
void ProcessThread::own_thread()
{
    enum class Format { UNKNOWN, RAW8, RAW16, MJPEG, YUYV, BGR8 };

    Format format = Format::UNKNOWN;
    int cv_format = CV_MAKETYPE( CV_8U, 1 );

    sepia::Stream::image_header_t* hdr = m_input->getHeader( m_id );
    switch( hdr->fourcc )
    {
    case 0x00000000:
        if( hdr->bpp == 8 )
        {
            format = Format::RAW8;
            cv_format = CV_MAKETYPE( CV_8U, 1 );
        }
        else if( hdr->bpp == 16 )
        {
            format = Format::RAW16;
            cv_format = CV_MAKETYPE( CV_16U, 1 );
        }
        else if( hdr->bpp == 24 )
        {
            format = Format::BGR8;
            cv_format = CV_MAKETYPE( CV_8U, 3 );
        }
        break;
    case FOURCC( 'M', 'J', 'P', 'G'):
        format = Format::MJPEG;
        cv_format = CV_MAKETYPE( CV_8U, 3 ); // format after conversion
        break;
    default:
        break;
    }

    cv::Mat input_frame( m_input->getHeader( m_id )->height, m_input->getHeader( m_id )->width, cv_format, m_input->getAddress( m_id ) );

    cv::Mat converted_frame( m_output->getHeader( m_id )->height, m_output->getHeader( m_id )->width, CV_8UC3 );

    if( m_rectifier == NULL )
    {
        converted_frame.data = reinterpret_cast< unsigned char* >( m_output->getAddress( m_id ) );
    }

    cv::Mat rectified_frame( m_output->getHeader( m_id )->height, m_output->getHeader( m_id )->width, CV_8UC3, m_output->getAddress( m_id ) );

    JpegDecoder decoder;

    while( !m_terminate )
    {
        if( format == Format::RAW8 || format == Format::RAW16 )
        {
            cv::demosaicing( input_frame, converted_frame, cv::COLOR_BayerBG2BGR_EA );
        }
        else if( format == Format::MJPEG )
        {
            // perform JPEG decode here
            decoder.readHeader( reinterpret_cast< unsigned char* >( input_frame.data ), m_input->getHeader( m_id )->size );
            decoder.readData( reinterpret_cast< unsigned char* >( converted_frame.data ), m_input->getHeader( m_id )->width * 3, true );
        }
        else {

        }

        if( m_rectifier != NULL )
        {
            if( m_id == 0 )
            {
                m_rectifier->remapLeft( &converted_frame, &rectified_frame );
            }
            else if( m_id == 1 )
            {
                m_rectifier->remapRight( &converted_frame, &rectified_frame );
            }
        }

        m_barrier->wait();
        if( m_id == 0 )
        {
            m_output->update();
            m_input->update();
        }
        m_barrier->wait();
        input_frame.data = reinterpret_cast< unsigned char* >( m_input->getAddress( m_id ) );

        if( m_rectifier != NULL )
        {
            rectified_frame.data = reinterpret_cast< unsigned char* >( m_output->getAddress( m_id ) );
        }
        else
        {
            converted_frame.data = reinterpret_cast< unsigned char* >( m_output->getAddress( m_id ) );
        }
    }
}
Пример #15
0
int32_t cc_getRLSCCChirp(Chirp *chirp)
{
	
	int16_t* c_components = new int16_t[MAX_BLOBS*4];
	
	
	uint32_t numRls, result;//, prebuf;
	uint32_t *memory = (uint32_t *)RLS_MEMORY;
	result = cc_getRLSFrame(memory, LUT_MEMORY, &numRls);
	
	CBlobAssembler blobber;
	
	int32_t row;
	uint32_t i, startCol, length;
	uint8_t model;

	for (i=0, row=-1; i<numRls; i++)
	{
			if (memory[i]==0)
			{
					row++;
					continue;
			}
			model = memory[i]&0x03;
			memory[i] >>= 3;
			startCol = memory[i]&0x1ff;
			memory[i] >>= 9;
			length = memory[i]&0x1ff;
			if(!handleRL(&blobber, model, row, startCol, length))
				break;
	}
	
	blobber.EndFrame();
	blobber.SortFinished();
	
	//
	// Take Finished blobs and return with chirp
	//
	CBlob *blob, *temp;
	blob = blobber.finishedBlobs;
	
	uint32_t cc_num = 0;
	temp = blob;
	while (temp)
	{
		int16_t top, right, bottom, left;
		temp->getBBox(left, top, right, bottom);
		
		// Don't want objects with area less than 9...
		if ((right-left)*(bottom-top) < 9)
			break;
		
		temp = temp->next;
		cc_num++;
	}
	
	// Remove the rest that we don't care about
	/*while(temp)
	{
		CBlob *next = temp->next;
		temp->~CBlob();
		temp = NULL;
		temp = next;
	}*/
	
	cc_num = (cc_num < 15) ? cc_num : MAX_BLOBS;

	// Populate return w/ result
	//void* mem = malloc(sizeof(int16_t)*cc_num*4);
	//if (mem == NULL)
	//	int i = 0;
	//free(mem);
	//int16_t* c_components = new int16_t[cc_num*4];
	//g_mem += sizeof(int16_t)*cc_num*4;
	memset((void *)c_components, 0, sizeof(uint16_t)*cc_num*4);

	for (int i = 0; i < cc_num; i++)
	{
		int16_t top, right, bottom, left;
		blob->getBBox(left, top, right, bottom);
		c_components[(i*4)+0] = top;
		c_components[(i*4)+1] = right;
		c_components[(i*4)+2] = bottom;
		c_components[(i*4)+3] = left;

		blob = blob->next;
	}
	
	//CRP_RETURN(chirp, USE_BUFFER(SRAM0_SIZE, SRAM0_LOC), HTYPE(0), UINT16(0), UINT16(0), UINTS8(0, 0), END);
	//prebuf = chirp->getPreBufLen();
	
	blobber.Reset();
	
	CRP_RETURN(chirp, HTYPE(FOURCC('V','I','S','U')), UINTS16(cc_num*4, c_components), END);
	
	delete[] c_components;
	//g_mem -= sizeof(int16_t)*cc_num*4;

	return result;
}
Пример #16
0
static int convert_support_fourcc(int fourcc)
{
	switch (fourcc)
	{
		case FOURCC('B','A','S','0'):
			return feature_bas0;

		case FOURCC('B','A','S','E'):
			return feature_base;

		case FOURCC('A','U','T','0'):
			return  feature_auto;

		case FOURCC('U','C','M','0'):
		case FOURCC('U','C','M','D'):
			return feature_ucmd;

		case FOURCC('Z','L','I','F'):
			return feature_zlif;

		case FOURCC('B','B','S','0'):
			return feature_bbs;

		case FOURCC('T','I','G','R'):
			return feature_tiger;

		case FOURCC('B','L','O','M'):
		case FOURCC('B','L','O','0'):
			return feature_bloom;

		case FOURCC('P','I','N','G'):
			return feature_ping;

		case FOURCC('L','I','N','K'):
			return feature_link;

		case FOURCC('A','D','C','S'):
			return feature_adcs;

		// ignore these extensions, they are not useful for the hub.
		case FOURCC('D','H','T','0'):
			return 0;

		default:
			LOG_DEBUG("Unknown extension: %x", fourcc);
			return 0;
	}
}
int main( int argc, char **argv )
{
	unicap_handle_t handle;
	unicap_device_t device;
	unicap_format_t format_spec;
	unicap_format_t format;
	unicap_data_buffer_t buffer;
	unicap_data_buffer_t *returned_buffer;
	int width, height;
	
	int i;

	SDL_Surface *screen;
	SDL_Overlay *overlay;

	int quit=0;
	int imgcnt = 0;

	printf( "select video device\n" );
	for( i = 0; SUCCESS( unicap_enumerate_devices( NULL, &device, i ) ); i++ )
	{
		printf( "%i: %s\n", i, device.identifier );
	}
	if( --i > 0 )
	{
		printf( "Select video capture device: " );
		scanf( "%d", &i );
	}

	if( !SUCCESS( unicap_enumerate_devices( NULL, &device, i ) ) )
	{
		fprintf( stderr, "Failed to get info for device '%s'\n", device.identifier );
		exit( 1 );
	}

	/*
	  Acquire a handle to this device
	 */
	if( !SUCCESS( unicap_open( &handle, &device ) ) )
	{
		fprintf( stderr, "Failed to open device: %s\n", device.identifier );
		exit( 1 );
	}

	printf( "Opened video capture device: %s\n", device.identifier );

	/*
	  Create a format specification to limit the list of formats returned by 
	  unicap_enumerate_formats to the ones with the color format 'UYVY'
	 */
	unicap_void_format( &format_spec );
	format_spec.fourcc = FOURCC('U','Y','V','Y');
	
	/*
	  Get the list of video formats of the colorformat UYVY
	 */
	for( i = 0; SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, i ) ); i++ )
	{
		printf( "%d: %s [%dx%d]\n", 
				i,
				format.identifier, 
				format.size.width, 
				format.size.height );
	}
	if( --i > 0 )
	{
		printf( "Select video format: " );
		scanf( "%d", &i );
	}
	if( !SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, i ) ) )
	{
		fprintf( stderr, "Failed to get video format\n" );
		exit( 1 );
	}
	
   /*
     If a video format has more than one size, ask for which size to use
   */
   if( format.size_count )
   {
      for( i = 0; i < format.size_count; i++ )
      {
	 printf( "%d: %dx%d\n", i, format.sizes[i].width, format.sizes[i].height );
      }
      do
      {
	 printf( "Select video format size: " );
	 scanf( "%d", &i );
      }while( ( i < 0 ) && ( i > format.size_count ) );
      format.size.width = format.sizes[i].width;
      format.size.height = format.sizes[i].height;
   }

	/*
	  Set this video format
	 */
	if( !SUCCESS( unicap_set_format( handle, &format ) ) )
	{
		fprintf( stderr, "Failed to set video format\n" );
		exit( 1 );
	}

	/*
	  Initialize the image buffer
	 */
	memset( &buffer, 0x0, sizeof( unicap_data_buffer_t ) );

	/**
	   Init SDL & SDL_Overlay
	 **/
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
	{
	   fprintf(stderr, "Failed to initialize SDL:  %s\n", SDL_GetError());
	   exit(1);
	}
	
	atexit(SDL_Quit);

	/*
	  Make sure the video window does not get too big. 
	 */
	width = MIN( format.size.width, 800 );
	height = MIN( format.size.height, 600 );

	screen = SDL_SetVideoMode( width, height, 32, SDL_HWSURFACE);
	if ( screen == NULL ) {
	   fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
	   exit(1);
	}
	
	overlay = SDL_CreateYUVOverlay( format.size.width, 
									format.size.height, SDL_UYVY_OVERLAY, screen );
	if( overlay == NULL )
	{
	   fprintf( stderr, "Unable to create overlay: %s\n", SDL_GetError() );
	   exit( 1 );
	}

	/*
	  Pass the pointer to the overlay to the unicap data buffer. 
	 */
	buffer.data = overlay->pixels[0];	
   buffer.buffer_size = format.size.width * format.size.height * format.bpp / 8;
	
	/*
	  Start the capture process on the device
	 */
	if( !SUCCESS( unicap_start_capture( handle ) ) )
	{
		fprintf( stderr, "Failed to start capture on device: %s\n", device.identifier );
		exit( 1 );
	}
	

	while( !quit )
	{
		SDL_Rect rect;
		SDL_Event event;

		rect.x = 0;
		rect.y = 0;
		rect.w = width;
		rect.h = height;
		/*
		  Queue the buffer
		  
		  The buffer now gets filled with image data by the capture device
		*/
		if( !SUCCESS( unicap_queue_buffer( handle, &buffer ) ) )
		{
			fprintf( stderr, "Failed to queue a buffer on device: %s\n", device.identifier );
			exit( 1 );
		}
		
		/*
		  Wait until the image buffer is ready
		*/
		if( !SUCCESS( unicap_wait_buffer( handle, &returned_buffer ) ) )
		{
			fprintf( stderr, "Failed to wait for buffer on device: %s\n", device.identifier );
		}

		/*
		  Display the video data
		 */
		SDL_UnlockYUVOverlay( overlay );
		SDL_DisplayYUVOverlay( overlay, &rect );

		while( SDL_PollEvent( &event ) )
		{
			switch( event.type )
			{
				case SDL_QUIT:
					quit = 1;
					break;
					
				case SDL_MOUSEBUTTONDOWN:
				{
					unsigned char *pixels;
					struct jpeg_compress_struct cinfo;
					struct jpeg_error_mgr jerr;
					FILE *outfile;
					JSAMPROW row_pointer[1];
					int row_stride;
					char filename[128];

					struct timeval t1, t2;
					unsigned long long usecs;
					
					sprintf( filename, "%04d.jpg", imgcnt++ );
					
					cinfo.err = jpeg_std_error(&jerr);
					/* Now we can initialize the JPEG compression object. */
					jpeg_create_compress(&cinfo);
					if ((outfile = fopen( filename, "wb" ) ) == NULL ) 
					{
						fprintf(stderr, "can't open %s\n", "file");
						exit(1);
					}
					jpeg_stdio_dest(&cinfo, outfile);
					
					cinfo.image_width = format.size.width; 	/* image width and height, in pixels */
					cinfo.image_height = format.size.height;
					cinfo.input_components = 3;		/* # of color components per pixel */
					cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
					
					jpeg_set_defaults(&cinfo);
					pixels = malloc( format.size.width * format.size.height * 3 );
					uyvy2rgb24( pixels, returned_buffer->data,
						    format.size.width * format.size.height * 3,
						    format.size.width * format.size.height * 2 );

					gettimeofday( &t1, NULL );
					jpeg_start_compress(&cinfo, TRUE);
					while( cinfo.next_scanline < cinfo.image_height )
					{
						row_pointer[0] = &pixels[cinfo.next_scanline * format.size.width * 3 ];
						(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
					}
					jpeg_finish_compress(&cinfo);
					gettimeofday( &t2, NULL );

					usecs = t2.tv_sec * 1000000LL + t2.tv_usec;
					usecs -= ( t1.tv_sec * 1000000LL + t1.tv_usec );
					
					printf( "Compression took: %lld usec\n", usecs );

					/* After finish_compress, we can close the output file. */
					fclose(outfile);
					jpeg_destroy_compress(&cinfo);
					
					free( pixels );
				}
				
				break;
				
				
				default: 
					break;
			}
		}
		SDL_LockYUVOverlay(overlay);
	}
	
	/*
	  Stop the device
	 */
	if( !SUCCESS( unicap_stop_capture( handle ) ) )
	{
		fprintf( stderr, "Failed to stop capture on device: %s\n", device.identifier );
	}

	/*
	  Close the device 

	  This invalidates the handle
	 */
	if( !SUCCESS( unicap_close( handle ) ) )
	{
		fprintf( stderr, "Failed to close the device: %s\n", device.identifier );
	}

	SDL_Quit();
	
	return 0;
}
// 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;
}
Пример #19
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;
}
Пример #20
0
#include "internal_includes/tokens.h"
#include "internal_includes/structs.h"
#include "internal_includes/decode.h"
#include "stdlib.h"
#include "stdio.h"
#include "internal_includes/reflect.h"
#include "internal_includes/debug.h"

#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 ))
static enum {FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C')}; //DirectX byte code
static enum {FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R')}; //Shader model 4 code
static enum {FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X')}; //Shader model 5 code
static enum {FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F')}; //Resource definition (e.g. constant buffers)
static enum {FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N')}; //Input signature
static enum {FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E')}; //Interface (for dynamic linking)
static enum {FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N')}; //Output signature

typedef struct DXBCContainerHeaderTAG
{
	unsigned fourcc;
	uint32_t unk[4];
	uint32_t one;
	uint32_t totalSize;
	uint32_t chunkCount;
} DXBCContainerHeader;

typedef struct DXBCChunkHeaderTAG
{
	unsigned fourcc;
	unsigned size;
} DXBCChunkHeader;
Пример #21
0
 FourCC GetWidgetTypeID() const {return FOURCC('LITE');}
Пример #22
0
#include <console.h>

Door::Door() : MoveableBase()
{
}

Door::~Door()
{
}

int Door::getDatGroup()
{
   return (DataBlockManager::DoorDataType);
}

IMPLEMENT_PERSISTENT_TAGS(Door, FOURCC('D', 'O', 'O', 'R'), DoorPersTag);

Persistent::Base::Error Door::read(StreamIO &sio, int iVer, int iUsr)
{
   return (Parent::read(sio, iVer, iUsr));
}

Persistent::Base::Error Door::write(StreamIO &sio, int iVer, int iUsr)
{
   return (Parent::write(sio, iVer, iUsr));
}

void Door::onFirst()
{
   if (const char *lpcszScript = scriptName("onClose"))
   {
Пример #23
0
int CDVDOverlayCodecTX3G::Decode(DemuxPacket *pPacket)
{
  if (m_pOverlay)
    SAFE_RELEASE(m_pOverlay);

  uint8_t *data = pPacket->pData;
  int size = pPacket->iSize;

  m_pOverlay = new CDVDOverlayText();
  CDVDOverlayCodec::GetAbsoluteTimes(m_pOverlay->iPTSStartTime, m_pOverlay->iPTSStopTime, pPacket, m_pOverlay->replace);

  // do not move this. READ_XXXX macros modify pos.
  uint8_t  *pos = data;
  uint8_t  *end = pos + size;

  // Parse the packet as a TX3G TextSample.
  // Look for a single StyleBox ('styl') and 
  // read all contained StyleRecords.
  // Ignore all other box types.
  // NOTE: Buffer overflows on read are not checked.
  // ALSO: READ_XXXX/SKIP_XXXX macros will modify pos.
  uint16_t textLength = READ_U16();
  uint8_t *text = READ_ARRAY(textLength);

  int numStyleRecords = 0;
  uint8_t *bgnStyle   = (uint8_t*)calloc(textLength, 1);
  uint8_t *endStyle   = (uint8_t*)calloc(textLength, 1);
  int bgnColorIndex = 0, endColorIndex = 0;
  uint32_t textColorRGBA = m_textColor;
  while (pos < end)
  {
    // Read TextSampleModifierBox
    uint32_t size = READ_U32();
    if (size == 0)
      size = pos - end;   // extends to end of packet
    if (size == 1)
    {
      CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: TextSampleModifierBox has unsupported large size" );
      break;
    }
    uint32_t type = READ_U32();
    if (type == FOURCC("uuid"))
    {
      CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: TextSampleModifierBox has unsupported extended type" );
      break;
    }

    if (type == FOURCC("styl"))
    {
      // Found a StyleBox. Parse the contained StyleRecords
      if ( numStyleRecords != 0 )
      {
        CLog::Log(LOGDEBUG, "CDVDOverlayCodecTX3G: found additional StyleBoxes on subtitle; skipping" );
        SKIP_ARRAY(size);
        continue;
      }

      numStyleRecords = READ_U16();
      for (int i = 0; i < numStyleRecords; i++)
      {
        StyleRecord curRecord;
        curRecord.bgnChar         = READ_U16();
        curRecord.endChar         = READ_U16();
        curRecord.fontID          = READ_U16();
        curRecord.faceStyleFlags  = READ_U8();
        curRecord.fontSize        = READ_U8();
        curRecord.textColorRGBA   = READ_U32();

        bgnStyle[curRecord.bgnChar] |= curRecord.faceStyleFlags;
        endStyle[curRecord.endChar] |= curRecord.faceStyleFlags;
        bgnColorIndex = curRecord.bgnChar;
        endColorIndex = curRecord.endChar;
        textColorRGBA = curRecord.textColorRGBA;
      }
    }
    else
    {
      // Found some other kind of TextSampleModifierBox. Skip it.
      SKIP_ARRAY(size);
    }
  }

  // Copy text to out and add HTML markup for the style records
  int charIndex = 0;
  CStdStringA strUTF8;
  for (pos = text, end = text + textLength; pos < end; pos++)
  {
    if ((*pos & 0xC0) == 0x80)
    {
      // Is a non-first byte of a multi-byte UTF-8 character
      strUTF8.append((const char*)pos, 1);
      continue;   // ...without incrementing 'charIndex'
    }

    uint8_t bgnStyles = bgnStyle[charIndex];
    uint8_t endStyles = endStyle[charIndex];

    // [B] or [/B] -> toggle bold on and off
    // [I] or [/I] -> toggle italics on and off
    // [COLOR ffab007f] or [/COLOR] -> toggle color on and off
    // [CAPS <option>]  or [/CAPS]  -> toggle capatilization on and off

    if (endStyles & BOLD)
      strUTF8.append("[/B]");
    if (endStyles & ITALIC)
      strUTF8.append("[/I]");
    // we do not support underline
    //if (endStyles & UNDERLINE)
    //  strUTF8.append("[/U]");
    if (endColorIndex == charIndex && textColorRGBA != m_textColor)
      strUTF8.append("[/COLOR]");

    // invert the order from above so we bracket the text correctly.
    if (bgnColorIndex == charIndex && textColorRGBA != m_textColor)
      strUTF8.AppendFormat("[COLOR %8x]", textColorRGBA);
    // we do not support underline
    //if (bgnStyles & UNDERLINE)
    //  strUTF8.append("[U]");
    if (bgnStyles & ITALIC)
      strUTF8.append("[I]");
    if (bgnStyles & BOLD)
      strUTF8.append("[B]");

    // stuff the UTF8 char
    strUTF8.append((const char*)pos, 1);

    // this is a char index, not a byte index.
    charIndex++;
  }
  
  free(bgnStyle);
  free(endStyle);
    
  if (strUTF8.IsEmpty())
    return OC_BUFFER;

  if (strUTF8[strUTF8.size()-1] == '\n')
    strUTF8.Delete(strUTF8.size()-1);

  // add a new text element to our container
  m_pOverlay->AddElement(new CDVDOverlayText::CElementText(strUTF8.c_str()));

  return OC_OVERLAY;
}
Пример #24
0
void
xtr_alac_c::create_file(xtr_base_c *master, KaxTrackEntry &track) {
  init_content_decoder(track);

  auto channels = kt_get_a_channels(track);
  auto priv     = FindChild<KaxCodecPrivate>(&track);
  if (!priv)
    mxerror(boost::format(Y("Track %1% with the CodecID '%2%' is missing the \"codec private\" element and cannot be extracted.\n")) % m_tid % m_codec_id);

  m_priv = decode_codec_private(priv);
  if (m_priv->get_size() != sizeof(alac::codec_config_t))
    mxerror(boost::format(Y("ALAC private data size mismatch\n")));

  xtr_base_c::create_file(master, track);

  m_out->write(std::string{"caff"});                             // mFileType
  m_out->write_uint16_be(1);                                     // mFileVersion
  m_out->write_uint16_be(0);                                     // mFileFlags

  m_out->write(std::string{"desc"});                             // Audio Description chunk
  m_out->write_uint64_be(32ULL);                                 // mChunkSize
  m_out->write_double(static_cast<int>(kt_get_a_sfreq(track)));  // mSampleRate
  m_out->write(std::string{"alac"});                             // mFormatID
  m_out->write_uint32_be(0);                                     // mFormatFlags
  m_out->write_uint32_be(0);                                     // mBytesPerPacket
  m_out->write_uint32_be(caf::defs::default_frames_per_packet);  // mFramesPerPacket
  m_out->write_uint32_be(channels);                              // mChannelsPerFrame
  m_out->write_uint32_be(0);                                     // mBitsPerChannel

  auto kuki_size = 12 + 36 + 8 + (2 < channels ? 24 : 0);        // add the size of ALACChannelLayoutInfo for more than 2 channels
  m_out->write(std::string{"kuki"});
  m_out->write_uint64_be(kuki_size);
  m_out->write_uint8('\0');
  m_out->write_uint8('\0');
  m_out->write_uint8('\0');
  m_out->write_uint8('\14');
  m_out->write(std::string{"frma"});
  m_out->write(std::string{"alac"});

  m_out->write_uint32_be(12 + sizeof(alac::codec_config_t));     // ALAC Specific Info size = 36 (12 + sizeof(ALAXSpecificConfig))
  m_out->write(std::string{"alac"});                             // ALAC Specific Info ID
  m_out->write_uint32_be(0L);                                    // Version Flags

  m_out->write(m_priv);                                          // audio specific config

  auto alo = caf::channel_layout_t();
  if (2 < channels) {
    switch (channels) {
      case 3:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_3_0_b;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center;
        break;
      case 4:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_4_0_b;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::center_surround;
        break;
      case 5:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_5_0_d;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_surround | caf::channel_layout_t::right_surround;
        break;
      case 6:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_5_1_d;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_surround | caf::channel_layout_t::right_surround | caf::channel_layout_t::lfe_screen;
        break;
      case 7:
        alo.channel_layout_tag = caf::channel_layout_t::aac_6_1;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_surround
                               | caf::channel_layout_t::right_surround | caf::channel_layout_t::center_surround | caf::channel_layout_t::lfe_screen;
        break;
      case 8:
        alo.channel_layout_tag = caf::channel_layout_t::mpeg_7_1_b;
        alo.channel_bitmap     = caf::channel_layout_t::left | caf::channel_layout_t::right | caf::channel_layout_t::center | caf::channel_layout_t::left_center
                               | caf::channel_layout_t::right_center | caf::channel_layout_t::left_surround | caf::channel_layout_t::right_surround | caf::channel_layout_t::lfe_screen;
        break;
    }

    auto acli = caf::channel_layout_info_t();

    put_uint32_be(&acli.channel_layout_info_size, 24);                         // = sizeof(ALACChannelLayoutInfo)
    put_uint32_be(&acli.channel_layout_info_id,   FOURCC('c', 'h', 'a', 'n')); // = 'chan'
    put_uint32_be(&acli.channel_layout_tag,       alo.channel_layout_tag);
    m_out->write(&acli, sizeof(acli));
  }

  // Terminator atom
  m_out->write_uint32_be(8);        // Channel Layout Info Size
  m_out->write_uint32_be(0);        // Channel Layout Info ID

  if (2 < channels) {
    m_out->write(std::string{"chan"}); // 'chan' chunk immediately following the kuki
    m_out->write_uint64_be(12ULL);     // = sizeof(ALACAudioChannelLayout)

    m_out->write_uint32_be(alo.channel_layout_tag);
    m_out->write_uint32_be(alo.channel_bitmap);
    m_out->write_uint32_be(alo.number_channel_descriptions);
  }

  m_free_chunk_offset = m_out->getFilePointer();    // remember the location of
  m_free_chunk_size   = 16384;

  auto free_chunk = memory_c::alloc(m_free_chunk_size);
  memset(free_chunk->get_buffer(), 0, sizeof(m_free_chunk_size));

  // the 'free' chunk
  m_out->write(std::string{"free"});
  m_out->write_uint64_be(m_free_chunk_size);
  m_out->write(free_chunk);

  m_data_chunk_offset = m_out->getFilePointer();
  m_out->write(std::string{"data"}); // Audio Data Chunk
  m_out->write_uint64_be(-1LL);      // mChunkSize (= -1 if unknown)
  m_out->write_uint32_be(1);         // mEditCount
}
Пример #25
0
namespace stagefright {

// static
const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
// static
const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
// static
const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
// static
const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');

const uint32_t kAuxTypeCenc = FOURCC('c', 'e', 'n', 'c');

static const uint32_t kMAX_ALLOCATION =
    (SIZE_MAX < INT32_MAX ? SIZE_MAX : INT32_MAX) - 128;

////////////////////////////////////////////////////////////////////////////////

struct SampleTable::CompositionDeltaLookup {
    CompositionDeltaLookup();

    void setEntries(
            const uint32_t *deltaEntries, size_t numDeltaEntries);

    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);

private:
    Mutex mLock;

    const uint32_t *mDeltaEntries;
    size_t mNumDeltaEntries;

    size_t mCurrentDeltaEntry;
    size_t mCurrentEntrySampleIndex;

    DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
};

SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
    : mDeltaEntries(NULL),
      mNumDeltaEntries(0),
      mCurrentDeltaEntry(0),
      mCurrentEntrySampleIndex(0) {
}

void SampleTable::CompositionDeltaLookup::setEntries(
        const uint32_t *deltaEntries, size_t numDeltaEntries) {
    Mutex::Autolock autolock(mLock);

    mDeltaEntries = deltaEntries;
    mNumDeltaEntries = numDeltaEntries;
    mCurrentDeltaEntry = 0;
    mCurrentEntrySampleIndex = 0;
}

uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
        uint32_t sampleIndex) {
    Mutex::Autolock autolock(mLock);

    if (mDeltaEntries == NULL) {
        return 0;
    }

    if (sampleIndex < mCurrentEntrySampleIndex) {
        mCurrentDeltaEntry = 0;
        mCurrentEntrySampleIndex = 0;
    }

    while (mCurrentDeltaEntry < mNumDeltaEntries) {
        uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
        if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
            return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
        }

        mCurrentEntrySampleIndex += sampleCount;
        ++mCurrentDeltaEntry;
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////////

SampleTable::SampleTable(const sp<DataSource> &source)
    : mDataSource(source),
      mChunkOffsetOffset(-1),
      mChunkOffsetType(0),
      mNumChunkOffsets(0),
      mSampleToChunkOffset(-1),
      mNumSampleToChunkOffsets(0),
      mSampleSizeOffset(-1),
      mSampleSizeFieldSize(0),
      mDefaultSampleSize(0),
      mNumSampleSizes(0),
      mTimeToSampleCount(0),
      mTimeToSample(NULL),
      mSampleTimeEntries(NULL),
      mCompositionTimeDeltaEntries(NULL),
      mNumCompositionTimeDeltaEntries(0),
      mCompositionDeltaLookup(new CompositionDeltaLookup),
      mSyncSampleOffset(-1),
      mNumSyncSamples(0),
      mSyncSamples(NULL),
      mLastSyncSampleIndex(0),
      mSampleToChunkEntries(NULL),
      mCencInfo(NULL),
      mCencInfoCount(0),
      mCencDefaultSize(0)
{
    mSampleIterator = new SampleIterator(this);
}

SampleTable::~SampleTable() {
    delete[] mSampleToChunkEntries;
    mSampleToChunkEntries = NULL;

    delete[] mSyncSamples;
    mSyncSamples = NULL;

    delete mCompositionDeltaLookup;
    mCompositionDeltaLookup = NULL;

    delete[] mCompositionTimeDeltaEntries;
    mCompositionTimeDeltaEntries = NULL;

    delete[] mSampleTimeEntries;
    mSampleTimeEntries = NULL;

    delete[] mTimeToSample;
    mTimeToSample = NULL;

    if (mCencInfo) {
        for (uint32_t i = 0; i < mCencInfoCount; i++) {
            if (mCencInfo[i].mSubsamples) {
                delete[] mCencInfo[i].mSubsamples;
            }
        }
        delete[] mCencInfo;
    }

    delete mSampleIterator;
    mSampleIterator = NULL;
}

bool SampleTable::isValid() const {
    return mChunkOffsetOffset >= 0
        && mSampleToChunkOffset >= 0
        && mSampleSizeOffset >= 0
        && mTimeToSample != NULL;
}

status_t SampleTable::setChunkOffsetParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    if (mChunkOffsetOffset >= 0) {
        return ERROR_MALFORMED;
    }

    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);

    mChunkOffsetOffset = data_offset;
    mChunkOffsetType = type;

    if (data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumChunkOffsets = U32_AT(&header[4]);

    if (mChunkOffsetType == kChunkOffsetType32) {
        if (data_size < 8 + (uint64_t)mNumChunkOffsets * 4) {
            return ERROR_MALFORMED;
        }
    } else {
        if (data_size < 8 + (uint64_t)mNumChunkOffsets * 8) {
            return ERROR_MALFORMED;
        }
    }

    return OK;
}

status_t SampleTable::setSampleToChunkParams(
        off64_t data_offset, size_t data_size) {
    if (mSampleToChunkOffset >= 0) {
        return ERROR_MALFORMED;
    }

    mSampleToChunkOffset = data_offset;

    if (data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumSampleToChunkOffsets = U32_AT(&header[4]);

    if (data_size < 8 + (uint64_t)mNumSampleToChunkOffsets * 12) {
        return ERROR_MALFORMED;
    }

    mSampleToChunkEntries =
        new SampleToChunkEntry[mNumSampleToChunkOffsets];

    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
        uint8_t buffer[12];
        if (mDataSource->readAt(
                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
                != (ssize_t)sizeof(buffer)) {
            return ERROR_IO;
        }

        if (!U32_AT(buffer)) {
          ALOGE("error reading sample to chunk table");
          return ERROR_MALFORMED;  // chunk index is 1 based in the spec.
        }

        // We want the chunk index to be 0-based.
        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
    }

    return OK;
}

status_t SampleTable::setSampleSizeParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    if (mSampleSizeOffset >= 0) {
        return ERROR_MALFORMED;
    }

    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);

    mSampleSizeOffset = data_offset;

    if (data_size < 12) {
        return ERROR_MALFORMED;
    }

    uint8_t header[12];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mDefaultSampleSize = U32_AT(&header[4]);
    mNumSampleSizes = U32_AT(&header[8]);

    if (type == kSampleSizeType32) {
        mSampleSizeFieldSize = 32;

        if (mDefaultSampleSize != 0) {
            return OK;
        }

        if (data_size < 12 + (uint64_t)mNumSampleSizes * 4) {
            return ERROR_MALFORMED;
        }
    } else {
        if ((mDefaultSampleSize & 0xffffff00) != 0) {
            // The high 24 bits are reserved and must be 0.
            return ERROR_MALFORMED;
        }

        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
        mDefaultSampleSize = 0;

        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
            && mSampleSizeFieldSize != 16) {
            return ERROR_MALFORMED;
        }

        if (data_size < 12 + ((uint64_t)mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
            return ERROR_MALFORMED;
        }
    }

    return OK;
}

status_t SampleTable::setTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    if (mTimeToSample != NULL || data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mTimeToSampleCount = U32_AT(&header[4]);
    if (mTimeToSampleCount > kMAX_ALLOCATION / 2 / sizeof(uint32_t)) {
        // Avoid later overflow.
        return ERROR_MALFORMED;
    }
    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];

    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
    if (mDataSource->readAt(
                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
        return ERROR_IO;
    }

    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
        mTimeToSample[i] = ntohl(mTimeToSample[i]);
    }

    return OK;
}

status_t SampleTable::setCompositionTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    ALOGI("There are reordered frames present.");

    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
        return ERROR_MALFORMED;
    }

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header))
            < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    uint32_t numEntries = U32_AT(&header[4]);

    if (data_size != ((uint64_t)numEntries + 1) * 8) {
        return ERROR_MALFORMED;
    }

    mNumCompositionTimeDeltaEntries = numEntries;
    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];

    if (mDataSource->readAt(
                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
            < (ssize_t)numEntries * 8) {
        delete[] mCompositionTimeDeltaEntries;
        mCompositionTimeDeltaEntries = NULL;

        return ERROR_IO;
    }

    for (size_t i = 0; i < 2 * numEntries; ++i) {
        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
    }

    mCompositionDeltaLookup->setEntries(
            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);

    return OK;
}

status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
    if (mSyncSampleOffset >= 0 || data_size < 8) {
        return ERROR_MALFORMED;
    }

    mSyncSampleOffset = data_offset;

    uint8_t header[8];
    if (mDataSource->readAt(
                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
        return ERROR_IO;
    }

    if (U32_AT(header) != 0) {
        // Expected version = 0, flags = 0.
        return ERROR_MALFORMED;
    }

    mNumSyncSamples = U32_AT(&header[4]);
    if (mNumSyncSamples > kMAX_ALLOCATION / sizeof(uint32_t)) {
        // Avoid later overflow.
        return ERROR_MALFORMED;
    }

    if (mNumSyncSamples < 2) {
        ALOGV("Table of sync samples is empty or has only a single entry!");
    }

    mSyncSamples = new uint32_t[mNumSyncSamples];
    size_t size = mNumSyncSamples * sizeof(uint32_t);
    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
            != (ssize_t)size) {
        return ERROR_IO;
    }

    for (size_t i = 0; i < mNumSyncSamples; ++i) {
        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
    }

    return OK;
}

static status_t
validateCencBoxHeader(
        sp<DataSource>& data_source, off64_t& data_offset,
        uint8_t* out_version, uint32_t* out_aux_type) {
    *out_aux_type = 0;

    if (data_source->readAt(data_offset++, out_version, 1) < 1) {
        ALOGE("error reading sample aux info header");
        return ERROR_IO;
    }

    uint32_t flags;
    if (!data_source->getUInt24(data_offset, &flags)) {
        ALOGE("error reading sample aux info flags");
        return ERROR_IO;
    }
    data_offset += 3;

    if (flags & 1) {
        uint32_t aux_type;
        uint32_t aux_param;
        if (!data_source->getUInt32(data_offset, &aux_type) ||
            !data_source->getUInt32(data_offset + 4, &aux_param)) {
            ALOGE("error reading aux info type");
            return ERROR_IO;
        }
        data_offset += 8;
        *out_aux_type = aux_type;
    }

    return OK;
}

status_t
SampleTable::setSampleAuxiliaryInformationSizeParams(
        off64_t data_offset, size_t data_size, uint32_t drm_scheme) {
    off64_t data_end = data_offset + data_size;

    uint8_t version;
    uint32_t aux_type;
    status_t err = validateCencBoxHeader(
                mDataSource, data_offset, &version, &aux_type);
    if (err != OK) {
        return err;
    }

    if (aux_type && aux_type != kAuxTypeCenc && drm_scheme != kAuxTypeCenc) {
        // Quietly skip aux types we don't care about.
        return OK;
    }

    if (!mCencSizes.isEmpty() || mCencDefaultSize) {
        ALOGE("duplicate cenc saiz box");
        return ERROR_MALFORMED;
    }

    if (version) {
        ALOGV("unsupported cenc saiz version");
        return ERROR_UNSUPPORTED;
    }

    if (mDataSource->readAt(
                data_offset++, &mCencDefaultSize, sizeof(mCencDefaultSize))
                < sizeof(mCencDefaultSize)) {
        return ERROR_IO;
    }

    if (!mDataSource->getUInt32(data_offset, &mCencInfoCount)) {
        return ERROR_IO;
    }
    data_offset += 4;

    if (!mCencDefaultSize) {
        mCencSizes.insertAt(0, 0, mCencInfoCount);
        if (mDataSource->readAt(
                    data_offset, mCencSizes.editArray(), mCencInfoCount)
                    < mCencInfoCount) {
            return ERROR_IO;
        }
        data_offset += mCencInfoCount;
    }

    CHECK(data_offset == data_end);

    return parseSampleCencInfo();
}

status_t
SampleTable::setSampleAuxiliaryInformationOffsetParams(
        off64_t data_offset, size_t data_size, uint32_t drm_scheme) {
    off64_t data_end = data_offset + data_size;

    uint8_t version;
    uint32_t aux_type;
    status_t err = validateCencBoxHeader(mDataSource, data_offset,
                                         &version, &aux_type);
    if (err != OK) {
        return err;
    }

    if (aux_type && aux_type != kAuxTypeCenc && drm_scheme != kAuxTypeCenc) {
        // Quietly skip aux types we don't care about.
        return OK;
    }

    if (!mCencOffsets.isEmpty()) {
        ALOGE("duplicate cenc saio box");
        return ERROR_MALFORMED;
    }

    uint32_t cencOffsetCount;
    if (!mDataSource->getUInt32(data_offset, &cencOffsetCount)) {
        ALOGE("error reading cenc aux info offset count");
        return ERROR_IO;
    }
    data_offset += 4;

    mCencOffsets.setCapacity(cencOffsetCount);
    if (!version) {
        for (uint32_t i = 0; i < cencOffsetCount; i++) {
            uint32_t tmp;
            if (!mDataSource->getUInt32(data_offset, &tmp)) {
                ALOGE("error reading cenc aux info offsets");
                return ERROR_IO;
            }
            mCencOffsets.push(tmp);
            data_offset += 4;
        }
    } else {
        for (uint32_t i = 0; i < cencOffsetCount; i++) {
            if (!mDataSource->getUInt64(data_offset, &mCencOffsets.editItemAt(i))) {
                ALOGE("error reading cenc aux info offsets");
                return ERROR_IO;
            }
            data_offset += 8;
        }
    }

    CHECK(data_offset == data_end);

    return parseSampleCencInfo();
}

status_t
SampleTable::parseSampleCencInfo() {
    if ((!mCencDefaultSize && !mCencInfoCount) || mCencOffsets.isEmpty()) {
        // We don't have all the cenc information we need yet. Quietly fail and
        // hope we get the data we need later in the track header.
        ALOGV("Got half of cenc saio/saiz pair. Deferring parse until we get the other half.");
        return OK;
    }

    if (!mCencSizes.isEmpty() && mCencOffsets.size() > 1 &&
        mCencSizes.size() != mCencOffsets.size()) {
        return ERROR_MALFORMED;
    }

    if (mCencInfoCount > kMAX_ALLOCATION / sizeof(SampleCencInfo)) {
        // Avoid future OOM.
        return ERROR_MALFORMED;
    }

    mCencInfo = new SampleCencInfo[mCencInfoCount];
    for (uint32_t i = 0; i < mCencInfoCount; i++) {
        mCencInfo[i].mSubsamples = NULL;
    }

    uint64_t nextOffset = mCencOffsets[0];
    for (uint32_t i = 0; i < mCencInfoCount; i++) {
        uint8_t size = mCencDefaultSize ? mCencDefaultSize : mCencSizes[i];
        uint64_t offset = mCencOffsets.size() == 1 ? nextOffset : mCencOffsets[i];
        nextOffset = offset + size;

        auto& info = mCencInfo[i];

        if (size < IV_BYTES) {
            ALOGE("cenc aux info too small");
            return ERROR_MALFORMED;
        }

        if (mDataSource->readAt(offset, info.mIV, IV_BYTES) < IV_BYTES) {
            ALOGE("couldn't read init vector");
            return ERROR_IO;
        }
        offset += IV_BYTES;

        if (size == IV_BYTES) {
            info.mSubsampleCount = 0;
            continue;
        }

        if (size < IV_BYTES + sizeof(info.mSubsampleCount)) {
            ALOGE("subsample count overflows sample aux info buffer");
            return ERROR_MALFORMED;
        }

        if (!mDataSource->getUInt16(offset, &info.mSubsampleCount)) {
            ALOGE("error reading sample cenc info subsample count");
            return ERROR_IO;
        }
        offset += sizeof(info.mSubsampleCount);

        if (size < IV_BYTES + sizeof(info.mSubsampleCount) + info.mSubsampleCount * 6) {
            ALOGE("subsample descriptions overflow sample aux info buffer");
            return ERROR_MALFORMED;
        }

        info.mSubsamples = new SampleCencInfo::SubsampleSizes[info.mSubsampleCount];
        for (uint16_t j = 0; j < info.mSubsampleCount; j++) {
            auto& subsample = info.mSubsamples[j];
            if (!mDataSource->getUInt16(offset, &subsample.mClearBytes) ||
                !mDataSource->getUInt32(offset + sizeof(subsample.mClearBytes),
                                        &subsample.mCipherBytes)) {
                ALOGE("error reading cenc subsample aux info");
                return ERROR_IO;
            }
            offset += 6;
        }
    }

    return OK;
}

uint32_t SampleTable::countChunkOffsets() const {
    return mNumChunkOffsets;
}

uint32_t SampleTable::countSamples() const {
    return mNumSampleSizes;
}

status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    Mutex::Autolock autoLock(mLock);

    *max_size = 0;

    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
        size_t sample_size;
        status_t err = getSampleSize_l(i, &sample_size);

        if (err != OK) {
            return err;
        }

        if (sample_size > *max_size) {
            *max_size = sample_size;
        }
    }

    return OK;
}

uint32_t abs_difference(uint32_t time1, uint32_t time2) {
    return time1 > time2 ? time1 - time2 : time2 - time1;
}

// static
int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;

    if (a->mCompositionTime < b->mCompositionTime) {
        return -1;
    } else if (a->mCompositionTime > b->mCompositionTime) {
        return 1;
    }

    return 0;
}

void SampleTable::buildSampleEntriesTable() {
    Mutex::Autolock autoLock(mLock);

    if (mSampleTimeEntries != NULL) {
        return;
    }

    mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];

    uint32_t sampleIndex = 0;
    uint32_t sampleTime = 0;

    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
        uint32_t n = mTimeToSample[2 * i];
        uint32_t delta = mTimeToSample[2 * i + 1];

        for (uint32_t j = 0; j < n; ++j) {
            if (sampleIndex < mNumSampleSizes) {
                // Technically this should always be the case if the file
                // is well-formed, but you know... there's (gasp) malformed
                // content out there.

                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;

                uint32_t compTimeDelta =
                    mCompositionDeltaLookup->getCompositionTimeOffset(
                            sampleIndex);

                mSampleTimeEntries[sampleIndex].mCompositionTime =
                    sampleTime + compTimeDelta;
            }

            ++sampleIndex;
            sampleTime += delta;
        }
    }

    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
          CompareIncreasingTime);
}

status_t SampleTable::findSampleAtTime(
        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
    buildSampleEntriesTable();

    uint32_t left = 0;
    uint32_t right = mNumSampleSizes;
    while (left < right) {
        uint32_t center = (left + right) / 2;
        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;

        if (req_time < centerTime) {
            right = center;
        } else if (req_time > centerTime) {
            left = center + 1;
        } else {
            left = center;
            break;
        }
    }

    if (left == mNumSampleSizes) {
        if (flags == kFlagAfter) {
            return ERROR_OUT_OF_RANGE;
        }

        --left;
    }

    uint32_t closestIndex = left;

    switch (flags) {
        case kFlagBefore:
        {
            while (closestIndex > 0
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            > req_time) {
                --closestIndex;
            }
            break;
        }

        case kFlagAfter:
        {
            while (closestIndex + 1 < mNumSampleSizes
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            < req_time) {
                ++closestIndex;
            }
            break;
        }

        default:
        {
            CHECK(flags == kFlagClosest);

            if (closestIndex > 0) {
                // Check left neighbour and pick closest.
                uint32_t absdiff1 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex].mCompositionTime,
                            req_time);

                uint32_t absdiff2 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
                            req_time);

                if (absdiff1 > absdiff2) {
                    closestIndex = closestIndex - 1;
                }
            }

            break;
        }
    }

    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;

    return OK;
}

status_t SampleTable::findSyncSampleNear(
        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
    Mutex::Autolock autoLock(mLock);

    *sample_index = 0;

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = start_sample_index;
        return OK;
    }

    if (mNumSyncSamples == 0) {
        *sample_index = 0;
        return OK;
    }

    uint32_t left = 0;
    uint32_t right = mNumSyncSamples;
    while (left < right) {
        uint32_t center = left + (right - left) / 2;
        uint32_t x = mSyncSamples[center];

        if (start_sample_index < x) {
            right = center;
        } else if (start_sample_index > x) {
            left = center + 1;
        } else {
            left = center;
            break;
        }
    }
    if (left == mNumSyncSamples) {
        if (flags == kFlagAfter) {
            ALOGE("tried to find a sync frame after the last one: %d", left);
            return ERROR_OUT_OF_RANGE;
        }
        left = left - 1;
    }

    // Now ssi[left] is the sync sample index just before (or at)
    // start_sample_index.
    // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples.

    uint32_t x = mSyncSamples[left];

    if (left + 1 < mNumSyncSamples) {
        uint32_t y = mSyncSamples[left + 1];

        // our sample lies between sync samples x and y.

        status_t err = mSampleIterator->seekTo(start_sample_index);
        if (err != OK) {
            return err;
        }

        uint32_t sample_time = mSampleIterator->getSampleTime();

        err = mSampleIterator->seekTo(x);
        if (err != OK) {
            return err;
        }
        uint32_t x_time = mSampleIterator->getSampleTime();

        err = mSampleIterator->seekTo(y);
        if (err != OK) {
            return err;
        }

        uint32_t y_time = mSampleIterator->getSampleTime();

        if (abs_difference(x_time, sample_time)
                > abs_difference(y_time, sample_time)) {
            // Pick the sync sample closest (timewise) to the start-sample.
            x = y;
            ++left;
        }
    }

    switch (flags) {
        case kFlagBefore:
        {
            if (x > start_sample_index) {
                CHECK(left > 0);

                x = mSyncSamples[left - 1];

                if (x > start_sample_index) {
                    // The table of sync sample indices was not sorted
                    // properly.
                    return ERROR_MALFORMED;
                }
            }
            break;
        }

        case kFlagAfter:
        {
            if (x < start_sample_index) {
                if (left + 1 >= mNumSyncSamples) {
                    return ERROR_OUT_OF_RANGE;
                }

                x = mSyncSamples[left + 1];

                if (x < start_sample_index) {
                    // The table of sync sample indices was not sorted
                    // properly.
                    return ERROR_MALFORMED;
                }
            }

            break;
        }

        default:
            break;
    }

    *sample_index = x;

    return OK;
}

status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
    Mutex::Autolock autoLock(mLock);

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = 0;
        return OK;
    }

    uint32_t bestSampleIndex = 0;
    size_t maxSampleSize = 0;

    static const size_t kMaxNumSyncSamplesToScan = 20;

    // Consider the first kMaxNumSyncSamplesToScan sync samples and
    // pick the one with the largest (compressed) size as the thumbnail.

    size_t numSamplesToScan = mNumSyncSamples;
    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
        numSamplesToScan = kMaxNumSyncSamplesToScan;
    }

    for (size_t i = 0; i < numSamplesToScan; ++i) {
        uint32_t x = mSyncSamples[i];

        // Now x is a sample index.
        size_t sampleSize;
        status_t err = getSampleSize_l(x, &sampleSize);
        if (err != OK) {
            return err;
        }

        if (i == 0 || sampleSize > maxSampleSize) {
            bestSampleIndex = x;
            maxSampleSize = sampleSize;
        }
    }

    *sample_index = bestSampleIndex;

    return OK;
}

status_t SampleTable::getSampleSize_l(
        uint32_t sampleIndex, size_t *sampleSize) {
    return mSampleIterator->getSampleSizeDirect(
            sampleIndex, sampleSize);
}

status_t SampleTable::getMetaDataForSample(
        uint32_t sampleIndex,
        off64_t *offset,
        size_t *size,
        uint32_t *compositionTime,
        uint32_t *duration,
        bool *isSyncSample,
        uint32_t *decodeTime) {
    Mutex::Autolock autoLock(mLock);

    status_t err;
    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
        return err;
    }

    if (offset) {
        *offset = mSampleIterator->getSampleOffset();
    }

    if (size) {
        *size = mSampleIterator->getSampleSize();
    }

    if (compositionTime) {
        *compositionTime = mSampleIterator->getSampleTime();
    }

    if (decodeTime) {
        *decodeTime = mSampleIterator->getSampleDecodeTime();
    }

    if (duration) {
        *duration = mSampleIterator->getSampleDuration();
    }

    if (isSyncSample) {
        *isSyncSample = false;
        if (mSyncSampleOffset < 0) {
            // Every sample is a sync sample.
            *isSyncSample = true;
        } else {
            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
                ? mLastSyncSampleIndex : 0;

            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
                ++i;
            }

            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
                *isSyncSample = true;
            }

            mLastSyncSampleIndex = i;
        }
    }

    return OK;
}

uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
}

status_t
SampleTable::getSampleCencInfo(
        uint32_t sample_index, Vector<uint16_t>& clear_sizes,
        Vector<uint32_t>& cipher_sizes, uint8_t iv[]) {
    CHECK(clear_sizes.isEmpty() && cipher_sizes.isEmpty());

    if (sample_index >= mCencInfoCount) {
        ALOGE("cenc info requested for out of range sample index");
        return ERROR_MALFORMED;
    }

    auto& info = mCencInfo[sample_index];
    clear_sizes.setCapacity(info.mSubsampleCount);
    cipher_sizes.setCapacity(info.mSubsampleCount);

    for (uint32_t i = 0; i < info.mSubsampleCount; i++) {
        clear_sizes.push(info.mSubsamples[i].mClearBytes);
        cipher_sizes.push(info.mSubsamples[i].mCipherBytes);
    }

    memcpy(iv, info.mIV, IV_BYTES);

    return OK;
}

}  // namespace stagefright
Пример #26
0
#include <swscale.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}


#define FOURCC(a,b,c,d) (unsigned int)((((unsigned int)a))+(((unsigned int)b)<<8)+(((unsigned int)c)<<16)+(((unsigned int)d)<<24))

typedef struct PixelFormatTag {
	PixelFormat pix_fmt;
    unsigned int fourcc;
} PixelFormatTag;

static const PixelFormatTag pixelFormatTags[] = {
	/* Planar formats */
    { PIX_FMT_YUV420P, 	FOURCC('I', '4', '2', '0') },
    { PIX_FMT_YUV420P, 	FOURCC('I', 'Y', 'U', 'V') },
    { PIX_FMT_YUV420P, 	FOURCC('Y', 'V', '1', '2') },
    { PIX_FMT_YUV410P, 	FOURCC('Y', 'U', 'V', '9') },
    { PIX_FMT_YUV411P, 	FOURCC('Y', '4', '1', 'B') },
    { PIX_FMT_YUV422P, 	FOURCC('Y', '4', '2', 'B') },
    { PIX_FMT_GRAY8,   	FOURCC('Y', '8', '0', '0') },
    { PIX_FMT_GRAY8,   	FOURCC(' ', ' ', 'Y', '8') },

    //v4l
    { PIX_FMT_GRAY8,   	FOURCC('G', 'R', 'E', 'Y') },
    //{ PIX_FMT_... 	FOURCC('H', '2', '4', '0') },	//HI420 BT848, seems to not exist in ffmpeg
    { PIX_FMT_RGB565,  	FOURCC('R', 'G', 'B', '6') },	//RGB565
    { PIX_FMT_RGB555 , 	FOURCC('R', 'G', 'B', '5') },	//RGB15
    { PIX_FMT_RGB32,   	FOURCC('R', 'G', 'B', '4') },	//RGB32
    { PIX_FMT_YUYV422, 	FOURCC('Y', 'U', 'Y', 'V') },
// 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;
}
Пример #28
0
}

static const ProcModule g_module[] =
{
	{
	"cc_getRLSFrame",
	(ProcPtr)cc_getRLSFrameChirp, 
	{END}, 
	"Get a frame of color run-length segments (RLS)"
	"@r 0 if success, negative if error"
	"@r CCQ1 formated data, including 8-palette"
	},
	{
	"cc_setModel",
	(ProcPtr)cc_setModel, 
	{CRP_UINT8, CRP_HTYPE(FOURCC('R','E','G','1')), END}, 
	"Set model by selecting box in image"
	"@p model numerical index of model, can be 0-5"
	"@p pixels user-selected pixels"
	"@r 0 if success, negative if error"
	},
	{
	"cc_setMemory",
	(ProcPtr)cc_setMemory,
	{CRP_UINT32, CRP_UINTS8, END},
	"" 
	},
	{
	"cc_getRLSCC",
	(ProcPtr)cc_getRLSCCChirp,
	{END},
Пример #29
0
extern int output_flv(struct mp4_context_t const* mp4_context,
                      unsigned int* trak_sample_start,
                      unsigned int* trak_sample_end,
                      struct bucket_t** buckets,
                      struct mp4_split_options_t* options)
{
  struct moov_t* moov = mp4_context->moov;
  unsigned int track = 0;

  for(track = 0; track != moov->tracks_; ++track)
  {
    struct trak_t* trak = moov->traks_[track];
    struct stsd_t const* stsd = trak->mdia_->minf_->stbl_->stsd_;
    struct sample_entry_t const* sample_entry = &stsd->sample_entries_[0];
    unsigned int start_sample = trak_sample_start[track];
    unsigned int end_sample = trak_sample_end[track];
    unsigned int s;

    if(trak->mdia_->hdlr_->handler_type_ != FOURCC('v', 'i', 'd', 'e'))
      continue;

    if(trak->mdia_->hdlr_->handler_type_ == FOURCC('v', 'i', 'd', 'e'))
    {
      unsigned char* buffer = (unsigned char*)malloc(1 + 1 + 3 + sample_entry->codec_private_data_length_);
      unsigned char* p = buffer;

      p = write_8(p, 0x17);
      p = write_8(p, RTMP_AVC_SEQUENCE_HEADER);
      p = write_24(p, 0);
      memcpy(p, sample_entry->codec_private_data_,
             sample_entry->codec_private_data_length_);
      p += sample_entry->codec_private_data_length_;
      bucket_insert_tail(buckets, bucket_init_memory(buffer, p - buffer));
      free(buffer);
    } else
    if(trak->mdia_->hdlr_->handler_type_ == FOURCC('s', 'o', 'u', 'n'))
    {
      unsigned char* buffer = (unsigned char*)malloc(1 + 1 + sample_entry->codec_private_data_length_);
      unsigned char* p = buffer;

      p = write_8(p, 0xaf);
      p = write_8(p, RTMP_AAC_SEQUENCE_HEADER);

      memcpy(p, sample_entry->codec_private_data_,
             sample_entry->codec_private_data_length_);
      p += sample_entry->codec_private_data_length_;
      bucket_insert_tail(buckets, bucket_init_memory(buffer, p - buffer));
      free(buffer);
    } else
    {
      continue;
    }

    for(s = start_sample; s != end_sample; ++s)
    {
      uint64_t sample_pos = trak->samples_[s].pos_;
      unsigned int sample_size = trak->samples_[s].size_;
      int cto = trak->samples_[s].cto_;

      // FLV uses a fixed 1000 timescale
      unsigned int composition_time = (unsigned int)
        (trak_time_to_moov_time(cto, 1000, trak->mdia_->mdhd_->timescale_));

      MP4_INFO(
        "frame=%u pts=%u offset=%llu size=%u\n",
        s, composition_time, sample_pos, sample_size);

      if(trak->mdia_->hdlr_->handler_type_ == FOURCC('v', 'i', 'd', 'e'))
      {
//        if(is_avc)
        {
          // VIDEODATA
          unsigned char header[5];
          unsigned int is_keyframe = trak->samples_[s].is_ss_;
          unsigned int codec_id = 7;          // AVC
          write_8(header, ((is_keyframe ? 1 : 2) << 4) + codec_id);

          write_8(header + 1, RTMP_AVC_NALU);
          write_24(header + 2, composition_time);
          bucket_insert_tail(buckets, bucket_init_memory(header, 5));
          bucket_insert_tail(buckets, bucket_init_file(sample_pos, sample_size));
        }
      }
      else
      {
        // AUDIODATA
        unsigned char header[2];
        write_8(header, 0xaf);
        write_8(header + 1, RTMP_AAC_RAW);
        // AACAUDIODATA
        bucket_insert_tail(buckets, bucket_init_memory(header, 2));
        bucket_insert_tail(buckets, bucket_init_file(sample_pos, sample_size));
      }
    }
  }

  return 1;
}
Пример #30
0
 FourCC GetWidgetTypeID() const { return FOURCC('SLGP'); }