Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a2d8709 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Squashed commit of the following:"

parents 0d41be3a 1faa92a1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ LOCAL_SRC_FILES += \
        MPEG4Extractor.cpp        \
        MPEG4Writer.cpp           \
        MediaExtractor.cpp        \
        SampleIterator.cpp        \
        SampleTable.cpp           \
        ShoutcastSource.cpp       \
        StagefrightMediaScanner.cpp \
+7 −10
Original line number Diff line number Diff line
@@ -232,8 +232,9 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData(
            uint32_t sampleIndex;
            uint32_t sampleTime;
            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
                    && track->sampleTable->getDecodingTime(
                        sampleIndex, &sampleTime) == OK) {
                    && track->sampleTable->getMetaDataForSample(
                        sampleIndex, NULL /* offset */, NULL /* size */,
                        &sampleTime) == OK) {
                track->meta->setInt64(
                        kKeyThumbnailTime,
                        ((int64_t)sampleTime * 1000000) / track->timescale);
@@ -929,20 +930,16 @@ status_t MPEG4Source::read(
    if (mBuffer == NULL) {
        newBuffer = true;

        status_t err = mSampleTable->getSampleOffsetAndSize(
                mCurrentSampleIndex, &offset, &size);

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

        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
        status_t err =
            mSampleTable->getMetaDataForSample(
                    mCurrentSampleIndex, &offset, &size, &dts);

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

        err = mGroup->acquire_buffer(&mBuffer);

        if (err != OK) {
            CHECK_EQ(mBuffer, NULL);
            return err;
+310 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "SampleIterator"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#include "include/SampleIterator.h"

#include <arpa/inet.h>

#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/Utils.h>

#include "include/SampleTable.h"

namespace android {

SampleIterator::SampleIterator(SampleTable *table)
    : mTable(table),
      mInitialized(false),
      mTimeToSampleIndex(0),
      mTTSSampleIndex(0),
      mTTSSampleTime(0),
      mTTSCount(0),
      mTTSDuration(0) {
    reset();
}

void SampleIterator::reset() {
    mSampleToChunkIndex = 0;
    mFirstChunk = 0;
    mFirstChunkSampleIndex = 0;
    mStopChunk = 0;
    mStopChunkSampleIndex = 0;
    mSamplesPerChunk = 0;
    mChunkDesc = 0;
}

status_t SampleIterator::seekTo(uint32_t sampleIndex) {
    LOGV("seekTo(%d)", sampleIndex);

    if (mTable->mSampleToChunkOffset < 0
            || mTable->mChunkOffsetOffset < 0
            || mTable->mSampleSizeOffset < 0
            || mTable->mTimeToSampleCount == 0) {

        return ERROR_MALFORMED;
    }

    if (mInitialized && mCurrentSampleIndex == sampleIndex) {
        return OK;
    }

    if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) {
        reset();
    }

    if (sampleIndex >= mStopChunkSampleIndex) {
        status_t err;
        if ((err = findChunkRange(sampleIndex)) != OK) {
            LOGE("findChunkRange failed");
            return err;
        }
    }

    CHECK(sampleIndex < mStopChunkSampleIndex);

    uint32_t chunk =
        (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk
        + mFirstChunk;

    if (!mInitialized || chunk != mCurrentChunkIndex) {
        mCurrentChunkIndex = chunk;

        status_t err;
        if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
            LOGE("getChunkOffset return error");
            return err;
        }

        mCurrentChunkSampleSizes.clear();

        uint32_t firstChunkSampleIndex =
            mFirstChunkSampleIndex
                + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk);

        for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
            size_t sampleSize;
            if ((err = getSampleSizeDirect(
                            firstChunkSampleIndex + i, &sampleSize)) != OK) {
                LOGE("getSampleSizeDirect return error");
                return err;
            }

            mCurrentChunkSampleSizes.push(sampleSize);
        }
    }

    uint32_t chunkRelativeSampleIndex =
        (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk;

    mCurrentSampleOffset = mCurrentChunkOffset;
    for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) {
        mCurrentSampleOffset += mCurrentChunkSampleSizes[i];
    }

    mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex];
    if (sampleIndex < mTTSSampleIndex) {
        mTimeToSampleIndex = 0;
        mTTSSampleIndex = 0;
        mTTSSampleTime = 0;
        mTTSCount = 0;
        mTTSDuration = 0;
    }

    status_t err;
    if ((err = findSampleTime(sampleIndex, &mCurrentSampleTime)) != OK) {
        LOGE("findSampleTime return error");
        return err;
    }

    mCurrentSampleIndex = sampleIndex;

    mInitialized = true;

    return OK;
}

status_t SampleIterator::findChunkRange(uint32_t sampleIndex) {
    CHECK(sampleIndex >= mFirstChunkSampleIndex);

    while (sampleIndex >= mStopChunkSampleIndex) {
        if (mSampleToChunkIndex == mTable->mNumSampleToChunkOffsets) {
            return ERROR_OUT_OF_RANGE;
        }

        mFirstChunkSampleIndex = mStopChunkSampleIndex;

        const SampleTable::SampleToChunkEntry *entry =
            &mTable->mSampleToChunkEntries[mSampleToChunkIndex];

        mFirstChunk = entry->startChunk;
        mSamplesPerChunk = entry->samplesPerChunk;
        mChunkDesc = entry->chunkDesc;

        if (mSampleToChunkIndex + 1 < mTable->mNumSampleToChunkOffsets) {
            mStopChunk = entry[1].startChunk;

            mStopChunkSampleIndex =
                mFirstChunkSampleIndex
                    + (mStopChunk - mFirstChunk) * mSamplesPerChunk;
        } else {
            mStopChunk = 0xffffffff;
            mStopChunkSampleIndex = 0xffffffff;
        }

        ++mSampleToChunkIndex;
    }

    return OK;
}

status_t SampleIterator::getChunkOffset(uint32_t chunk, off_t *offset) {
    *offset = 0;

    if (chunk >= mTable->mNumChunkOffsets) {
        return ERROR_OUT_OF_RANGE;
    }

    if (mTable->mChunkOffsetType == SampleTable::kChunkOffsetType32) {
        uint32_t offset32;

        if (mTable->mDataSource->readAt(
                    mTable->mChunkOffsetOffset + 8 + 4 * chunk,
                    &offset32,
                    sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
            return ERROR_IO;
        }

        *offset = ntohl(offset32);
    } else {
        CHECK_EQ(mTable->mChunkOffsetType, SampleTable::kChunkOffsetType64);

        uint64_t offset64;
        if (mTable->mDataSource->readAt(
                    mTable->mChunkOffsetOffset + 8 + 8 * chunk,
                    &offset64,
                    sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
            return ERROR_IO;
        }

        *offset = ntoh64(offset64);
    }

    return OK;
}

status_t SampleIterator::getSampleSizeDirect(
        uint32_t sampleIndex, size_t *size) {
    *size = 0;

    if (sampleIndex >= mTable->mNumSampleSizes) {
        return ERROR_OUT_OF_RANGE;
    }

    if (mTable->mDefaultSampleSize > 0) {
        *size = mTable->mDefaultSampleSize;
        return OK;
    }

    switch (mTable->mSampleSizeFieldSize) {
        case 32:
        {
            if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + 4 * sampleIndex,
                        size, sizeof(*size)) < (ssize_t)sizeof(*size)) {
                return ERROR_IO;
            }

            *size = ntohl(*size);
            break;
        }

        case 16:
        {
            uint16_t x;
            if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + 2 * sampleIndex,
                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
                return ERROR_IO;
            }

            *size = ntohs(x);
            break;
        }

        case 8:
        {
            uint8_t x;
            if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + sampleIndex,
                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
                return ERROR_IO;
            }

            *size = x;
            break;
        }

        default:
        {
            CHECK_EQ(mTable->mSampleSizeFieldSize, 4);

            uint8_t x;
            if (mTable->mDataSource->readAt(
                        mTable->mSampleSizeOffset + 12 + sampleIndex / 2,
                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
                return ERROR_IO;
            }

            *size = (sampleIndex & 1) ? x & 0x0f : x >> 4;
            break;
        }
    }

    return OK;
}

status_t SampleIterator::findSampleTime(
        uint32_t sampleIndex, uint32_t *time) {
    if (sampleIndex >= mTable->mNumSampleSizes) {
        return ERROR_OUT_OF_RANGE;
    }

    while (sampleIndex >= mTTSSampleIndex + mTTSCount) {
        if (mTimeToSampleIndex == mTable->mTimeToSampleCount) {
            return ERROR_OUT_OF_RANGE;
        }

        mTTSSampleIndex += mTTSCount;
        mTTSSampleTime += mTTSCount * mTTSDuration;

        mTTSCount = mTable->mTimeToSample[2 * mTimeToSampleIndex];
        mTTSDuration = mTable->mTimeToSample[2 * mTimeToSampleIndex + 1];

        ++mTimeToSampleIndex;
    }

    *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);

    return OK;
}

}  // namespace android
+79 −244
Original line number Diff line number Diff line
@@ -15,9 +15,11 @@
 */

#define LOG_TAG "SampleTable"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#include "include/SampleTable.h"
#include "include/SampleIterator.h"

#include <arpa/inet.h>

@@ -27,10 +29,16 @@

namespace android {

static const uint32_t kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
static const uint32_t kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
static const uint32_t kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
static const uint32_t kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
// 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');

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

SampleTable::SampleTable(const sp<DataSource> &source)
    : mDataSource(source),
@@ -46,12 +54,20 @@ SampleTable::SampleTable(const sp<DataSource> &source)
      mTimeToSampleCount(0),
      mTimeToSample(NULL),
      mSyncSampleOffset(-1),
      mNumSyncSamples(0) {
      mNumSyncSamples(0),
      mSampleToChunkEntries(NULL) {
    mSampleIterator = new SampleIterator(this);
}

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

    delete[] mTimeToSample;
    mTimeToSample = NULL;

    delete mSampleIterator;
    mSampleIterator = NULL;
}

status_t SampleTable::setChunkOffsetParams(
@@ -124,6 +140,25 @@ status_t SampleTable::setSampleToChunkParams(
        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;
}

@@ -250,217 +285,10 @@ uint32_t SampleTable::countChunkOffsets() const {
    return mNumChunkOffsets;
}

status_t SampleTable::getChunkOffset(uint32_t chunk_index, off_t *offset) {
    *offset = 0;

    if (mChunkOffsetOffset < 0) {
        return ERROR_MALFORMED;
    }

    if (chunk_index >= mNumChunkOffsets) {
        return ERROR_OUT_OF_RANGE;
    }

    if (mChunkOffsetType == kChunkOffsetType32) {
        uint32_t offset32;

        if (mDataSource->readAt(
                    mChunkOffsetOffset + 8 + 4 * chunk_index,
                    &offset32,
                    sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
            return ERROR_IO;
        }

        *offset = ntohl(offset32);
    } else {
        CHECK_EQ(mChunkOffsetType, kChunkOffsetType64);

        uint64_t offset64;
        if (mDataSource->readAt(
                    mChunkOffsetOffset + 8 + 8 * chunk_index,
                    &offset64,
                    sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
            return ERROR_IO;
        }

        *offset = ntoh64(offset64);
    }

    return OK;
}

status_t SampleTable::getChunkForSample(
        uint32_t sample_index,
        uint32_t *chunk_index,
        uint32_t *chunk_relative_sample_index,
        uint32_t *desc_index) {
    *chunk_index = 0;
    *chunk_relative_sample_index = 0;
    *desc_index = 0;

    if (mSampleToChunkOffset < 0) {
        return ERROR_MALFORMED;
    }

    if (sample_index >= countSamples()) {
        return ERROR_END_OF_STREAM;
    }

    uint32_t first_chunk = 0;
    uint32_t samples_per_chunk = 0;
    uint32_t chunk_desc_index = 0;

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

        uint32_t stop_chunk = U32_AT(buffer);
        if (sample_index < (stop_chunk - first_chunk) * samples_per_chunk) {
            break;
        }

        sample_index -= (stop_chunk - first_chunk) * samples_per_chunk;
        first_chunk = stop_chunk;
        samples_per_chunk = U32_AT(&buffer[4]);
        chunk_desc_index = U32_AT(&buffer[8]);

        ++index;
    }

    *chunk_index = sample_index / samples_per_chunk + first_chunk - 1;
    *chunk_relative_sample_index = sample_index % samples_per_chunk;
    *desc_index = chunk_desc_index;

    return OK;
}

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

status_t SampleTable::getSampleSize(
        uint32_t sample_index, size_t *sample_size) {
    *sample_size = 0;

    if (mSampleSizeOffset < 0) {
        return ERROR_MALFORMED;
    }

    if (sample_index >= mNumSampleSizes) {
        return ERROR_OUT_OF_RANGE;
    }

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

    switch (mSampleSizeFieldSize) {
        case 32:
        {
            if (mDataSource->readAt(
                        mSampleSizeOffset + 12 + 4 * sample_index,
                        sample_size, sizeof(*sample_size)) < (ssize_t)sizeof(*sample_size)) {
                return ERROR_IO;
            }

            *sample_size = ntohl(*sample_size);
            break;
        }

        case 16:
        {
            uint16_t x;
            if (mDataSource->readAt(
                        mSampleSizeOffset + 12 + 2 * sample_index,
                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
                return ERROR_IO;
            }

            *sample_size = ntohs(x);
            break;
        }

        case 8:
        {
            uint8_t x;
            if (mDataSource->readAt(
                        mSampleSizeOffset + 12 + sample_index,
                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
                return ERROR_IO;
            }

            *sample_size = x;
            break;
        }

        default:
        {
            CHECK_EQ(mSampleSizeFieldSize, 4);

            uint8_t x;
            if (mDataSource->readAt(
                        mSampleSizeOffset + 12 + sample_index / 2,
                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
                return ERROR_IO;
            }

            *sample_size = (sample_index & 1) ? x & 0x0f : x >> 4;
            break;
        }
    }

    return OK;
}

status_t SampleTable::getSampleOffsetAndSize(
        uint32_t sample_index, off_t *offset, size_t *size) {
    Mutex::Autolock autoLock(mLock);

    *offset = 0;
    *size = 0;

    uint32_t chunk_index;
    uint32_t chunk_relative_sample_index;
    uint32_t desc_index;
    status_t err = getChunkForSample(
            sample_index, &chunk_index, &chunk_relative_sample_index,
            &desc_index);

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

    err = getChunkOffset(chunk_index, offset);

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

    for (uint32_t j = 0; j < chunk_relative_sample_index; ++j) {
        size_t sample_size;
        err = getSampleSize(sample_index - j - 1, &sample_size);

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

        *offset += sample_size;
    }

    err = getSampleSize(sample_index, size);

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

    return OK;
}

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

@@ -468,7 +296,7 @@ status_t SampleTable::getMaxSampleSize(size_t *max_size) {

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

        if (err != OK) {
            return err;
@@ -482,34 +310,6 @@ status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    return OK;
}

status_t SampleTable::getDecodingTime(uint32_t sample_index, uint32_t *time) {
    // XXX FIXME idiotic (for the common use-case) O(n) algorithm below...

    Mutex::Autolock autoLock(mLock);

    if (sample_index >= mNumSampleSizes) {
        return ERROR_OUT_OF_RANGE;
    }

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

        if (sample_index < cur_sample + n) {
            *time += delta * (sample_index - cur_sample);

            return OK;
        }

        *time += delta * n;
        cur_sample += n;
    }

    return ERROR_OUT_OF_RANGE;
}

uint32_t abs_difference(uint32_t time1, uint32_t time2) {
    return time1 > time2 ? time1 - time2 : time2 - time1;
}
@@ -539,7 +339,7 @@ status_t SampleTable::findClosestSample(
            }

            if (flags & kSyncSample_Flag) {
                return findClosestSyncSample(*sample_index, sample_index);
                return findClosestSyncSample_l(*sample_index, sample_index);
            }

            return OK;
@@ -552,7 +352,7 @@ status_t SampleTable::findClosestSample(
    return ERROR_OUT_OF_RANGE;
}

status_t SampleTable::findClosestSyncSample(
status_t SampleTable::findClosestSyncSample_l(
        uint32_t start_sample_index, uint32_t *sample_index) {
    *sample_index = 0;

@@ -590,6 +390,8 @@ status_t SampleTable::findClosestSyncSample(
}

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

    if (mSyncSampleOffset < 0) {
        // All samples are sync-samples.
        *sample_index = 0;
@@ -620,7 +422,7 @@ status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {

        // Now x is a sample index.
        size_t sampleSize;
        status_t err = getSampleSize(x, &sampleSize);
        status_t err = getSampleSize_l(x, &sampleSize);
        if (err != OK) {
            return err;
        }
@@ -636,5 +438,38 @@ status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
    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,
        off_t *offset,
        size_t *size,
        uint32_t *decodingTime) {
    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 (decodingTime) {
        *decodingTime = mSampleIterator->getSampleTime();
    }

    return OK;
}

}  // namespace android
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <utils/Vector.h>

namespace android {

struct SampleTable;

struct SampleIterator {
    SampleIterator(SampleTable *table);

    status_t seekTo(uint32_t sampleIndex);

    uint32_t getChunkIndex() const { return mCurrentChunkIndex; }
    uint32_t getDescIndex() const { return mChunkDesc; }
    off_t getSampleOffset() const { return mCurrentSampleOffset; }
    size_t getSampleSize() const { return mCurrentSampleSize; }
    uint32_t getSampleTime() const { return mCurrentSampleTime; }

    status_t getSampleSizeDirect(
            uint32_t sampleIndex, size_t *size);

private:
    SampleTable *mTable;

    bool mInitialized;

    uint32_t mSampleToChunkIndex;
    uint32_t mFirstChunk;
    uint32_t mFirstChunkSampleIndex;
    uint32_t mStopChunk;
    uint32_t mStopChunkSampleIndex;
    uint32_t mSamplesPerChunk;
    uint32_t mChunkDesc;

    uint32_t mCurrentChunkIndex;
    off_t mCurrentChunkOffset;
    Vector<size_t> mCurrentChunkSampleSizes;

    uint32_t mTimeToSampleIndex;
    uint32_t mTTSSampleIndex;
    uint32_t mTTSSampleTime;
    uint32_t mTTSCount;
    uint32_t mTTSDuration;

    uint32_t mCurrentSampleIndex;
    off_t mCurrentSampleOffset;
    size_t mCurrentSampleSize;
    uint32_t mCurrentSampleTime;

    void reset();
    status_t findChunkRange(uint32_t sampleIndex);
    status_t getChunkOffset(uint32_t chunk, off_t *offset);
    status_t findSampleTime(uint32_t sampleIndex, uint32_t *time);

    SampleIterator(const SampleIterator &);
    SampleIterator &operator=(const SampleIterator &);
};

}  // namespace android
Loading