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

📄 umc_mp4_spl.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
          nBaseOffset += 8;
        }
      }

      if (pTraf->tfhd.flags & DURATION_IS_EMPTY) {
          // duration is empty, no track run
          // TO DO: add one fragment containing only one sample, sample size and
          // position are both zero. sample time stamp is set to default sample duration.
      }

      Ipp64u nLastBaseOffset = nBaseOffset;
      for (Ipp32u k = 0; k < pTraf->entry_count; k++) {

        // zero or more Trak Run Boxes
        T_trun* pTrun = pTraf->trun[k];

        if ((pTrun == NULL) || (pTrun->sample_count == 0))
          continue;

        /*** where to connect current track fragment ***/
        Ipp32u nTrack;
        umcRes = MapTrafIDToTrackID(pTraf->tfhd.track_ID, nTrack);
        if (umcRes != UMC_OK)
          continue;

        if (pTrun->flags & DATA_OFFSET_PRESENT) {
          // data-offset-present
          if (nBaseOffset + pTrun->data_offset > nLastBaseOffset)
            nLastBaseOffset = nBaseOffset + pTrun->data_offset;
        }

        umcRes = AddMoofRunToIndex(nTrack, pTrex, pTraf, pTrun, nLastBaseOffset);
        UMC_CHECK_STATUS(umcRes)
      }

      nBaseOffset = nLastBaseOffset;
    }

  }

  return UMC_OK;
}


AudioStreamType AudioObjectTypeID(Ipp32u value)
{
  switch(value)
  {
    case 0x6b:
      return UMC::MPEG1_AUDIO;
    case 0x69:
      return UMC::MPEG2_AUDIO;
    case 0x66:
    case 0x67:
    case 0x68:
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x04:
    case 0x06:
      return UMC::AAC_MPEG4_STREAM;
    default:
      return UMC::UNDEF_AUDIO;
  }
}

VideoStreamType GetVideoStreamType(Ipp8u value)
{
  switch (value) {
    case 0x14:
    case 0x20:
      return MPEG4_VIDEO;
    case 0x60:  // 13818-2
    case 0x61:  // 13818-2
    case 0x62:  // 13818-2
    case 0x63:  // 13818-2
    case 0x64:  // 13818-2
    case 0x65:  // 13818-2
      return MPEG2_VIDEO;
    case 0x6A:
      return MPEG1_VIDEO;
    case 0x6C:  // 10918-1
      return MJPEG_VIDEO;
    case 0xf1:
      return H264_VIDEO;
    case 0xf2:
      return H263_VIDEO;
    case 0xf3:
      return H261_VIDEO;
    default:
      return UNDEF_VIDEO;
  }
}

AudioStreamType GetAudioStreamType(Ipp8u value)
{
  switch (value) {
  case 0x40:  // 14496-3
  case 0x66:  // 13818-7
  case 0x67:  // 13818-7
  case 0x68:  // 13818-7
    return AAC_MPEG4_STREAM;
  case 0x69:  // 13818-3
    return MPEG2_AUDIO;
  case 0x6B:  // 11172-3
    return MPEG1_AUDIO;
  default:
    return UNDEF_AUDIO;
  }
}

Ipp32u GetChannelMask(Ipp32s channels)
{
  switch(channels) {
    case 1:
      return  CHANNEL_FRONT_CENTER;
    case 2:
      return  CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT;
    case 3:
      return  CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER;
    case 4:
      return  CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
              CHANNEL_TOP_CENTER;
    case 5:
      return  CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
              CHANNEL_BACK_LEFT  | CHANNEL_BACK_RIGHT;
    case 6:
      return  CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
              CHANNEL_BACK_LEFT  | CHANNEL_BACK_RIGHT | CHANNEL_LOW_FREQUENCY;
    case 7:
      return  CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT | CHANNEL_FRONT_CENTER |
              CHANNEL_BACK_LEFT  | CHANNEL_BACK_RIGHT | CHANNEL_LOW_FREQUENCY |
              CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER;
    default:
      return 0;
  }
}

