mp4_producer_audio.c

来自「最新MTK手机软件源码」· C语言 代码 · 共 1,614 行 · 第 1/4 页

C
1,614
字号
MP4_Producer_Status MP4_Produce_Trak_Audio(STMp4Producer *pstMp4Producer, kal_uint32 *puBoxSize, kal_uint32 uAudioDataOffset)
{
   MP4_Producer_Status ret;
   kal_uint32 uFilePos;
   kal_uint32 uTkhdSize, uMdiaSize;

   MP4_PRODUCER_CHECK_ARG(pstMp4Producer!=NULL);
   MP4_PRODUCER_CHECK_ARG(puBoxSize!=NULL);

   /* header */
   if((ret=mp4_produce_box(pstMp4Producer, BOX_TYPE_TRAK, 0, &uFilePos))!=MP4_PRODUCER_OK)
      return ret;
   *puBoxSize = 8;

   /* track header (tkhd) */
   if((ret=mp4_produce_tkhd(pstMp4Producer, &uTkhdSize))!=MP4_PRODUCER_OK)
      return ret;
   *puBoxSize += uTkhdSize;

   /* media information (mdia) */
   if((ret=mp4_produce_mdia(pstMp4Producer, &uMdiaSize, uAudioDataOffset))!=MP4_PRODUCER_OK)
      return ret;
   *puBoxSize += uMdiaSize;

   /* update box size */
  	if ((pstMp4Producer->eFSALErr=FSAL_Write_UINT_AT(pstMp4Producer->pstFSAL, *puBoxSize, uFilePos))!=FSAL_OK)
		return MP4_PRODUCER_FILE_WRITE_ERROR;

   return MP4_PRODUCER_OK;
}


MP4_Producer_Status MP4_Produce_MovieHeader(STMp4Producer *pstMp4Producer, kal_uint32 uAudioDataOffset)
{
   MP4_Producer_Status ret;
   kal_uint32 uFilePos;
   kal_uint32 uBoxSize, uMvhdSize, uTrakSize;

   /* header */
   if((ret=mp4_produce_box(pstMp4Producer, BOX_TYPE_MOOV, 0, &uFilePos))!=MP4_PRODUCER_OK)
      return ret;
   uBoxSize = 8;

   if((ret=mp4_produce_mvhd(pstMp4Producer, &uMvhdSize))!=MP4_PRODUCER_OK)
      return ret;
   uBoxSize += uMvhdSize;

   if((ret=MP4_Produce_Trak_Audio(pstMp4Producer, &uTrakSize, uAudioDataOffset))!=MP4_PRODUCER_OK)
      return ret;
   uBoxSize += uTrakSize;

   /* update box size */
  	if ((pstMp4Producer->eFSALErr=FSAL_Write_UINT_AT(pstMp4Producer->pstFSAL, uBoxSize, uFilePos))!=FSAL_OK)
		return MP4_PRODUCER_FILE_WRITE_ERROR;

   return MP4_PRODUCER_OK;
}



MP4_Producer_Status mp4_produce_mdat(STMp4Producer *pstMp4Producer)
{
   return MP4_PRODUCER_OK;
}



MP4_Producer_Status MP4_Produce_Init(STMp4Producer *pstMp4Producer, STMp4SampleDataAudio *pstMp4SampleData, STFSAL *pstFSAL)
{
//   MP4_Producer_Status ret;

   MP4_PRODUCER_CHECK_ARG(pstMp4Producer!=NULL);
   MP4_PRODUCER_CHECK_ARG(pstMp4SampleData!=NULL);
   MP4_PRODUCER_CHECK_ARG(pstFSAL!=NULL);

   pstMp4Producer->pstMp4SampleData = pstMp4SampleData;
   pstMp4Producer->pstFSAL = pstFSAL;
   pstMp4Producer->eCurTrack = MP4_TRACK_AUDIO;

//   if((ret=MP4_Produce_FileTypeBox(pstMp4Producer))!=MP4_PRODUCER_OK)
//      return ret;

//   if((ret=mp4_produce_mdat(pstMp4Producer))!=MP4_PRODUCER_OK)
//      return ret;

//   if((ret=MP4_Produce_MovieHeader(pstMp4Producer))!=MP4_PRODUCER_OK)
//      return ret;

   return MP4_PRODUCER_OK;
}



