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

📄 umc_mpeg2_enc.cpp

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

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

#include "ipps.h"
#include "umc_mpeg2_enc_defs.h"
#include "vm_time.h"
#include "vm_sys_info.h"

using namespace UMC;

static const Ipp64f ratetab[8]=
  {24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0};

MPEG2VideoEncoderBase::MPEG2VideoEncoderBase ()
{
  m_Inited = 0;
  picture_structure = FRAME_PICTURE;
  top_field_first = 0; // 1 when !progressive
  repeat_first_field = 0;
  vbv_delay   = 19887;
  onlyIFrames = 0;
  encodeInfo.lFlags = FLAG_VENC_REORDER;
  frame_loader = NULL;

  pMBInfo = 0;
  threadsAllocated = 0;
  threadSpec = NULL;
  threads    = NULL;
  vlcTableB15 = 0;
  vlcTableB5c_e = 0;

  m_lpbReference = NULL;
  mid_Reference = MID_INVALID;
  pRotFrames[0] = RotatingFrames;
  pRotFrames[1] = RotatingFrames+2;

  tmpFrame_buf = NULL;
  mid_tmpFrame_buf = MID_INVALID;
  tmpFrame = NULL;

  VideoData_buff = NULL;
  frames_buff = NULL;
  is_frames_buff_locked = 0;
  mid_frames_buff = MID_INVALID;
  buff_size = 0;

  quantiser_scale_value = -1;
  intra_dc_precision = 0; // 8 bit
  varThreshold = 0;
  prqscale[0] = prqscale[1] = prqscale[2] = 0;
  prsize[0]   = prsize[1]   = prsize[2]   = 0;

  pMotionData = NULL;
  MotionDataCount = 0;
}

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

static Ipp32u VM_THREAD_CALLCONVENTION ThreadWorkingRoutine(void* ptr)
{
  threadInfo* th = (threadInfo*)ptr;

  for (;;) {
    // wait for start
    if (VM_OK != vm_event_wait(&th->start_event)) {
      vm_debug_trace(VM_DEBUG_PROGRESS, VM_STRING("ThreadWorkingRoutine result wait start_event\n"));
    }

    if (VM_TIMEOUT != vm_event_timed_wait(&th->quit_event, 0)) {
      break;
    }

    switch (th->m_lpOwner->picture_coding_type) {
    case I_PICTURE:
      th->m_lpOwner->encodeI(th->numTh);
      break;
    case P_PICTURE:
      th->m_lpOwner->encodeP(th->numTh);
      break;
    case B_PICTURE:
      th->m_lpOwner->encodeB(th->numTh);
      break;
    }

    if (VM_OK != vm_event_signal(&th->stop_event)) {
      vm_debug_trace(VM_DEBUG_PROGRESS, VM_STRING("ThreadWorkingRoutine result signal stop_event\n"));
    }

    //vm_time_sleep(0);
  }

  return 0;
}

Status MPEG2VideoEncoderBase::Init(BaseCodecParams *params)
{
  Ipp32s i, j;
  Ipp32s sizeChanged = !m_Inited;

  VideoEncoderParams *VideoParams = DynamicCast<VideoEncoderParams>(params);
  if(VideoParams != 0) { // at least VideoEncoder parameters
    MPEG2EncoderParams *info = DynamicCast<MPEG2EncoderParams>(params);
    if (VideoParams->info.clip_info.width <= 0 || VideoParams->info.clip_info.height <= 0) {
      return UMC_ERR_INVALID_PARAMS;
    }
    // trying to support size change
    sizeChanged = sizeChanged ||
      (VideoParams->info.clip_info.width != encodeInfo.info.clip_info.width) ||
      (VideoParams->info.clip_info.height != encodeInfo.info.clip_info.height);
    // good to have more checks before overwriting
    if(NULL != info) { // Mpeg2 encoder parameters
      // trying to support chroma_format change
      sizeChanged = sizeChanged ||
        (info->info.color_format != encodeInfo.info.color_format);
      encodeInfo = *info;
    } else
      *(VideoEncoderParams*) &encodeInfo = *VideoParams;
  } else if (NULL != params) {
    *(BaseCodecParams*) &encodeInfo = *params;
  } else if (!m_Inited) { // 0 when initialized means Reset
    return UMC_ERR_NULL_PTR;
  }

  if(params == NULL) { // Reset or SetParams(0)
    m_FirstFrame = 1;
    B_count      = 0;
    closed_gop = 1;
    buff_ind = 0;
    num_btype = 0;
    num_new = -1;
    curr_gop = 0;
    return UMC_OK;
  }

  BaseCodec::Init(params); // to prepare allocator
  SetAspectRatio(encodeInfo.info.aspect_ratio_width, encodeInfo.info.aspect_ratio_height);

  // FrameRate to code and extensions and back to exact value
  if(UMC_OK != SetFrameRate(encodeInfo.info.framerate, encodeInfo.mpeg1))
  {
    vm_debug_trace(VM_DEBUG_WARNING, VM_STRING("invalid frame rate set to 30 fps\n"));
    frame_rate_code = 5;
    frame_rate_extension_n = 0;
    frame_rate_extension_d = 0;
    encodeInfo.info.framerate = 30;
  }
  encodeInfo.info.framerate = ratetab[frame_rate_code - 1]*(frame_rate_extension_n+1)/(frame_rate_extension_d+1);
  encodeInfo.Profile_and_Level_Checks();
  encodeInfo.RelationChecks();

#undef  VM_DEBUG_FUNC_NAME
#define VM_DEBUG_FUNC_NAME VM_STRING("Init")
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.numThreads);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.clip_info.width);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.clip_info.height);
  vm_debug_trace_f(VM_DEBUG_INFO, encodeInfo.info.framerate);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.bitrate);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.gopSize);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.IPDistance);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.profile);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.level);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.aspect_ratio_width);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.aspect_ratio_height);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.video_format);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.interlace_type);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.FieldPicture);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.info.color_format);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.frame_pred_frame_dct[0]);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.frame_pred_frame_dct[1]);
  vm_debug_trace_i(VM_DEBUG_INFO, encodeInfo.frame_pred_frame_dct[2]);
#undef  VM_DEBUG_FUNC_NAME
#define VM_DEBUG_FUNC_NAME NULL

  // allocate ranges, compute search ranges and f_code
  if (pMotionData && MotionDataCount < encodeInfo.IPDistance) {
    MP2_FREE(pMotionData);
    pMotionData = 0;
    MotionDataCount = 0;
  }
  if (pMotionData == 0) {
    pMotionData = MP2_ALLOC(MotionData, encodeInfo.IPDistance);
    if( !pMotionData )
      return UMC_ERR_ALLOC;
    MotionDataCount = encodeInfo.IPDistance;
  }
  for (i = 0; i < encodeInfo.IPDistance; i++) {
    for (j = 0; j < 2; j++) { // x/y
      if (i==0) { // P
        pMotionData[i].searchRange[0][j] = encodeInfo.rangeP[j];
        RANGE_TO_F_CODE(pMotionData[i].searchRange[0][j], pMotionData[i].f_code[0][j]);
        pMotionData[i].searchRange[0][j] = 4 << pMotionData[i].f_code[0][j];
        pMotionData[i].f_code[1][j] = 15;
        pMotionData[i].searchRange[1][j] = 0;
      } else { // B
        pMotionData[i].searchRange[0][j] =
          (encodeInfo.rangeB[0][0]*(encodeInfo.IPDistance-i) + encodeInfo.rangeB[1][0]*(i-1))/(encodeInfo.IPDistance-1);
        pMotionData[i].searchRange[1][j] =
          (encodeInfo.rangeB[1][0]*(encodeInfo.IPDistance-i) + encodeInfo.rangeB[0][0]*(i-1))/(encodeInfo.IPDistance-1);
        RANGE_TO_F_CODE(pMotionData[i].searchRange[0][j], pMotionData[i].f_code[0][j]);
        pMotionData[i].searchRange[0][j] = 4 << pMotionData[i].f_code[0][j];
        RANGE_TO_F_CODE(pMotionData[i].searchRange[1][j], pMotionData[i].f_code[1][j]);
        pMotionData[i].searchRange[1][j] = 4 << pMotionData[i].f_code[1][j];
      }
    }
  }

  if (encodeInfo.info.interlace_type == PROGRESSIVE ||
      encodeInfo.info.interlace_type == INTERLEAVED_BOTTOM_FIELD_FIRST)
    top_field_first = 0;
  else
    top_field_first = 1;

  if(!m_Inited) { // only first call
    DC_Tbl[0] = Y_DC_Tbl;
    DC_Tbl[1] = Cr_DC_Tbl;
    DC_Tbl[2] = Cr_DC_Tbl;
    ippiCreateRLEncodeTable(Table15, &vlcTableB15);
    ippiCreateRLEncodeTable(dct_coeff_next_RL, &vlcTableB5c_e);
    for(i=0; i<4; i++) {
      RotatingFrames[i] = new VideoData;
    }
  }

  // chroma format dependent
  BlkWidth_c = (encodeInfo.info.color_format != YUV444) ? 8 : 16;
  BlkStride_c = 16;//BlkWidth_c;
  BlkHeight_c = (encodeInfo.info.color_format == YUV420) ? 8 : 16;
  chroma_fld_flag = (encodeInfo.info.color_format == YUV420) ? 0 : 1;

  switch (encodeInfo.info.color_format) {
  case YUV420:
    block_count = 6;
    func_getdiff_frame_c = ippiGetDiff8x8_8u16s_C1;
    func_getdiff_field_c = ippiGetDiff8x4_8u16s_C1;
    func_getdiffB_frame_c = ippiGetDiff8x8B_8u16s_C1;
    func_getdiffB_field_c = ippiGetDiff8x4B_8u16s_C1;
    func_mc_frame_c = ippiMC8x8_8u_C1;
    func_mc_field_c = ippiMC8x4_8u_C1;
    func_mcB_frame_c = ippiMC8x8B_8u_C1;
    func_mcB_field_c = ippiMC8x4B_8u_C1;
    break;

  case YUV422:
    block_count = 8;
    func_getdiff_frame_c = ippiGetDiff8x16_8u16s_C1;
    func_getdiff_field_c = ippiGetDiff8x8_8u16s_C1;
    func_getdiffB_frame_c = ippiGetDiff8x16B_8u16s_C1;
    func_getdiffB_field_c = ippiGetDiff8x8B_8u16s_C1;
    func_mc_frame_c = ippiMC8x16_8u_C1;
    func_mc_field_c = ippiMC8x8_8u_C1;
    func_mcB_frame_c = ippiMC8x16B_8u_C1;
    func_mcB_field_c = ippiMC8x8B_8u_C1;
    break;

  case YUV444:
    block_count = 12;
    func_getdiff_frame_c = ippiGetDiff16x16_8u16s_C1;
    func_getdiff_field_c = ippiGetDiff16x8_8u16s_C1;
    func_getdiffB_frame_c = ippiGetDiff16x16B_8u16s_C1;
    func_getdiffB_field_c = ippiGetDiff16x8B_8u16s_C1;
    func_mc_frame_c = ippiMC16x16_8u_C1;
    func_mc_field_c = ippiMC16x8_8u_C1;
    func_mcB_frame_c = ippiMC16x16B_8u_C1;
    func_mcB_field_c = ippiMC16x8B_8u_C1;
    break;
  }

  for (i = 0; i < 4; i++) {
    frm_dct_step[i] = BlkStride_l*sizeof(Ipp16s);
    fld_dct_step[i] = 2*BlkStride_l*sizeof(Ipp16s);
  }
  for (i = 4; i < block_count; i++) {
    frm_dct_step[i] = BlkStride_c*sizeof(Ipp16s);
    fld_dct_step[i] = BlkStride_c*sizeof(Ipp16s) << chroma_fld_flag;
  }

  frm_diff_off[0] = 0;
  frm_diff_off[1] = 8;
  frm_diff_off[2] = BlkStride_l*8;
  frm_diff_off[3] = BlkStride_l*8 + 8;
  frm_diff_off[4] = OFF_U;
  frm_diff_off[5] = OFF_V;
  frm_diff_off[6] = OFF_U + BlkStride_c*8;
  frm_diff_off[7] = OFF_V + BlkStride_c*8;
  frm_diff_off[8] = OFF_U + 8;
  frm_diff_off[9] = OFF_V + 8;
  frm_diff_off[10] = OFF_U + BlkStride_c*8 + 8;
  frm_diff_off[11] = OFF_V + BlkStride_c*8 + 8;

  fld_diff_off[0] = 0;
  fld_diff_off[1] = 8;
  fld_diff_off[2] = BlkStride_l;
  fld_diff_off[3] = BlkStride_l + 8;
  fld_diff_off[4] = OFF_U;
  fld_diff_off[5] = OFF_V;
  fld_diff_off[6] = OFF_U + BlkStride_c;
  fld_diff_off[7] = OFF_V + BlkStride_c;
  fld_diff_off[8] = OFF_U + 8;
  fld_diff_off[9] = OFF_V + 8;
  fld_diff_off[10] = OFF_U + BlkStride_c + 8;
  fld_diff_off[11] = OFF_V + BlkStride_c + 8;

  // frame size dependent
  // macroblock aligned size
  MBcountH = (encodeInfo.info.clip_info.width + 15)/16;
  MBcountV = (encodeInfo.info.clip_info.height + 15)/16;
  if(encodeInfo.info.interlace_type != PROGRESSIVE) {
    MBcountV = (MBcountV + 1) & ~1;
  }
  MBcount = MBcountH * MBcountV;

  YFrameHSize = MBcountH * 16;
  YFrameVSize = MBcountV * 16;
  UVFrameHSize = (encodeInfo.info.color_format == YUV444) ? YFrameHSize : (YFrameHSize >> 1);
  UVFrameVSize = (encodeInfo.info.color_format == YUV420) ? (YFrameVSize >> 1) : YFrameVSize;
  YFrameSize = YFrameHSize*YFrameVSize;
  UVFrameSize = UVFrameHSize*UVFrameVSize;
  YUVFrameSize = YFrameSize + 2*UVFrameSize;
  encodeInfo.m_SuggestedInputSize = YUVFrameSize;

  block_offset_frm[0]  = 0;
  block_offset_frm[1]  = 8;
  block_offset_frm[2]  = 8*YFrameHSize;
  block_offset_frm[3]  = 8*YFrameHSize + 8;
  block_offset_frm[4]  = 0;
  block_offset_frm[5]  = 0;
  block_offset_frm[6]  = 8*UVFrameHSize;
  block_offset_frm[7]  = 8*UVFrameHSize;
  block_offset_frm[8]  = 8;
  block_offset_frm[9]  = 8;
  block_offset_frm[10] = 8*UVFrameHSize + 8;
  block_offset_frm[11] = 8*UVFrameHSize + 8;

  block_offset_fld[0]  = 0;
  block_offset_fld[1]  = 8;
  block_offset_fld[2]  = YFrameHSize;
  block_offset_fld[3]  = YFrameHSize + 8;
  block_offset_fld[4]  = 0;
  block_offset_fld[5]  = 0;
  block_offset_fld[6]  = UVFrameHSize;
  block_offset_fld[7]  = UVFrameHSize;
  block_offset_fld[8]  = 8;
  block_offset_fld[9]  = 8;
  block_offset_fld[10] = UVFrameHSize + 8;
  block_offset_fld[11] = UVFrameHSize + 8;

  // verify bitrate
  {
    Ipp32s BitRate = encodeInfo.info.bitrate;
    Ipp64f pixrate = encodeInfo.info.framerate * YUVFrameSize * 8;
    if((Ipp64f)encodeInfo.info.bitrate > pixrate)
      BitRate = (Ipp32s)(pixrate); // too high
    if(BitRate != 0 && (Ipp64f)encodeInfo.info.bitrate < pixrate/500)
      BitRate = (Ipp32s)(pixrate/500); // too low
    if ((Ipp32s)encodeInfo.info.bitrate != BitRate) {
      vm_debug_trace1(VM_DEBUG_WARNING, VM_STRING("BitRate value fixed to %d\n"), (BitRate+399)/400*400);
    }
    encodeInfo.info.bitrate = (BitRate+399)/400*400; // 400 bps step
  }

  if(sizeChanged) {
    if (pMBInfo != 0)
      MP2_FREE(pMBInfo);
    pMBInfo = MP2_ALLOC(MBInfo, MBcount);
    if (pMBInfo == 0) {
      return UMC_ERR_ALLOC;
    }
    ippsZero_8u((Ipp8u*)pMBInfo, sizeof(MBInfo)*MBcount);

    if (tmpFrame_buf) {
      m_pMemoryAllocator->Free(mid_tmpFrame_buf);
      tmpFrame_buf = NULL;
    }
    if (tmpFrame) {
      delete tmpFrame;
      tmpFrame = NULL;
    }

    // allocate reference frames
    if (m_lpbReference != NULL)
      m_pMemoryAllocator->Free(mid_Reference);

    if (UMC_OK != m_pMemoryAllocator->Alloc(&mid_Reference,
#ifdef ME_REF_ORIGINAL
        4*YUVFrameSize + ALIGN_VALUE,
#else
        2*YUVFrameSize + ALIGN_VALUE,

⌨️ 快捷键说明

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