SampleTable和SampleIterator的初始化和设置

包含转化媒体时间到实际的sample的信息,是一个容器,包含下面的所有的表
if (chunk_type ==  FOURCC('s', 't', 'b', 'l')) {
    ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
    mLastTrack->sampleTable =  new SampleTable(mDataSource);
}
初始化所有变量的值,主要是各个boxer数据部分的偏移地址,以便于调用readAt函数读取解析
SampleTable::SampleTable(const sp &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);
}
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;
}
==============================================================
http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7925.html
每个chunk的相对于文件起始位置的偏移
        case FOURCC('s', 't', 'c', 'o'):
        case FOURCC('c', 'o', '6', '4'):
        {
            status_t err =
                mLastTrack-> sampleTable->setChunkOffsetParams(
                        chunk_type, data_offset, chunk_data_size);
            *offset += chunk_size;
            break;
        }
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);
     stco boxer数据部分的偏移位置
     mChunkOffsetOffset = data_offset;
    mChunkOffsetType = type;

     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]);
chunk的数目,每个chunk具体文件开始的便宜用4个字节或者八个字节来记录,
以四个字节为例子:
第一个chunk的便宜位置:U32_AT(&header[mChunkOffsetOffset+ 8+0*4]);
第二个chunk的便宜位置:U32_AT(&header[mChunkOffsetOffset+ 8+1*4]);
第三个chunk的便宜位置:U32_AT(&header[mChunkOffsetOffset+ 8+2*4]);
第四个chunk的便宜位置:U32_AT(&header[mChunkOffsetOffset+ 8+3*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;
}
===========================================================
http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7922.html
sample to chunk,也即是当前这个sample在哪一个chunk
        case FOURCC('s', 't', 's', 'c'):
        {
            status_t err =
                mLastTrack->sampleTable-> setSampleToChunkParams(
                        data_offset, chunk_data_size);
            *offset += chunk_size;
            break;
        }

status_t SampleTable::setSampleToChunkParams(
        off64_t data_offset, size_t data_size) {
    mSampleToChunkOffset = 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;
    }
     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]);
    }
每个sampleToChunk占12个字节:每四个字节表示不同的含义
偏移地址计算公式:mSampleToChunkOffset + 8 + i * 12
每四字节的含义:
1:这个table使用的第一个chunk序号
2:当前trunk内的sample数目
3:与这些sample关联的sample description的序号
    return OK;
}
===================================================
http://www.52rd.com/Blog/Detail_RD.Blog_wqyuwss_7924.html
stsz 记录了每个sample的大小以及全部sample的数目
        case FOURCC('s', 't', 's', 'z'):
        case FOURCC('s', 't', 'z', '2'):
        {
            status_t err =
                mLastTrack->sampleTable-> setSampleSizeParams(
                        chunk_type, data_offset, chunk_data_size);
            size_t max_size;
            err =  mLastTrack->sampleTable->getMaxSampleSize(&max_size);

            // Assume that a given buffer only contains at most 10 fragments,
            // each fragment originally prefixed with a 2 byte length will
            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
            // and thus will grow by 2 bytes per fragment.
             mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
            *offset += chunk_size;

             // Calculate average frame rate.
计算公式看起来非常简单: 总时长/总的帧数
            const char *mime;
            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
            if (!strncasecmp("video/", mime, 6)) {
                size_t nSamples = mLastTrack->sampleTable->countSamples();
                int64_t durationUs;
                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
                    if (durationUs > 0) {
                         int32_t frameRate = (nSamples * 1000000LL +
                                    (durationUs >> 1)) / durationUs;
                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
                    }
                }
            }
            break;
        }
status_t SampleTable::setSampleSizeParams(
        uint32_t type, off64_t data_offset, size_t data_size) {
    mSampleSizeOffset = data_offset;
    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]);  默认的每一个sample的大小,如果大于0,则表示所有的sample大小一致,即为 mDefaultSampleSize
    mNumSampleSizes = U32_AT(&header[8]);     sample的数目
    if (type == kSampleSizeType32) {
         mSampleSizeFieldSize = 32;用四个字节来表示每一个sample的大小,所以数据去总长度不能小于12 + mNumSampleSizes * 4
        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;用来表示sample大小的字节数
        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;
}
下面的各个函数是计算每一个sample的大小,然后选择大小最大的那个,就是四字节四字节的读取
status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    Mutex::Autolock autoLock(mLock);
    *max_size = 0;
    for ( uint32_t i = 0; i < mNumSampleSizes; ++i) {  循环获取每个sample的大小
        size_t sample_size;
        status_t err = getSampleSize_l(i, &sample_size);
        if (sample_size > *max_size) {
            *max_size = sample_size;
        }
    }
    return OK;
}
status_t SampleTable::getSampleSize_l(
        uint32_t sampleIndex, size_t *sampleSize) {
    return mSampleIterator->getSampleSizeDirect(
            sampleIndex, sampleSize);
}
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:
        {
                         红色部分为每一个sample的偏移位置
            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;
}
===================================================
http://www.52rd.com/blog/Detail_RD.Blog_wqyuwss_7920.html
每一个时间点映射到具体的sample上,Time-to-sample atoms存储了media sample的duration信息,提供了时间对具体data sample的映射方法,通过这个atom,你可以找到任何时间的sample
        case FOURCC('s', 't', 't', 's'):
        {
            status_t err =
                mLastTrack->sampleTable-> setTimeToSampleParams(
                        data_offset, chunk_data_size);
            *offset += chunk_size;
            break;
        }
status_t SampleTable::setTimeToSampleParams(
        off64_t data_offset, size_t data_size) {
    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];   这里为什么要乘2呢???
    size_t size = sizeof(uint32_t) *  mTimeToSampleCount * 2;
     mTimeToSample每个元素占四个字节,最后得到mTimeToSample这张表
    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;
}
========================================================

        case FOURCC('c', 't', 't', 's'):
        {
            status_t err =
                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
                        data_offset, chunk_data_size);
            *offset += chunk_size;
            break;
        }
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;
    }
    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;
}
==================================================
http://www.cnblogs.com/haibindev/archive/2011/10/17/2214518.html
可随机访问的sample列表,关键帧列表
        case FOURCC('s', 't', 's', 's'):
        {
            status_t err =
                mLastTrack->sampleTable->setSyncSampleParams(
                        data_offset, chunk_data_size);
            *offset += chunk_size;
            break;
        }
status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
     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;
}

你可能感兴趣的:(android多媒体)