MP4_Producer_Status MP4_Produce_CalculateLimitedAudioFileSize(
   STFSAL *pstFSAL, kal_uint32 uNumBytesLimit, kal_uint32 uMilliSecondsLimit,
   kal_uint8 bAMRType, kal_uint32 *puResultBytes)
{
   kal_uint32 uSpeechFrameLimit;
   kal_uint32 uSpeechFrameCount;
   kal_uint32 uAudioFileLen;
   kal_uint32 uAMRFilePos;
   FSAL_Status eFSALRet;

   ASSERT(pstFSAL!=NULL);
   ASSERT(puResultBytes!=NULL);

   eFSALRet = FSAL_GetFileSize(pstFSAL, &uAudioFileLen);
   if (eFSALRet!=FSAL_OK)
      return MP4_PRODUCER_FILE_ACCESS_ERROR;

   if (uAudioFileLen<8)
      return MP4_PRODUCER_AUDIO_FILE_TOO_SMALL;

   uAMRFilePos = 8;
   *puResultBytes = 8;
   uSpeechFrameLimit = uMilliSecondsLimit / 20;
   uSpeechFrameCount = 0;

   /* parse each audio frame */
   while(uAMRFilePos < uAudioFileLen) {
      unsigned char bFrameHeader;
      unsigned char bFrameType;
      unsigned char bFrameLength;
      unsigned char bFQI;

      eFSALRet = FSAL_Seek(pstFSAL, uAMRFilePos);
      if(eFSALRet!=FSAL_OK)
      {
         return MP4_PRODUCER_FILE_SEEK_ERROR;
      }

      eFSALRet = FSAL_Read_Bytes(pstFSAL, &bFrameHeader, 1);
      if(eFSALRet != FSAL_OK)
         return MP4_PRODUCER_FILE_READ_ERROR;

      bFrameType = (bFrameHeader >> 3)&0x0F;
      bFQI = (bFrameHeader >> 2)&0x01;
      if( bFQI == 0 )
      {
         return MP4_PRODUCER_AMR_FQI_INVALID;
      }
      // ASSERT(bFQI==1);
      // After this line, bFQI is no more valid and hence can be used as temporary variable.

      if (bAMRType==0)
         bFQI = 8; /* AMR */
      else
         bFQI = 9; /* AMR-WB */

      if (bFrameType <= bFQI) {
         bFrameLength = (lenSpeechBitsAMR[bFrameType] + 7) / 8;
      } else if (bFrameType == 15) {
         bFrameLength = 0;
      } else {
         return MP4_PRODUCER_AMR_FRAME_INVALID;
      }

      uAMRFilePos += (bFrameLength + 1);
      uSpeechFrameCount++;

      if (uAMRFilePos > uNumBytesLimit)
         break;

      if (uSpeechFrameCount > uSpeechFrameLimit)
         break;

      /* Handle the case for partial frame */
      if (uAMRFilePos > uAudioFileLen)
         break;

      *puResultBytes += (bFrameLength + 1);
   }

   return MP4_PRODUCER_OK;
}

#ifdef WIN32_UNIT_TEST

#define mu_run_test(test)          \
  do {                             \
    char *message;                 \
    printf("Doing: %s\n", #test);  \
    message = test(); tests_run++; \
    if (message) return message;   \
  } while (0)
extern int tests_run;

int tests_run = 0;

/* No Speech Frame */
const unsigned char amr_file_1[8] = {
   /* 8 bytes file header */
   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
};

/* One Speech Frame */
const unsigned char amr_file_2[22] = {
   /* 8 bytes file header */
   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   /* 5.15kbps: 1 byte frame header 13 bytes frame data */
   0x0C, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
};

/* Two Speech Frame */
const unsigned char amr_file_3[36] = {
   /* 8 bytes file header */
   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   /* 5.15kbps: 1 byte frame header 13 bytes frame data */
   0x0C, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
   /* 5.15kbps: 1 byte frame header 13 bytes frame data */
   0x0C, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
};

/* File Size Less Than 8 */
const unsigned char amr_file_4[7] = {
   1, 2, 3, 4, 5, 6, 7
};

/* File With Invalid FQI */
const unsigned char amr_file_5[9] = {
   /* 8 bytes file header */
   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   /* invalid frame header */
   0
};

/* File With Invalid Frame Header */
const unsigned char amr_file_6[9] = {
   /* 8 bytes file header */
   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   /* invalid frame header */
   0x74
};

/* File with partial frame */
const unsigned char amr_file_7[32] = {
   /* 8 bytes file header */
   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   /* 5.15kbps: 1 byte frame header 13 bytes frame data */
   0x0C, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
   /* 5.15kbps: 1 byte frame header 13 bytes frame data */
   0x0C, 1, 2, 3, 4, 5, 6, 7, 8, 9
};

STFSAL stFSAL;
FSAL_Status eFSALStatus;
kal_uint32 uResultBytes;
MP4_Producer_Status eMp4ProducerStatus;

static char* mu_CalculateLimitedAudioFileSize_1(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_1));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_1, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 0, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 7, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 8, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 9, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char* mu_CalculateLimitedAudioFileSize_2(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_2));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_2, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 0, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 7, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 8, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 9, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 21, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 22, 0, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 8);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 22, 20, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 22);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 22, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 22);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char* mu_CalculateLimitedAudioFileSize_3(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_3));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_3, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 36, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 36);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 36, 80, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 36);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 72, 80, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 36);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 35, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 22);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char* mu_CalculateLimitedAudioFileSize_4(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_4));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_4, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 36, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_AUDIO_FILE_TOO_SMALL);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char* mu_CalculateLimitedAudioFileSize_5(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_5));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_5, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 36, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_AMR_FQI_INVALID);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char* mu_CalculateLimitedAudioFileSize_6(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_6));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_6, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 36, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_AMR_FRAME_INVALID);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char* mu_CalculateLimitedAudioFileSize_7(void)
{
   FSAL_Direct_SetRamFileSize(&stFSAL, sizeof(amr_file_7));
   eFSALStatus = FSAL_Open(&stFSAL, (void*)amr_file_7, FSAL_ROMFILE);
   ASSERT(eFSALStatus == FSAL_OK);
   eMp4ProducerStatus = MP4_Produce_CalculateLimitedAudioFileSize(&stFSAL, 36, 40, 0, &uResultBytes);
   ASSERT(eMp4ProducerStatus == MP4_PRODUCER_OK);
   ASSERT(uResultBytes == 22);
   eFSALStatus = FSAL_Close(&stFSAL);
   ASSERT(eFSALStatus == FSAL_OK);
   return NULL;
}

static char * all_tests() {
  mu_run_test(mu_CalculateLimitedAudioFileSize_1);
  mu_run_test(mu_CalculateLimitedAudioFileSize_2);
  mu_run_test(mu_CalculateLimitedAudioFileSize_3);
  mu_run_test(mu_CalculateLimitedAudioFileSize_4);
  mu_run_test(mu_CalculateLimitedAudioFileSize_5);
  mu_run_test(mu_CalculateLimitedAudioFileSize_6);
  mu_run_test(mu_CalculateLimitedAudioFileSize_7);
  return 0;
}

int main(int argc, char **argv)
{
   char *result = all_tests();
   if (result != 0) {
      printf("Failed at: %s\n", result);
   } else {
      printf("ALL TESTS PASSED\n");
   }
   printf("Tests run: %d\n", tests_run);

   return (result != 0);
}
#endif

⌨️ 快捷键说明

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