⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4_parser_stbl.c

📁 最新MTK手机软件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
   kal_uint32 uOffset;
   kal_uint8 bTrackNo;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puChunkOffset!=NULL);

   if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
      return ret;

   MP4_PARSER_ASSERT(uChunkNo<pstMp4Parser->stMp4Track[bTrackNo].uChunkCount);

   uOffset = pstMp4Parser->stMp4Track[bTrackNo].uOffsetChunkOffsetTable;
   uOffset += (uChunkNo * 4);

   if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstMp4Parser->pstFSAL, uOffset))!=FSAL_OK)
      return MP4_PARSER_FILE_SEEK_ERROR;

   if ((pstMp4Parser->eFSALErr=FSAL_Read_UINT(pstMp4Parser->pstFSAL, puChunkOffset))!=FSAL_OK)
      return MP4_PARSER_FILE_READ_ERROR;

   return MP4_PARSER_OK;
}



/* --------------------- Sample To Chunk Table related functions --------------------- */

/*******************************************************************************
   Get the the number of entries in the STSC box of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetSampleToChunkEntryCount(STMp4Parser *pstMp4Parser, MP4_Track_Type type, kal_uint32 *puEntryCount)
{
   MP4_Parser_Status ret;
   kal_uint8 bTrackNo;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puEntryCount!=NULL);

   if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
      return ret;

   *puEntryCount = pstMp4Parser->stMp4Track[bTrackNo].uSampleToChunkEntryCount;

   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the index of the first chunk of the specified run in the STSC box
   of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetFirstChunkInRun(STMp4Parser *pstMp4Parser, kal_uint32 uRun,
                                                kal_uint32 *puFirstChunkInRun, MP4_Track_Type type)
{
   MP4_Parser_Status ret;
   kal_uint32 uOffset;
   kal_uint8 bTrackNo;
   STFSAL *pstFSAL_STCO;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puFirstChunkInRun!=NULL);

   if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK) {
      return ret;
   }

   MP4_PARSER_ASSERT(uRun<pstMp4Parser->stMp4Track[bTrackNo].uSampleToChunkEntryCount);

   pstFSAL_STCO = pstMp4Parser->stMp4Track[bTrackNo].pstFSAL_STCO;
   if (pstFSAL_STCO == NULL)
      pstFSAL_STCO = pstMp4Parser->pstFSAL;

   uOffset = pstMp4Parser->stMp4Track[bTrackNo].uOffsetSampleToChunkTable;
   uOffset += (uRun * 12);

   if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstFSAL_STCO, uOffset))!=FSAL_OK)
      return MP4_PARSER_FILE_SEEK_ERROR;

   if ((pstMp4Parser->eFSALErr=FSAL_Read_UINT(pstFSAL_STCO, puFirstChunkInRun))!=FSAL_OK)
      return MP4_PARSER_FILE_READ_ERROR;

   *puFirstChunkInRun -= 1; /// index from 0

   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the number of samples per chunk of the specified run in the STSC box
   of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetSamplePerChunkInRun(STMp4Parser *pstMp4Parser, kal_uint32 uRun,
                                                    kal_uint32 *puSamplePerChunk, MP4_Track_Type type)
{
   MP4_Parser_Status ret;
   kal_uint32 uOffset;
   kal_uint8  bTrackNo;
   STMp4Track *pCurTrack;
   STFSAL *pstFSAL_STCO;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puSamplePerChunk!=NULL);

   if ((ret=MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
      return ret;
   pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);

   MP4_PARSER_ASSERT(uRun < pCurTrack->uSampleToChunkEntryCount);

   pstFSAL_STCO = pCurTrack->pstFSAL_STCO;
   if (pstFSAL_STCO == NULL)
      pstFSAL_STCO = pstMp4Parser->pstFSAL;

   uOffset = pCurTrack->uOffsetSampleToChunkTable;
   uOffset += (uRun * 12 + 4);

   if ((pstMp4Parser->eFSALErr=FSAL_Seek(pstFSAL_STCO, uOffset))!=FSAL_OK)
      return MP4_PARSER_FILE_SEEK_ERROR;

   if ((pstMp4Parser->eFSALErr=FSAL_Read_UINT(pstFSAL_STCO, puSamplePerChunk))!=FSAL_OK)
      return MP4_PARSER_FILE_READ_ERROR;

   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the number of the chunk and the file offset of the chunk
   where the specified sample resides in.
*******************************************************************************/
static MP4_Parser_Status MP4_GetChunkNoAndOffset(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo,
                                                 kal_uint32 *puSampleInChunk, kal_uint32 *puSampleOffsetChunk,
                                                 MP4_Track_Type eTrackType )
{
   MP4_Parser_Status ret;
   kal_uint32 uSamplePerChunk;
   kal_uint32 uSampleToChunkIndex = 0;
   kal_uint32 uFirstChunk, uLastChunk;
   kal_uint32 uSampleToChunkEntryCount = 0;
   kal_uint32 uSampleSumPrev = 0, uSampleSum = 0;
   STMp4Track *pCurTrack;
   kal_uint8  bTrackNo;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puSampleInChunk!=NULL);
   MP4_PARSER_CHECK_ARG(puSampleOffsetChunk!=NULL);

   if ((ret = MP4_GetTrackNoByType(pstMp4Parser, eTrackType, &bTrackNo))!=MP4_PARSER_OK)
       return ret;
   pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);

   if ((ret = MP4_GetSampleToChunkEntryCount(pstMp4Parser, eTrackType, &uSampleToChunkEntryCount))!=MP4_PARSER_OK)
       return ret;

   if (pCurTrack->uSTSCCacheTableEntryCount > 0)
   {  /// STSC cache is enabled. Perform binary search in the cache.
      kal_uint16 start_index, end_index;
      STSC_Cache_Entry *stsc_cache_table;

      stsc_cache_table = pCurTrack->pSTSCCacheTable;
      start_index = 0;
      end_index = pCurTrack->uSTSCCacheTableEntryCount-1;
      while ((end_index-start_index)>1)
      {
         kal_uint16 middle_index = (start_index+end_index)>>1;
         if( uSampleNo > stsc_cache_table[middle_index].accumulated_sample_count )
            start_index = middle_index;
         else
            end_index = middle_index;
      }

      if (start_index)
      {
         uSampleToChunkIndex=end_index * pCurTrack->uSTSCCacheTableStepSize;
         uSampleSum = stsc_cache_table[start_index].accumulated_sample_count;
         uSampleSumPrev = uSampleSum;
      }
   }

   for (; uSampleToChunkIndex<uSampleToChunkEntryCount; uSampleToChunkIndex++) {
      if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, eTrackType))!=MP4_PARSER_OK)
         return ret;
      if (uSampleToChunkIndex == uSampleToChunkEntryCount-1) {
         if ((ret = MP4_GetChunkCount(pstMp4Parser, eTrackType, &uLastChunk))!=MP4_PARSER_OK)
            return ret;
         uLastChunk--;
      } else {
         if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, eTrackType))!=MP4_PARSER_OK)
            return ret;
         uLastChunk--;
      }
      if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, eTrackType))!=MP4_PARSER_OK)
         return ret;
      uSampleSum += (uLastChunk - uFirstChunk + 1)*uSamplePerChunk;
      if (uSampleNo<uSampleSum) {
         *puSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
         *puSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;

         pCurTrack->uSampleToChunkIndex = uSampleToChunkIndex;
         pCurTrack->uSamplePerChunk     = uSamplePerChunk;
         pCurTrack->uFirstChunk         = uFirstChunk;
         pCurTrack->uSampleSum          = uSampleSum;
         pCurTrack->uSampleSumPrev      = uSampleSumPrev;

         return MP4_PARSER_OK;
      }
      uSampleSumPrev = uSampleSum;
   }
   return MP4_PARSER_INTERNAL_ERROR;
}

