📄 shape.cpp
字号:
/*************************************************************************
This software module was originally developed by
Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
(April, 1997)
and edited by
Wei Wu (weiwu@stallion.risc.rockwell.com) Rockwell Science Center
and also edited by
Yoshihiro Kikuchi (TOSHIBA CORPORATION)
Takeshi Nagai (TOSHIBA CORPORATION)
Toshiaki Watanabe (TOSHIBA CORPORATION)
Noboru Yamaguchi (TOSHIBA CORPORATION)
Mathias Wien (wien@ient.rwth-aachen.de) RWTH Aachen / Robert BOSCH GmbH
and also edited by
Yoshinori Suzuki (Hitachi, Ltd.)
Sehoon Son (shson@unitel.co.kr) Samsung AIT
in the course of development of the MPEG-4 Video (ISO/IEC 14496-2).
This software module is an implementation of a part of one or more MPEG-4 Video tools
as specified by the MPEG-4 Video.
ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications
thereof for use in hardware or software products claiming conformance to the MPEG-4 Video.
Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents.
The original developer of this software module and his/her company,
the subsequent editors and their companies,
and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation.
Copyright is not released for non MPEG-4 Video conforming products.
Microsoft retains full right to use the code for his/her own purpose,
assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products.
This copyright notice must be included in all copies or derivative works.
Copyright (c) 1996, 1997.
Module Name:
shpenc.hpp
Abstract:
binary shape encoder with context-based arithmatic coder
Revision History:
Feb.16 1999 : add Quarter Sample
Mathias Wien (wien@ient.rwth-aachen.de)
Feb.23 1999 : GMC added by Yoshinori Suzuki (Hitachi, Ltd.)
*************************************************************************/
#include "typeapi.h"
#include "entropy/entropy.hpp"
#include "entropy/huffman.hpp"
#include "entropy/bitstrm.hpp"
#include "global.hpp"
#include "mode.hpp"
#include "codehead.h"
#include "cae.h"
#include "vopses.hpp"
#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#endif // __MFC_
own Int* CVideoObject::computeShapeSubBlkIndex (Int iSubBlkSize, Int iSrcSize)
{
Int* rgiShapeSubBlkIndex = new Int [MB_SIZE * MB_SIZE / iSubBlkSize / iSubBlkSize];
Int nBorderLine = (iSrcSize - MB_SIZE) / 2;
CoordI iX, iY, i = 0;
for (iY = nBorderLine; iY < (MB_SIZE + nBorderLine); iY += iSubBlkSize) {
for (iX = nBorderLine; iX < (MB_SIZE + nBorderLine); iX += iSubBlkSize)
rgiShapeSubBlkIndex [i++] = iY * iSrcSize + iX;
}
return rgiShapeSubBlkIndex;
}
Void CVideoObject::downSampleShapeMCPred(const PixelC*ppxlcSrc,
PixelC* ppxlcDst,Int iRate)
{
assert(iRate==1 || iRate==2 || iRate==4);
static Int rgiScan[16] = {0,1,MC_BAB_SIZE,MC_BAB_SIZE+1,
2,3,MC_BAB_SIZE+2,MC_BAB_SIZE+3,
2*MC_BAB_SIZE,2*MC_BAB_SIZE+1,2*MC_BAB_SIZE+2,2*MC_BAB_SIZE+3,
3*MC_BAB_SIZE,3*MC_BAB_SIZE+1,3*MC_BAB_SIZE+2,3*MC_BAB_SIZE+3};
static Int rgiThresh[5] = {0,0,OPAQUE,0,7*OPAQUE};
Int iBdrThresh=0;
if(iRate>2)
iBdrThresh=OPAQUE;
Int iThreshold = rgiThresh[iRate];
#ifdef __TRACE_AND_STATS_
//m_pbitstrmOut->trace ((PixelC*)ppxlcSrc, MC_BAB_SIZE, MC_BAB_SIZE, "MB_MC_BAB_ORIG");
#endif //__TRACE_AND_STATS_
const PixelC *ppxlcSrcScan = ppxlcSrc+(MC_BAB_SIZE+1)*MC_BAB_BORDER;
Int iDstSize = 2*MC_BAB_BORDER+(MC_BAB_SIZE-2*MC_BAB_BORDER)/iRate;
PixelC *ppxlcDstScan = ppxlcDst+(iDstSize+1)*MC_BAB_BORDER;
Int iX,iY,i,iSum,iSum1,iSum2,iSum3,iSum4;
Int iRateSqd=iRate*iRate;
const PixelC *ppxlcSrcBdr1 = ppxlcSrc+MC_BAB_SIZE*MC_BAB_BORDER;
const PixelC *ppxlcSrcBdr2 = ppxlcSrc+2*MC_BAB_SIZE-1;
const PixelC *ppxlcSrcBdr3 = ppxlcSrc+MC_BAB_BORDER;
const PixelC *ppxlcSrcBdr4 = ppxlcSrc+MC_BAB_SIZE*(MC_BAB_SIZE-1)+MC_BAB_BORDER;
PixelC *ppxlcDstBdr1 = ppxlcDst+iDstSize*MC_BAB_BORDER;
PixelC *ppxlcDstBdr2 = ppxlcDst+2*iDstSize-1;
PixelC *ppxlcDstBdr3 = ppxlcDst+MC_BAB_BORDER;
PixelC *ppxlcDstBdr4 = ppxlcDst+iDstSize*(iDstSize-1)+MC_BAB_BORDER;
for(iY=MC_BAB_BORDER;iY<iDstSize-MC_BAB_BORDER;iY++)
{
for(iX=MC_BAB_BORDER;iX<iDstSize-MC_BAB_BORDER;iX++,ppxlcDstScan++)
{
iSum=0;
for(i=0;i<iRateSqd;i++)
iSum+=ppxlcSrcScan[rgiScan[i]];
*ppxlcDstScan=(iSum>iThreshold)?OPAQUE:TRANSPARENT;
ppxlcSrcScan+=iRate;
}
ppxlcDstScan+=2*MC_BAB_BORDER;
ppxlcSrcScan+=MC_BAB_SIZE*iRate-MC_BAB_SIZE+2*MC_BAB_BORDER;
// border
iSum1=iSum2=iSum3=iSum4=0;
for(i=0;i<iRate;i++)
{
iSum1+=ppxlcSrcBdr1[i*MC_BAB_SIZE];
iSum2+=ppxlcSrcBdr2[i*MC_BAB_SIZE];
iSum3+=ppxlcSrcBdr3[i];
iSum4+=ppxlcSrcBdr4[i];
}
*ppxlcDstBdr1=(iSum1>iBdrThresh)?OPAQUE:TRANSPARENT;
*ppxlcDstBdr2=(iSum2>iBdrThresh)?OPAQUE:TRANSPARENT;
*ppxlcDstBdr3++=(iSum3>iBdrThresh)?OPAQUE:TRANSPARENT;
*ppxlcDstBdr4++=(iSum4>iBdrThresh)?OPAQUE:TRANSPARENT;
ppxlcDstBdr1+=iDstSize;
ppxlcDstBdr2+=iDstSize;
ppxlcSrcBdr1+=MC_BAB_SIZE*iRate;
ppxlcSrcBdr2+=MC_BAB_SIZE*iRate;
ppxlcSrcBdr3+=iRate;
ppxlcSrcBdr4+=iRate;
}
// corners
ppxlcDst[0]=ppxlcSrc[0];
ppxlcDst[iDstSize-1]=ppxlcSrc[MC_BAB_SIZE-1];
ppxlcDst[(iDstSize-1)*iDstSize]=ppxlcSrc[(MC_BAB_SIZE-1)*MC_BAB_SIZE];
ppxlcDst[iDstSize*iDstSize-1]=ppxlcSrc[MC_BAB_SIZE*MC_BAB_SIZE-1];
#ifdef __TRACE_AND_STATS_
//m_pbitstrmOut->trace ((PixelC*)ppxlcDst, iDstSize, iDstSize, "MB_MC_BAB_DOWN");
#endif // __TRACE_AND_STATS_
}
Void CVideoObject::upSampleShape(PixelC*ppxlcBYFrm,const PixelC* rgpxlcSrc, PixelC* rgpxlcDst)
{
if(m_iInverseCR==2)
adaptiveUpSampleShape(rgpxlcSrc, rgpxlcDst,8,8);
else
{
static PixelC rgpxlcTmp[12*12];
assert(m_iInverseCR==4);
adaptiveUpSampleShape(rgpxlcSrc, rgpxlcTmp,4,4);
Int iSizeTmp=12;
Int iSizeSrc=8;
Int i,j;
// top left corner
rgpxlcTmp[0]=rgpxlcSrc[0];
rgpxlcTmp[1]=rgpxlcSrc[1];
rgpxlcTmp[iSizeTmp]=rgpxlcSrc[iSizeSrc];
rgpxlcTmp[iSizeTmp+1]=rgpxlcSrc[iSizeSrc+1];
// top right corner
rgpxlcTmp[iSizeTmp-2]=rgpxlcSrc[iSizeSrc-2];
rgpxlcTmp[iSizeTmp-1]=rgpxlcSrc[iSizeSrc-1];
rgpxlcTmp[(iSizeTmp<<1)-2]=rgpxlcSrc[(iSizeSrc<<1)-2];
rgpxlcTmp[(iSizeTmp<<1)-1]=rgpxlcSrc[(iSizeSrc<<1)-1];
// top border
for(j=0;j<2;j++)
for(i=BAB_BORDER;i<iSizeTmp-BAB_BORDER;i++)
rgpxlcTmp[j*iSizeTmp+i]=rgpxlcSrc[j*iSizeSrc+i/2+1];
// left border
for(i=0;i<2;i++)
for(j=BAB_BORDER;j<iSizeTmp-BAB_BORDER;j++)
rgpxlcTmp[j*iSizeTmp+i]=rgpxlcSrc[(j/2+1)*iSizeSrc+i];
/*Int iTmp = m_iWidthCurrBAB;
m_iInverseCR = 2;
m_iWidthCurrBAB = 12;
subsampleLeftTopBorderFromVOP (ppxlcBYFrm, rgpxlcTmp);
m_iInverseCR = 4;
m_iWidthCurrBAB = iTmp;*/
adaptiveUpSampleShape(rgpxlcTmp, rgpxlcDst,8,8);
}
}
Int CVideoObject::getContextUS( PixelC a,
PixelC b,
PixelC c,
PixelC d,
PixelC e,
PixelC f,
PixelC g,
PixelC h)
{
Int ret =(Int)(a+(b<<1)+(c<<2)+(d<<3)+(e<<4)+(f<<5)+(g<<6)+(h<<7));
return ret;
}
PixelC CVideoObject::getRefValue(const PixelC* ppxlcRow,
Int x_adr, Int y_adr,
Int h_size, Int v_size)
{
assert ((x_adr>=-2) && (x_adr<=h_size+1) && (y_adr>=-2) && (y_adr<=v_size+1));
Int x_lim, y_lim;
PixelC ret;
if(x_adr>=0 && x_adr<h_size && y_adr>=0 && y_adr<v_size) {
ret=(ppxlcRow[y_adr*(h_size+BAB_BORDER_BOTH)+x_adr]>0) ? 1 : 0;
} else {
if(y_adr<0 || (x_adr<0 && y_adr<v_size)) {
ret=(ppxlcRow[y_adr*(h_size+BAB_BORDER_BOTH)+x_adr]>0) ? 1 : 0;
} else {
x_lim=(x_adr<0)? 0: (x_adr>=h_size)? h_size-1 :x_adr;
y_lim=(y_adr<0)? 0: (y_adr>=v_size)? v_size-1 :y_adr;
ret=(ppxlcRow[y_lim*(h_size+BAB_BORDER_BOTH)+x_lim]>0) ? 1 : 0;
}
}
return ret;
}
Void CVideoObject::adaptiveUpSampleShape (const PixelC* rgpxlcSrc,
PixelC* rgpxlcDst,
Int h_size, Int v_size)
{
Int x[12], y[12], other_total, context, rvalue, th, m;
Int width_up = h_size << 1;
Int width_up_border = width_up + BAB_BORDER_BOTH;
Int j, i, py, px, py_st, py_en, px_st, px_en, py_p;
PixelC val[12];
const PixelC* ppxlcRow = rgpxlcSrc + BAB_BORDER+BAB_BORDER * (h_size + BAB_BORDER_BOTH);
/* -- 4 5 -- */
/* 6 0 1 7 */
/* 8 2 3 9 */
/* -- 10 11 -- */
for (j = -1; j < v_size; j++) {
y[0] = y[1] = y[6] =y[7] = j;
y[2] = y[3] = y[8] =y[9] = j + 1;
y[4] = y[5] = j - 1;
y[10]= y[11]= j + 2;
if (j > -1)
py_st = 0;
else
py_st = 1;
if (j < v_size - 1)
py_en = 2;
else
py_en = 1;
for(i = -1; i < h_size; i++) {
x[0] = x[2] = x[4] = x[10] = i;
x[1] = x[3] = x[5] = x[11] = i+1;
x[6] = x[8] = i - 1;
x[7] = x[9] = i + 2;
for(m = 0; m < 12; m++)
val[m] = getRefValue (ppxlcRow, x[m], y[m], h_size, v_size);
if (i > -1)
px_st = 0;
else
px_st = 1;
if (i < h_size-1)
px_en = 2;
else
px_en=1;
other_total = val[4] + val[5] + val[6] + val[7] + val[8] + val[9] + val[10] + val[11];
for (py = py_st; py < py_en; py++) {
py_p = ((j << 1) + 1 + py + BAB_BORDER) * width_up_border + (i << 1) + 1;
for (px = px_st; px < px_en; px++) {
if(px < 1 && py < 1) {
context = getContextUS (val[5], val[4], val[6], val[8], val[10], val[11], val[9], val[7]);
th = grgchInterpolationFilterTh[context];
rvalue = (val[0] << 2) + ((val[1] + val[2] + val[3]) << 1) + other_total;
}
else if (py < 1) {
context = getContextUS(val[9], val[7], val[5], val[4], val[6], val[8], val[10], val[11]);
th = grgchInterpolationFilterTh [context];
rvalue = (val[1] << 2) + ((val[0] + val[2] + val[3]) << 1) + other_total;
}
else if (px < 1) {
context = getContextUS(val[6], val[8], val[10], val[11], val[9], val[7], val[5], val[4]);
th = grgchInterpolationFilterTh [context];
rvalue = (val[2] << 2) + ((val[1] + val[0] + val[3]) << 1) + other_total;
}
else {
context = getContextUS(val[10], val[11], val[9], val[7], val[5], val[4], val[6], val[8]);
th = grgchInterpolationFilterTh [context];
rvalue = (val[3] << 2) + ((val[1] + val[2] + val[0]) << 1) + other_total;
}
rgpxlcDst [py_p+(px+BAB_BORDER)] = (rvalue > th) ? opaqueValue: transpValue;
}
}
}
}
}
Void CVideoObject::copyLeftTopBorderFromVOP (PixelC* ppxlcSrc, PixelC* ppxlcDst)
{
PixelC* ppxlcSrcTop1 = ppxlcSrc - BAB_BORDER * m_iFrameWidthY - BAB_BORDER;
PixelC* ppxlcSrcTop2 = ppxlcSrcTop1 + m_iFrameWidthY;
PixelC* ppxlcSrcLeft1 = ppxlcSrcTop1;
PixelC* ppxlcSrcLeft2 = ppxlcSrcLeft1 + 1;
PixelC* ppxlcDstTop1 = ppxlcDst;
PixelC* ppxlcDstTop2 = ppxlcDst + TOTAL_BAB_SIZE;
PixelC* ppxlcDstLeft = ppxlcDst;
CoordI iPixel;
// Modified for error resilient mode by Toshiba(1997-11-14)
for (iPixel = 0; iPixel < BAB_BORDER; iPixel++) {
if (!m_bVPNoLeftTop) {
ppxlcDstTop1 [iPixel] = *ppxlcSrcTop1;
//src pixel never out of bound due to padding of Ref1
ppxlcDstTop2 [iPixel] = *ppxlcSrcTop2;
//BY should be intialized as zero outside of VOP
}
else {
ppxlcDstTop1 [iPixel] = (PixelC) 0;
ppxlcDstTop2 [iPixel] = (PixelC) 0;
}
ppxlcSrcTop1++;
ppxlcSrcTop2++;
}
for (iPixel = BAB_BORDER; iPixel < TOTAL_BAB_SIZE-BAB_BORDER; iPixel++) {
if (!m_bVPNoTop) {
ppxlcDstTop1 [iPixel] = *ppxlcSrcTop1;
//src pixel never out of bound due to padding of Ref1
ppxlcDstTop2 [iPixel] = *ppxlcSrcTop2;
//BY should be intialized as zero outside of VOP
}
else {
ppxlcDstTop1 [iPixel] = (PixelC) 0;
ppxlcDstTop2 [iPixel] = (PixelC) 0;
}
ppxlcSrcTop1++;
ppxlcSrcTop2++;
}
for (iPixel = TOTAL_BAB_SIZE-BAB_BORDER; iPixel < TOTAL_BAB_SIZE; iPixel++) {
if (!m_bVPNoRightTop) {
ppxlcDstTop1 [iPixel] = *ppxlcSrcTop1;
//src pixel never out of bound due to padding of Ref1
ppxlcDstTop2 [iPixel] = *ppxlcSrcTop2;
//BY should be intialized as zero outside of VOP
}
else {
ppxlcDstTop1 [iPixel] = (PixelC) 0;
ppxlcDstTop2 [iPixel] = (PixelC) 0;
}
ppxlcSrcTop1++;
ppxlcSrcTop2++;
}
ppxlcSrcLeft1 += BAB_BORDER*m_iFrameWidthY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -