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

📄 umc_mpeg2_dec.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) 2003-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"
#if defined (UMC_ENABLE_MPEG2_VIDEO_DECODER)

#include "vm_sys_info.h"
#include "vm_time.h"
#include "umc_video_data.h"
#include "umc_video_processing.h"
#include "umc_memory_allocator.h"
#include "umc_mpeg2_dec_base.h"
#include "umc_mpeg2_dec.h"
#include "umc_mpeg2_dec_tbl.h"

using namespace UMC;

#define ALIGN_VALUE  16
namespace UMC
{
VideoDecoder *CreateMPEG2Decoder() { return new MPEG2VideoDecoder(); }
}

static IppStatus mp2_HuffmanTableInitAlloc(Ipp32s *tbl, Ipp32s bits_table0, mp2_VLCTable *vlc)
{
  Ipp32s *ptbl;
  Ipp16s bad_value = 0;
  Ipp32s max_bits;
  Ipp32s num_tbl;
  Ipp32s i, j, k, m, n;
  Ipp32s bits, code, value;
  Ipp32s bits0, bits1;
  Ipp32s min_value, max_value, spec_value;
  Ipp32s min_code0, min_code1;
  Ipp32s max_code0, max_code1;
  Ipp32s prefix_code1 = -1;
  Ipp32s bits_table1 = 0;
  Ipp32s *buffer = NULL;
  Ipp32s *codes;
  Ipp32s *cbits;
  Ipp32s *values;
  Ipp16s *table0 = NULL;
  Ipp16s *table1 = NULL;

  /* get number of entries (n) */
  max_bits = *tbl++;
  num_tbl = *tbl++;
  for (i = 0; i < num_tbl; i++) {
    *tbl++;
  }
  n = 0;
  ptbl = tbl;
  for (bits = 1; bits <= max_bits; bits++) {
    m = *ptbl;
    if (m < 0) break;
    n += m;
    ptbl += 2*m + 1;
  }

  /* alloc internal table */
  buffer = new Ipp32s[3*n];
  if (!buffer) return ippStsErr;
  codes = buffer;
  cbits = buffer + n;
  values = buffer + 2*n;

  /* read VLC to internal table */
  min_value = 0x7fffffff;
  max_value = 0;
  spec_value = 0;
  ptbl = tbl;
  k = 0;
  for (bits = 1; bits <= max_bits; bits++) {
    if (*ptbl < 0) break;
    m = *ptbl++;
    for (i = 0; i < m; i++) {
      code = *ptbl++;
      value = *ptbl++;
      code &= ((1 << bits) - 1);
      if (value < min_value) min_value = value;
      if (value > max_value) {
        if (!spec_value && value >= 0xffff) {
          spec_value = value;
        } else {
          max_value = value;
        }
      }
      codes[k] = code << (30 - bits);
      cbits[k] = bits;
      values[k] = value;
      k++;
    }
  }

  if (!bits_table0) {
    bits_table0 = max_bits;
    bits_table1 = 0;
    vlc->threshold_table0 = 0;
  }
  bits0 = bits_table0;
  //for (bits0 = 1; bits0 < max_bits; bits0++)
  if (bits0 > 0 && bits0 < max_bits) {
    min_code0 = min_code1 = 0x7fffffff;
    max_code0 = max_code1 = 0;
    for (i = 0; i < n; i++) {
      code = codes[i];
      bits = cbits[i];
      if (bits <= bits0) {
        if (code > max_code0) max_code0 = code;
        if (code < min_code0) min_code0 = code;
      } else {
        if (code > max_code1) max_code1 = code;
        if (code < min_code1) min_code1 = code;
      }
    }
    if ((max_code0 < min_code1) || (max_code1 < min_code0)) {
      for (j = 0; j < 29; j++) {
        if ((min_code1 ^ max_code1) & (1 << (29 - j))) break;
      }
      bits1 = max_bits - j;
      if (bits0 == bits_table0) {
        bits_table1 = bits1;
        prefix_code1 = min_code1 >> (30 - bits0);
        vlc->threshold_table0 = min_code0 >> (30 - max_bits);
      }
    }
  }

  if (bits_table0 > 0 && bits_table0 < max_bits && !bits_table1) {
    if (buffer) delete[] buffer;
    return ippStsErr;
  }

  bad_value = (bad_value << 8) | VLC_BAD;

  table0 = ippsMalloc_16s(1 << bits_table0);
  ippsSet_16s(bad_value, table0, 1 << bits_table0);
  if (bits_table1) {
    table1 = ippsMalloc_16s(1 << bits_table1);
    ippsSet_16s(bad_value, table1, 1 << bits_table1);
  }
  for (i = 0; i < n; i++) {
    code = codes[i];
    bits = cbits[i];
    value = values[i];
    if (bits <= bits_table0) {
      code = code >> (30 - bits_table0);
      for (j = 0; j < (1 << (bits_table0 - bits)); j++) {
        table0[code + j] = (Ipp16s)((value << 8) | bits);
      }
    } else {
      code = code >> (30 - max_bits);
      code = code & ((1 << bits_table1) - 1);
      for (j = 0; j < (1 << (max_bits - bits)); j++) {
        table1[code + j] = (Ipp16s)((value << 8) | bits);
      }
    }
  }

  if (bits_table1) { // fill VLC_NEXTTABLE
    if (prefix_code1 == -1) {
      if (buffer) delete[] buffer;
      return ippStsErr;
    }
    bad_value = (bad_value &~ 255) | VLC_NEXTTABLE;
    for (j = 0; j < (1 << ((bits_table0 - (max_bits - bits_table1)))); j++) {
      table0[prefix_code1 + j] = bad_value;
    }
  }

  vlc->max_bits = max_bits;
  vlc->bits_table0 = bits_table0;
  vlc->bits_table1 = bits_table1;
  vlc->table0 = table0;
  vlc->table1 = table1;

  if (buffer) delete[] buffer;
  return ippStsNoErr;
}

static void mp2_HuffmanTableFree(mp2_VLCTable *vlc) {
  if (vlc->table0) {
    ippsFree(vlc->table0);
    vlc->table0 = NULL;
  }
  if (vlc->table1) {
    ippsFree(vlc->table1);
    vlc->table1 = NULL;
  }
}

bool MPEG2VideoDecoderBase::InitTables()
{
  if (ippStsNoErr != mp2_HuffmanTableInitAlloc(MBAdressing, 5, &vlcMBAdressing))
    return false;

  if (ippStsNoErr != mp2_HuffmanTableInitAlloc(IMBType, 0, &vlcMBType[0]))
    return false;

  if (ippStsNoErr != mp2_HuffmanTableInitAlloc(PMBType, 0, &vlcMBType[1]))
    return false;

  if (ippStsNoErr != mp2_HuffmanTableInitAlloc(BMBType, 0, &vlcMBType[2]))
    return false;

  if (ippStsNoErr != mp2_HuffmanTableInitAlloc(MBPattern, 5, &vlcMBPattern))
    return false;

  if (ippStsNoErr != mp2_HuffmanTableInitAlloc(MotionVector, 5, &vlcMotionVector))
    return false;

  return true;
}


bool MPEG2VideoDecoderBase::DeleteTables()
{
  // release tools
    if(Video)
    {
        ippsFree(Video[0]);
        Video[0] = NULL;
        ippsFree(Video);
        Video = NULL;
    }

    if(frame_buffer.ptr_context_data)
    {
        //ippsFree(frame_buffer.ptr_context_data);
      m_pMemoryAllocator->Free(frame_buffer.mid_context_data);
      frame_buffer.ptr_context_data = NULL;
    }
    if ( m_bOwnAllocator && m_pMemoryAllocator !=0 ) {
      delete m_pMemoryAllocator;
      m_bOwnAllocator = false;
      m_pMemoryAllocator = 0;
    }

    // release tables
    mp2_HuffmanTableFree(&vlcMBAdressing);
    mp2_HuffmanTableFree(&vlcMBType[0]);
    mp2_HuffmanTableFree(&vlcMBType[1]);
    mp2_HuffmanTableFree(&vlcMBType[2]);
    mp2_HuffmanTableFree(&vlcMBPattern);
    mp2_HuffmanTableFree(&vlcMotionVector);

    return UMC_OK;
}

