sptenc.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:33k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*************************************************************************
  2. This software module was originally developed by 
  3. Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
  4. (date: Augest, 1997)
  5. and also edited by
  6. David B. Shu (dbshu@hrl.com), Hughes Electronics/HRL Laboratories
  7. in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). 
  8. This software module is an implementation of a part of one or more MPEG-4 Video tools 
  9. as specified by the MPEG-4 Video. 
  10. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications 
  11. thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. 
  12. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. 
  13. The original developer of this software module and his/her company, 
  14. the subsequent editors and their companies, 
  15. and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. 
  16. Copyright is not released for non MPEG-4 Video conforming products. 
  17. Microsoft retains full right to use the code for his/her own purpose, 
  18. assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. 
  19. This copyright notice must be included in all copies or derivative works. 
  20. Copyright (c) 1996, 1997.
  21. Module Name:
  22. sptenc.cpp
  23. Abstract:
  24. Sprite Encoder.
  25. Revision History:
  26. *************************************************************************/
  27. #include <stdio.h>
  28. #include <iostream.h>
  29. #include <fstream.h>
  30. #include <math.h>
  31. #include <stdlib.h>
  32. #include "basic.hpp"
  33. #include "typeapi.h"
  34. #include "codehead.h"
  35. #include "global.hpp"
  36. #include "entropy/bitstrm.hpp"
  37. #include "entropy/entropy.hpp"
  38. #include "entropy/huffman.hpp"
  39. #include "mode.hpp"
  40. #include "dct.hpp"
  41. #include "vopses.hpp"
  42. #include "vopseenc.hpp"
  43. #ifdef __MFC_
  44. #ifdef _DEBUG
  45. #undef THIS_FILE
  46. static char BASED_CODE THIS_FILE[] = __FILE__;
  47. #endif
  48. #define new DEBUG_NEW    
  49. #endif // __MFC_
  50. Void CVideoObjectEncoder::encodeSptTrajectory (Time t, const CSiteD* rgstDest, const CRct& rctWarp)
  51. // code sprite trajactory and make reconstructed frame
  52. {
  53. m_t = t;
  54. m_statsVOP.reset ();
  55. m_pbitstrmOut->reset ();
  56. cout << "nVOP " << m_uiVOId << "n";
  57. m_vopmd.vopPredType = SPRITE;
  58. m_rctCurrVOPY = rctWarp;
  59. codeVOPHead ();
  60. cout << "t" << "Time..." << m_t << " (" << m_t/m_volmd.dFrameHz << " sec)n";
  61. cout.flush ();
  62. if (m_iNumOfPnts > 0) {
  63. quantizeSptTrajectory (rgstDest, rctWarp);
  64. codeWarpPoints ();
  65. }
  66. if (m_sptMode != BASIC_SPRITE)
  67. encodeSpritePiece (t);
  68. if (m_iNumOfPnts > 0) {
  69.         if(m_iNumOfPnts==2 || m_iNumOfPnts==3) {
  70. FastAffineWarp (rctWarp, rctWarp / 2, m_uiWarpingAccuracy, m_iNumOfPnts);
  71.         }
  72.         else {
  73. CPerspective2D perspYA (m_iNumOfPnts, m_rgstSrcQ, m_rgstDstQ, m_uiWarpingAccuracy);
  74. warpYA (perspYA, rctWarp, m_uiWarpingAccuracy);
  75. CSiteD rgstSrcQUV [4], rgstDstQUV [4];
  76. for (Int i = 0; i < m_iNumOfPnts; i++) {
  77. rgstSrcQUV [i] = (m_rgstSrcQ [i] - CSiteD (0.5, 0.5)) / 2;
  78. rgstDstQUV [i] = (m_rgstDstQ [i] - CSiteD (0.5, 0.5)) / 2;
  79. }
  80. CPerspective2D perspUV (m_iNumOfPnts, rgstSrcQUV, rgstDstQUV, m_uiWarpingAccuracy);
  81. warpUV (perspUV, rctWarp / 2, m_uiWarpingAccuracy);
  82. }
  83. }
  84. // Begin: modified by Hughes   4/9/98
  85. // if((!tentativeFirstSpriteVop) &&  (m_sptMode == BASIC_SPRITE)) {
  86. // Transmit sprite_trasmit_mode="stop" at the first Sprite VOP.
  87. // This is a tentative solution for bitstream exchange of
  88. // normal sprite bitstreams. This part needs to be changed
  89. // when low latency sprites is integrated.
  90. // m_pbitstrmOut->putBits (0, 2, "sprite_transmit_mode");
  91. // tentativeFirstSpriteVop = 1;
  92. // }
  93. // End: modified by Hughes   4/9/98
  94. m_statsVOP.nBitsStuffing += m_pbitstrmOut->flush ();
  95. m_statsVOL += m_statsVOP;
  96. }
  97. Void CVideoObjectEncoder::quantizeSptTrajectory (const CSiteD* rgstDest, CRct rctWarp)
  98. // construction of m_rgstSrcQ and m_rgstDstQ
  99. {
  100. CSiteD rgstSrcQ [4];
  101. rgstSrcQ [0] = CSiteD (rctWarp.left, rctWarp.top);
  102. rgstSrcQ [1] = CSiteD (rctWarp.right, rctWarp.top);
  103. rgstSrcQ [2] = CSiteD (rctWarp.left, rctWarp.bottom);
  104. rgstSrcQ [3] = CSiteD (rctWarp.right, rctWarp.bottom);
  105. for (Int i = 0; i < m_iNumOfPnts; i++) {
  106. // quantization rgstSrc
  107. CoordD x = rgstSrcQ [i].x, y = rgstSrcQ [i].y;
  108. Int rnd = (x > 0) ? (Int) (2.0 * x + .5) : (Int) (2.0 * x - .5);
  109. m_rgstSrcQ [i].x = (CoordD) rnd / (CoordD) 2.;
  110. rnd = (y > 0) ? (Int) (2.0 * y + .5) : (Int) (2.0 * y - .5);
  111. m_rgstSrcQ [i].y = (CoordD) rnd / (CoordD) 2.;
  112. // quantization rgstDest
  113. x = rgstDest [i].x;
  114. y = rgstDest [i].y;
  115. rnd = (x > 0) ? (Int) (2.0 * x + .5) : (Int) (2.0 * x - .5);
  116. m_rgstDstQ [i].x = (CoordD) rnd / (CoordD) 2.;
  117. rnd = (y > 0) ? (Int) (2.0 * y + .5) : (Int) (2.0 * y - .5);
  118. m_rgstDstQ [i].y = (CoordD) rnd / (CoordD) 2.;
  119. }
  120. }
  121. UInt CVideoObjectEncoder::codeWarpPoints ()
  122. {
  123. UInt nBits = 0;
  124. assert (m_iNumOfPnts > 0);
  125. // Dest corner points MV encoding
  126. // construct u, v, du, dv
  127. Int rgiU [4], rgiV [4], rgiDU [4], rgiDV [4];
  128. Int j;
  129. for (j = 0; j < m_iNumOfPnts; j++) {  //here both m_rgstDstQ and m_rgstSrcQ are in fulpel accuracy
  130. rgiU [j] = (Int) (2 * (m_rgstDstQ [j].x -  m_rgstSrcQ [j].x));
  131. rgiV [j] = (Int) (2 * (m_rgstDstQ [j].y -  m_rgstSrcQ [j].y));
  132. }
  133. rgiDU [0] = rgiU [0]; rgiDV [0] = rgiV [0];
  134. rgiDU [1] = rgiU [1] - rgiU [0]; rgiDV [1] = rgiV [1] - rgiV [0];
  135. rgiDU [2] = rgiU [2] - rgiU [0]; rgiDV [2] = rgiV [2] - rgiV [0];
  136. rgiDU [3] = rgiU [3] - rgiU [2] - rgiU [1] + rgiU [0]; rgiDV [3] = rgiV [3] - rgiV [2] - rgiV [1] + rgiV [0];
  137. // du, dv encoding
  138. Int rgiWrpPnt0Del [2];
  139. COutBitStream* pobstrmWrpPt0 = m_pentrencSet->m_pentrencWrpPnt -> bitstream ();
  140. pobstrmWrpPt0->trace (m_rgstDstQ [0], "SPRT_Warp_Point_Q");
  141. for (j = 0; j < m_iNumOfPnts; j++) { 
  142. rgiWrpPnt0Del [0] = rgiDU [j]; //make them half pel units
  143. rgiWrpPnt0Del [1] = rgiDV [j]; //make them half pel units
  144. for (UInt iXorY = 0; iXorY < 2; iXorY++) {
  145. assert (rgiWrpPnt0Del [iXorY] >= -16383 && rgiWrpPnt0Del [iXorY] <= 16383);
  146. UInt uiAbsWrpPnt0Del = (UInt) abs (rgiWrpPnt0Del [iXorY]);
  147. Long lSz = 0;
  148. for (Int i = 14; i > 0; i--) {
  149. if (uiAbsWrpPnt0Del & (1 << (i - 1))) {
  150. lSz = i;
  151. break;
  152. }
  153. }
  154. m_pentrencSet->m_pentrencWrpPnt->encodeSymbol(lSz, "SPRT_Warp_Point"); // huffman encode 
  155.  
  156. if (rgiWrpPnt0Del [iXorY] > 0)
  157. pobstrmWrpPt0->putBits (rgiWrpPnt0Del [iXorY], lSz, "SPRT_Warp_Point_Sgn"); //fix length code
  158. else if (rgiWrpPnt0Del[iXorY] < 0)
  159. pobstrmWrpPt0->putBits (~abs(rgiWrpPnt0Del [iXorY]), lSz, "SPRT_Warp_Point_Sgn"); //fix length code
  160. pobstrmWrpPt0->putBits (MARKER_BIT, 1, "Marker_Bit");
  161. nBits += lSz + lSz + 1;
  162. }
  163. }
  164. return nBits;
  165. }
  166. //low latency stuff from now on
  167. static CRct InitPieceRect ;
  168. static CRct InitPartialRect ;
  169. // code initial sprite piece 
  170. Void CVideoObjectEncoder::encodeInitSprite (const CRct& rctOrg)
  171. {
  172. m_rctOrg =  rctOrg;
  173. if (( m_rctSpt.width < rctOrg.width)  &&    // handle the bream caption case
  174. ( m_rctSpt.height() < rctOrg.height() ) ) {
  175. m_vopmd.SpriteXmitMode = NEXT;
  176. encode (TRUE, -1, IVOP);
  177. return;
  178. }
  179. m_bSptZoom = FALSE;  // Assuming sprite is not zooming
  180. m_bSptHvPan = TRUE;  // Assuming sprite is panning horizontally
  181. m_bSptRightPiece = TRUE;  // Assuming sent right side of the sprite piece
  182. /* Int OldCount =*/ m_pbitstrmOut -> getCounter (); // used to compute average macroblock bits
  183. //  save sprite object information
  184. m_pvopcSpt =  m_pvopcOrig;
  185. m_rctSptQ =  m_pvopcSpt -> whereY ();
  186. if (m_volmd.fAUsage != RECTANGLE) {
  187. m_iPieceWidth = m_rctSptQ.width - 2 * EXPANDY_REF_FRAME;
  188. m_iPieceHeight = m_rctSptQ.height() - 2 * EXPANDY_REF_FRAME;
  189. m_rctCurrVOPY = CRct(0, 0, m_iPieceWidth, m_iPieceHeight);
  190. }
  191. // Begin: modified by Hughes   4/9/98
  192. // m_rctSptExp = m_rctCurrVOPY;  // see initialSpritePiece()
  193. // end:  modified by Hughes   4/9/98
  194. m_iNumMBX = m_rctSptExp.width / MB_SIZE; 
  195. m_iNumMBY = m_rctSptExp.height () / MB_SIZE;
  196. m_ppPieceMBstatus = new SptMBstatus* [m_iNumMBY]; 
  197. m_ppUpdateMBstatus = new SptMBstatus* [m_iNumMBY];
  198. m_rgmbmdSpt = new CMBMode* [m_iNumMBY];
  199. m_rgpmbmCurr_Spt = new MacroBlockMemory** [m_iNumMBY];
  200. // Begin: modified by Hughes   4/9/98
  201. Int iNumMB = m_iNumMBX * m_iNumMBY;
  202. m_rgmbmdSprite = new CMBMode [iNumMB];
  203. Int iMBY;
  204. // Int iMBX, iMBY;
  205. // end:  modified by Hughes   4/9/98
  206. Int iMB, iBlk;
  207. Int nBlk = (m_volmd.fAUsage == EIGHT_BIT) ? 10 : 6;
  208. for (iMBY = 0; iMBY < m_iNumMBY; iMBY++) {
  209. m_ppPieceMBstatus[iMBY] = new SptMBstatus [m_iNumMBX];
  210. m_ppUpdateMBstatus[iMBY] = new SptMBstatus [m_iNumMBX];
  211. m_rgmbmdSpt[iMBY] = new CMBMode [m_iNumMBX];
  212. m_rgpmbmCurr_Spt[iMBY] = new MacroBlockMemory* [m_iNumMBX];
  213. for (iMB = 0; iMB < m_iNumMBX; iMB++) {
  214. m_rgpmbmCurr_Spt[iMBY][iMB] = new MacroBlockMemory;
  215. m_rgpmbmCurr_Spt[iMBY][iMB]->rgblkm = new BlockMemory [nBlk];
  216. for (iBlk = 0; iBlk < nBlk; iBlk++) {
  217. (m_rgpmbmCurr_Spt[iMBY][iMB]->rgblkm) [iBlk] = new Int [(BLOCK_SIZE << 1) - 1];
  218. }
  219. // Begin: modified by Hughes   4/9/98
  220. m_ppPieceMBstatus[iMBY][iMB] = NOT_DONE;
  221. m_ppUpdateMBstatus[iMBY][iMB] = NOT_DONE;
  222. // end:  modified by Hughes   4/9/98
  223. }
  224. }
  225. // Begin: modified by Hughes   4/9/98
  226. /*
  227. CRct rctRefFrameY ;
  228. if (m_volmd.fAUsage != RECTANGLE) 
  229. {
  230. m_pvopcSptP = new CVOPU8YUVBA (*m_pvopcSpt, m_volmd.fAUsage, m_rctSptPieceY);
  231. m_rctSptPieceY = findTightBoundingBox (m_pvopcSptP);
  232. delete m_pvopcSptP;
  233. }
  234. rctRefFrameY = m_rctSptPieceY ;
  235. m_rctCurrVOPY = rctRefFrameY;
  236. m_rctSptPieceY.shift(m_rctSpt.left, m_rctSpt.top);   // absolute coordinates for VOP
  237. if ( m_sptMode == PIECE_UPDATE)
  238. m_vopmd.SpriteXmitMode  = UPDATE;
  239.   // encode initial sprite piece
  240. m_pvopcSptP = new CVOPU8YUVBA (*m_pvopcSpt, m_volmd.fAUsage, rctRefFrameY);
  241. m_rctRefFrameY = CRct (
  242. -EXPANDY_REF_FRAME, -EXPANDY_REF_FRAME, 
  243. EXPANDY_REF_FRAME + rctRefFrameY.width, 
  244. EXPANDY_REF_FRAME + rctRefFrameY.height()
  245. );
  246. m_rctRefFrameY.shift (rctRefFrameY.left, rctRefFrameY.top);
  247. m_rctRefFrameUV = m_rctRefFrameY.downSampleBy2 ();
  248. m_pvopcOrig = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY); 
  249. VOPOverlay (*m_pvopcSptP, *m_pvopcOrig);
  250. m_pvopcOrig->setBoundRct (rctRefFrameY);
  251. // dshu: begin of modification  
  252. delete m_pvopcRefQ0;
  253. delete m_pvopcRefQ1;
  254. // dshu: end of modification
  255. m_pvopcRefQ1 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
  256.   m_pvopcRefQ0 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
  257. m_iFrameWidthY = m_pvopcRefQ0->whereY ().width;
  258. m_iFrameWidthUV = m_pvopcRefQ0->whereUV ().width;
  259. m_iFrameWidthYxMBSize = MB_SIZE * m_pvopcRefQ0->whereY ().width; 
  260. m_iFrameWidthYxBlkSize = BLOCK_SIZE * m_pvopcRefQ0->whereY ().width; 
  261. m_iFrameWidthUVxBlkSize = BLOCK_SIZE * m_pvopcRefQ0->whereUV ().width;
  262. m_iPieceHeight = rctRefFrameY.height () / MB_SIZE;
  263. m_iPieceWidth= rctRefFrameY.width  / MB_SIZE;
  264. m_iPieceXoffset= (rctRefFrameY.left - m_rctSptExp.left) / MB_SIZE;
  265. m_iPieceYoffset= (rctRefFrameY.top - m_rctSptExp.top) / MB_SIZE;
  266. if (m_volmd.fAUsage == RECTANGLE) {
  267. // m_rctCurrVOPY = CRct (0, 0, iSessionWidthRound, iSessionHeightRound);
  268. m_pvopcOrig->setBoundRct (m_rctCurrVOPY);
  269. m_rctCurrVOPUV = m_rctCurrVOPY.downSampleBy2 ();
  270. m_rctRefVOPY0 = m_rctCurrVOPY;
  271. m_rctRefVOPY0.expand (EXPANDY_REFVOP);
  272. m_rctRefVOPUV0 = m_rctRefVOPY0.downSampleBy2 ();
  273. m_rctRefVOPY1 = m_rctRefVOPY0;
  274. m_rctRefVOPUV1 = m_rctRefVOPUV0;
  275. m_rctRefVOPZoom0 = m_rctRefVOPY0.upSampleBy2 ();
  276. m_rctRefVOPZoom1 = m_rctRefVOPY1.upSampleBy2 ();
  277. m_pvopcRefOrig0->setBoundRct (m_rctRefVOPY0);
  278. m_pvopcRefOrig1->setBoundRct (m_rctRefVOPY1);
  279. computeVOLConstMembers (); // these VOP members are the same for all frames
  280. }
  281. m_tPiece = -1;
  282. encode (TRUE, -1, IVOP);
  283. m_pvopcSptQ = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctSptQ);  
  284. VOPOverlay(*m_pvopcRefQ1, *m_pvopcSptQ, 1);
  285.   delete m_pvopcSptP;   m_pvopcSptP = NULL;  
  286. delete m_pvopcOrig;   m_pvopcOrig  = NULL;
  287. delete m_pvopcRefQ0; m_pvopcRefQ0 = NULL;
  288. delete m_pvopcRefQ1;
  289. m_pvopcRefQ1 =  m_pvopcSptQ ; // to support "rgpvoenc [BASE_LAYER] -> swapRefQ1toSpt (); "
  290. m_iNumMBX = m_rctSptExp.width / MB_SIZE; 
  291. m_iNumMBY = m_rctSptExp.height () / MB_SIZE;
  292. CMBMode* pmbmd = m_rgmbmdRef;
  293. IntraPredDirection* Spreddir;
  294. IntraPredDirection* preddir;
  295. // initialize  MB hole status array
  296. Int iMB_left = (rctRefFrameY.left - m_rctSptExp.left) / MB_SIZE;
  297. Int iMB_right = (rctRefFrameY.right - m_rctSptExp.left) / MB_SIZE;  
  298. Int iMB_top = (rctRefFrameY.top - m_rctSptExp.top) / MB_SIZE;
  299. Int iMB_bottom = (rctRefFrameY.bottom - m_rctSptExp.top) / MB_SIZE;
  300. for (iMBY = 0; iMBY < m_iNumMBY; iMBY++) 
  301. for (iMBX = 0; iMBX < m_iNumMBX; iMBX++) {
  302. if ((iMBX >= iMB_left && iMBX < iMB_right) && (iMBY >= iMB_top && iMBY < iMB_bottom)) 
  303. {
  304. m_ppPieceMBstatus[iMBY][iMBX] = PIECE_DONE;
  305. m_rgmbmdSpt[iMBY][iMBX] = CMBMode (*pmbmd);
  306. Spreddir = m_rgmbmdSpt[iMBY][iMBX].m_preddir;
  307. preddir = (*pmbmd).m_preddir;
  308. memcpy (Spreddir, preddir, 10  * sizeof (IntraPredDirection));
  309. pmbmd++;
  310. }
  311. else
  312. m_ppPieceMBstatus[iMBY][iMBX] = NOT_DONE;
  313. m_ppUpdateMBstatus[iMBY][iMBX] = NOT_DONE;
  314. }
  315. Int Curr = (m_pbitstrmOut -> getCounter ()) - OldCount;
  316. Int Num_MB = (iMB_right-iMB_left) * (iMB_bottom-iMB_top);
  317. m_pSptmbBits[AVGPIECEMB] = Curr / Num_MB; // average macroblock bits used by a sprite piece
  318. InitPieceRect = rctRefFrameY; 
  319. InitPartialRect = InitPieceRect; 
  320. m_rctPieceQ = InitPieceRect;
  321. */
  322. #ifdef __TRACE_AND_STATS_
  323. m_pbitstrmOut -> trace (-1, "VOP_Time");
  324. #endif // __TRACE_AND_STATS_
  325. m_rctPieceQ = CRct ( m_rctSptPieceY.left, m_rctSptPieceY.top, m_rctSptPieceY.left, m_rctSptPieceY.top);
  326. m_pvopcSptQ = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctSptQ);  
  327. m_pvopcRefQ1 =  m_pvopcSptQ ; // to support "rgpvoenc [BASE_LAYER] -> swapRefQ1toSpt (); "
  328. m_pbitstrmOut->reset (); // inserted as a result of half day debug
  329. // end:  modified by Hughes   4/9/98
  330. m_tPiece = m_nFirstFrame;
  331. m_tUpdate = m_nFirstFrame;
  332. m_vopmd.SpriteXmitMode = PIECE;
  333. if ( m_sptMode == BASIC_SPRITE)
  334. m_vopmd.SpriteXmitMode  = NEXT;
  335. }
  336. Void CVideoObjectEncoder::initialSpritePiece (Int iSessionWidth, Int iSessionHeight)
  337. {
  338. // identify initial sprite piece
  339. CRct rctRefFrameY, rct ;
  340. Bool SpriteObject =  (m_sptMode == PIECE_UPDATE) || ( m_sptMode == BASIC_SPRITE);
  341. // Begin: modified by Hughes   4/9/98
  342. m_rctSptExp = CRct (0, 0, iSessionWidth, iSessionHeight);  // m_rctSptExp is specified in relative coordinate
  343. // end:  modified by Hughes   4/9/98
  344. if (!SpriteObject) 
  345. {
  346. if (m_iNumOfPnts == 0) 
  347. rct =  CRct (0, 0, iSessionWidth, iSessionHeight);
  348. else
  349. rct = InitialPieceRect (0);
  350. rctRefFrameY = CRct (rct.left, rct.top, rct.right, (rct.bottom + 16 - rct.height()/2));    //dshu: 12/22/97
  351. // rctRefFrameY = CRct (rct.left, rct.top, rct.right, (rct.bottom - rct.width/2));  
  352. }
  353. else
  354. rctRefFrameY = CRct (0, 0, iSessionWidth, iSessionHeight);
  355. if (!SpriteObject)
  356. rctRefFrameY =  PieceExpand (rctRefFrameY);
  357. m_rctSptPieceY =  rctRefFrameY;
  358. }
  359. CRct CVideoObjectEncoder::InitialPieceRect (Time ts)
  360. {
  361. CRct rctSpt, rctSptQ;
  362. CSiteD rgstSrcQ [4];
  363. rgstSrcQ [0] = CSiteD (m_rctOrg.left, m_rctOrg.top);
  364. rgstSrcQ [1] = CSiteD (m_rctOrg.right, m_rctOrg.top);
  365. rgstSrcQ [2] = CSiteD (m_rctOrg.left, m_rctOrg.bottom);
  366. rgstSrcQ [3] = CSiteD (m_rctOrg.right, m_rctOrg.bottom);
  367. for (Int i = 0; i < m_iNumOfPnts; i++) {
  368. // quantization rgstSrc
  369. CoordD x = rgstSrcQ [i].x, y = rgstSrcQ [i].y;
  370. Int rnd = (x > 0) ? (Int) (2.0 * x + .5) : (Int) (2.0 * x - .5);
  371. m_rgstSrcQ [i].x = (CoordD) rnd / (CoordD) 2.;
  372. rnd = (y > 0) ? (Int) (2.0 * y + .5) : (Int) (2.0 * y - .5);
  373. m_rgstSrcQ [i].y = (CoordD) rnd / (CoordD) 2.;
  374. }
  375.    
  376. rctSptQ = CornerWarp (m_pprgstDest[ts], m_rgstSrcQ); 
  377. rctSpt = CRct (rctSptQ.left, 0, rctSptQ.right, m_rctSpt.height());  
  378. return rctSpt;
  379. }
  380. CRct CVideoObjectEncoder::CornerWarp (const CSiteD* rgstDst, 
  381.   const CSiteD* rgstSrcQ)
  382. {
  383. CSiteD stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp;
  384. CPerspective2D persp (m_iNumOfPnts, rgstSrcQ, rgstDst, m_uiWarpingAccuracy);
  385. stdLeftTopWarp = (persp * CSiteD (0, 0)).s;
  386. stdRightTopWarp = (persp * CSiteD (m_rctOrg.width, 0)).s;
  387. stdLeftBottomWarp = (persp * CSiteD (0, m_rctOrg.height())).s;
  388. stdRightBottomWarp = (persp * CSiteD (m_rctOrg.width, m_rctOrg.height())).s;
  389. CRct rctWarp (stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp);
  390. UInt accuracy1 = 1 << (m_uiWarpingAccuracy + 1);
  391. rctWarp =  rctWarp / accuracy1 ; 
  392. rctWarp.shift(-m_rctSpt.left, -m_rctSpt.top);  // rectangle is w.r.t. UL corner of sprite object
  393. return rctWarp;
  394. }
  395. Void CVideoObjectEncoder::encodeSpritePiece (Time t)
  396. // code sprite pieces 
  397. {
  398. if (m_vopmd.SpriteXmitMode  == STOP)
  399. return ;
  400. if ((m_vopmd.SpriteXmitMode  == PIECE) || (m_vopmd.SpriteXmitMode  == UPDATE)){
  401. m_pvopcSptQ -> shift(-m_rctSpt.left, -m_rctSpt.top); // prepare m_pvopcSptQ to merge new piece
  402. UInt uiF = t + m_volmd.iTemporalRate;
  403. uiF = ( uiF >  m_nLastFrame) ?  m_nLastFrame :  uiF;
  404. UInt uiSptPieceSize = m_iBufferSize/(300/m_volmd.iTemporalRate);
  405. CRct rct = m_rctPieceQ;
  406. if (( m_sptMode != PIECE_UPDATE) && (m_tPiece == (Time) m_nFirstFrame))
  407. {
  408. // Begin: modified by Hughes   4/9/98
  409. InitPieceRect = encPiece (m_rctSptPieceY);
  410. rct = InitPieceRect;
  411. // End: modified by Hughes   4/9/98
  412. rct = CRct (rct.left, (rct.top - 3*MB_SIZE + m_rctSpt.height()/2), rct.right, m_rctSpt.height()); // dshu: 1/4/98  
  413. InitPartialRect = encPiece (rct);
  414. m_vopmd.SpriteXmitMode = UPDATE;
  415. m_rctUpdateQ = CRct ( rct.left, rct.top, rct.left, rct.bottom);
  416. CRct rcttemp = encPiece (rct);
  417. rcttemp = encPiece (CRct ( rct.left, m_rctPieceQ.top, rct.right, rct.top));
  418. m_vopmd.SpriteXmitMode = PIECE;
  419. m_tPiece =  uiF;
  420. if (m_iNumOfPnts == 0)
  421. m_vopmd.SpriteXmitMode  = NEXT; 
  422. }
  423. else  {
  424. if (( InitPartialRect.right >= InitPieceRect.right) &&
  425. ( InitPartialRect.left <= InitPieceRect.left))  {
  426. CRct rctSptQ = ZoomOrPan ();
  427. encSptPiece (rctSptQ, uiSptPieceSize);
  428. while ((m_tPiece < (Time) uiF) &&
  429. (m_vopmd.SpriteXmitMode  == PIECE) )
  430. encSptPiece (ZoomOrPan (), uiSptPieceSize);
  431. }
  432. else {
  433. m_bSptRightPiece = TRUE;
  434. encSptPiece (m_rctUpdateQ, uiSptPieceSize);
  435. InitPartialRect = m_rctUpdateQ;
  436. }
  437. Bool StartUpdate = (m_tPiece >= (Time) m_nLastFrame) 
  438. && (m_tUpdate == (Time) m_nFirstFrame);
  439. if ( StartUpdate ) {
  440. m_vopmd.SpriteXmitMode  = UPDATE;
  441. if(( t < (Time) m_nLastFrame) && (m_sptMode != PIECE_OBJECT)) {
  442. // identify initial update piece
  443. rct = InitialPieceRect (t-m_nFirstFrame);
  444. Int left = (rct.left < m_rctSptExp.left) ?  m_rctSptExp.left : rct.left;
  445. Int right = (rct.right > m_rctSptExp.right) ?  m_rctSptExp.right : rct.right;
  446. InitPieceRect = CRct (left, rct.top, right, rct.bottom);
  447. rct = InitPieceRect ;
  448. if (m_sptMode == PIECE_UPDATE) {
  449. cout << "t" << "n start sending updates for sprite..."  << "n";
  450. cout.flush ();
  451. m_tUpdate = -1;
  452. m_rctUpdateQ = CRct ( left, rct.top, left, rct.bottom);
  453. m_pSptmbBits[AVGUPDATEMB] = m_pSptmbBits[AVGUPDATEMB] ;
  454. rct = PieceSize (TRUE, uiSptPieceSize);
  455. }
  456. rct = encPiece (rct);
  457. InitPartialRect = m_rctUpdateQ;
  458. m_tUpdate = t;
  459. }
  460. else 
  461. m_vopmd.SpriteXmitMode = NEXT;
  462. }
  463. }
  464. m_pvopcSptQ -> shift(m_rctSpt.left, m_rctSpt.top);  // prepare m_pvopcSptQ for warping
  465. m_vopmd.vopPredType = SPRITE;
  466. // --- begin of bug fix (David Shu)
  467. if (m_volmd.fAUsage != RECTANGLE)
  468. {
  469. CRct r1 =  m_rctSptQ;
  470. m_rctSptQ = m_rctSptExp;
  471. m_rctCurrVOPY  = CRct(0,0, m_rctSptQ.width, m_rctSptQ.height());
  472. m_rctCurrVOPUV = m_rctCurrVOPY.downSampleBy2 ();
  473. m_rctRefFrameY = CRct (-EXPANDY_REF_FRAME, -EXPANDY_REF_FRAME,
  474. EXPANDY_REF_FRAME + m_rctSptQ.width, EXPANDY_REF_FRAME + m_rctSptQ.height());
  475. m_rctRefFrameUV = m_rctRefFrameY.downSampleBy2 ();
  476. setRefStartingPointers ();
  477. m_iFrameWidthY = m_rctRefFrameY.width;
  478. m_iFrameWidthUV = m_rctRefFrameUV.width;
  479. m_iFrameWidthYxMBSize = MB_SIZE * m_iFrameWidthY;
  480. m_iFrameWidthYxBlkSize = BLOCK_SIZE * m_iFrameWidthY;
  481. m_iFrameWidthUVxBlkSize = BLOCK_SIZE * m_iFrameWidthUV;
  482. m_iOffsetForPadY = m_rctRefFrameY.offset (m_rctCurrVOPY.left, m_rctCurrVOPY.top);
  483. m_iOffsetForPadUV = m_rctRefFrameUV.offset (m_rctCurrVOPUV.left,m_rctCurrVOPUV.top);
  484. padSprite() ;  //    final padding just before warping
  485. m_rctSptQ = r1;
  486. }
  487. // --- end of bug fix
  488. }
  489. if (m_vopmd.SpriteXmitMode  != STOP){
  490. SptXmitMode  PieceXmitMode = m_vopmd.SpriteXmitMode;
  491. if (m_vopmd.SpriteXmitMode  == NEXT )
  492. {
  493. PieceXmitMode = STOP ;
  494. m_vopmd.SpriteXmitMode  = STOP;
  495. m_iNumMBX = m_rctSptExp.width / MB_SIZE; 
  496. m_iNumMBY = m_rctSptExp.height () / MB_SIZE;
  497. Int nBlk = (m_volmd.fAUsage == EIGHT_BIT) ? 10 : 6;
  498. for (Int iMBY = 0; iMBY < m_iNumMBY; iMBY++){
  499. for (Int iMB = 0; iMB < m_iNumMBX; iMB++) {
  500. for (Int iBlk = 0; iBlk < nBlk; iBlk++)
  501. delete [] (m_rgpmbmCurr_Spt[iMBY][iMB]->rgblkm) [iBlk];
  502. delete [] m_rgpmbmCurr_Spt [iMBY][iMB]->rgblkm;
  503. delete [] m_rgpmbmCurr_Spt [iMBY][iMB];
  504. }
  505. delete [] m_ppPieceMBstatus[iMBY] ; 
  506. delete [] m_ppUpdateMBstatus[iMBY] ;  
  507. delete [] m_rgmbmdSpt[iMBY] ;
  508. delete [] m_rgpmbmCurr_Spt[iMBY];
  509. }
  510. delete [] m_ppPieceMBstatus ; 
  511. delete [] m_ppUpdateMBstatus ;  
  512. delete [] m_rgmbmdSpt ;
  513. delete [] m_rgpmbmCurr_Spt;
  514. // Begin: modified by Hughes   4/9/98
  515. delete [] m_rgmbmdSprite ;    
  516. // end:  modified by Hughes   4/9/98
  517. }
  518. else
  519. m_vopmd.SpriteXmitMode  = PAUSE;
  520. codeVOSHead ();
  521. if (m_vopmd.SpriteXmitMode  != STOP)
  522. m_vopmd.SpriteXmitMode  = PieceXmitMode;
  523. }
  524. }
  525. Void CVideoObjectEncoder::encSptPiece (CRct rctSptQ, UInt uiSptPieceSize)
  526. {
  527. UInt uiTR = m_volmd.iTemporalRate;
  528. CRct rctSpt = (m_vopmd.SpriteXmitMode == PIECE ) ? m_rctPieceQ : m_rctUpdateQ ; 
  529. CRct rctSptQNew = rctSpt;
  530. CRct rctPiece = PieceSize (m_bSptRightPiece, uiSptPieceSize);
  531. rctSpt.include(rctPiece);
  532. UInt uiF = (m_vopmd.SpriteXmitMode == PIECE ) ? m_tPiece : m_tUpdate;
  533. UInt boundary = m_nLastFrame ;
  534. if ( rctSptQ.valid() && (rctSptQNew != m_rctSptExp)) {
  535. rctSptQ = rctSpt;
  536. uiF += uiTR ;  
  537. while ((rctSptQNew.right <= rctSptQ.right) && (rctSptQNew.left >= rctSptQ.left) 
  538. && (uiF <= boundary)) {
  539. CRct rctWarpNew = CornerWarp (m_pprgstDest[uiF- m_nFirstFrame], m_rgstSrcQ);
  540. if (rctWarpNew.left < m_rctSptExp.left) rctWarpNew.left = m_rctSptExp.left;
  541. if (rctWarpNew.right > m_rctSptExp.right) rctWarpNew.right = m_rctSptExp.right;
  542. rctSptQNew.include (rctWarpNew);
  543. uiF = ((rctSptQNew.right <= rctSptQ.right) && (rctSptQNew.left >= rctSptQ.left))
  544. ? (uiF + uiTR) : (uiF - uiTR);
  545. }
  546. Int left = (rctPiece.left < rctSptQNew.left) ?  rctSptQNew.left :  rctPiece.left;
  547. Int right = (rctPiece.right > rctSptQNew.right) ?  rctSptQNew.right :  rctPiece.right;
  548. if ((right-MB_SIZE) > left)
  549. rctSpt = encPiece (CRct (left, m_rctSptExp.top, right, m_rctSptExp.bottom));
  550. }
  551. else {
  552. uiF = boundary;
  553. }
  554. if (uiF  > boundary)
  555. uiF = boundary;
  556. if (m_vopmd.SpriteXmitMode == PIECE )
  557. m_tPiece = uiF;
  558. if (m_vopmd.SpriteXmitMode == UPDATE ) 
  559. m_tUpdate = uiF;
  560. if (uiF  >= boundary) {
  561. if (( m_sptMode == PIECE_OBJECT) || m_vopmd.SpriteXmitMode == UPDATE )
  562. m_vopmd.SpriteXmitMode = NEXT;
  563. }
  564. }
  565. CRct CVideoObjectEncoder::PieceSize (Bool rightpiece, UInt uiSptPieceSize)
  566. {
  567. Int right, left;
  568. CRct rctSptQ = (m_vopmd.SpriteXmitMode == PIECE ) ? m_rctPieceQ : m_rctUpdateQ ; 
  569. Int AvgBitsMb = (m_vopmd.SpriteXmitMode == PIECE ) ? m_pSptmbBits [AVGUPDATEMB] : m_pSptmbBits[AVGUPDATEMB];
  570. assert (AvgBitsMb != 0);
  571. m_iPieceHeight = (MB_SIZE-1 + m_rctPieceQ.height ()) / MB_SIZE;
  572. m_iPieceWidth= (Int) (0.5 + uiSptPieceSize/(AvgBitsMb * m_iPieceHeight));
  573. m_iPieceWidth= (m_iPieceWidth<2)? 2 : m_iPieceWidth;
  574. if (rightpiece) {
  575. right = rctSptQ.right + MB_SIZE * m_iPieceWidth;
  576. if (right > m_rctSptExp.right) {
  577. right = m_rctSptExp.right;
  578. }
  579. if ((m_vopmd.SpriteXmitMode == UPDATE ) && (right > m_rctPieceQ.right)) {
  580. right = m_rctPieceQ.right;
  581. }
  582. left = rctSptQ.right;
  583. }
  584. else  {
  585. left = rctSptQ.left - MB_SIZE* m_iPieceWidth;
  586. if (left < m_rctSptExp.left) {
  587. left = m_rctSptExp.left ;
  588. }
  589. if ((m_vopmd.SpriteXmitMode == UPDATE ) && (left < m_rctPieceQ.left)) {
  590. left = m_rctPieceQ.left ;
  591. }
  592. right = rctSptQ.left;
  593. }
  594. CRct rctSptPieceY = CRct (left, m_rctSptExp.top, right, m_rctSptExp.bottom);
  595. if ((m_tUpdate > (Time) m_nFirstFrame) || (m_vopmd.SpriteXmitMode == PIECE )) 
  596. if (rightpiece) {
  597. if (left > (m_rctSptExp.left+MB_SIZE))
  598. {
  599. left -=  MB_SIZE;
  600. rctSptPieceY = CRct (left, rctSptPieceY.top, rctSptPieceY.right, rctSptPieceY.bottom);
  601. }
  602. }
  603. else{
  604. if (right < (m_rctSptExp.right - MB_SIZE))
  605. {
  606. right +=  MB_SIZE;
  607. rctSptPieceY = CRct (rctSptPieceY.left, rctSptPieceY.top, right, rctSptPieceY.bottom);
  608. }
  609. }
  610. return rctSptPieceY;
  611. }
  612. CRct CVideoObjectEncoder::encPiece (CRct rctpiece)
  613. {
  614. Time ts;
  615. //Int right = rctpiece.right; 
  616. //Int left = rctpiece.left;
  617. CRct rctSpt = (m_vopmd.SpriteXmitMode == PIECE ) ? m_rctPieceQ : m_rctUpdateQ ; 
  618. CRct rctSptPieceY = PieceExpand (rctpiece);
  619. // m_rctSptPieceY = rctSptPieceY;
  620. // m_rctSptPieceY.shift(m_rctSpt.left, m_rctSpt.top);
  621. if (m_volmd.fAUsage == RECTANGLE) {
  622. m_rctCurrVOPY = rctSptPieceY;
  623. m_rctCurrVOPUV = m_rctCurrVOPY.downSampleBy2 ();
  624. }
  625. m_iPieceWidth= rctSptPieceY.width / MB_SIZE;
  626. m_iPieceHeight= rctSptPieceY.height () / MB_SIZE;
  627. m_iPieceXoffset= (rctSptPieceY.left - m_rctSptExp.left) / MB_SIZE;
  628. m_iPieceYoffset= (rctSptPieceY.top - m_rctSptExp.top) / MB_SIZE;
  629. rctSpt.include(rctSptPieceY);
  630. codeVOSHead ();
  631. Int OldCount = m_pbitstrmOut -> getCounter ();
  632.   // encode sprite piece
  633. m_pvopcSptP = new CVOPU8YUVBA (*m_pvopcSpt, m_volmd.fAUsage, rctSptPieceY);
  634. m_pvopcSptP -> shift (-rctSptPieceY.left, -rctSptPieceY.top);
  635. CRct rctRefFrameY = m_pvopcSptP -> whereY() ;
  636. m_rctCurrVOPY = CRct (0, 0, rctRefFrameY.width, rctRefFrameY.height());
  637. m_rctCurrVOPUV = m_rctCurrVOPY.downSampleBy2 ();
  638. m_rctRefFrameY = CRct (
  639. -EXPANDY_REF_FRAME, -EXPANDY_REF_FRAME, 
  640. EXPANDY_REF_FRAME + rctRefFrameY.width, EXPANDY_REF_FRAME + rctRefFrameY.height()
  641. );
  642. m_rctRefFrameUV = m_rctRefFrameY.downSampleBy2 ();
  643. m_pvopcOrig = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY); 
  644. VOPOverlay (*m_pvopcSptP, *m_pvopcOrig);
  645. m_pvopcOrig->setBoundRct (m_rctCurrVOPY);
  646. m_pvopcRefQ1 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
  647. delete m_pvopcSptP;
  648. m_pvopcSptP = new CVOPU8YUVBA (*m_pvopcSptQ, m_volmd.fAUsage, rctSptPieceY);  // extract reference
  649. m_pvopcSptP -> shift (-rctSptPieceY.left, -rctSptPieceY.top);
  650. VOPOverlay (*m_pvopcSptP, *m_pvopcRefQ1);
  651. if (m_vopmd.SpriteXmitMode == PIECE ) {
  652. m_rctPieceQ = rctSpt;
  653. ts = m_tPiece;
  654. m_vopmd.vopPredType = IVOP;
  655. }
  656. else {
  657. m_rctUpdateQ = rctSpt;
  658. ts = m_tUpdate;
  659. m_vopmd.vopPredType = PVOP;
  660. }
  661.   m_pvopcRefQ0 = new CVOPU8YUVBA (m_volmd.fAUsage, m_rctRefFrameY);
  662. m_iFrameWidthY = m_pvopcRefQ0->whereY ().width;
  663. m_iFrameWidthUV = m_pvopcRefQ0->whereUV ().width;
  664. m_iFrameWidthYxMBSize = MB_SIZE * m_pvopcRefQ0->whereY ().width; 
  665. m_iFrameWidthYxBlkSize = BLOCK_SIZE * m_pvopcRefQ0->whereY ().width; 
  666. m_iFrameWidthUVxBlkSize = BLOCK_SIZE * m_pvopcRefQ0->whereUV ().width;
  667. encode (TRUE, ts, m_vopmd.vopPredType);
  668. // encode (TRUE, ts, m_vopmd.SpriteXmitMode);
  669. m_pvopcRefQ1 -> shift (rctSptPieceY.left, rctSptPieceY.top);  
  670. VOPOverlay (*m_pvopcRefQ1, *m_pvopcSptQ, 1);
  671. delete m_pvopcSptP;
  672. delete m_pvopcOrig;  m_pvopcOrig = NULL ;
  673. delete m_pvopcRefQ0; m_pvopcRefQ0 = NULL ;
  674. delete m_pvopcRefQ1; m_pvopcRefQ1 = NULL ;
  675.   if (m_iNumOfPnts == 0) {
  676. m_pvopcRefQ1 = m_pvopcSptQ;   // to avoid "rgpvoenc [BASE_LAYER] -> swapRefQ1toSpt (); "
  677. }
  678. Int Curr = (m_pbitstrmOut -> getCounter ()) - OldCount;
  679. if (m_iNumSptMB > 0) {
  680. if (m_vopmd.SpriteXmitMode == PIECE ) 
  681. m_pSptmbBits[AVGPIECEMB] = Curr / m_iNumSptMB; // average macroblock bits used by a sprite piece
  682. if (m_vopmd.SpriteXmitMode == UPDATE ) 
  683. m_pSptmbBits[AVGUPDATEMB] = Curr / m_iNumSptMB; // average macroblock bits used by a sprite piece 
  684. }
  685. return rctSpt;
  686. }
  687. CRct CVideoObjectEncoder::ZoomOrPan ()
  688. {
  689. CRct rctWarpNew ;
  690. CRct rctWarpOld ;
  691. UInt uiTR = m_volmd.iTemporalRate;
  692. UInt uiF = (m_vopmd.SpriteXmitMode == PIECE ) ? m_tPiece : m_tUpdate;
  693. UInt boundary = m_nLastFrame ;
  694. if (uiF >= boundary)
  695. return rctWarpNew;
  696. rctWarpNew = CornerWarp (m_pprgstDest[uiF- m_nFirstFrame], m_rgstSrcQ);
  697. rctWarpOld = rctWarpNew;
  698. // determine if sprite is zooming or panning?
  699. while (rctWarpNew == rctWarpOld) {
  700. uiF += uiTR ;
  701. rctWarpNew = CornerWarp (m_pprgstDest[uiF- m_nFirstFrame], m_rgstSrcQ);
  702. }
  703. if ((rctWarpNew.right > rctWarpOld.right) && (rctWarpNew.left < rctWarpOld.left))
  704. m_bSptZoom = TRUE;  // sprite is zooming
  705. else {
  706. m_bSptZoom = FALSE ;  // sprite is panning  
  707. if (rctWarpNew.left < rctWarpOld.left)
  708. m_bSptRightPiece = FALSE;  // sprite is panning to the left
  709. else
  710. m_bSptRightPiece = TRUE;  // sprite is panning to the right
  711. }
  712. rctWarpNew.include (rctWarpOld);
  713. return rctWarpNew;
  714. }
  715. Void CVideoObjectEncoder::codeVOSHead ()   
  716. {
  717. m_pbitstrmOut -> putBits (m_vopmd.SpriteXmitMode, NUMBITS_SPRITE_XMIT_MODE, "Sprite_TRANSMIT_MODE");
  718. if (( m_vopmd.SpriteXmitMode != STOP) &&( m_vopmd.SpriteXmitMode != PAUSE)) {
  719. // Sprite piece overhead code
  720.   //static UInt uiNumBitsStart = 4* NUMBITS_SPRITE_MB_OFFSET + NUMBITS_SPRITE_XMIT_MODE + NUMBITS_VOP_QUANTIZER;
  721. Int stepToBeCoded = (m_vopmd.SpriteXmitMode == UPDATE) ? m_vopmd.intStep : m_vopmd.intStepI;
  722. m_pbitstrmOut -> putBits (stepToBeCoded, NUMBITS_VOP_QUANTIZER, "sprite_Piece_Quantier");
  723. m_pbitstrmOut -> putBits (m_iPieceWidth, (UInt) NUMBITS_SPRITE_MB_OFFSET, "sprite_Piece_width"); //plus 9 bits
  724. m_pbitstrmOut -> putBits (m_iPieceHeight, (UInt) NUMBITS_SPRITE_MB_OFFSET, "sprite_Piece_height"); //plus 9 bits
  725. // Begin: modified by Hughes   4/9/98
  726. m_pbitstrmOut -> putBits (MARKER_BIT, MARKER_BIT, "Marker_Bit");
  727. // End: modified by Hughes   4/9/98
  728. m_pbitstrmOut -> putBits (m_iPieceXoffset, (UInt) NUMBITS_SPRITE_MB_OFFSET, "sprite_Piece_Xoffset"); //plus 9 bits
  729. m_pbitstrmOut -> putBits (m_iPieceYoffset, (UInt) NUMBITS_SPRITE_MB_OFFSET, "sprite_Piece_Yoffset"); //plus 9 bits
  730. }
  731. }
  732. CRct CVideoObjectEncoder::findTightBoundingBox (CVOPU8YUVBA* vopuc)
  733. {
  734. const CRct& rctOrig =  vopuc -> whereY ();
  735. CoordI left = rctOrig.right - 1;
  736. CoordI top = rctOrig.bottom - 1;
  737. CoordI right = rctOrig.left;
  738. CoordI bottom = rctOrig.top;
  739. const PixelC* ppxlcBY = vopuc->pixelsBY ();
  740. for (CoordI y = rctOrig.top; y < rctOrig.bottom; y++) {
  741. for (CoordI x = rctOrig.left; x < rctOrig.right; x++) {
  742. if (*ppxlcBY != transpValue) {
  743. left = min (left, x);
  744. top = min (top, y);
  745. right = max (right, x);
  746. bottom = max (bottom, y);
  747. }
  748. ppxlcBY++;
  749. }
  750. }
  751. right++;
  752. bottom++;
  753. if (left % 2 != 0)
  754. left--;
  755. if (top % 2 != 0)
  756. top--;
  757. return PieceExpand (CRct (left, top, right, bottom));
  758. }
  759. //  extend the rctOrg size to multiples of MBSize w.r.t. m_rctSptExp 
  760. CRct CVideoObjectEncoder::PieceExpand (const CRct& rctOrg)
  761. {
  762. // Begin: modified by Hughes   4/9/98
  763. // Int left = rctOrg.left ;
  764. // Int right = rctOrg.right ;
  765. // Int top = rctOrg.top ;
  766. // Int bottom = rctOrg.bottom ;
  767. Int left = (rctOrg.left < m_rctSptExp.left) ? m_rctSptExp.left : rctOrg.left;
  768. Int right = (rctOrg.right > m_rctSptExp.right) ? m_rctSptExp.right : rctOrg.right;
  769. Int top = (rctOrg.top < m_rctSptExp.top) ? m_rctSptExp.top : rctOrg.top;
  770. Int bottom = (rctOrg.bottom > m_rctSptExp.bottom) ? m_rctSptExp.bottom : rctOrg.bottom;
  771. // End: modified by Hughes   4/9/98
  772. Int iMod = (left - m_rctSptExp.left) % MB_SIZE;
  773. if (iMod > 0)
  774. left -= iMod;
  775. iMod = (right - left) % MB_SIZE;
  776. if (iMod > 0)
  777. right += MB_SIZE - iMod;
  778. iMod = (top - m_rctSptExp.top) % MB_SIZE;
  779. if (iMod > 0)
  780. top -= iMod;
  781. iMod = (bottom - top) % MB_SIZE;
  782. if (iMod > 0)
  783. bottom += MB_SIZE - iMod;
  784. // for update pieces, skip the entire row of MBs if the cooresponding object piece if missing
  785. if (m_vopmd.SpriteXmitMode == UPDATE) {
  786. Int iMBX, iMBX_left, iMBX_right ;
  787. Int iMBY, iMBY_top, iMBY_bottom ;
  788. iMBX_left =  (left - m_rctSptExp.left) / MB_SIZE;
  789. iMBX_right =  (right - m_rctSptExp.left) / MB_SIZE;
  790. iMBY_top =  (top - m_rctSptExp.top) / MB_SIZE;
  791. iMBY_bottom =  (bottom - m_rctSptExp.top) / MB_SIZE;
  792. for (iMBY = iMBY_top; iMBY < iMBY_bottom; iMBY++) {
  793. for (iMBX = iMBX_left; iMBX < iMBX_right; iMBX++) {
  794. if ( m_ppPieceMBstatus[iMBY][iMBX] != PIECE_DONE) {
  795. top = top  +  MB_SIZE;
  796. break;
  797. }
  798. }
  799. }
  800. for (iMBY = iMBY_bottom-1; iMBY > iMBY_top; iMBY--) {
  801. for (iMBX = iMBX_left; iMBX < iMBX_right; iMBX++) {
  802. if ( m_ppPieceMBstatus[iMBY][iMBX] != PIECE_DONE) {
  803. bottom = bottom  -  MB_SIZE;
  804. break;
  805. }
  806. }
  807. }
  808. }
  809. return CRct(left, top, right, bottom);
  810. }