static MP4_Parser_Status MP4_GetChunkNoAndOffset_Next(STMp4Parser *pstMp4Parser, kal_uint32 *uSampleInChunk, kal_uint32 *uSampleOffsetChunk, MP4_Track_Type type)
{
   kal_uint32 uSampleToChunkIndex, uSampleNo;
   kal_uint32 uFirstChunk, uLastChunk;
   kal_uint32 uSampleToChunkEntryCount;
   kal_uint32 uSamplePerChunk;
   kal_uint32 uSampleSum, uSampleSumPrev;
   MP4_Parser_Status ret;
   STMp4Track *pCurTrack;
   kal_uint8  bTrackNo;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(uSampleInChunk!=NULL);
   MP4_PARSER_CHECK_ARG(uSampleOffsetChunk!=NULL);

   if ((ret = MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
       return ret;
   pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);

   uSampleNo                = pCurTrack->uCurSampleNo;
   uSampleToChunkEntryCount = pCurTrack->uSampleToChunkEntryCount;
   uSampleToChunkIndex      = pCurTrack->uSampleToChunkIndex;
   uSampleSum               = pCurTrack->uSampleSum;
   uSampleSumPrev           = pCurTrack->uSampleSumPrev;
   uSamplePerChunk          = pCurTrack->uSamplePerChunk;
   uFirstChunk              = pCurTrack->uFirstChunk;

   if (uSampleNo<uSampleSum) {
      *uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
      *uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
      return MP4_PARSER_OK;
   }

   uSampleSumPrev = uSampleSum;
   uSampleToChunkIndex++;

   if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, type))!=MP4_PARSER_OK) {
      return ret;
   }

   if (uSampleToChunkIndex == uSampleToChunkEntryCount-1) {
      if ((ret = MP4_GetChunkCount(pstMp4Parser, type, &uLastChunk))!=MP4_PARSER_OK) {
         return ret;
      }
      uLastChunk--;
   } else {
      if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, type))!=MP4_PARSER_OK) {
         return ret;
      }
      uLastChunk--;
   }

   if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, type))!=MP4_PARSER_OK) {
      return ret;
   }

   uSampleSum += (uLastChunk - uFirstChunk + 1)*uSamplePerChunk;

   *uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
   *uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
   
   pCurTrack->uSampleToChunkIndex = uSampleToChunkIndex;
   pCurTrack->uSamplePerChunk     = uSamplePerChunk;
   pCurTrack->uFirstChunk         = uFirstChunk;
   pCurTrack->uSampleSum          = uSampleSum;
   pCurTrack->uSampleSumPrev      = uSampleSumPrev;
   
   return MP4_PARSER_OK;
}

static MP4_Parser_Status MP4_GetChunkNoAndOffset_Previous(STMp4Parser *pstMp4Parser, kal_uint32 *uSampleInChunk, kal_uint32 *uSampleOffsetChunk, MP4_Track_Type type)
{
   kal_uint32 uSampleToChunkIndex, uSampleNo;
   kal_uint32 uFirstChunk, uLastChunk;
   kal_uint32 uSampleToChunkEntryCount;
   kal_uint32 uSamplePerChunk;
   kal_uint32 uSampleSum, uSampleSumPrev;
   MP4_Parser_Status ret;
   STMp4Track *pCurTrack;
   kal_uint8  bTrackNo;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(uSampleInChunk!=NULL);
   MP4_PARSER_CHECK_ARG(uSampleOffsetChunk!=NULL);

   if ((ret = MP4_GetTrackNoByType(pstMp4Parser, type, &bTrackNo))!=MP4_PARSER_OK)
       return ret;
   pCurTrack = &(pstMp4Parser->stMp4Track[bTrackNo]);

   uSampleNo                = pCurTrack->uCurSampleNo;
   uSampleToChunkEntryCount = pCurTrack->uSampleToChunkEntryCount;
   uSampleToChunkIndex      = pCurTrack->uSampleToChunkIndex;
   uSampleSum               = pCurTrack->uSampleSum;
   uSampleSumPrev           = pCurTrack->uSampleSumPrev;
   uSamplePerChunk          = pCurTrack->uSamplePerChunk;
   uFirstChunk              = pCurTrack->uFirstChunk;

   if (uSampleNo > uSampleSumPrev) {
      *uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
      *uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
      return MP4_PARSER_OK;
   }

   uSampleSum = uSampleSumPrev;
   uSampleToChunkIndex--;
   if ((ret = MP4_GetSamplePerChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uSamplePerChunk, type))!=MP4_PARSER_OK) {
      return ret;
   }

   if (uSampleToChunkIndex == uSampleToChunkEntryCount-1) {
      if ((ret = MP4_GetChunkCount(pstMp4Parser, type, &uLastChunk))!=MP4_PARSER_OK) {
         return ret;
      }
      uLastChunk--;
   } else {
      if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex+1, &uLastChunk, type))!=MP4_PARSER_OK) {
         return ret;
      }
      uLastChunk--;
   }

   if ((ret = MP4_GetFirstChunkInRun(pstMp4Parser, uSampleToChunkIndex, &uFirstChunk, type))!=MP4_PARSER_OK) {
      return ret;
   }

   uSampleSumPrev -= (uLastChunk - uFirstChunk + 1)*uSamplePerChunk;

   *uSampleInChunk = (uSampleNo - uSampleSumPrev) / uSamplePerChunk + uFirstChunk;
   *uSampleOffsetChunk = (uSampleNo - uSampleSumPrev) % uSamplePerChunk;
   
   pCurTrack->uSampleToChunkIndex = uSampleToChunkIndex;
   pCurTrack->uSamplePerChunk     = uSamplePerChunk;
   pCurTrack->uFirstChunk         = uFirstChunk;
   pCurTrack->uSampleSum          = uSampleSum;
   pCurTrack->uSampleSumPrev      = uSampleSumPrev;

   return MP4_PARSER_OK;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -