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

📄 umc_mpeg2_dec_pic.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 "umc_mpeg2_dec_defs.h"
#include "umc_mpeg2_dec_base.h"
#include "umc_video_data.h"
#include "umc_structures.h"

#pragma warning(disable: 4244)

using namespace UMC;

extern Ipp8u default_intra_quantizer_matrix[64];

// can decode all headers, except of slices
// bitstream should point to next after header byte
Status MPEG2VideoDecoderBase::DecodeHeader(Ipp32s startcode, IppVideoContext* video)
{
  Ipp32u code;

  switch(startcode) {
    case SEQUENCE_HEADER_CODE:
      return (DecodeSequenceHeader(video));
    case SEQUENCE_END_CODE:
      return (UMC_OK);
    case GROUP_START_CODE:
      GET_BITS_LONG(video->bs, 27, code)
      sequenceHeader.broken_link = code & 1;
      sequenceHeader.closed_gop  = code & 2;
      sequenceHeader.gop_picture = (code>>2) & 0x3f;
      sequenceHeader.gop_second  = ((code>>8) & 0x3f) + ((code>>15) & 0x3f)*60 + ((code>>21) & 0x1f)*3600;
      sequenceHeader.stream_time_temporal_reference = -1; //-2; // new count
      return (UMC_OK); // ignore for a while
    case EXTENSION_START_CODE:
      SHOW_TO9BITS(video->bs, 4, code)
      //extensions
      switch(code) {
        case SEQUENCE_EXTENSION_ID:
          {
            Ipp32u bit_rate_extension, chroma_format;
            GET_BITS32(video->bs, code)
            sequenceHeader.profile                          = (code >> 24) & 0x7;//ignore escape bit
            sequenceHeader.level                            = (code >> 20) & 0xf;
            sequenceHeader.progressive_sequence             = (code >> 19) & 1;
            chroma_format               = 1 << ((code >> 17) & ((1 << 2) - 1));
            m_ClipInfo.clip_info.width  = (m_ClipInfo.clip_info.width  & 0xfff)
              | ((code >> (15-12)) & 0x3000);
            m_ClipInfo.clip_info.height = (m_ClipInfo.clip_info.height & 0xfff)
              | ((code >> (13-12)) & 0x3000);
            bit_rate_extension = (code >> 1) & 0xfff;

            GET_BITS(video->bs, 16, code)
            sequenceHeader.frame_rate_extension_d           = code & 31;
            sequenceHeader.frame_rate_extension_n           = (code >> 5) & 3;

            switch (chroma_format)
            {
            case 2:
                m_ClipInfo.color_format = YUV420;
                break;
            case 4:
                m_ClipInfo.color_format = YUV422;
                break;
            case 8:
                m_ClipInfo.color_format = YUV444;
                break;
            default:
                break;
            }

            if(bit_rate_extension != 0) {
              m_ClipInfo.bitrate = (m_ClipInfo.bitrate / 400) & 0x3ffff;
              m_ClipInfo.bitrate |= (bit_rate_extension<<18);
              if(m_ClipInfo.bitrate >= 0x40000000/100) // check if fit to 32u
                m_ClipInfo.bitrate = 0xffffffff;
              else
                m_ClipInfo.bitrate *= 400;
            }
            sequenceHeader.extension_start_code_ID          = SEQUENCE_EXTENSION_ID; //needed?
          }
          break;
        case SEQUENCE_DISPLAY_EXTENSION_ID:
          sequence_display_extension();
          break;
        case QUANT_MATRIX_EXTENSION_ID:
          quant_matrix_extension();
          break;
        case COPYRIGHT_EXTENSION_ID:
          copyright_extension();
          break;
        case PICTURE_DISPLAY_EXTENSION_ID:
          picture_display_extension();
          break;
        case SEQUENCE_SCALABLE_EXTENSION_ID:
          sequence_scalable_extension();
          break;
        case PICTURE_CODING_EXTENSION_ID: // can move after picture header (if mpeg2)
          //picture_coding_extension();
          {
            GET_BITS32(video->bs,code)
            VM_ASSERT((code>>28) == PICTURE_CODING_EXTENSION_ID);
            PictureHeader.repeat_first_field           = (code >> 1) & 1;
            PictureHeader.alternate_scan               = (code >> 2) & 1;
            PictureHeader.intra_vlc_format             = (code >> 3) & 1;
            PictureHeader.q_scale_type                 = (code >> 4) & 1;
            PictureHeader.concealment_motion_vectors   = (code >> 5) & 1;
            PictureHeader.frame_pred_frame_dct         = (code >> 6) & 1;
            PictureHeader.top_field_first              = (code >> 7) & 1;
            PictureHeader.picture_structure            = (code >> 8) & 3;
            PictureHeader.intra_dc_precision           = (code >> 10) & 3;
            PictureHeader.f_code[3]                    = (code >> 12) & 15;
            PictureHeader.f_code[2]                    = (code >> 16) & 15;
            PictureHeader.f_code[1]                    = (code >> 20) & 15;
            PictureHeader.f_code[0]                    = (code >> 24) & 15;

            GET_1BIT(video->bs, PictureHeader.progressive_frame)
            GET_1BIT(video->bs, code)
            PictureHeader.r_size[0] = PictureHeader.f_code[0] - 1;
            PictureHeader.r_size[1] = PictureHeader.f_code[1] - 1;
            PictureHeader.r_size[2] = PictureHeader.f_code[2] - 1;
            PictureHeader.r_size[3] = PictureHeader.f_code[3] - 1;

            PictureHeader.curr_intra_dc_multi = intra_dc_multi[PictureHeader.intra_dc_precision];
            PictureHeader.curr_reset_dc          = reset_dc[PictureHeader.intra_dc_precision];
            Ipp32s i, f;
            for(i = 0; i < 4; i++) {
                f = 1 << PictureHeader.r_size[i];
                PictureHeader.low_in_range[i] = -(f * 16);
                PictureHeader.high_in_range[i] = (f * 16) - 1;
                PictureHeader.range[i] = f * 32;
            }
            if(code)
            {
                GET_BITS_LONG(video->bs, 20, code)
            }
            if(PictureHeader.picture_structure == FRAME_PICTURE) {
              frame_buffer.field_buffer_index = 0; // avoid field parity loss in resync
            }

            for (i = 0; i < m_nNumberOfThreads; i++) {
              ippiDecodeInterInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, &Video[i]->decodeInterSpec);
              Video[i]->decodeIntraSpec.intraVLCFormat = PictureHeader.intra_vlc_format;
              Video[i]->decodeIntraSpec.intraShiftDC = PictureHeader.curr_intra_dc_multi;
              ippiDecodeIntraInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, Video[i]->decodeIntraSpec.intraVLCFormat, Video[i]->decodeIntraSpec.intraShiftDC, &Video[i]->decodeIntraSpec);

              ippiDecodeInterInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, &Video[i]->decodeInterSpecChroma);
              ippiDecodeIntraInit_MPEG2(NULL, PictureHeader.alternate_scan | IPPVC_LEAVE_QUANT_UNCHANGED, Video[i]->decodeIntraSpec.intraVLCFormat, Video[i]->decodeIntraSpec.intraShiftDC, &Video[i]->decodeIntraSpecChroma);
            }
          }
          break;
        case PICTURE_SPARTIAL_SCALABLE_EXTENSION_ID:
          picture_spartial_scalable_extension();
          break;
        case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID:
          picture_temporal_scalable_extension();
          break;
        default:
          //VM_ASSERT(0);
          break;
      }
      return (UMC_OK);
    case USER_DATA_START_CODE:
      {
        if(m_pCCData /*&& gop_flag*/)
        {
            ReadCCData();
        }
        else
        {
            //other user info, skip it
            SHOW_BITS_LONG(video->bs,24,code)
            while(code != 0x000001)
            {
                GET_TO9BITS(video->bs, 8, code)
                SHOW_BITS_LONG(video->bs,24,code)
            }
        }
      }
      return (UMC_OK);
    case PICTURE_START_CODE:
      return (DecodePictureHeader());
    default:
      return (UMC_ERR_INVALID_STREAM); // unexpected
  }

}

