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

📄 umc_spl_base.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
字号:
/*//////////////////////////////////////////////////////////////////////////////
//
//                  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) 2007 Intel Corporation. All Rights Reserved.
//
*/


#include <ipps.h>
#include "ippdefs.h"
#include "vm_semaphore.h"
#include "vm_thread.h"
#include "vm_types.h"
#include "vm_time.h"
#include "bstream.h"
#include "umc_media_data.h"
#include "umc_cyclic_buffer.h"

#include "umc_spl_base.h"

enum
{
#ifndef _WIN32_WCE
    TIME_TO_SLEEP = 5,
#else
    TIME_TO_SLEEP = 0,
#endif
};

namespace UMC
{

struct ReadESThreadParam
{
    Ipp32s        uiPin;
    SplitterBase* pThis;
};


SplitterBase::SplitterBase():
    m_pDataReader(NULL),
    m_ReaderMutex(),
    m_pTrackIndex(NULL),
    m_ppMediaBuffer(NULL),
    m_ppLockedFrame(NULL),
    m_bFlagStop(true),
    m_pReadESThread(NULL),
    m_pInfo(NULL),
    m_pReader(NULL)
{
}

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

Status SplitterBase::Init(SplitterParams &init_params)
{
  Status umcRes;
  m_pReader = init_params.m_pDataReader;
  umcRes = m_ReaderMutex.Init();
  return umcRes;
}

Status SplitterBase::Close()
{
  StopSplitter();
  m_pReader = NULL;
  m_ReaderMutex.Close();
  return UMC_OK;
}

Status SplitterBase::StopSplitter()
{
  if (m_bFlagStop)
    return UMC_OK;

  if (m_pReader == NULL)
    return UMC_ERR_NOT_INITIALIZED;

  Status umcRes;
  IndexEntry entry;
  Ipp32u i;

  m_bFlagStop = true;
  for (i = 0; i < m_pInfo->m_nOfTracks; i++) {
    if (vm_thread_is_valid(&m_pReadESThread[i])) {
      vm_thread_wait(&m_pReadESThread[i]);
      vm_thread_close(&m_pReadESThread[i]);
      vm_thread_set_invalid(&m_pReadESThread[i]);
    }
    if (m_ppMediaBuffer[i]) {
      umcRes = m_ppMediaBuffer[i]->Reset();
      UMC_CHECK_STATUS(umcRes)
    }
    if (m_ppLockedFrame[i]) {
      umcRes = m_ppLockedFrame[i]->Reset();
      UMC_CHECK_STATUS(umcRes)
    }
  }

  return UMC_OK;
}

Status SplitterBase::GetInfo(SplitterInfo** ppInfo)
{
  ppInfo[0] = m_pInfo;
  return UMC_OK;
}

void SplitterBase::ReadES(Ipp32u uiPin)
{
  Status umcRes;
  TrackIndex *pIndex = &m_pTrackIndex[uiPin];
  IndexEntry m_Frame;
  MediaData in;
  int i;

  if (m_pInfo->m_dRate == 0)
    return;

  umcRes = pIndex->Get(m_Frame);
  while (umcRes == UMC_OK && !m_bFlagStop) {

    umcRes = m_ppMediaBuffer[uiPin]->LockInputBuffer(&in);
    while (umcRes == UMC_ERR_NOT_ENOUGH_BUFFER) {
      if (m_bFlagStop) {
        return;
      }
      vm_time_sleep(TIME_TO_SLEEP);
      umcRes = m_ppMediaBuffer[uiPin]->LockInputBuffer(&in);
    }

    m_ReaderMutex.Lock();
    m_pReader->SetPosition((Ipp64u)m_Frame.stPosition);
    m_pReader->GetData(in.GetDataPointer(), &m_Frame.uiSize);
    m_ReaderMutex.Unlock();

    in.SetDataSize(m_Frame.uiSize);
    in.SetTime(m_Frame.dPts, m_Frame.dDts);
    in.SetFrameType(NONE_PICTURE);
    if (TRACK_ANY_VIDEO & m_pInfo->m_ppTrackInfo[uiPin]->m_Type)
        in.SetFrameType((FrameType)m_Frame.uiFlags);

    m_ppMediaBuffer[uiPin]->UnLockInputBuffer(&in);
    vm_time_sleep(0);

    if (m_pInfo->m_dRate == 1) {
      umcRes = pIndex->Next(m_Frame);
    } else if (m_pInfo->m_dRate > 0) {
      for (i = 0; i < m_pInfo->m_dRate; i++) {
        umcRes = pIndex->Next(m_Frame);
        if (umcRes != UMC_OK)
          break;
      }
      if (umcRes == UMC_OK)
        umcRes = pIndex->NextKey(m_Frame);
    } else {  /*** m_pInfo->m_dRate < 0 ***/
      for (i = 0; i < -m_pInfo->m_dRate; i++) {
        umcRes = pIndex->Prev(m_Frame);
        if (umcRes != UMC_OK)
          break;
      }
      if (umcRes == UMC_OK)
        umcRes = pIndex->PrevKey(m_Frame);
    }

  }

  if (umcRes != UMC_OK) {
    m_ppMediaBuffer[uiPin]->UnLockInputBuffer(NULL, UMC_ERR_END_OF_STREAM);
  }

}

Ipp32u SplitterBase::ReadESThreadCallback(void* ptr)
{
  VM_ASSERT(NULL != ptr);
  ReadESThreadParam* m_pParam = (ReadESThreadParam*)ptr;

  m_pParam->pThis->ReadES(m_pParam->uiPin);
  delete ptr;
  return 0;
}


Status SplitterBase::Run()
{
  if (!m_bFlagStop)
      return UMC_OK;

  Ipp32u i;
  int res;

  m_bFlagStop = false;
  for (i = 0; i < m_pInfo->m_nOfTracks; i++) {
    if (((m_pInfo->m_dRate == 1.0) ||
        (m_pInfo->m_ppTrackInfo[i]->m_Type & TRACK_ANY_VIDEO)) &&
        (m_pInfo->m_ppTrackInfo[i]->m_isSelected)) {
      ReadESThreadParam* m_pESParam = new ReadESThreadParam;
      m_pESParam->uiPin = i;
      m_pESParam->pThis = this;

      res = vm_thread_create(&m_pReadESThread[i], (vm_thread_callback)ReadESThreadCallback, (void *)m_pESParam);
      if (res != 1) {
        return UMC_ERR_FAILED;
      }
    }
  }

  return UMC_OK;
}

Status SplitterBase::GetNextData(MediaData* data, Ipp32u nTrack)
{
    Status umcRes;

    if ((nTrack < 0) || (nTrack > m_pInfo->m_nOfTracks))
        return UMC_ERR_FAILED;

    if (!m_ppMediaBuffer[nTrack] || !m_pInfo->m_ppTrackInfo[nTrack]->m_isSelected)
        return UMC_ERR_FAILED;

    if (m_ppLockedFrame[nTrack]->GetDataSize()) {
      m_ppLockedFrame[nTrack]->SetDataSize(0);
      m_ppMediaBuffer[nTrack]->UnLockOutputBuffer(m_ppLockedFrame[nTrack]);
    }

    umcRes = m_ppMediaBuffer[nTrack]->LockOutputBuffer(data);
    if (umcRes == UMC_OK) {
      *(m_ppLockedFrame[nTrack]) = *data;
    }

    return umcRes;
}

Status SplitterBase::CheckNextData(MediaData* data, Ipp32u nTrack)
{
    Status umcRes;

    if ((nTrack < 0) || (nTrack > m_pInfo->m_nOfTracks))
        return UMC_ERR_FAILED;

    if (!m_ppMediaBuffer[nTrack] || !m_pInfo->m_ppTrackInfo[nTrack]->m_isSelected)
        return UMC_ERR_FAILED;

    umcRes = m_ppMediaBuffer[nTrack]->LockOutputBuffer(data);
    if (umcRes == UMC_OK) {
      // this is to prevent END_OF_STREAM occasionally returned by SampleBuffer
      m_ppMediaBuffer[nTrack]->UnLockOutputBuffer(data);
    }

    return umcRes;
}

Status SplitterBase::SetTimePosition(Ipp64f position)
{
  IndexEntry entry;
  Ipp32u i;

  StopSplitter(); /* close read threads and reset buffers */

  // tune up time position using one of video tracks
  for (i = 0; i < m_pInfo->m_nOfTracks; i++) {
    if (m_pInfo->m_ppTrackInfo[i]->m_Type & TRACK_ANY_VIDEO &&
        m_pInfo->m_ppTrackInfo[i]->m_isSelected) {
      m_pTrackIndex[i].First(entry);
      // add origin time stamp
      position += entry.GetTimeStamp();
      m_pTrackIndex[i].Get(entry, position);
      if (I_PICTURE != entry.uiFlags)
        m_pTrackIndex[i].PrevKey(entry);
      // save time stamp of nearest previous key frame
      position = entry.GetTimeStamp();
      break;
    }
  }

  // position all tracks to one time position
  for (i = 0; i < m_pInfo->m_nOfTracks; i++)
    m_pTrackIndex[i].Get(entry, position);

  return UMC_OK;
}

Status SplitterBase::GetTimePosition(Ipp64f& position)
{
  IndexEntry entry;
  Ipp32u i;

  /* get TimePos of the first selected video track */
  for (i = 0; i < m_pInfo->m_nOfTracks; i++) {
    if (m_pInfo->m_ppTrackInfo[i]->m_Type & TRACK_ANY_VIDEO &&
        m_pInfo->m_ppTrackInfo[i]->m_isSelected) {
      m_pTrackIndex[i].Get(entry);
      break;
    }
  }

  /* if no video get TimePos of the first selected track */
  if (i == m_pInfo->m_nOfTracks) {
    for (i = 0; i < m_pInfo->m_nOfTracks; i++) {
      if (m_pInfo->m_ppTrackInfo[i]->m_isSelected) {
        m_pTrackIndex[i].Get(entry);
        break;
      }
    }
  }

  position = entry.GetTimeStamp();
  return UMC_OK;
}

Status SplitterBase::SetRate(Ipp64f rate)
{
  if (m_pReader == NULL)
    return UMC_ERR_NOT_INITIALIZED;

  m_pInfo->m_dRate = (Ipp32s)rate;
  StopSplitter();
  return UMC_OK;
}

} // namespace UMC

⌨️ 快捷键说明

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