Ipp32u VM_THREAD_CALLCONVENTION MPEG2VideoDecoderBase::ThreadWorkingRoutine(void *lpv)
{
    THREAD_ID *             lpThreadId;
    MPEG2VideoDecoderBase * lpOwner;

    // check error(s)
    if (NULL == lpv)
        return 0xbaadf00d;

    lpThreadId  = reinterpret_cast<THREAD_ID *> (lpv);
    lpOwner     = reinterpret_cast<MPEG2VideoDecoderBase *> (lpThreadId->m_lpOwner);

    // wait for start
    vm_event_wait(lpOwner->m_lpStartEvent + lpThreadId->m_nNumber);

    while (VM_TIMEOUT == vm_event_timed_wait(&(lpOwner->m_lpQuit[lpThreadId->m_nNumber]), 0))
    {
        lpOwner->DecodeSlices(lpThreadId->m_nNumber);
        // set finish
        vm_event_signal(lpOwner->m_lpStopEvent + lpThreadId->m_nNumber);

        //vm_time_sleep(0);

        // wait for start
        vm_event_wait(lpOwner->m_lpStartEvent + lpThreadId->m_nNumber);
    }

    return lpThreadId->m_nNumber;

}


Status MPEG2VideoDecoderBase::ThreadingSetup(Ipp32s maxThreads)
{
    Ipp32s i;
    Ipp32s aligned_size;


    if(maxThreads == 0)
        m_nNumberOfThreads = vm_sys_info_get_cpu_num();
    else
        m_nNumberOfThreads = maxThreads;

    if (0 >= m_nNumberOfThreads)
        m_nNumberOfThreads = 1;
    else if (8 < m_nNumberOfThreads)
        m_nNumberOfThreads = 8;

    Video = (IppVideoContext**)ippsMalloc_8u(m_nNumberOfThreads*sizeof(IppVideoContext*));
    if(!Video) return UMC_ERR_ALLOC;

    aligned_size = (Ipp32s)((sizeof(IppVideoContext) + 15) &~ 15);

    Video[0] = (IppVideoContext*)ippsMalloc_8u(m_nNumberOfThreads*aligned_size);
    if(!Video[0]) return UMC_ERR_ALLOC;
    memset(Video[0], 0, m_nNumberOfThreads*aligned_size);
    for(i = 0; i < m_nNumberOfThreads; i++)
    {
      if (i)
        Video[i] = (IppVideoContext*)((Ipp8u *)Video[0] + i*aligned_size);

      // Intra&inter spec
      memset(&Video[i]->decodeIntraSpec, 0, sizeof(IppiDecodeIntraSpec_MPEG2));
      memset(&Video[i]->decodeInterSpec, 0, sizeof(IppiDecodeInterSpec_MPEG2));
      ippiDecodeInterInit_MPEG2(NULL, IPPVC_MPEG1_STREAM, &Video[i]->decodeInterSpec);
      Video[i]->decodeInterSpecChroma = Video[i]->decodeInterSpec;
      Video[i]->decodeInterSpec.idxLastNonZero = 63;
      Video[i]->decodeIntraSpec.intraVLCFormat = PictureHeader.intra_vlc_format;
      Video[i]->decodeIntraSpec.intraShiftDC = PictureHeader.curr_intra_dc_multi;
    }

    // create threading tools
    if (1 < m_nNumberOfThreads)
    {
        // create exit event(s)
        m_lpQuit = new vm_event[m_nNumberOfThreads];
        if (NULL == m_lpQuit)
            return UMC_ERR_ALLOC;

        for (i = 1; i < m_nNumberOfThreads; i++)
        {
            vm_event_set_invalid(m_lpQuit + i);
            if (VM_OK != vm_event_init(m_lpQuit + i, 0, 0))
                return UMC_ERR_INIT;
        }

        // create start event(s)
        m_lpStartEvent = new vm_event[m_nNumberOfThreads];
        if (NULL == m_lpStartEvent)
            return UMC_ERR_ALLOC;

        for (i = 1; i < m_nNumberOfThreads; i++)
        {
            vm_event_set_invalid(m_lpStartEvent + i);
            if (VM_OK != vm_event_init(m_lpStartEvent + i, 0, 0))
                return UMC_ERR_INIT;
        }

        // create stop event(s)
        m_lpStopEvent = new vm_event[m_nNumberOfThreads];
        if (NULL == m_lpStopEvent)
            return UMC_ERR_ALLOC;
        for (i = 1;i < m_nNumberOfThreads;i += 1)
        {
            vm_event_set_invalid(m_lpStopEvent + i);
            if (VM_OK != vm_event_init(m_lpStopEvent + i, 0, 0))
                return UMC_ERR_INIT;
        }

        // allocate thread ID(s)
        m_lpThreadsID = new THREAD_ID[m_nNumberOfThreads];
        if (NULL == m_lpThreadsID)
            return UMC_ERR_ALLOC;

        // starting thread(s)
        m_lpThreads = new vm_thread[m_nNumberOfThreads];
        if (NULL == m_lpThreads)
            return UMC_ERR_ALLOC;

        for (i = 1;i < m_nNumberOfThreads;i += 1)
        {
            vm_thread_set_invalid(m_lpThreads + i);
            m_lpThreadsID[i].m_nNumber = i;
            m_lpThreadsID[i].m_lpOwner = this;
            if (0 == vm_thread_create(m_lpThreads + i, ThreadWorkingRoutine, m_lpThreadsID + i))
                return UMC_ERR_INIT;
        }
    }

    m_nNumberOfAllocatedThreads = m_nNumberOfThreads;

    return UMC_OK;
}


Status MPEG2VideoDecoderBase::Init(BaseCodecParams *pInit)
{
    MediaData *data;
    Status ret;

    VideoDecoderParams *init = DynamicCast<VideoDecoderParams, BaseCodecParams>(pInit);
    if(!init)
        return UMC_ERR_INIT;

    data = init->m_pData;
    if (data != 0 && data->GetDataSize() == 0)
      data = 0;

    // checks or create memory allocator;
    ret = BaseCodec::Init(pInit);
    if(ret != UMC_OK)
      return ret;

    if((init->lFlags & FLAG_VDEC_4BYTE_ACCESS) != 0)
      return UMC_ERR_UNSUPPORTED;

    Reset();

    m_ClipInfo = init->info;
    m_lFlags = init->lFlags;
    m_PostProcessing = init->pPostProcessing;

    // creates thread's structures (Video[])
    if(UMC_OK != ThreadingSetup(init->numThreads))
        return UMC_ERR_ALLOC;

    if (data != 0) {
      PrepareBuffer(data);

      // get sequence header start code
      // search while not found or EOD
      if(UMC_OK != FindSequenceHeader(Video[0]))
        return (UMC_ERR_SYNC);

      if(UMC_OK != DecodeSequenceHeader(Video[0]))
          return (UMC_ERR_INVALID_STREAM);

      FlushBuffer(data, false);
    } else { // get stream parameters from sVideoInfo
      if(UMC_OK != DecodeSequenceHeader( 0 ))
        return (UMC_ERR_INVALID_PARAMS);
    }

    m_ccCurrData.SetBufferPointer(NULL, 0);
    m_pCCData = new SampleBuffer;
    if(m_pCCData)
    {
        Status res = UMC_OK;
        MediaBufferParams initPar;
        initPar.m_prefInputBufferSize = initPar.m_prefOutputBufferSize = 1024;
        initPar.m_numberOfFrames = 20;
        initPar.m_pMemoryAllocator = m_pMemoryAllocator;

        res = m_pCCData->Init(&initPar);
        if(res != UMC_OK)
        {
            m_pCCData->Close();
            delete m_pCCData;
            m_pCCData = NULL;
        }
    }

    if (false == InitTables())
        return UMC_ERR_INIT;

    sequenceHeader.frame_count    = 0;
    sequenceHeader.stream_time    = 0;
    sequenceHeader.is_skipped_b   = 0;

    sequenceHeader.num_of_skipped   = 0;
    sequenceHeader.bdied            = 0;

    frame_buffer.prev_index =  0;
    frame_buffer.curr_index =  0;
    frame_buffer.next_index =  1;

⌨️ 快捷键说明

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