//Sequence Header search. Stops after header start code
Status MPEG2VideoDecoderBase::FindSequenceHeader(IppVideoContext *video)
{
  Ipp32u code;
  do {
    GET_START_CODE(video->bs, code);
    if(SEQUENCE_HEADER_CODE == code)
      return (UMC_OK);
  } while ( code != UMC_ERR_NOT_ENOUGH_DATA );

  return UMC_ERR_NOT_ENOUGH_DATA;
}

// when video == 0 uses m_ClipInfo values
Status MPEG2VideoDecoderBase::DecodeSequenceHeader(IppVideoContext* video)
{
    Ipp32u load_non_intra_quantizer_matrix = 0;
    Ipp32u load_intra_quantizer_matrix = 0;
    Ipp32u constrained_parameters_flag;
    Ipp32u frame_rate_code, dar_code;
    Ipp32s i;
    Ipp32u code;
    Status ret;
    Ipp8u  iqm[64];
    Ipp8u  niqm[64];

    if (video != 0) {
      if(GET_REMAINED_BYTES(video->bs) < 8) {
        // return header back
        UNGET_BITS_32(video->bs)
        return (UMC_ERR_NOT_ENOUGH_DATA);
      }

      GET_BITS32(video->bs, code)
      frame_rate_code = code  & ((1 << 4) - 1);
      m_ClipInfo.clip_info.height    = (code >> 8) & ((1 << 12) - 1);
      m_ClipInfo.clip_info.width     = (code >> 20) & ((1 << 12) - 1);

      dar_code = (code >> 4) & ((1 << 4) - 1);

      GET_BITS32(video->bs, code)
        m_ClipInfo.bitrate                 = (code >> 14) * 400;
      constrained_parameters_flag        = (code >> 2)  & 1;
      load_intra_quantizer_matrix        = (code >> 1)  & 1;
      load_non_intra_quantizer_matrix    = code  & 1; // could be changed

      if(load_intra_quantizer_matrix) {
        GET_BITS(video->bs, 7, iqm[0])
        iqm[0] |= (load_non_intra_quantizer_matrix << 7);
        for(i=1; i<64; i++) {
          GET_BITS(video->bs, 8, iqm[i])
        }
        GET_1BIT(video->bs, load_non_intra_quantizer_matrix);
      }
      if(load_non_intra_quantizer_matrix) {
        for(i=0; i<64; i++) {
          GET_BITS(video->bs, 8, niqm[i])
        }
      }

      VideoStreamType newtype = MPEG1_VIDEO;
      if(!constrained_parameters_flag) {
        FIND_START_CODE(video->bs,code)
        if(code == EXTENSION_START_CODE) {
          SKIP_BITS_32(video->bs);
          SHOW_TO9BITS(video->bs, 4, code)
          if(code == SEQUENCE_EXTENSION_ID) {
            newtype = MPEG2_VIDEO;
            DecodeHeader(EXTENSION_START_CODE, video);
          }
        }
      }
      if(m_ClipInfo.stream_type == UNDEF_VIDEO)
        m_ClipInfo.stream_type = newtype;
      else if(m_ClipInfo.stream_type != newtype)
        return (UMC_ERR_INVALID_STREAM);
      FIND_START_CODE(video->bs, code);
      while(code == EXTENSION_START_CODE || code == USER_DATA_START_CODE)
      {
        SKIP_BITS_32(video->bs);
        DecodeHeader(code, video);
        FIND_START_CODE(video->bs, code);
      }

    }

    if(m_ClipInfo.stream_type == MPEG1_VIDEO) {
      sequenceHeader.progressive_sequence = 1;
      m_ClipInfo.color_format             = YUV420;
    }
    if(m_ClipInfo.color_format != YUV422) {
      m_ClipInfo.color_format = YUV420;
    }

    if(m_ClipInfo.stream_type == UNDEF_VIDEO ||
       m_ClipInfo.clip_info.width <= 0 || m_ClipInfo.clip_info.width >= 0x10000 ||
       m_ClipInfo.clip_info.height <= 0 || m_ClipInfo.clip_info.height >= 0x10000)
      return UMC_ERR_INVALID_PARAMS; // if was not set in params
    if (m_ClipInfo.framerate <= 0)
      m_ClipInfo.framerate = 30; // to avoid divide by zero

    // now compute and set params

    frame_buffer.field_buffer_index = 0;

    sequenceHeader.mb_width = (m_ClipInfo.clip_info.width + 15) >> 4;
    sequenceHeader.mb_height= (m_ClipInfo.clip_info.height + 15) >> 4;
    if(!sequenceHeader.progressive_sequence) {
      sequenceHeader.mb_height = (sequenceHeader.mb_height + 1) & ~1;
    }
    sequenceHeader.numMB = sequenceHeader.mb_width*sequenceHeader.mb_height;

    if (UMC_OK != UpdateFrameBuffer()) { // create or update internal buffer
      return (UMC_ERR_ALLOC);
    }

    Ipp32s flag_mpeg1 = (m_ClipInfo.stream_type == MPEG1_VIDEO) ? IPPVC_MPEG1_STREAM : 0;
    for (i = 0; i < m_nNumberOfThreads; i++) {
      ippiDecodeIntraInit_MPEG2(NULL, flag_mpeg1, PictureHeader.intra_vlc_format, PictureHeader.curr_intra_dc_multi, &Video[i]->decodeIntraSpec);
      ippiDecodeInterInit_MPEG2(NULL, flag_mpeg1, &Video[i]->decodeInterSpec);

      Video[i]->decodeInterSpecChroma = Video[i]->decodeInterSpec;
      Video[i]->decodeIntraSpecChroma = Video[i]->decodeIntraSpec;
    }

    if (video != 0) {
      sequenceHeader.is_decoded = 1;

      if(load_intra_quantizer_matrix)
      {
        for (i = 0; i < m_nNumberOfThreads; i++) {
          ippiDecodeIntraInit_MPEG2(iqm, flag_mpeg1, PictureHeader.intra_vlc_format, PictureHeader.curr_intra_dc_multi, &Video[i]->decodeIntraSpec);
          Video[i]->decodeIntraSpecChroma = Video[i]->decodeIntraSpec;
        }
      }

      if(load_non_intra_quantizer_matrix)
      {
        for (i = 0; i < m_nNumberOfThreads; i++) {
          ippiDecodeInterInit_MPEG2(niqm, flag_mpeg1, &Video[i]->decodeInterSpec);
          Video[i]->decodeInterSpecChroma = Video[i]->decodeInterSpec;
        }
      }

⌨️ 快捷键说明

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