Status MP4Splitter::FillAudioInfo(T_trak_data *pTrak, Ipp32u nTrack)
{
  AudioStreamInfo *pAudioInfo = (AudioStreamInfo *)(m_pInfo->m_ppTrackInfo[nTrack]->m_pStreamInfo);
  T_stsd_table_data *table = pTrak->mdia.minf.stbl.stsd.table;
  Ipp8u *ptr = NULL;
  Ipp32s len = 0;

  /*** AMR audio ***/
  if (table->damr.decoderConfigLen) {
    len = table->damr.decoderConfigLen;
    ptr = table->damr.decoderConfig;
  } else
  /*** AAC audio ***/
  if (table->esds.decoderConfigLen) {
    len = table->esds.decoderConfigLen;
    ptr = table->esds.decoderConfig;
  }

  if (len) {
    MediaData *pDecSpecInfo = new MediaData(len);
    UMC_CHECK_PTR(pDecSpecInfo)
    memcpy(pDecSpecInfo->GetDataPointer(), ptr, len);
    pDecSpecInfo->SetDataSize(len);
    pDecSpecInfo->SetTime(0, 0);
    m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo = pDecSpecInfo;
  }

  if (table->damr.decoderConfigLen == 0) {
    pAudioInfo->bitPerSample = 16;
    pAudioInfo->bitrate = table->esds.avgBitrate;
    pAudioInfo->channels = table->channels;
    pAudioInfo->sample_frequency = table->sample_rate;
    pAudioInfo->channel_mask = GetChannelMask(table->channels);
#if defined(_WIN32_WCE) /* conversion from unsigned __int64 to double not implemented */
    Ipp64s s64_dur = (Ipp64s)(pTrak->mdia.mdhd.duration / 2);
    pAudioInfo->duration = (Ipp64f)s64_dur / pTrak->mdia.mdhd.time_scale;
    pAudioInfo->duration *= 2;
#else
    pAudioInfo->duration = (Ipp64f)pTrak->mdia.mdhd.duration / pTrak->mdia.mdhd.time_scale;
#endif
    pAudioInfo->is_protected = (table->is_protected) ? true : false;
    pAudioInfo->stream_type = GetAudioStreamType(table->esds.objectTypeID);
    pAudioInfo->stream_subtype = UNDEF_AUDIO_SUBTYPE;
    switch (pAudioInfo->stream_type) {
    case AAC_MPEG4_STREAM:
      m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_AAC;

      /*** update audio_info from DecSpecInfo ***/
      if (m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo) {
        sAudio_specific_config  audio_config_data;
        sBitsreamBuffer         bs;

//        T_mdia_data m_Mdia = m_headerMPEG4.moov.trak[nTrack]->mdia;

        INIT_BITSTREAM(&bs, m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo->GetDataPointer())
        bs.nDataLen = m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo->GetDataSize();
        if (!dec_audio_specific_config(&audio_config_data,&bs)) {
          //dec_audio_specific_config returns 0, if everything is OK.
          pAudioInfo->stream_type = AudioObjectTypeID(audio_config_data.audioObjectType);
          pAudioInfo->sample_frequency = get_sampling_frequency(&audio_config_data, 0);

          if (1 == audio_config_data.sbrPresentFlag) {
            pAudioInfo->sample_frequency = get_sampling_frequency(&audio_config_data, 1);
          }

          pAudioInfo->channels = get_channels_number(&audio_config_data);
        }
      }
      break;
    case MPEG2_AUDIO:
      m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEGA;
      break;
    case MPEG1_AUDIO:
      m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEGA;
      break;
    default:
      m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_UNKNOWN;
    }
  } else {  /*** AMR audio ***/
    pAudioInfo->sample_frequency = 8000;
    pAudioInfo->channels = 1;
    pAudioInfo->stream_type = AMR_NB_AUDIO;
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_AMR;
  }
  pAudioInfo->streamPID = pTrak->tkhd.track_id;

  return UMC_OK;
}

