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

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

#include <string.h>
#include "vm_debug.h"
#include "umc_video_data.h"
#include "umc_mjpeg_video_decoder.h"
#include "membuffin.h"
#include "jpegdec.h"

// VD: max num of padding bytes at the end of AVI frame
//     should be 1 by definition (padding up to Ipp16s boundary),
//     but in reality can be bigger
#define AVI_MAX_PADDING_BYTES 4


namespace UMC {

VideoDecoder *CreateMJPEGDecoder() { return new MJPEGVideoDecoder(); }


MJPEGVideoDecoder::MJPEGVideoDecoder(void)
{
  m_IsInit      = false;
  m_firstFrame  = false;
  m_firstField  = false;
  m_interleaved = false;
  m_frameMID    = 0;
  m_frameNo     = 0;
  m_frame       = 0;
  m_frameStep   = 0;
  m_fieldStep   = 0;
  m_dec_time    = 0.0;
  m_dec         = 0;
} // ctor


MJPEGVideoDecoder::~MJPEGVideoDecoder(void)
{
  Close();
} // dtor


Status MJPEGVideoDecoder::Init(BaseCodecParams* lpInit)
{
  UMC::Status status;

  VideoDecoderParams* pDecoderParams;

  pDecoderParams = DynamicCast<VideoDecoderParams>(lpInit);

  if(0 == pDecoderParams)
    return UMC_ERR_NULL_PTR;

  status = Close();
  if(UMC_OK != status)
    return UMC_ERR_INIT;

  status = VideoDecoder::Init(lpInit);
  if(UMC_OK != status)
    return UMC_ERR_INIT;

  m_DecoderParams  = *pDecoderParams;

  m_ClipInfo       = pDecoderParams->info;
  m_PostProcessing = pDecoderParams->pPostProcessing;

  status = m_LastDecodedFrame.ReleaseImage();
  if(UMC_OK != status)
    return status;

  m_IsInit       = true;
  m_firstFrame   = true;
  m_interleaved  = false;
  m_frameNo      = 0;
  m_frame        = 0;
  m_frameStep    = 0;
  m_fieldStep    = 0;

  if(0 == m_dec)
  {
    m_dec = new CJPEGDecoder;
    if(0 == m_dec)
      return UMC_ERR_ALLOC;
  }

  return UMC_OK;
} // MJPEGVideoDecoder::Init()


Status MJPEGVideoDecoder::Reset(void)
{
  if(0 != m_frameMID)
  {
    m_pMemoryAllocator->Unlock(m_frameMID);
    m_pMemoryAllocator->Free(m_frameMID);
    m_frameMID = 0;
  }

  m_IsInit       = true;
  m_firstFrame   = true;
  m_frameNo      = 0;
  m_interleaved  = false;
  m_frame        = 0;
  m_frameStep    = 0;
  m_fieldStep    = 0;

  m_dec->Reset();

  return UMC_OK;
} // MJPEGVideoDecoder::Reset()


Status MJPEGVideoDecoder::Close(void)
{
  if(0 != m_frameMID)
  {
    m_pMemoryAllocator->Unlock(m_frameMID);
    m_pMemoryAllocator->Free(m_frameMID);
    m_frameMID = 0;
  }

  m_IsInit       = false;
  m_firstFrame   = false;
  m_firstField   = false;
  m_interleaved  = false;
  m_frameNo      = 0;
  m_frame        = 0;
  m_frameStep    = 0;
  m_fieldStep    = 0;

  if(0 != m_dec)
    delete m_dec;

  m_dec = 0;

  return VideoDecoder::Close();
} // MJPEGVideoDecoder::Close()


Status MJPEGVideoDecoder::GetFrame(MediaData* in, MediaData* out)
{
  Ipp32s     nSize;
  Ipp32s     nUsedBytes;
  Ipp8u*     pBitStream;
  Status     status;

  if(0 == in)
    return UMC_ERR_NOT_ENOUGH_DATA;

  if(0 == out)
    return UMC_ERR_NULL_PTR;

  nUsedBytes = 0;
  pBitStream = (Ipp8u*)in->GetDataPointer();
  nSize      = (Ipp32s)in->GetDataSize();

  vm_debug_trace1(VM_DEBUG_NONE, __VM_STRING("MJPEG, frame: %d\n"), m_frameNo);

  if(m_firstFrame)
  {
    m_firstFrame = false;
    m_firstField = true;

    status = _GetFrameInfo(pBitStream,nSize);
    if(UMC_OK != status)
      return status;

    if(0 == m_pMemoryAllocator)
      return UMC_ERR_ALLOC;

    status = m_pMemoryAllocator->Alloc(&m_frameMID,m_frameStep*m_frameDims.height,UMC_ALLOC_PERSISTENT,16);
    if(UMC_OK != status)
      return UMC_ERR_ALLOC;

    m_frame = (Ipp8u*)m_pMemoryAllocator->Lock(m_frameMID);
    if(0 == m_frame)
      return UMC_ERR_ALLOC;
  }

  CMemBuffInput stream;

  stream.Open(pBitStream,nSize);

  if(m_interleaved)
  {
    // interleaved frame

    // get field
    status = _DecodeField(&stream, &nUsedBytes);
    if(UMC_OK != status)
      return status;

    if(m_firstField)
    {
      // request next field
      m_firstField = !m_firstField;
      in->MoveDataPointer(nUsedBytes);
      return UMC_ERR_NOT_ENOUGH_DATA;
    }
    else
    {
      m_firstField = !m_firstField;
    }
  }
  else
  {
    // progressive frame

    status = _DecodeField(&stream, &nUsedBytes);
    if(UMC_OK != status)
      return status;
  }

  in->MoveDataPointer(nUsedBytes);

  // got complete frame
  m_frameNo++;

  m_ClipInfo.clip_info.width  = m_frameDims.width;
  m_ClipInfo.clip_info.height = m_frameDims.height;

  if (m_interleaved)
    m_ClipInfo.clip_info.height *= 2;

  if (m_LastDecodedFrame.GetColorFormat() != m_colorFormat)
  {
    m_LastDecodedFrame.Init(m_ClipInfo.clip_info.width,
                            m_ClipInfo.clip_info.height,
                            m_colorFormat);
  }

  m_LastDecodedFrame.SetFrameType(I_PICTURE);
  m_LastDecodedFrame.SetTime(in->GetTime());
  m_LastDecodedFrame.SetPlanePointer(m_frame, 0);
  m_LastDecodedFrame.SetPlanePitch(m_frameStep, 0);

  if (!m_PostProcessing)
  {
    m_PostProcessing = createVideoProcessing();
    m_allocatedPostProcessing = m_PostProcessing;
  }

  status = m_PostProcessing->GetFrame(&m_LastDecodedFrame, out);
  if(UMC_OK != status)
  {
    return status;
  }

  // can't calculate time for the next frame
  in->SetTime(-1.0);

  return status;
} // MJPEGVideoDecoder::GetFrame()


Status MJPEGVideoDecoder::_GetFrameInfo(Ipp8u* pBitStream, Ipp32s nSize)
{
  Ipp32s   nchannels;
  Ipp32s   precision;
  JSS      sampling;
  JCOLOR   color;
  CMemBuffInput in;
  JERRCODE jerr;

  if(0 == m_dec)
    return UMC_ERR_NOT_INITIALIZED;

  in.Open(pBitStream,nSize);

  jerr = m_dec->SetSource(&in);
  if(JPEG_OK != jerr)
    return UMC_ERR_FAILED;

  jerr = m_dec->ReadHeader(
    &m_frameDims.width,&m_frameDims.height,&nchannels,&color,&sampling,&precision);

  if(JPEG_ERR_BUFF == jerr)
    return UMC_ERR_NOT_ENOUGH_DATA;

  if(JPEG_OK != jerr)
    return UMC_ERR_FAILED;

  if(JS_422 == sampling && JC_YCBCR == color)
  {
    m_colorFormat = YUY2;
    m_frameStep = m_frameDims.width*2;
  }
  else
  {
    m_colorFormat = RGB24;
    m_frameStep = m_frameDims.width*3 + DIB_PAD_BYTES(m_frameDims.width,3);
  }

  // frame is interleaved if clip height is twice more than JPEG frame height
  if(m_frameDims.height == (m_DecoderParams.info.clip_info.height >> 1))
  {
    m_interleaved = true;
    m_frameDims.height *= 2;
  }

  return UMC_OK;
} // MJPEGVideoDecoder::_GetFrameInfo()


Status MJPEGVideoDecoder::_DecodeField(CBaseStreamInput* in, Ipp32s* cnt)
{
  Ipp32s   dstStep;
  Ipp8u*   pDst;
  JCOLOR   color;
  JSS      sampling;
  JERRCODE jerr;

  if(0 == m_dec)
    return UMC_ERR_NOT_INITIALIZED;

  jerr = m_dec->SetSource(in);
  if(JPEG_OK != jerr)
    return UMC_ERR_FAILED;

  jerr = m_dec->ReadHeader(
    &m_frameDims.width, &m_frameDims.height, &m_frameChannels, &color, &sampling, &m_framePrecision);

  if(JPEG_ERR_BUFF == jerr)
    return UMC_ERR_NOT_ENOUGH_DATA;

  if(JPEG_OK != jerr)
    return UMC_ERR_FAILED;

  pDst    = m_frame;
  dstStep = m_frameStep;

  if(m_dec->IsAVI1APP0Detected())
  {
    switch(m_dec->GetAVI1APP0Polarity())
    {
      default:
      case 0:
        pDst    = m_interleaved & !m_firstField ? m_frame + m_frameStep : m_frame;
        dstStep = m_interleaved ? m_frameStep*2 : m_frameStep;
        break;

      case 1:
        pDst    = m_firstField ? m_frame : m_frame + m_frameStep;
        dstStep = m_frameStep*2;
        break;

      case 2:
        pDst    = m_firstField ? m_frame : m_frame + m_frameStep;
        dstStep = m_frameStep*2;
        break;
    }
  }

  if(JS_422 == sampling && JC_YCBCR == color)
  {
    jerr = m_dec->SetDestination(pDst, dstStep, m_frameDims, m_frameChannels, color, sampling);
  }
  else
  {
    jerr = m_dec->SetDestination(pDst, dstStep, m_frameDims, m_frameChannels, JC_BGR);
  }

  if(JPEG_OK != jerr)
    return UMC_ERR_FAILED;

  jerr = m_dec->ReadData();

  if(JPEG_ERR_BUFF == jerr)
    return UMC_ERR_NOT_ENOUGH_DATA;

  if(JPEG_OK != jerr)
    return UMC_ERR_FAILED;

  *cnt = m_dec->GetNumDecodedBytes();

  return UMC_OK;
} // MJPEGVideoDecoder::_DecodeField()

} // end namespace UMC

⌨️ 快捷键说明

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