📄 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 Laboratoriesin 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.cppAbstract: Sprite Encoder.Revision History:*************************************************************************/#include <stdio.h>#include <iostream.h>#include <fstream.h>#include <math.h>#include <stdlib.h>#include "basic.hpp"#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_FILEstatic 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; } } m_pentrencSet->m_pentrencWrpPnt->encodeSymbol(lSz, "SPRT_Warp_Point"); // huffman encode 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 + lSz + 1; } } return nBits;}//low latency stuff from now onstatic 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; m_iPieceXoffset= (rctRefFrameY.left - m_rctSptExp.left) / MB_SIZE; m_iPieceYoffset= (rctRefFrameY.top - m_rctSptExp.top) / MB_SIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -