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),
         mCompositionTimeDeltaEnt ries(NULL),
         mNumCompositionTimeDelta Entries(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->setCompositionTimeToSamp leParams(
                                    data_offset, chunk_data_size);
                  *offset += chunk_size;
                  break;
            }
status_t SampleTable::setCompositionTimeToSamp leParams(
            off64_t data_offset, size_t data_size) {
      ALOGI("There are reordered frames present.");
      if (mCompositionTimeDeltaEnt ries != 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;
      }
      mNumCompositionTimeDelta Entries = numEntries;
      mCompositionTimeDeltaEnt ries = new uint32_t[2 * numEntries];
      if (mDataSource->readAt(
                        data_offset + 8, mCompositionTimeDeltaEnt ries, numEntries * 8)
                  < (ssize_t)numEntries * 8) {
            delete[] mCompositionTimeDeltaEnt ries;
            mCompositionTimeDeltaEnt ries = NULL;
            return ERROR_IO;
      }
      for (size_t i = 0; i < 2 * numEntries; ++i) {
            mCompositionTimeDeltaEnt ries[i] = ntohl(mCompositionTimeDeltaEnt ries[i]);
      }
      mCompositionDeltaLookup->setEntries(
                  mCompositionTimeDeltaEnt ries, mNumCompositionTimeDelta Entries);
      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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值