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

📄 umc_mp4_spl.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*//////////////////////////////////////////////////////////////////////////////
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//          Copyright(c) 2004-2007 Intel Corporation. All Rights Reserved.
//
*/

#include <ipps.h>
#include "ippdefs.h"
#include "vm_thread.h"
#include "vm_types.h"
#include "vm_time.h"
#include "umc_media_data.h"
#include "umc_cyclic_buffer.h"
#include "mp4cmn_config.h"
#include "bstream.h"
#include "umc_mp4_spl.h"
#include "umc_automatic_mutex.h"
#include "umc_structures.h"

namespace UMC
{

Splitter *CreateMPEG4Splitter() { return (new MP4Splitter()); }

MP4Splitter::MP4Splitter():
    SplitterBase(),
    m_nFragPosEnd(0),
    m_pLastPTS(NULL)
{
}

MP4Splitter::~MP4Splitter()
{
    Close();
}

Status MP4Splitter::CheckInit()
{
  // already initialized
  if ((m_pReader == NULL) ||
      (!m_ReaderMutex.IsInited()) ||
      (m_pTrackIndex == NULL) ||
      (m_ppMediaBuffer == NULL) ||
      (m_ppLockedFrame == NULL) ||
      (m_pInfo == NULL))
    return UMC_ERR_NOT_INITIALIZED;

  return UMC_OK;
}

Status MP4Splitter::Clear_track(T_trak_data* pTrak)
{
  Ipp32u j = 0;

  if (pTrak) {
    for (j = 0; j < pTrak->mdia.minf.stbl.stsd.total_entries; j++) {
      if (!pTrak->mdia.minf.stbl.stsd.table[j].esds.flags) {
        if (pTrak->mdia.minf.stbl.stsd.table[j].esds.decoderConfigLen) {
          ippsFree(pTrak->mdia.minf.stbl.stsd.table[j].esds.decoderConfig);
          pTrak->mdia.minf.stbl.stsd.table[j].esds.decoderConfig = NULL;
        }
      }
      if (pTrak->mdia.minf.stbl.stsd.table[j].avcC.decoderConfigLen) {
        ippsFree(pTrak->mdia.minf.stbl.stsd.table[j].avcC.decoderConfig);
        pTrak->mdia.minf.stbl.stsd.table[j].avcC.decoderConfig = NULL;
      }
      if (pTrak->mdia.minf.stbl.stsd.table[j].damr.decoderConfigLen) {
        ippsFree(pTrak->mdia.minf.stbl.stsd.table[j].damr.decoderConfig);
        pTrak->mdia.minf.stbl.stsd.table[j].damr.decoderConfig = NULL;
      }
    }

    if (!(pTrak->mdia.minf.stbl.stsz.flags)) {
      if (!pTrak->mdia.minf.stbl.stsz.sample_size) {
        if (pTrak->mdia.minf.stbl.stsz.table)
          ippsFree(pTrak->mdia.minf.stbl.stsz.table);
        pTrak->mdia.minf.stbl.stsz.table = NULL;
      }
    }

    if(!(pTrak->mdia.minf.stbl.stsc.flags)) {
      if (pTrak->mdia.minf.stbl.stsc.table)
        ippsFree(pTrak->mdia.minf.stbl.stsc.table);
      pTrak->mdia.minf.stbl.stsc.table = NULL;
    }

    if (pTrak->mdia.minf.stbl.ctts.table)
      ippsFree(pTrak->mdia.minf.stbl.ctts.table);
    pTrak->mdia.minf.stbl.ctts.table = NULL;


    if (pTrak->mdia.minf.stbl.co64.table)
      ippsFree(pTrak->mdia.minf.stbl.co64.table);
    pTrak->mdia.minf.stbl.co64.table = NULL;


    if(!(pTrak->mdia.minf.stbl.stco.flags)) {
      if (pTrak->mdia.minf.stbl.stco.table)
        ippsFree(pTrak->mdia.minf.stbl.stco.table);
      pTrak->mdia.minf.stbl.stco.table = NULL;
    }

    if(!(pTrak->mdia.minf.stbl.stts.flags)) {
      if (pTrak->mdia.minf.stbl.stts.table)
        ippsFree(pTrak->mdia.minf.stbl.stts.table);
      pTrak->mdia.minf.stbl.stts.table = NULL;
    }

    if(!(pTrak->mdia.minf.stbl.stss.flags)) {
      if (pTrak->mdia.minf.stbl.stss.table)
        ippsFree(pTrak->mdia.minf.stbl.stss.table);
      pTrak->mdia.minf.stbl.stss.table = NULL;
    }

    if(!(pTrak->mdia.minf.stbl.stsd.flags)) {
      if (pTrak->mdia.minf.stbl.stsd.table)
        ippsFree(pTrak->mdia.minf.stbl.stsd.table);
      pTrak->mdia.minf.stbl.stsd.table = NULL;
    }

    if (!(pTrak->mdia.minf.dinf.dref.flags)) {
      for (j = 0; j < pTrak->mdia.minf.dinf.dref.total_entries; j++) {
        if (pTrak->mdia.minf.dinf.dref.table[j].data_reference)
          ippsFree(pTrak->mdia.minf.dinf.dref.table[j].data_reference);
        pTrak->mdia.minf.dinf.dref.table[j].data_reference = NULL;
      }
      if (pTrak->mdia.minf.dinf.dref.table) {
        ippsFree(pTrak->mdia.minf.dinf.dref.table);
      }
      pTrak->mdia.minf.dinf.dref.table = NULL;
    }

    ippsFree(pTrak);
  }
  return UMC_OK;
}

void MP4Splitter::FillSampleSizeAndType(T_trak_data *trak,
                                        IndexFragment &frag)
{
  Ipp32u i;
  T_stsz_data stsz = trak->mdia.minf.stbl.stsz;
  T_stss_data stss = trak->mdia.minf.stbl.stss;

  for (i = 0; i < (Ipp32u)frag.iNOfEntries; i++) {
    if (stsz.sample_size == 0) {
      frag.pEntryArray[i].uiSize = trak->mdia.minf.stbl.stsz.table[i].size;
    } else {
      frag.pEntryArray[i].uiSize = stsz.sample_size;
    }
    if (stss.table == NULL) {
      frag.pEntryArray[i].uiFlags = I_PICTURE;
    }
  }
  if (stss.table) {
    for (i = 0; i < stss.total_entries; i++) {
      frag.pEntryArray[stss.table[i].sample_number - 1].uiFlags = I_PICTURE;
    }
  }
}

void MP4Splitter::FillSamplePos(T_trak_data *trak,
                                IndexFragment &frag)
{
  Ipp32u i;

  // chunk offset box (32 bit version)
  T_stco_data& stco = trak->mdia.minf.stbl.stco;
  // chunk offset box (64 bit version)
  T_co64_data& co64 = trak->mdia.minf.stbl.co64;
  // sample to chunk box
  T_stsc_data& stsc = trak->mdia.minf.stbl.stsc;

  Ipp64u nSampleOffset = 0;
  Ipp32u stco_i = 1;
  Ipp32u stsc_i = 0;
  Ipp32u samp_i = 0;

  while (samp_i < (Ipp32u)frag.iNOfEntries) {

    if (stco.total_entries) {
      if (stco_i > stco.total_entries)
        break;
      nSampleOffset = stco.table[stco_i - 1].offset;
    } else {
      if (stco_i > co64.total_entries)
        break;
      nSampleOffset = co64.table[stco_i - 1].offset;
    }

    /* skipping invalid entries */
    while (stsc_i < stsc.total_entries - 1) {
      if (stsc.table[stsc_i + 1].chunk - stsc.table[stsc_i].chunk <= 0) {
        stsc_i++;
      } else {
        break;
      }
    }

    for (i = 0; i < stsc.table[stsc_i].samples; i++) {
      frag.pEntryArray[samp_i].stPosition = (size_t)nSampleOffset;
      nSampleOffset += frag.pEntryArray[samp_i].uiSize;
      samp_i++;
      if (samp_i >= (Ipp32u)frag.iNOfEntries)
        break;
    }

    stco_i++;
    if (stsc_i < stsc.total_entries - 1 &&
        stco_i == stsc.table[stsc_i + 1].chunk) {
        stsc_i++;
    }

  }

}

void MP4Splitter::FillSampleTimeStamp(T_trak_data *trak,
                                      IndexFragment &frag)
{
  // decoding time to sample box
  T_stts_data& stts = trak->mdia.minf.stbl.stts;
  // composition time to sample box
  T_ctts_data& ctts = trak->mdia.minf.stbl.ctts;
  Ipp32s nTimeScale = trak->mdia.mdhd.time_scale;

  if (nTimeScale == 0) {
    frag.iNOfEntries = 0;
    return;
  }

  Ipp32u i;
  Ipp32u stts_i;
  Ipp32u samp_i = 0;
  Ipp32u ctts_i = 0;
  Ipp32u nTimeStamp = 0;

  for (stts_i = 0; stts_i < stts.total_entries; stts_i++) {
    for (i = 0; i < stts.table[stts_i].sample_count; i++) {
      if (ctts.total_entries == 0) { // composition time stamp not present
        frag.pEntryArray[samp_i].dPts = (Ipp64f)nTimeStamp / nTimeScale;
        frag.pEntryArray[samp_i].dDts = -1.0;
      } else {
        frag.pEntryArray[samp_i].dPts =
        frag.pEntryArray[samp_i].dDts = (Ipp64f)nTimeStamp;
      }
      nTimeStamp += stts.table[stts_i].sample_duration;
      samp_i++;
      if (samp_i >= (Ipp32u)frag.iNOfEntries)
        break;
    }
  }

  if (ctts.total_entries == 0) {
    if (samp_i < (Ipp32u)frag.iNOfEntries) {
      frag.iNOfEntries = samp_i;
    }
    return;
  }

  samp_i = 0;

  for (ctts_i = 0; ctts_i < ctts.total_entries; ctts_i++) {
    for (i = 0; i < ctts.table[ctts_i].sample_count; i++) {
      frag.pEntryArray[samp_i].dPts += ctts.table[ctts_i].sample_offset;
      frag.pEntryArray[samp_i].dPts /= nTimeScale;
      frag.pEntryArray[samp_i].dDts /= nTimeScale;
      samp_i++;
      if (samp_i >= (Ipp32u)frag.iNOfEntries)
        return;
    }
  }

  if (samp_i < (Ipp32u)frag.iNOfEntries)
    frag.iNOfEntries = samp_i;

}

Status MP4Splitter::AddMoovToIndex(Ipp32u iES)
{
  IndexFragment frag;
  T_trak_data *trak = m_headerMPEG4.moov.trak[iES];
  Ipp32u nEntries = trak->mdia.minf.stbl.stsz.total_entries;

  frag.iNOfEntries = nEntries;
  if (frag.iNOfEntries <= 0)
    return UMC_OK;
  frag.pEntryArray = new IndexEntry[nEntries];
  if (NULL == frag.pEntryArray)
      return UMC_ERR_ALLOC;

  FillSampleSizeAndType(trak, frag);
  FillSamplePos(trak, frag);
  FillSampleTimeStamp(trak, frag);

  m_pLastPTS[iES] = frag.pEntryArray[frag.iNOfEntries-1].GetTimeStamp();

  return m_pTrackIndex[iES].Add(frag);
}

Status MP4Splitter::AddMoofRunToIndex(Ipp32u iES, T_trex_data *pTrex, T_traf *pTraf,
                                      T_trun *pTrun, Ipp64u &nBaseOffset)
{
  IndexFragment frag;
  Ipp32u i;

  Ipp64f rTimeScale = m_headerMPEG4.moov.trak[iES]->mdia.mdhd.time_scale;
  if (rTimeScale <= 0)
    return UMC_ERR_FAILED;

  frag.iNOfEntries = pTrun->sample_count;
  frag.pEntryArray = new IndexEntry[pTrun->sample_count];
  if (NULL == frag.pEntryArray)
      return UMC_ERR_ALLOC;

  for (i = 0; i < pTrun->sample_count; i++) {
    if (m_bFlagStop)
      return UMC_OK;

    // sample size present in trun
    if (pTrun->flags & SAMPLE_SIZE_PRESENT) {
      frag.pEntryArray[i].uiSize = pTrun->table_trun[i].sample_size;
    }
    // sample size present in track fragment header box (tfhd)
    else if (pTraf->tfhd.flags & DEFAULT_SAMPLE_SIZE_PRESENT) {
      frag.pEntryArray[i].uiSize = pTraf->tfhd.default_sample_size;
    } else {
      // default sample size in Track Extends box
      frag.pEntryArray[i].uiSize = pTrex->default_sample_size;
    }

    frag.pEntryArray[i].stPosition = (size_t)nBaseOffset;
    // update base offset for next sample
    nBaseOffset = frag.pEntryArray[i].stPosition + frag.pEntryArray[i].uiSize;


    Ipp32u duration = 0;
    // sample duration present in Track Fragment Run box
    if (pTrun->flags & SAMPLE_DURATION_PRESENT) {
      duration = pTrun->table_trun[i].sample_duration;
    }
    // sample duration present in Track Fragment Header box
    else if (pTraf->tfhd.flags & DEFAULT_SAMPLE_DURATION_PRESENT) {
      duration = pTraf->tfhd.default_sample_duration;
    } else {
      duration = pTrex->default_sample_duration;
    }

    // sample-composition-time-offset-present
    if (pTrun->flags & SAMPLE_COMPOSITION_TIME_OFFSETS_PRESENT) {
        duration += pTrun->table_trun[i].sample_composition_time_offset;
    }

    if (rTimeScale) {
      frag.pEntryArray[i].dPts = duration/rTimeScale;
    }

    frag.pEntryArray[i].dPts += m_pLastPTS[iES];
    m_pLastPTS[iES] = frag.pEntryArray[i].GetTimeStamp();

  }

  return m_pTrackIndex[iES].Add(frag);
}

Ipp32u MP4Splitter::InitMoofThreadCallback(void* pParam)
{
  VM_ASSERT(NULL != pParam);
  UMC::MP4Splitter* pThis = (MP4Splitter*)pParam;
  pThis->InitMoof();
  return 0;
}

Status MP4Splitter::MapTrafIDToTrackID (Ipp32u trafID, Ipp32u &nTrack)
{
  Ipp32u i;

  for (i = 0; i < m_pInfo->m_nOfTracks; i++) {
    if (m_pInfo->m_ppTrackInfo[i]->m_PID == trafID) {
      nTrack = i;
      return UMC_OK;
    }
  }
  return UMC_ERR_FAILED;
}

/* reads the next fragment and adds it to the index */
Status MP4Splitter::InitMoof()
{
  Ipp32u iES, jES;
  Status umcRes = CheckInit();

  if (umcRes != UMC_OK)
    return umcRes;

  while (!m_bFlagStop) {
    umcRes = SelectNextFragment();
    UMC_CHECK_STATUS(umcRes)

    Ipp64u nBaseOffset = 0;
    for (iES = 0; iES < m_headerMPEG4.moof.total_tracks; iES++) {

      // track fragment
      T_traf* pTraf = m_headerMPEG4.moof.traf[iES];
      if (pTraf == NULL)
        continue;

      // track extend box
      T_trex_data* pTrex = NULL;
      // finding a corresponding trex box based on track ID
      for (jES = 0; jES < m_headerMPEG4.moov.mvex.total_tracks; jES++) {
        if (m_headerMPEG4.moov.mvex.trex[jES] == NULL)
          continue;

        if (pTraf->tfhd.track_ID == m_headerMPEG4.moov.mvex.trex[jES]->track_ID) {
          pTrex = m_headerMPEG4.moov.mvex.trex[jES];
          break;
        }
      }
      if (pTrex == NULL)
          continue;

      if (pTraf->tfhd.flags & BASE_DATA_OFFSET_PRESENT) {
        // base data offset present
        nBaseOffset = pTraf->tfhd.base_data_offset;
      }

      if ((iES == 0) && (nBaseOffset == 0)) {
        // first byte after enclosing moof box;
        nBaseOffset = m_headerMPEG4.moof.end;

        // offset by 8 bytes (compact mdat box) or 16 bytes (large size)
        if (m_headerMPEG4.data.is_large_size) {
          nBaseOffset += 16;
        } else {

⌨️ 快捷键说明

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