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

📄 mp4_parser_stbl.c

📁 最新MTK手机软件源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}

/*******************************************************************************
   Get the file offset of the specified sample in the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetSampleOffset(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo, kal_uint32 *puSampleOffset, MP4_Track_Type type)
{
   MP4_Parser_Status ret;
   STMp4Track *pCurTrack;
   kal_uint8  bTrackNo;
   kal_uint32 uSampleInChunk, uSampleOffsetChunk;

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

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

   /// locate the chuck of the sample
   if ((ret=MP4_GetChunkNoAndOffset(pstMp4Parser, uSampleNo, &uSampleInChunk, &uSampleOffsetChunk, type))!=MP4_PARSER_OK)
      return ret;
   
   /// Check if the single-point cache is valid or not
   if (pCurTrack->uSampleOffset_Cache != 0) {
      if (pCurTrack->uSampleInChunk_Cache == uSampleInChunk) {
         /// Case 1: uSampleNo == uCurSampleNo
         if (uSampleNo == pCurTrack->uCurSampleNo) {
            *puSampleOffset = pCurTrack->uSampleOffset_Cache;
            return MP4_PARSER_OK;
         }

         /// Case 2: uSampleNo > uCurSampleNo, seek forward from current sample
         if (uSampleNo > pCurTrack->uCurSampleNo) {
            kal_uint32 i = uSampleNo - pCurTrack->uCurSampleNo + 1;
            while (--i > 0) {
               if ((ret=MP4_GetSampleOffset_Next(pstMp4Parser, puSampleOffset, type))!=MP4_PARSER_OK)
                  return ret;
            }
            return MP4_PARSER_OK;
         }
      }

      /// Case 3: uSampleNo < uCurSampleNo and (uCurSampleNo - uSampleNo) < uSampleOffsetChunk
      /// In this case, seek backward from current sample
      if ((uSampleNo < pCurTrack->uCurSampleNo) && 
          ((pCurTrack->uCurSampleNo - uSampleNo) < uSampleOffsetChunk)) {
         kal_uint32 i = pCurTrack->uCurSampleNo - uSampleNo + 1;
         while (--i > 0) {
            if ((ret=MP4_GetSampleOffset_Previous(pstMp4Parser, puSampleOffset, type))!=MP4_PARSER_OK)
               return ret;
         }
         return MP4_PARSER_OK;
      }
   }

   {
      /// Case 4: General case, seek forward from the beginning of the chunk
      kal_uint32 j, k;
      kal_uint32 temp_offset;

      if ((ret=MP4_GetChunkOffset(pstMp4Parser, uSampleInChunk, &temp_offset, type))!=MP4_PARSER_OK)
         return ret;

      k = uSampleNo - uSampleOffsetChunk;
      for (j=uSampleOffsetChunk+1; --j>0; ) {
         kal_uint32 uSampleSize;
         if ((ret=MP4_GetSampleSize(pstMp4Parser, k++, &uSampleSize, type))!=MP4_PARSER_OK)
            return ret;
         temp_offset += uSampleSize;
      }
      *puSampleOffset = temp_offset;
      pCurTrack->uCurSampleNo         = uSampleNo;
      pCurTrack->uSampleInChunk_Cache = uSampleInChunk;
      pCurTrack->uSampleOffset_Cache  = temp_offset;
      return MP4_PARSER_OK;
   }
}

/*******************************************************************************
   Get the file offset of the "NEXT" sample in the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetSampleOffset_Next(STMp4Parser *pstMp4Parser, kal_uint32 *puSampleOffset, MP4_Track_Type type)
{
   kal_uint32 uSampleInChunk, uSampleOffsetChunk;
   kal_uint32 uSampleSize;
   MP4_Parser_Status ret;
   kal_uint8  bTrackNo;
   STMp4Track *pCurTrack;

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

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

   pCurTrack->uCurSampleNo++;

   /// locate the chuck of the sample
   if ((ret=MP4_GetChunkNoAndOffset_Next(pstMp4Parser, &uSampleInChunk, &uSampleOffsetChunk, type))!=MP4_PARSER_OK) {
      return ret;
   }

   if (uSampleInChunk == pCurTrack->uSampleInChunk_Cache) {
      if ((ret=MP4_GetSampleSize(pstMp4Parser, pCurTrack->uCurSampleNo - 1, &uSampleSize, type))!=MP4_PARSER_OK) {
         return ret;
      }
      *puSampleOffset = pCurTrack->uSampleOffset_Cache + uSampleSize;
   } else {
      if ((ret=MP4_GetChunkOffset(pstMp4Parser, uSampleInChunk, puSampleOffset, type))!=MP4_PARSER_OK) {
      	 return ret;
      }
      pCurTrack->uSampleInChunk_Cache = uSampleInChunk;
   }

   pCurTrack->uSampleOffset_Cache = *puSampleOffset;

   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the file offset of the "PREVIOUS" sample in the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetSampleOffset_Previous(STMp4Parser *pstMp4Parser, kal_uint32 *puSampleOffset, MP4_Track_Type type)
{
   kal_uint32 uSampleInChunk, uSampleOffsetChunk;
   kal_uint32 uSampleSize;
   MP4_Parser_Status ret;
   kal_uint8  bTrackNo;
   STMp4Track *pCurTrack;

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

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

   pCurTrack->uCurSampleNo--;

   /// locate the chuck of the sample
   if ((ret=MP4_GetChunkNoAndOffset_Previous(pstMp4Parser, &uSampleInChunk, &uSampleOffsetChunk, type))!=MP4_PARSER_OK) {
      return ret;
   }

   if (uSampleInChunk == pCurTrack->uSampleInChunk_Cache) {
      /// Get the size of current sample
      if ((ret=MP4_GetSampleSize(pstMp4Parser, pCurTrack->uCurSampleNo, &uSampleSize, type))!=MP4_PARSER_OK) {
         return ret;
      }
      *puSampleOffset = pCurTrack->uSampleOffset_Cache - uSampleSize;
   } else {
      kal_uint32 temp_offset, k, j;
      if ((ret=MP4_GetChunkOffset(pstMp4Parser, uSampleInChunk, &temp_offset, type))!=MP4_PARSER_OK) {
      	 return ret;
      }
      k = pCurTrack->uCurSampleNo - uSampleOffsetChunk;
      for (j=uSampleOffsetChunk+1; --j>0; ) {
         kal_uint32 uSampleSize;
         if ((ret=MP4_GetSampleSize(pstMp4Parser, k++, &uSampleSize, type))!=MP4_PARSER_OK)
            return ret;
         temp_offset += uSampleSize;
      }
      *puSampleOffset = temp_offset;
      pCurTrack->uSampleInChunk_Cache = uSampleInChunk;
   }
   pCurTrack->uSampleOffset_Cache = *puSampleOffset;

   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the file offsets of certain number of consecutive sample in the
   specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetSampleOffset_Array(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo, kal_uint32 *puSampleOffsetArray, kal_uint32 *pArraySize, MP4_Track_Type eTrackType)
{
   kal_uint32 uIndex;
   MP4_Parser_Status ret;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puSampleOffsetArray!=NULL);
   MP4_PARSER_CHECK_ARG(pArraySize!=0);

   if ((ret=MP4_GetSampleOffset(pstMp4Parser, uSampleNo, &(puSampleOffsetArray[0]) , eTrackType))!=MP4_PARSER_OK){
      *pArraySize = 0;
      return ret;
   }

   for (uIndex=1; uIndex<*pArraySize; uIndex++) {
      if ((ret=MP4_GetSampleOffset_Next(pstMp4Parser, &(puSampleOffsetArray[uIndex]) , eTrackType))!=MP4_PARSER_OK)
      {
         *pArraySize = uIndex;
         return ret;
      }
   }

   return MP4_PARSER_OK;
}



/* --------------------- Decoding Time to Sample Table related functions --------------------- */

/*******************************************************************************
   Get the sample count of sample delta of the specified index in the STTS table
   of the specified track.
*******************************************************************************/
static MP4_Parser_Status MP4_GetSampleCountAndDelta(STMp4Parser *pstMp4Parser, kal_uint32 uIndex,
                                                    kal_uint32 *puSampleCount, kal_uint32 *puSampleDelta,
                                                    MP4_Track_Type type)
{
   MP4_Parser_Status ret;
   kal_uint32 uOffset;
   kal_uint8 bTrackNo;

   MP4_PARSER_CHECK_ARG(pstMp4Parser!=NULL);
   MP4_PARSER_CHECK_ARG(puSampleCount!=NULL);
   MP4_PARSER_CHECK_ARG(puSampleDelta!=NULL);

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

   MP4_PARSER_ASSERT(uIndex < pstMp4Parser->stMp4Track[bTrackNo].uTimeToSampleTableEntryCount);

   uOffset = pstMp4Parser->stMp4Track[bTrackNo].uOffsetTimeToSampleTable;
   uOffset += (uIndex * 8);

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

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

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

   /// trick: use the average sample duration instead if the recorded one is negative.
   if (*puSampleDelta & 0x80000000) {
      *puSampleDelta = pstMp4Parser->stMp4Track[bTrackNo].uMediaDuration / pstMp4Parser->stMp4Track[bTrackNo].uSampleCount;
   }

   /// to prevent from divided by zero
   if (*puSampleDelta == 0) {
      *puSampleDelta = 1;
   }

   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the decode time delta of the specified sample in the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetDecodeTimeDelta(STMp4Parser *pstMp4Parser, kal_uint32 uSampleNo,
                                         kal_uint64 *puDecodeTimeDelta, MP4_Track_Type eTrackType)
{
   kal_uint32 uDecodeTimeToSampleTableSize;
   kal_uint32 uThisSampleCount;
   kal_uint32 uThisSampleDelta;
   kal_uint32 uCurSampleCount = 0;
   kal_uint32 uIndex = 0;
   kal_uint8  bTrackNo;
   MP4_Parser_Status ret;
   STMp4Track *pCurTrack;

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

   *puDecodeTimeDelta = 0;

   if ((ret=MP4_GetSampleCount(pstMp4Parser, eTrackType, &uThisSampleCount))!=MP4_PARSER_OK)
      return ret;

   if (uSampleNo >= uThisSampleCount)
      return MP4_PARSER_NO_SUCH_SAMPLE;

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

   if (pCurTrack->uSTTSCacheTableEntryCount > 0) {
      kal_uint16 start_index, end_index;
      STTS_Cache_Entry *stts_cache_table;

      stts_cache_table = pCurTrack->pSTTSCacheTable;

      do { /// Initial Cache
         MP4_STTS_ProcCacheTableByTrack(pstMp4Parser, eTrackType, 32 );
      }
      while (pCurTrack->uSTTSCacheIndex != pCurTrack->uSTTSCacheTableEntryCount &&
          uSampleNo > stts_cache_table[pCurTrack->uSTTSCacheIndex-1].accumulated_sample_count);

      start_index = 0;
      end_index = pCurTrack->uSTTSCacheIndex-1;
      while ((end_index-start_index)>1) {
         kal_uint16 middle_index = (start_index+end_index)>>1;
         if (uSampleNo > stts_cache_table[middle_index].accumulated_sample_count)
            start_index = middle_index;
         else
            end_index = middle_index;
      }
      if (start_index) {
         uIndex = end_index * pCurTrack->uSTTSCacheTableStepSize;
         uCurSampleCount = stts_cache_table[start_index].accumulated_sample_count;
      }
   }

   uDecodeTimeToSampleTableSize = pCurTrack->uTimeToSampleTableEntryCount;

   for (; uIndex<uDecodeTimeToSampleTableSize; uIndex++) {
      if ((ret=MP4_GetSampleCountAndDelta(pstMp4Parser, uIndex, &uThisSampleCount, &uThisSampleDelta, eTrackType))!=MP4_PARSER_OK)
         return ret;
      uCurSampleCount += uThisSampleCount;
      if (uCurSampleCount > uSampleNo) {
         pCurTrack->uDecodeTimeDelta_SampleNo        = uSampleNo;
         pCurTrack->uDecodeTimeDelta_ThisSampleDelta = uThisSampleDelta;
         pCurTrack->uDecodeTimeDelta_CurSampleCount  = uCurSampleCount;
         pCurTrack->uDecodeTimeDelta_TableIndex      = uIndex;
         *puDecodeTimeDelta = uThisSampleDelta;
         break;
      }
   }
   return MP4_PARSER_OK;
}

/*******************************************************************************
   Get the decode time delta of the "NEXT" sample in the specified track.
*******************************************************************************/
MP4_Parser_Status MP4_GetDecodeTimeDelta_Next(STMp4Parser *pstMp4Parser, kal_uint64 *puDecodeTimeDelta,
                                              MP4_Track_Type eTrackType)
{
   MP4_Parser_Status ret;
   kal_uint32 uSampleNo;
   kal_uint32 uDecodeTimeToSampleTableSize;
   kal_uint32 uThisSampleCount;
   kal_uint32 uThisSampleDelta;
   kal_uint8  bTrackNo;
   STMp4Track *pCurTrack;

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

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

⌨️ 快捷键说明

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