Status MP4Splitter::FillVideoInfo(T_trak_data *pTrak, Ipp32u nTrack)
{
  VideoStreamInfo *pVideoInfo = (VideoStreamInfo *)(m_pInfo->m_ppTrackInfo[nTrack]->m_pStreamInfo);
  T_stsd_table_data *table = pTrak->mdia.minf.stbl.stsd.table;
  Ipp8u *ptr = NULL;
  Ipp32s len = 0;
  Status umcRes = UMC_OK;

  pVideoInfo->clip_info.width = table->width;
  pVideoInfo->clip_info.height = table->height;
  pVideoInfo->aspect_ratio_width = 1;
  pVideoInfo->aspect_ratio_height = 1;
  pVideoInfo->color_format = YV12;

  /*** update clip_info and interlace_type ***/
  if (table->esds.decoderConfigLen) {
    len = table->esds.decoderConfigLen;
    ptr = table->esds.decoderConfig;
    //get bitrate
    pVideoInfo->bitrate = table->esds.avgBitrate;
    //get info about stream from ESDS info
    umcRes = ParseESDSHeader(pTrak, nTrack);
  } else if (table->avcC.decoderConfigLen) {
    len = table->avcC.decoderConfigLen;
    ptr = table->avcC.decoderConfig;
    //get info about stream from avcC info
    umcRes = ParseAVCCHeader(pTrak, nTrack);
  }
  UMC_CHECK_STATUS(umcRes)

  if (len) {
    MediaData *pDecSpecInfo = new MediaData(len);
    UMC_CHECK_PTR(pDecSpecInfo)
    memcpy(pDecSpecInfo->GetDataPointer(), ptr, len);
    pDecSpecInfo->SetDataSize(len);
    pDecSpecInfo->SetTime(0, 0);
    m_pInfo->m_ppTrackInfo[nTrack]->m_pDecSpecInfo = pDecSpecInfo;
  }
  pVideoInfo->streamPID = pTrak->tkhd.track_id;

  //get duration
#if defined(_WIN32_WCE) /* conversion from unsigned __int64 to double not implemented */
    Ipp64s s64_dur = (Ipp64s)(pTrak->mdia.mdhd.duration / 2);
    pVideoInfo->duration = (Ipp64f)s64_dur / pTrak->mdia.mdhd.time_scale;
    pVideoInfo->duration *= 2;
#else
    pVideoInfo->duration = (Ipp64f)pTrak->mdia.mdhd.duration / pTrak->mdia.mdhd.time_scale;
#endif

  //get framerate
  if (pVideoInfo->duration)
    pVideoInfo->framerate = (Ipp64f)pTrak->mdia.minf.stbl.stsz.total_entries / pVideoInfo->duration;

/*
  if (pVideoInfo->duration > 0 && !m_headerMPEG4.moov.mvex.total_tracks) {
      pInfo->m_video_info.framerate = (m_Mdia.minf.stbl.stsz.total_entries) /
                                        pInfo->m_video_info.duration;
  } else {
    if (m_headerMPEG4.moov.mvex.total_tracks && m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration) {
        pInfo->m_video_info.framerate = m_Mdia.mdhd.time_scale/
          m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration;
    } else {
          if (m_headerMPEG4.moov.mvex.trex[uiPin] &&
              m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration) {
            pInfo->m_video_info.framerate = m_headerMPEG4.moov.mvex.trex[uiPin]->default_sample_duration;
          }
          //if duration was changed, after parsing of the all stream fragments
          else if (m_pFirstSegmentDuration && m_pFirstSegmentDuration[uiPin] > 0) {
              pInfo->m_video_info.framerate = (Ipp64f)(m_Mdia.minf.stbl.stsz.total_entries) /
                                                  m_pFirstSegmentDuration[uiPin];
            pInfo->m_video_info.framerate *= m_Mdia.mdhd.time_scale;
          } else {
            pInfo->m_video_info.framerate = 0;
          }
        }
    }
*/

    //get stream type
  pVideoInfo->stream_type = GetVideoStreamType(table->esds.objectTypeID);
  pVideoInfo->stream_subtype = UNDEF_VIDEO_SUBTYPE;
  if (pVideoInfo->stream_type == MPEG4_VIDEO) {
    pVideoInfo->stream_subtype = MPEG4_VIDEO_QTIME;
  } else if (pVideoInfo->stream_type == H264_VIDEO) {
    pVideoInfo->stream_subtype = AVC1_VIDEO;
  }

  switch (pVideoInfo->stream_type) {
  case MPEG4_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEG4V;
    break;
  case MPEG2_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEG2V;
    break;
  case MPEG1_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MPEG1V;
    break;
  case MJPEG_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_MJPEG;
    break;
  case H264_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_H264;
    break;
  case H263_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_H263;
    break;
  case H261_VIDEO:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_H261;
    break;
  default:
    m_pInfo->m_ppTrackInfo[nTrack]->m_Type = TRACK_UNKNOWN;
  }

  return UMC_OK;
}

Status MP4Splitter::Init(SplitterParams& init)
{
  Ipp32u iES, nAudio = 0, nVideo = 0;
  IndexEntry entry;
  Status umcRes;
  int i_a = 0, i_v = 0;

  if (init.m_pDataReader == NULL)
    return UMC_ERR_NOT_ENOUGH_DATA;

  m_bFlagStop = true;

  /* init LockableDataReader */
  umcRes = SplitterBase::Init(init);
  UMC_CHECK_STATUS(umcRes)

  m_pInfo = new SplitterInfo;
  UMC_CHECK_PTR(m_pInfo)

  m_pInfo->m_splitter_flags = init.m_lFlags;
  m_pInfo->m_SystemType = MP4_ATOM_STREAM;

  memset(&m_headerMPEG4, 0, sizeof(info_atoms));

  /* read moov atom */
  umcRes = ParseMP4Header();
  UMC_CHECK_STATUS(umcRes)

  m_pInfo->m_nOfTracks = m_headerMPEG4.moov.total_tracks;
#if defined(_WIN32_WCE) /* conversion from unsigned __int64 to double not implemented */
    Ipp64s s64_dur = (Ipp64s)(m_headerMPEG4.moov.mvhd.duration / 2);
    m_pInfo->m_dDuration = (Ipp64f)s64_dur / m_headerMPEG4.moov.mvhd.time_scale;
    m_pInfo->m_dDuration *= 2;
#else
    m_pInfo->m_dDuration = (Ipp64f)m_headerMPEG4.moov.mvhd.duration / m_headerMPEG4.moov.mvhd.time_scale;
#endif

  m_pTrackIndex = new TrackIndex[m_pInfo->m_nOfTracks];
  if (NULL == m_pTrackIndex)
      return UMC_ERR_ALLOC;

  UMC_ALLOC_ZERO_ARR(m_pInfo->m_ppTrackInfo, TrackInfo*, m_pInfo->m_nOfTracks)
  UMC_ALLOC_ZERO_ARR(m_ppMediaBuffer, MediaBuffer*, m_pInfo->m_nOfTracks)
  UMC_ALLOC_ZERO_ARR(m_ppLockedFrame, MediaData*, m_pInfo->m_nOfTracks)

  UMC_NEW_ARR(m_pReadESThread, vm_thread, m_pInfo->m_nOfTracks)
  UMC_ALLOC_ZERO_ARR(m_pLastPTS, Ipp64f, m_pInfo->m_nOfTracks)

  for (iES = 0; iES < m_pInfo->m_nOfTracks; iES++) {
    T_trak_data *pTrak = m_headerMPEG4.moov.trak[iES];
    MediaBufferParams mParams;
    int nBufferSize = 0;

    umcRes = AddMoovToIndex(iES);
    UMC_CHECK_STATUS(umcRes)

    m_pTrackIndex[iES].First(entry);

    m_pInfo->m_ppTrackInfo[iES] = new TrackInfo;
    m_pInfo->m_ppTrackInfo[iES]->m_PID = pTrak->tkhd.track_id;
    vm_thread_set_invalid(&m_pReadESThread[iES]);

    if (pTrak->mdia.minf.is_audio) {
      pAudioTrTbl[i_a++] = (Ipp8u)iES;
      nAudio++;
      m_pInfo->m_ppTrackInfo[iES]->m_pStreamInfo = new AudioStreamInfo;
      umcRes = FillAudioInfo(pTrak, iES);
      UMC_CHECK_STATUS(umcRes)
      if ((m_pInfo->m_dRate == 1) && (m_pInfo->m_splitter_flags & AUDIO_SPLITTER)) {
        m_pInfo->m_ppTrackInfo[iES]->m_isSelected = 1;
      }
    } else if (pTrak->mdia.minf.is_video) {
      pVideoTrTbl[i_v++] = (Ipp8u)iES;
      nVideo++;
      m_pInfo->m_ppTrackInfo[iES]->m_pStreamInfo = new VideoStreamInfo;
      umcRes = FillVideoInfo(pTrak, iES);
      UMC_CHECK_STATUS(umcRes)
      if (m_pInfo->m_splitter_flags & VIDEO_SPLITTER) {
        m_pInfo->m_ppTrackInfo[iES]->m_isSelected = 1;
      }
    } else {
      continue; // skip unsupported stream
    }

//    m_pInfo->m_ppTrackInfo[iES]->m_isSelected = 1;

    UMC_NEW(m_ppMediaBuffer[iES], SampleBuffer);
    UMC_NEW(m_ppLockedFrame[iES], MediaData);
    mParams.m_numberOfFrames = NUMBEROFFRAMES;
    nBufferSize = pTrak->mdia.minf.stbl.stsz.max_sample_size;

    if (pTrak->mdia.minf.is_audio) {
      if (nBufferSize < MINAUDIOBUFFERSIZE)
        nBufferSize = MINAUDIOBUFFERSIZE;
    } else if (pTrak->mdia.minf.is_video) {
      if (nBufferSize < MINVIDEOBUFFERSIZE)

⌨️ 快捷键说明

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