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

📄 umc_vc1_enc_brc_gop.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) 2007 Intel Corporation. All Rights Reserved.
//
//
//          VC-1 (VC1) encoder, bit rate control
//
*/
#include "umc_defs.h"

#if defined (UMC_ENABLE_VC1_VIDEO_ENCODER)

#include "umc_vc1_enc_brc_gop.h"
#include "umc_vc1_common_defs.h"
#include "umc_vc1_enc_debug.h"

namespace UMC_VC1_ENCODER
{

VC1BRC::VC1BRC(): m_GOPLength (1), m_BFrLength (0), m_SizeAbberation(0),
                  m_recoding(0),   m_currSize(0),   m_IdealFrameSize(0),
                  m_picType(VC1_I_FRAME),    m_ratio_min(0.6),m_buffer_overflow(1.1),
                  m_encMode(VC1_BRC_HIGHT_QUALITY_MODE)
{
    m_CurQuant.PQIndex = 1;
    m_CurQuant.HalfPQ = 1;

    m_Quant.IQuant = 1;
    m_Quant.PQuant = 1;
    m_Quant.BQuant = 1;
    m_Quant.LimIQuant = 1;
    m_Quant.LimPQuant = 1;
    m_Quant.LimBQuant = 1;
    m_Quant.IHalf = 0;
    m_Quant.PHalf = 0;
    m_Quant.BHalf = 0;
};
VC1BRC::~VC1BRC()
{
};

////////////////////////////////////////////
//          VC1BRC_I
////////////////////////////////////////////
VC1BRC_I::VC1BRC_I():m_needISize(0)
{
};

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

UMC::Status VC1BRC_I::Init(Ipp32u yuvFSize,  Ipp32u bitrate,  Ipp64f framerate,
                           Ipp32u mode,      Ipp32u GOPLength, Ipp32u BFrLength,
                           Ipp32u doubleQuant)
 {
    UMC::Status VC1Sts = UMC::UMC_OK;

    m_bitrate   = bitrate;
    m_framerate = framerate;
    m_GOPLength = GOPLength;
    m_BFrLength = BFrLength;

    m_IdealFrameSize = (Ipp32u)(bitrate/framerate/8);

    m_needISize = m_IdealFrameSize;

#ifdef VC1_GOP_DEBUG
    printf("\n\n m_GOPSize = %d\n", m_needISize);
#endif

    if(!doubleQuant)
    {
        Ipp32s AverageCompression = (Ipp32s)((yuvFSize)/m_needISize)/3;

        VC1_QUANT_CLIP(AverageCompression, 0);
        m_CurQuant.PQIndex = m_Quant.IQuant = AverageCompression;
    }
    else
    {
        if(doubleQuant > (VC1_MAX_QUANT*2))
            return UMC::UMC_ERR_ALLOC;

        m_encMode = VC1_BRC_CONST_QUANT_MODE;
        m_CurQuant.PQIndex = m_Quant.IQuant = m_Quant.PQuant = m_Quant.BQuant = (doubleQuant>>1);
        m_CurQuant.HalfPQ  = m_Quant.IHalf = m_Quant.PHalf = m_Quant.BHalf = doubleQuant&0x1;
    }

    switch(m_encMode)
    {
    case VC1_BRC_HIGHT_QUALITY_MODE:
    case VC1_BRC_CONST_QUANT_MODE:
        m_ratio_min       = (Ipp32f)(0.6);
        m_buffer_overflow = (Ipp32f)(1.1);
        break;
    default:
        m_ratio_min       = (Ipp32f)(0.6);
        m_buffer_overflow = (Ipp32f)(1.1);
        break;
    }

    return VC1Sts;
 };

void VC1BRC_I::Close()
{
    Reset();
};

void VC1BRC_I::Reset()
{
    //GOP parameters
    m_SizeAbberation = 0;

    //Frames parameters
    m_currSize = 0;

    //Flags
    m_recoding = 0;
};

UMC::Status VC1BRC_I::CheckFrameCompression(Ipp32u picType, Ipp32u currSize, UMC::Status HRDSts)
{
    UMC::Status UMCSts = UMC::UMC_OK;
    Ipp32s Sts = 0;
    Ipp32f ratio = 0;

    if(currSize < 0)
        return UMC::UMC_ERR_INVALID_PARAMS;

    m_currSize = currSize;
    ratio = ((Ipp32f)currSize/(Ipp32f)m_needISize);

#ifdef VC1_BRC_DEBUG
    printf("current ratio = %f\n", ratio);
#endif

#ifdef VC1_GOP_DEBUG
     printf("I ");
     printf("current ratio = %f   %d  %d % d\n", ratio, m_CurQuant.PQIndex, m_CurQuant.HalfPQ, currSize);
#endif

    switch(m_encMode)
    {
    case VC1_BRC_HIGHT_QUALITY_MODE:
        CheckFrame_QualityMode(ratio, HRDSts);
        break;
    case VC1_BRC_CONST_QUANT_MODE:
        break;
    default:
        break;
    }
    m_recoding++;

#ifdef VC1_BRC_DEBUG
    printf("coded size %d\n", currSize);
#endif

    return UMCSts;
};

void VC1BRC_I::CompleteFrame(Ipp32u picType)
{
    UMC::Status UMCSts = UMC::UMC_OK;
    Ipp32f ratioI = 0;
    Ipp32s prefINeedSize = m_needISize;

#ifdef BRC_TEST
     if(BRCFileSizeTest.RES_File)
        fprintf(BRCFileSizeTest.RES_File, "%d,",m_currSize);
#endif

    if(m_encMode == VC1_BRC_CONST_QUANT_MODE)
        return;


#ifdef VC1_GOP_DEBUG
    printf("\nGOP ratio = %f\n\n", ((Ipp32f)m_currSize/(Ipp32f)m_needISize));

    printf("-----------------------------------NEW GOP");
    printf("------------------------------------------\n\n\n");
#endif

    m_SizeAbberation += m_IdealFrameSize - m_currSize;

    //check overflow m_SizeAbberation
    if(m_SizeAbberation > 4*m_IdealFrameSize)
        m_SizeAbberation = 4*m_IdealFrameSize;

    if(m_SizeAbberation < (- 4*m_IdealFrameSize))
        m_SizeAbberation = -(4*m_IdealFrameSize);

    m_needISize = m_IdealFrameSize + m_SizeAbberation;

    //check m_needISize
    if(m_needISize > m_IdealFrameSize + (m_IdealFrameSize>>1))
        m_needISize = m_IdealFrameSize + (m_IdealFrameSize>>1);

    if(m_needISize < (m_IdealFrameSize>>1))
        m_needISize = (m_IdealFrameSize>>1);

#ifdef VC1_GOP_DEBUG
        printf("nextGOPSize = %d\n", m_needISize);
        printf("m_SizeAbberation = %d\n", m_SizeAbberation);
#endif

    ratioI = ((Ipp32f)prefINeedSize/(Ipp32f)m_needISize);

    QuantForNewGOP(ratioI);

    m_recoding = 0;

#ifdef VC1_BRC_DEBUG
    printf("\n\n\n");
#endif
};

void VC1BRC_I::CheckFrame_QualityMode(Ipp32f ratio, UMC::Status UMCSts)
{
    Ipp32s curQuant = 0;
    Ipp32s Sts = VC1_BRC_OK;
    bool HalfQP = 0;

    //new quant calculation
    curQuant = (Ipp32s)(ratio * m_CurQuant.PQIndex + 0.5);
    VC1_QUANT_CLIP(curQuant, 0);

    //check compression
    if((ratio <= m_buffer_overflow) && (ratio >= VC1_GOOD_COMPRESSION))
        Sts = VC1_BRC_OK;       //good frame
    else if(ratio > m_buffer_overflow)
        Sts |= VC1_BRC_NOT_ENOUGH_BUFFER; //could be critical situation, if HRD buffer small
    else  if(ratio <= m_ratio_min)
    {
        //very small frame
        Sts |= VC1_BRC_ERR_SMALL_FRAME;

        if(m_CurQuant.PQIndex > 1)
            HalfQP = 1;
    }
    else if(ratio >= VC1_MIN_RATIO_HALF)
    {
        if((m_CurQuant.PQIndex > 1) && ((Ipp32u)curQuant > m_CurQuant.PQIndex))
            HalfQP = 1;
        Sts |= VC1_BRC_SMALL_FRAME;
    }
    else
         Sts |= VC1_BRC_SMALL_FRAME;

    //check HRD status
    if(UMCSts ==  UMC::UMC_ERR_NOT_ENOUGH_BUFFER)
    {
        Sts |= VC1_BRC_NOT_ENOUGH_BUFFER;
        HalfQP = 0;
    }

    if(Sts != VC1_BRC_OK)
    {
#ifdef VC1_BRC_DEBUG
    printf("m_LimIQuant %d\n", m_Quant.LimIQuant);
#endif
        m_Quant.IQuant = (m_Quant.IQuant + curQuant)/2;

        if(Sts & VC1_BRC_NOT_ENOUGH_BUFFER)
        {
            if(ratio > VC1_RATIO_ILIM)
            {
                m_Quant.IQuant++;
                m_Quant.LimIQuant = m_CurQuant.PQIndex + 2;
            }
            else
            {
                if(m_CurQuant.PQIndex > 9)
                    m_Quant.LimIQuant = m_CurQuant.PQIndex + 1;
                else if(m_Quant.IQuant <= m_CurQuant.PQIndex)
                    HalfQP = 1;
            }
        }
        else if(Sts & VC1_BRC_ERR_SMALL_FRAME)
        {
            m_Quant.LimIQuant--;

            if(m_Quant.IQuant >= m_CurQuant.PQIndex)
                m_Quant.IQuant--;

            if((ratio > VC1_MIN_RATIO_HALF) &&  (m_CurQuant.PQIndex > 1))
                HalfQP = 1;

        }
        else if(Sts & VC1_BRC_SMALL_FRAME)
        {
            m_Quant.LimIQuant--;

            if((m_Quant.IQuant < m_CurQuant.PQIndex) && m_Quant.IQuant &&  (m_CurQuant.PQIndex > 1))
                HalfQP = 1;

        }

        VC1_QUANT_CLIP(m_Quant.LimIQuant,0);
        VC1_QUANT_CLIP(m_Quant.IQuant, m_Quant.LimIQuant);

        m_Quant.IHalf = HalfQP;
    }
 };

 void VC1BRC_I::QuantForNewGOP(Ipp32f ratio)
 {
     Ipp32s curQuant = 0;
    //new quant calculation
    curQuant = (Ipp32s)(ratio * m_Quant.IQuant + 0.5);
    VC1_QUANT_CLIP(curQuant, 0);

    if(curQuant != m_Quant.IQuant)
        m_Quant.IHalf = 0;

    m_Quant.IQuant = (m_Quant.IQuant + curQuant + 1)/2;
    //m_Quant.LimIQuant = (m_Quant.LimIQuant + m_Quant.IQuant - 1)/2;

    //VC1_QUANT_CLIP(m_Quant.LimIQuant,0);
    VC1_QUANT_CLIP(m_Quant.IQuant, m_Quant.LimIQuant);
 };

void VC1BRC_I::GetQuant(Ipp32u picType, Ipp8u* PQuant, bool* Half)
{
    m_CurQuant.PQIndex = m_Quant.IQuant;
    m_CurQuant.HalfPQ  = m_Quant.IHalf;

    if(m_CurQuant.PQIndex > 8)
        m_CurQuant.HalfPQ  = 0;

#ifdef VC1_BRC_DEBUG
    printf("cur quant %d\n", m_CurQuant.PQIndex);
    printf("half quant %d\n",  m_CurQuant.HalfPQ);
#endif

    *PQuant = m_CurQuant.PQIndex;
    *Half   = m_CurQuant.HalfPQ;
}

////////////////////////////////////////////
//          VC1BRC_IP
////////////////////////////////////////////
VC1BRC_IP::VC1BRC_IP() : m_I_GOPSize(0),      m_P_GOPSize(0),
                        m_needISize(0),      m_needPSize(0),
                        m_INum(0),           m_PNum(0),
                        m_CurrINum(0),       m_CurrPNum(0),
                        m_currFrameInGOP(0), m_poorRefFrame(0),
                        m_GOPHalfFlag(0),    m_GOPSize(0),
                        m_currGOPSize(0),    m_nextGOPSize(0),
                        m_currISize(0),      m_currPSize(0),
                        m_IP_size((Ipp32f)(VC1_P_SIZE)),
                        m_failPQuant(0),     m_failGOP(0),
                        m_AverageIQuant(0),  m_AveragePQuant(0)
{
};

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

UMC::Status VC1BRC_IP::Init(Ipp32u yuvFSize,  Ipp32u bitrate,  Ipp64f framerate,
                           Ipp32u mode,      Ipp32u GOPLength, Ipp32u BFrLength,
                           Ipp32u doubleQuant)
 {
    UMC::Status VC1Sts = UMC::UMC_OK;

    m_bitrate   = bitrate;
    m_framerate = framerate;
    m_GOPLength = GOPLength;
    m_BFrLength = BFrLength;

    m_INum = 1;
    m_PNum = GOPLength - 1;

    m_IdealFrameSize = (Ipp32u)(bitrate/framerate/8);
    m_GOPSize        = m_IdealFrameSize * m_GOPLength;
    m_nextGOPSize    = m_GOPSize;

#ifdef VC1_GOP_DEBUG
    printf("\n\n m_GOPSize = %d\n", m_GOPSize);
#endif
    m_needISize = (Ipp32s)(m_GOPSize/(1 + m_IP_size*m_PNum));
    m_needPSize = (Ipp32s)(m_IP_size*m_needISize);

    m_currISize = m_needISize;
    m_currPSize = m_needPSize;

    if(!doubleQuant)
    {
        Ipp32s AverageCompression = (Ipp32s)((yuvFSize)/m_needISize)/3;

        VC1_QUANT_CLIP(AverageCompression, 0);
        m_CurQuant.PQIndex = m_Quant.IQuant = AverageCompression;

        AverageCompression = (Ipp32s)((yuvFSize)/m_needPSize)/5;
        VC1_QUANT_CLIP(AverageCompression, 0);

        m_Quant.PQuant =  AverageCompression;

        if(m_Quant.PQuant > 2)
            m_Quant.PQuant -= 2;
    }
    else
    {
        if(doubleQuant > (VC1_MAX_QUANT*2))
            return UMC::UMC_ERR_ALLOC;

        m_encMode = VC1_BRC_CONST_QUANT_MODE;
        m_CurQuant.PQIndex = m_Quant.IQuant = m_Quant.PQuant = m_Quant.BQuant = (doubleQuant>>1);
        m_CurQuant.HalfPQ  = m_Quant.IHalf = m_Quant.PHalf = m_Quant.BHalf = doubleQuant&0x1;
    }

    switch(m_encMode)
    {
    case VC1_BRC_HIGHT_QUALITY_MODE:
    case VC1_BRC_CONST_QUANT_MODE:
        m_ratio_min       = (Ipp32f)(0.6);
        m_buffer_overflow = (Ipp32f)(1.1);
        break;
    default:
        m_ratio_min       = (Ipp32f)(0.6);
        m_buffer_overflow = (Ipp32f)(1.1);
        break;
    }

    return VC1Sts;
 };

void VC1BRC_IP::Close()
{
    Reset();
};

void VC1BRC_IP::Reset()
{
     //GOP parameters
    m_GOPSize      = m_IdealFrameSize * m_GOPLength;
    m_nextGOPSize  = m_GOPSize;

⌨️ 快捷键说明

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