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

📄 umc_mpeg2_enc.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
  bExtendGOP = false;

  for (ntry=0; ; ntry++) {
    // Save position after headers (only 0th thread)
    Ipp32s DisplayFrameNumber;

    PrepareBuffers();
    size = 0;

    // Mpeg2 sequence header
    if (m_FirstFrame || (picture_coding_type == I_PICTURE)) {
      PutSequenceHeader();
      PutSequenceExt();
      PutSequenceDisplayExt(); // no need

      // optionally output some text data
      PutUserData(0);

      PutGOPHeader(encodeInfo.numEncodedFrames);
      size = (32+7 + BITPOS(threadSpec[0]))>>3;
    }

    PictureRateControl(size*8+32);

    DisplayFrameNumber = encodeInfo.numEncodedFrames;
    if (picture_coding_type == B_PICTURE)
      DisplayFrameNumber--;
    else if(!closed_gop) // closed can be only while I is encoded
      DisplayFrameNumber += num_btype;
    temporal_reference = DisplayFrameNumber - m_GOP_Start;

    if(picture_coding_type == I_PICTURE) {
      if(quantiser_scale_value < 5)
        encodeInfo.intraVLCFormat[picture_coding_type - I_PICTURE] = 1;
      else if(quantiser_scale_value > 15)
        encodeInfo.intraVLCFormat[picture_coding_type - I_PICTURE] = 0;
      curr_intra_vlc_format = encodeInfo.intraVLCFormat[picture_coding_type - I_PICTURE];
    }

    PutPictureHeader();
    PutPictureCodingExt();
    PutUserData(2);

    if (encodeInfo.numThreads > 1) {
      // start additional thread(s)
      for (i = 0; i < encodeInfo.numThreads - 1; i++) {
        vm_event_signal(&threads[i]->start_event);
      }
    }

    switch (picture_coding_type) {
    case I_PICTURE:
      encodeI(0);
      break;
    case P_PICTURE:
      encodeP(0);
      break;
    case B_PICTURE:
      encodeB(0);
      break;
    }

    if (encodeInfo.numThreads > 1) {
      // wait additional thread(s)
      for (i = 0; i < encodeInfo.numThreads - 1; i++) {
        vm_event_wait(&threads[i]->stop_event);
      }
    }

    // flush buffer
    status = UMC_OK;
    p = out_pointer;
    Ipp32s fieldCount = 0;
    // move encoded data from all threads to first
    for (i = 0; i < encodeInfo.numThreads; i++) {
      // align to byte border (not word)
      FLUSH_BITSTREAM(threadSpec[i].bBuf.current_pointer, threadSpec[i].bBuf.bit_offset);
      size = BITPOS(threadSpec[i])>>3;
      fieldCount += threadSpec[i].fieldCount;
      if (size > thread_buffer_size) {
        status = UMC_ERR_NOT_ENOUGH_BUFFER;
        break;
      }
      if (i) {
        memcpy(p, threadSpec[i].bBuf.start_pointer, size);
      }
      p += size;
    }

    if(!curr_frame_dct)
      encodeInfo.altscan_tab[picture_coding_type-I_PICTURE] =
        (fieldCount > 0) ? 1 : 0;

    // align encoded size to 4
    while ((size_t)p & 3) *p++ = 0;

    // summary size
    size = (Ipp32s)(p - out_pointer);
    isfield = (picture_structure != FRAME_PICTURE);
    bitsize = size*8;
    if(encodeInfo.rc_mode == RC_CBR) {
      target_size = rc_tagsize[picture_coding_type-I_PICTURE];
      wanted_size = (Ipp32s)(target_size - rc_dev / 3 * target_size / rc_tagsize[0]);
      wanted_size >>= isfield;
    } else {
      target_size = wanted_size = bitsize; // no estimations
    }

    if(picture_coding_type == I_PICTURE) {
      if(bitsize > (MBcount*128>>isfield))
        encodeInfo.intraVLCFormat[0] = 1;
      else //if(bitsize < MBcount*192)
        encodeInfo.intraVLCFormat[0] = 0;
    }
#ifdef SCENE_DETECTION
    bSceneChanged = false;
    if ( picture_coding_type == P_PICTURE && second_field == 0 && bExtendGOP == false) { //
      Ipp32s numIntra = 0;
      Ipp32s t;
      for (t = 0; t < encodeInfo.numThreads; t++) {
        numIntra += threadSpec[t].numIntra;
      }
      if(picture_structure != FRAME_PICTURE)
        numIntra <<= 1; // MBcount for the frame picture

      if (numIntra*2 > MBcount*1 // 1/2 Intra: I frame instead of P
         ) {
        picture_coding_type = I_PICTURE;
        curr_gop = 0;
        bSceneChanged = true;
        mp_f_code = 0;
        m_GOP_Start_tmp = m_GOP_Start;
        m_GOP_Start = encodeInfo.numEncodedFrames;
        ntry = -1;
        continue;
      }
    }
    // scene change not detected
#endif
    oldq = prevq;
    prevq = quantiser_scale_value;
    bQuantiserChanged = false;

    if (status == UMC_ERR_NOT_ENOUGH_BUFFER || bitsize > rc_vbv_max
      || (bitsize > wanted_size*2 && (ntry==0 || oldq<prevq)) )
    {
      changeQuant(quantiser_scale_value + 1);
      if(prevq == quantiser_scale_value) {
        if (picture_coding_type == I_PICTURE && !m_FirstFrame &&
           (status == UMC_ERR_NOT_ENOUGH_BUFFER || bitsize > rc_vbv_max)) {
          picture_coding_type = P_PICTURE;
          m_GOP_Start = m_GOP_Start_tmp;
          mp_f_code = pMotionData[0].f_code;
          bExtendGOP = true;
          curr_gop += encodeInfo.IPDistance;
          ntry = -1;
          continue;
        }
        status = UMC_ERR_FAILED; // already maximum;
      } else {
        bQuantiserChanged = true;
        continue;
      }
    } else if (bitsize < rc_vbv_min )
    {
      if(ntry==0 || oldq>prevq)
        changeQuant(quantiser_scale_value - 1);
      if(prevq == quantiser_scale_value) {
        while(bitsize < rc_vbv_min) {
          *(Ipp32u*)p = 0;
          p += 4;
          size += 4;
          bitsize += 32;
        }
        status = UMC_OK; // already minimum;
      } else {
        bQuantiserChanged = true;
        continue;
      }
    }

    // if (!bQuantiserChanged && !bSceneChanged)
    m_FirstFrame = 0;
    qscale[picture_coding_type-I_PICTURE] = quantiser_scale_value;
    out_pointer += size;
    output_buffer_size -= size;
    mEncodedSize += size;
    PostPictureRateControl(size*8);
    return status;

  }
}

// Initializes internal frame so that it has original dimension but uses
// buffer with aligned dimension
void MPEG2VideoEncoderBase::InitInternalFrame(VideoData* frame)
{
  frame->SetAlignment(16);
  frame->Init(encodeInfo.info.clip_info.width, encodeInfo.info.clip_info.height, encodeInfo.info.color_format, 8);
  frame->SetPlanePitch(YFrameHSize, 0);
  frame->SetPlanePitch(UVFrameHSize, 1);
  frame->SetPlanePitch(UVFrameHSize, 2);
  frame->SetTime(-1);
}

// Initializes internal frame so that it has original dimension but uses
// buffer with aligned dimension.
// The length of the buffer must be YUVFrameSize.
void MPEG2VideoEncoderBase::SetInternalFramePointers(VideoData* frame, Ipp8u* buffer)
{
  frame->SetPlanePointer(buffer, 0); buffer += YFrameSize;
  frame->SetPlanePointer(buffer, 1); buffer += UVFrameSize;
  frame->SetPlanePointer(buffer, 2);
}

const Ipp32s sorted_ratio[][2] = {
  {1,32},{1,31},{1,30},{1,29},{1,28},{1,27},{1,26},{1,25},{1,24},{1,23},{1,22},{1,21},{1,20},{1,19},{1,18},{1,17},
  {1,16},{2,31},{1,15},{2,29},{1,14},{2,27},{1,13},{2,25},{1,12},{2,23},{1,11},{3,32},{2,21},{3,31},{1,10},{3,29},
  {2,19},{3,28},{1, 9},{3,26},{2,17},{3,25},{1, 8},{4,31},{3,23},{2,15},{3,22},{4,29},{1, 7},{4,27},{3,20},{2,13},
  {3,19},{4,25},{1, 6},{4,23},{3,17},{2,11},{3,16},{4,21},{1, 5},{4,19},{3,14},{2, 9},{3,13},{4,17},{1, 4},{4,15},
  {3,11},{2, 7},{3,10},{4,13},{1, 3},{4,11},{3, 8},{2, 5},{3, 7},{4, 9},{1, 2},{4, 7},{3, 5},{2, 3},{3, 4},{4, 5},
  {1,1},{4,3},{3,2},{2,1},{3,1},{4,1}
};

// sets framerate code and extensions
Status MPEG2VideoEncoderBase::SetFrameRate(Ipp64f new_fr, Ipp32s is_mpeg1)
{
  const Ipp32s srsize = sizeof(sorted_ratio)/sizeof(sorted_ratio[0]);
  const Ipp32s rtsize = sizeof(ratetab)/sizeof(ratetab[0]);
  Ipp32s i, j, besti=0, bestj=0;
  Ipp64f ratio, bestratio = 1.5;
  Ipp32s fr1001 = (Ipp32s)(new_fr*1001+.5);

  frame_rate_code = 5;
  frame_rate_extension_n = frame_rate_extension_d = 0;
  for(j=0;j<rtsize;j++) {
    Ipp32s try1001 = (Ipp32s)(ratetab[j]*1001+.5);
    if(fr1001 == try1001) {
      frame_rate_code = j+1;
      return UMC_OK;
    }
  }
  if(is_mpeg1) { // for mpeg2 will find frame_rate_extention
    return UMC_ERR_FAILED; // requires quite precise values: 0.05% or 0.02 Hz
  }

  if(new_fr < ratetab[0]/sorted_ratio[0][1]*0.7)
    return UMC_ERR_FAILED;

  for(j=0;j<rtsize;j++) {
    ratio = ratetab[j] - new_fr; // just difference here
    if(ratio < 0.0001 && ratio > -0.0001) { // was checked above with bigger range
      frame_rate_code = j+1;
      frame_rate_extension_n = frame_rate_extension_d = 0;
      return UMC_OK;
    }
    if(!is_mpeg1)
    for(i=0;i<srsize+1;i++) { // +1 because we want to analyze last point as well
      if(ratetab[j]*sorted_ratio[i][0] > new_fr*sorted_ratio[i][1] || i==srsize) {
        if(i>0) {
          ratio = ratetab[j]*sorted_ratio[i-1][0] / (new_fr*sorted_ratio[i-1][1]); // up to 1
          if(1/ratio < bestratio) {
            besti = i-1;
            bestj = j;
            bestratio = 1/ratio;
          }
        }
        if(i<srsize) {
          ratio = ratetab[j]*sorted_ratio[i][0] / (new_fr*sorted_ratio[i][1]); // down to 1
          if(ratio < bestratio) {
            besti = i;
            bestj = j;
            bestratio = ratio;
          }
        }
        break;
      }
    }
  }

  if(bestratio > 1.49)
    return UMC_ERR_FAILED;

  frame_rate_code = bestj+1;
  frame_rate_extension_n = sorted_ratio[besti][0]-1;
  frame_rate_extension_d = sorted_ratio[besti][1]-1;
  return UMC_OK;
}

Status MPEG2VideoEncoderBase::SetAspectRatio(Ipp32s hor, Ipp32s ver) // sets aspect code from h/v value
{
  if(hor*3 == ver*4) {
    aspectRatio_code = 2;
    encodeInfo.info.aspect_ratio_width = 4;
    encodeInfo.info.aspect_ratio_height = 3;
  } else if(hor*9 == ver*16) {
    aspectRatio_code = 3;
    encodeInfo.info.aspect_ratio_width = 16;
    encodeInfo.info.aspect_ratio_height = 9;
  } else if(hor*100 == ver*221) {
    aspectRatio_code = 4;
    encodeInfo.info.aspect_ratio_width = 221;
    encodeInfo.info.aspect_ratio_height = 100;
  } else {
    Ipp64f ratio = (Ipp64f)hor/ver;
    Ipp32s parx, pary;
    Ipp32s w = encodeInfo.info.clip_info.width;
    Ipp32s h = encodeInfo.info.clip_info.height;

    // in video_data
    DARtoPAR(w, h, hor, ver, &parx, &pary);
    DARtoPAR(h, w, parx, pary,
      &encodeInfo.info.aspect_ratio_width,
      &encodeInfo.info.aspect_ratio_height); // PAR to DAR

    if (parx == pary) aspectRatio_code = 1;
    else if (ratio > 1.25 && ratio < 1.4) aspectRatio_code = 2;
    else if (ratio > 1.67 && ratio < 1.88) aspectRatio_code = 3;
    else if (ratio > 2.10 && ratio < 2.30) aspectRatio_code = 4;
    else {
      aspectRatio_code = 1;
      vm_debug_trace(VM_DEBUG_WARNING, VM_STRING("Improper display aspect ratio"));
    }
  }
  return UMC_OK;
}

#define SHIFT_PTR(oldptr, oldbase, newbase) \
  ( (newbase) + ( (Ipp8u*)(oldptr) - (Ipp8u*)(oldbase) ) )

Status MPEG2VideoEncoderBase::LockBuffers(void)
{
  Ipp32s i;
  Ipp8u* newptr;

  if (m_lpbReference == 0) // wasn't allocated, error
    return UMC_ERR_NOT_INITIALIZED;
  newptr = (Ipp8u*) m_pMemoryAllocator->Lock(mid_Reference);
  if(newptr != m_lpbReference) { //ptr changed, need to reset pointers
    m_lpbReference = newptr;
    for(i=0; i<4; i++) {
#ifdef ME_REF_ORIGINAL
      SetInternalFramePointers(RotatingFrames[i],
        m_lpbReference + i*YUVFrameSize);
#else
      SetInternalFramePointers(RotatingFrames[i],
        m_lpbReference + (i>>1)*YUVFrameSize);
#endif
    }
  }

  if (frames_buff != 0 && is_frames_buff_locked == 0) {// nothing if hasn't been allocated
    newptr = (Ipp8u*)m_pMemoryAllocator->Lock(mid_frames_buff);
    if(newptr != frames_buff) { //ptr changed, need to reset pointers
      if(!newptr) {
        vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("External Lock failed\n"));
        return UMC_ERR_ALLOC;
      }
      frames_buff = newptr;
      for(i=0; i<buff_size; i++) {
        SetInternalFramePointers(VideoData_buff+i, frames_buff + i*YUVFrameSize);
      }
    }
  }

  if (tmpFrame_buf != 0) {// nothing if hasn't been allocated
    newptr = (Ipp8u*)m_pMemoryAllocator->Lock(mid_tmpFrame_buf);
    if(newptr != tmpFrame_buf) { //ptr changed, need to reset pointers
      if(!newptr) {
        vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("External Lock failed\n"));
        return UMC_ERR_ALLOC;
      }
      tmpFrame_buf = newptr;
      SetInternalFramePointers(tmpFrame, tmpFrame_buf);
    }
  }

  return UMC_OK;
}

Status MPEG2VideoEncoderBase::UnlockBuffers(void)
{
  Status sts, ret;
  ret = m_pMemoryAllocator->Unlock(mid_Reference);
  if (frames_buff != 0) {// nothing if hasn't been allocated
    sts = m_pMemoryAllocator->Unlock(mid_frames_buff);
    if(ret==UMC_OK) ret = sts;
    is_frames_buff_locked = 0;
  }
  if (tmpFrame_buf != 0) {// nothing if hasn't been allocated
    sts = m_pMemoryAllocator->Unlock(mid_tmpFrame_buf);
    if(ret==UMC_OK) ret = sts;
  }
  return ret;
}

#endif // UMC_ENABLE_MPEG2_VIDEO_ENCODER

⌨️ 快捷键说明

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