📄 sptenc.cpp
字号:
/*************************************************************************
This software module was originally developed by
Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
(date: Augest, 1997)
and also edited by
David B. Shu (dbshu@hrl.com), Hughes Electronics/HRL Laboratories
and also edited by
Yoshinori Suzuki (Hitachi, Ltd.)
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:
sptenc.cpp
Abstract:
Sprite Encoder.
Revision History:
*************************************************************************/
#include <stdio.h>
#include <fstream.h>
#include <math.h>
#include <stdlib.h>
#include "typeapi.h"
#include "codehead.h"
#include "global.hpp"
#include "entropy/bitstrm.hpp"
#include "entropy/entropy.hpp"
#include "entropy/huffman.hpp"
#include "mode.hpp"
#include "dct.hpp"
#include "vopses.hpp"
#include "vopseenc.hpp"
#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#endif // __MFC_
Void CVideoObjectEncoder::encodeSptTrajectory (Time t, const CSiteD* rgstDest, const CRct& rctWarp)
// code sprite trajactory and make reconstructed frame
{
m_t = t;
m_statsVOP.reset ();
m_pbitstrmOut->reset ();
cout << "\nVOP " << m_uiVOId << "\n";
m_vopmd.vopPredType = SPRITE;
m_rctCurrVOPY = rctWarp;
codeVOPHead ();
cout << "\t" << "Time..." << m_t << " (" << m_t/m_volmd.dFrameHz << " sec)\n";
cout.flush ();
if (m_iNumOfPnts > 0) {
quantizeSptTrajectory (rgstDest, rctWarp);
codeWarpPoints ();
}
if (m_sptMode != BASIC_SPRITE)
encodeSpritePiece (t);
if (m_iNumOfPnts > 0) {
if(m_iNumOfPnts==2 || m_iNumOfPnts==3) {
FastAffineWarp (rctWarp, rctWarp / 2, m_uiWarpingAccuracy, m_iNumOfPnts);
}
else {
CPerspective2D perspYA (m_iNumOfPnts, m_rgstSrcQ, m_rgstDstQ, m_uiWarpingAccuracy);
warpYA (perspYA, rctWarp, m_uiWarpingAccuracy);
CSiteD rgstSrcQUV [4], rgstDstQUV [4];
for (Int i = 0; i < m_iNumOfPnts; i++) {
rgstSrcQUV [i] = (m_rgstSrcQ [i] - CSiteD (0.5, 0.5)) / 2;
rgstDstQUV [i] = (m_rgstDstQ [i] - CSiteD (0.5, 0.5)) / 2;
}
CPerspective2D perspUV (m_iNumOfPnts, rgstSrcQUV, rgstDstQUV, m_uiWarpingAccuracy);
warpUV (perspUV, rctWarp / 2, m_uiWarpingAccuracy);
}
}
// Begin: modified by Hughes 4/9/98
// if((!tentativeFirstSpriteVop) && (m_sptMode == BASIC_SPRITE)) {
// Transmit sprite_trasmit_mode="stop" at the first Sprite VOP.
// This is a tentative solution for bitstream exchange of
// normal sprite bitstreams. This part needs to be changed
// when low latency sprites is integrated.
// m_pbitstrmOut->putBits (0, 2, "sprite_transmit_mode");
// tentativeFirstSpriteVop = 1;
// }
// End: modified by Hughes 4/9/98
m_statsVOP.nBitsStuffing += m_pbitstrmOut->flush ();
m_statsVOL += m_statsVOP;
}
Void CVideoObjectEncoder::quantizeSptTrajectory (const CSiteD* rgstDest, CRct rctWarp)
// construction of m_rgstSrcQ and m_rgstDstQ
{
CSiteD rgstSrcQ [4];
rgstSrcQ [0] = CSiteD (rctWarp.left, rctWarp.top);
rgstSrcQ [1] = CSiteD (rctWarp.right, rctWarp.top);
rgstSrcQ [2] = CSiteD (rctWarp.left, rctWarp.bottom);
rgstSrcQ [3] = CSiteD (rctWarp.right, rctWarp.bottom);
for (Int i = 0; i < m_iNumOfPnts; i++) {
// quantization rgstSrc
CoordD x = rgstSrcQ [i].x, y = rgstSrcQ [i].y;
Int rnd = (x > 0) ? (Int) (2.0 * x + .5) : (Int) (2.0 * x - .5);
m_rgstSrcQ [i].x = (CoordD) rnd / (CoordD) 2.;
rnd = (y > 0) ? (Int) (2.0 * y + .5) : (Int) (2.0 * y - .5);
m_rgstSrcQ [i].y = (CoordD) rnd / (CoordD) 2.;
// quantization rgstDest
x = rgstDest [i].x;
y = rgstDest [i].y;
rnd = (x > 0) ? (Int) (2.0 * x + .5) : (Int) (2.0 * x - .5);
m_rgstDstQ [i].x = (CoordD) rnd / (CoordD) 2.;
rnd = (y > 0) ? (Int) (2.0 * y + .5) : (Int) (2.0 * y - .5);
m_rgstDstQ [i].y = (CoordD) rnd / (CoordD) 2.;
}
}
UInt CVideoObjectEncoder::codeWarpPoints ()
{
UInt nBits = 0;
assert (m_iNumOfPnts > 0);
// Dest corner points MV encoding
// construct u, v, du, dv
Int rgiU [4], rgiV [4], rgiDU [4], rgiDV [4];
Int j;
for (j = 0; j < m_iNumOfPnts; j++) { //here both m_rgstDstQ and m_rgstSrcQ are in fulpel accuracy
rgiU [j] = (Int) (2 * (m_rgstDstQ [j].x - m_rgstSrcQ [j].x));
rgiV [j] = (Int) (2 * (m_rgstDstQ [j].y - m_rgstSrcQ [j].y));
}
rgiDU [0] = rgiU [0]; rgiDV [0] = rgiV [0];
rgiDU [1] = rgiU [1] - rgiU [0]; rgiDV [1] = rgiV [1] - rgiV [0];
rgiDU [2] = rgiU [2] - rgiU [0]; rgiDV [2] = rgiV [2] - rgiV [0];
rgiDU [3] = rgiU [3] - rgiU [2] - rgiU [1] + rgiU [0]; rgiDV [3] = rgiV [3] - rgiV [2] - rgiV [1] + rgiV [0];
// du, dv encoding
Int rgiWrpPnt0Del [2];
COutBitStream* pobstrmWrpPt0 = m_pentrencSet->m_pentrencWrpPnt -> bitstream ();
pobstrmWrpPt0->trace (m_rgstDstQ [0], "SPRT_Warp_Point_Q");
for (j = 0; j < m_iNumOfPnts; j++) {
rgiWrpPnt0Del [0] = rgiDU [j]; //make them half pel units
rgiWrpPnt0Del [1] = rgiDV [j]; //make them half pel units
for (UInt iXorY = 0; iXorY < 2; iXorY++) {
assert (rgiWrpPnt0Del [iXorY] >= -16383 && rgiWrpPnt0Del [iXorY] <= 16383);
UInt uiAbsWrpPnt0Del = (UInt) abs (rgiWrpPnt0Del [iXorY]);
Long lSz = 0;
for (Int i = 14; i > 0; i--) {
if (uiAbsWrpPnt0Del & (1 << (i - 1))) {
lSz = i;
break;
}
}
nBits += m_pentrencSet->m_pentrencWrpPnt->encodeSymbol(lSz, "SPRT_Warp_Point"); // huffman encode // GMC
if (rgiWrpPnt0Del [iXorY] > 0)
pobstrmWrpPt0->putBits (rgiWrpPnt0Del [iXorY], lSz, "SPRT_Warp_Point_Sgn"); //fix length code
else if (rgiWrpPnt0Del[iXorY] < 0)
pobstrmWrpPt0->putBits (~abs(rgiWrpPnt0Del [iXorY]), lSz, "SPRT_Warp_Point_Sgn"); //fix length code
pobstrmWrpPt0->putBits (MARKER_BIT, 1, "Marker_Bit");
nBits += lSz + 1; // GMC
}
}
return nBits;
}
//low latency stuff from now on
static CRct InitPieceRect ;
static CRct InitPartialRect ;
// code initial sprite piece
Void CVideoObjectEncoder::encodeInitSprite (const CRct& rctOrg)
{
m_rctOrg = rctOrg;
if (( m_rctSpt.width < rctOrg.width) && // handle the bream caption case
( m_rctSpt.height() < rctOrg.height() ) ) {
m_vopmd.SpriteXmitMode = NEXT;
encode (TRUE, -1, IVOP);
return;
}
m_bSptZoom = FALSE; // Assuming sprite is not zooming
m_bSptHvPan = TRUE; // Assuming sprite is panning horizontally
m_bSptRightPiece = TRUE; // Assuming sent right side of the sprite piece
Int OldCount = m_pbitstrmOut -> getCounter (); // used to compute average macroblock bits
// save sprite object information
m_pvopcSpt = m_pvopcOrig;
m_rctSptQ = m_pvopcSpt -> whereY ();
if (m_volmd.fAUsage != RECTANGLE) {
m_iPieceWidth = m_rctSptQ.width - 2 * EXPANDY_REF_FRAME;
m_iPieceHeight = m_rctSptQ.height() - 2 * EXPANDY_REF_FRAME;
m_rctCurrVOPY = CRct(0, 0, m_iPieceWidth, m_iPieceHeight);
}
// Begin: modified by Hughes 4/9/98
// m_rctSptExp = m_rctCurrVOPY; // see initialSpritePiece()
// end: modified by Hughes 4/9/98
m_iNumMBX = m_rctSptExp.width / MB_SIZE;
m_iNumMBY = m_rctSptExp.height () / MB_SIZE;
m_ppPieceMBstatus = new SptMBstatus* [m_iNumMBY];
m_ppUpdateMBstatus = new SptMBstatus* [m_iNumMBY];
m_rgmbmdSpt = new CMBMode* [m_iNumMBY];
m_rgpmbmCurr_Spt = new MacroBlockMemory** [m_iNumMBY];
// Begin: modified by Hughes 4/9/98
Int iNumMB = m_iNumMBX * m_iNumMBY;
m_rgmbmdSprite = new CMBMode [iNumMB];
Int iMBY;
// Int iMBX, iMBY;
// end: modified by Hughes 4/9/98
Int iMB, iBlk;
Int nBlk = (m_volmd.fAUsage == EIGHT_BIT) ? 10 : 6;
for (iMBY = 0; iMBY < m_iNumMBY; iMBY++) {
m_ppPieceMBstatus[iMBY] = new SptMBstatus [m_iNumMBX];
m_ppUpdateMBstatus[iMBY] = new SptMBstatus [m_iNumMBX];
m_rgmbmdSpt[iMBY] = new CMBMode [m_iNumMBX];
m_rgpmbmCurr_Spt[iMBY] = new MacroBlockMemory* [m_iNumMBX];
for (iMB = 0; iMB < m_iNumMBX; iMB++) {
m_rgpmbmCurr_Spt[iMBY][iMB] = new MacroBlockMemory;
m_rgpmbmCurr_Spt[iMBY][iMB]->rgblkm = new BlockMemory [nBlk];
for (iBlk = 0; iBlk < nBlk; iBlk++) {
(m_rgpmbmCurr_Spt[iMBY][iMB]->rgblkm) [iBlk] = new Int [(BLOCK_SIZE << 1) - 1];
}
// Begin: modified by Hughes 4/9/98
m_ppPieceMBstatus[iMBY][iMB] = NOT_DONE;
m_ppUpdateMBstatus[iMBY][iMB] = NOT_DONE;
// end: modified by Hughes 4/9/98
}
}
// Begin: modified by Hughes 4/9/98
/*
CRct rctRefFrameY ;
if (m_volmd.fAUsage != RECTANGLE)
{
m_pvopcSptP = new CVOPU8YUVBA (*m_pvopcSpt, m_volmd.fAUsage, m_rctSptPieceY);
m_rctSptPieceY = findTightBoundingBox (m_pvopcSptP);
delete m_pvopcSptP;
}
rctRefFrameY = m_rctSptPieceY ;
m_rctCurrVOPY = rctRefFrameY;
m_rctSptPieceY.shift(m_rctSpt.left, m_rctSpt.top); // absolute coordinates for VOP
if ( m_sptMode == PIECE_UPDATE)
m_vopmd.SpriteXmitMode = UPDATE;
// encode initial sprite piece
m_pvopcSptP = new CVOPU8YUVBA (*m_pvopcSpt, m_volmd.fAUsage, rctRefFrameY);
m_rctRefFrameY = CRct (
-EXPANDY_REF_FRAME, -EXPANDY_REF_FRAME,
EXPANDY_REF_FRAME + rctRefFrameY.width,
EXPANDY_REF_FRAME + rctRefFrameY.height()
);
m_rctRefFrameY.shift (rctRefFrameY.left, rctRefFrameY.top);
m_rctRefFrameUV = m_rctRefFrameY.downSampleBy2 ();
m_pvopcOrig = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
VOPOverlay (*m_pvopcSptP, *m_pvopcOrig);
m_pvopcOrig->setBoundRct (rctRefFrameY);
// dshu: begin of modification
delete m_pvopcRefQ0;
delete m_pvopcRefQ1;
// dshu: end of modification
m_pvopcRefQ1 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
m_pvopcRefQ0 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
m_iFrameWidthY = m_pvopcRefQ0->whereY ().width;
m_iFrameWidthUV = m_pvopcRefQ0->whereUV ().width;
m_iFrameWidthYxMBSize = MB_SIZE * m_pvopcRefQ0->whereY ().width;
m_iFrameWidthYxBlkSize = BLOCK_SIZE * m_pvopcRefQ0->whereY ().width;
m_iFrameWidthUVxBlkSize = BLOCK_SIZE * m_pvopcRefQ0->whereUV ().width;
m_iPieceHeight = rctRefFrameY.height () / MB_SIZE;
m_iPieceWidth= rctRefFrameY.width / MB_SIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -