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

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*************************************************************************
  2. This software module was originally developed by 
  3. Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
  4. (April, 1997)
  5. and edited by
  6.         Wei Wu (weiwu@stallion.risc.rockwell.com) Rockwell Science Center
  7. and also edited by
  8. Yoshihiro Kikuchi (TOSHIBA CORPORATION)
  9. Takeshi Nagai (TOSHIBA CORPORATION)
  10. Toshiaki Watanabe (TOSHIBA CORPORATION)
  11. Noboru Yamaguchi (TOSHIBA CORPORATION)
  12. in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). 
  13. This software module is an implementation of a part of one or more MPEG-4 Video tools 
  14. as specified by the MPEG-4 Video. 
  15. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications 
  16. thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. 
  17. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. 
  18. The original developer of this software module and his/her company, 
  19. the subsequent editors and their companies, 
  20. and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. 
  21. Copyright is not released for non MPEG-4 Video conforming products. 
  22. Microsoft retains full right to use the code for his/her own purpose, 
  23. assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. 
  24. This copyright notice must be included in all copies or derivative works. 
  25. Copyright (c) 1996, 1997.
  26. Module Name:
  27. shpenc.hpp
  28. Abstract:
  29. binary shape encoder with context-based arithmatic coder
  30. Revision History:
  31. *************************************************************************/
  32. #include "typeapi.h"
  33. #include "entropy/entropy.hpp"
  34. #include "entropy/huffman.hpp"
  35. #include "entropy/bitstrm.hpp"
  36. #include "global.hpp"
  37. #include "mode.hpp"
  38. #include "codehead.h"
  39. #include "cae.h"
  40. #include "vopses.hpp"
  41. #include "vopseenc.hpp"
  42. #ifdef __MFC_
  43. #ifdef _DEBUG
  44. #undef THIS_FILE
  45. static char BASED_CODE THIS_FILE[] = __FILE__;
  46. #endif
  47. #define new DEBUG_NEW    
  48. #endif // __MFC_
  49. Int CVideoObjectEncoder::codeIntraShape (PixelC* ppxlcSrcFrm, CMBMode* pmbmd, Int iMBX, Int iMBY)
  50. {
  51. m_iInverseCR = 1;
  52. m_iWidthCurrBAB = BAB_SIZE;
  53. #ifdef __TRACE_AND_STATS_
  54. if(pmbmd->m_rgTranspStatus [0] == NONE)
  55. m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL OPAQUE");
  56. else if(pmbmd->m_rgTranspStatus [0] == ALL)
  57. m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL TRANSP");
  58. else
  59. m_pbitstrmOut->trace (m_ppxlcCurrMBBY, MB_SIZE, MB_SIZE, "ORIGINAL_BAB");
  60. #endif // __TRACE_AND_STATS_
  61. Int iMBnum = VPMBnum(iMBX, iMBY);
  62. m_bVPNoLeft = bVPNoLeft(iMBnum, iMBX);
  63. m_bVPNoTop = bVPNoTop(iMBnum);
  64. m_bVPNoRightTop = bVPNoRightTop(iMBnum, iMBX);
  65. m_bVPNoLeftTop = bVPNoLeftTop(iMBnum, iMBX);
  66. if (pmbmd->m_rgTranspStatus [0] == NONE)
  67. pmbmd->m_shpmd = ALL_OPAQUE;
  68. else if (pmbmd->m_rgTranspStatus [0] == ALL)
  69. pmbmd->m_shpmd = ALL_TRANSP;
  70. else if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, MPEG4_TRANSPARENT, pmbmd))
  71. {
  72. pmbmd->m_shpmd = ALL_TRANSP;
  73. if ( !isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, MPEG4_OPAQUE, pmbmd))
  74. {
  75. // both opaque and transparent are good, so count pixels to decide
  76. Int i,iSum=0;
  77. for(i=0;i<MB_SQUARE_SIZE;i++)
  78. iSum+=(m_ppxlcCurrMBBY[i]>0);
  79. if(iSum>=(MB_SQUARE_SIZE>>1))
  80. pmbmd->m_shpmd = ALL_OPAQUE;
  81. }
  82. }
  83. else if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, MPEG4_OPAQUE, pmbmd))
  84. pmbmd->m_shpmd = ALL_OPAQUE;
  85. else
  86. pmbmd->m_shpmd = round (ppxlcSrcFrm, pmbmd);
  87. if(pmbmd->m_shpmd==ALL_TRANSP)
  88. {
  89. #ifdef __TRACE_AND_STATS_
  90. m_pbitstrmOut->trace ("MB_ALL_TRANSP");
  91. #endif // __TRACE_AND_STATS_
  92. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, MPEG4_TRANSPARENT);
  93. return codeShapeModeIntra (ALL_TRANSP, pmbmd, iMBX, iMBY);
  94. }
  95. else if(pmbmd->m_shpmd==ALL_OPAQUE)
  96. {
  97. #ifdef __TRACE_AND_STATS_
  98. m_pbitstrmOut->trace ("MB_ALL_OPAQUE");
  99. #endif // __TRACE_AND_STATS_
  100. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, MPEG4_OPAQUE);
  101. return codeShapeModeIntra (ALL_OPAQUE, pmbmd, iMBX, iMBY);
  102. }
  103. else
  104. {
  105. // intra CAE
  106. assert(pmbmd->m_shpmd == INTRA_CAE);
  107. #ifdef __TRACE_AND_STATS_
  108. m_pbitstrmOut->trace (m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, TOTAL_BAB_SIZE, "MB_RECON_BAB (Ignore border)");
  109. m_pbitstrmOut->trace (m_rgpxlcCaeSymbol, m_iWidthCurrBAB , m_iWidthCurrBAB , "MB_ENCODED_BAB");
  110. #endif // __TRACE_AND_STATS_
  111. if (m_bNoShapeChg) //must be partial
  112. copyReconShapeToRef (ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
  113. else
  114. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
  115. UInt nBitsMode = codeShapeModeIntra (INTRA_CAE, pmbmd, iMBX, iMBY);
  116. m_pbitstrmShapeMBOut->setBookmark ();
  117. UInt nBitsV = encodeCAEIntra (INTRA_CAE, VERTICAL);
  118. m_pbitstrmShapeMBOut->gotoBookmark ();
  119. UInt nBitsH = encodeCAEIntra (INTRA_CAE, HORIZONTAL);
  120. if (nBitsV < nBitsH)
  121. {
  122. m_pbitstrmShapeMBOut->gotoBookmark ();
  123. nBitsV = encodeCAEIntra (INTRA_CAE, VERTICAL);
  124. return nBitsV+nBitsMode;
  125. }
  126. else
  127. return nBitsH+nBitsMode;
  128. }
  129. }
  130. Int CVideoObjectEncoder::codeInterShape (PixelC* ppxlcSrcFrm,
  131.  CVOPU8YUVBA* pvopcRefQ,
  132.  CMBMode* pmbmd, 
  133.  const ShapeMode& shpmdColocatedMB,
  134.  const CMotionVector* pmv, 
  135.  CMotionVector* pmvBY, 
  136.  CoordI iX, CoordI iY, 
  137.  Int iMBX, Int iMBY)
  138. {
  139. m_iInverseCR = 1;
  140. m_iWidthCurrBAB = BAB_SIZE;
  141. pmbmd->m_shpmd = UNKNOWN;
  142. CMotionVector mvBYD (0, 0);
  143. CMotionVector mvShapeMVP;
  144. #ifdef __TRACE_AND_STATS_
  145. if(pmbmd->m_rgTranspStatus [0] == NONE)
  146. m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL OPAQUE");
  147. else if(pmbmd->m_rgTranspStatus [0] == ALL)
  148. m_pbitstrmOut->trace ("ORIGINAL BAB IS ALL TRANSP");
  149. else
  150. m_pbitstrmOut->trace (m_ppxlcCurrMBBY, MB_SIZE, MB_SIZE, "ORIGINAL_BAB");
  151. #endif // __TRACE_AND_STATS_
  152. Int iMBnum = VPMBnum(iMBX, iMBY);
  153. m_bVPNoLeft = bVPNoLeft(iMBnum, iMBX);
  154. m_bVPNoTop = bVPNoTop(iMBnum);
  155. m_bVPNoRightTop = bVPNoRightTop(iMBnum, iMBX);
  156. m_bVPNoLeftTop = bVPNoLeftTop(iMBnum, iMBX);
  157. if (pmbmd->m_rgTranspStatus [0] == ALL)
  158. pmbmd->m_shpmd = ALL_TRANSP;
  159. else if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, MPEG4_TRANSPARENT, pmbmd))
  160. {
  161. pmbmd->m_shpmd = ALL_TRANSP;
  162. if ( !isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, MPEG4_OPAQUE, pmbmd))
  163. {
  164. // both opaque and transparent are good, so count pixels to decide
  165. Int i,iSum=0;
  166. for(i=0;i<MB_SQUARE_SIZE;i++)
  167. iSum+=(m_ppxlcCurrMBBY[i]>0);
  168. if(iSum>=(MB_SQUARE_SIZE>>1))
  169. pmbmd->m_shpmd = ALL_OPAQUE;
  170. }
  171. }
  172. else if(pmbmd->m_rgTranspStatus [0] == NONE)
  173. pmbmd->m_shpmd = ALL_OPAQUE;
  174. else if(!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16, MPEG4_OPAQUE, pmbmd))
  175. pmbmd->m_shpmd = ALL_OPAQUE;
  176. if(pmbmd->m_shpmd!=ALL_TRANSP)
  177. {
  178. // find motion vectors
  179. mvShapeMVP = findShapeMVP (pmv, pmvBY, pmbmd, iMBX, iMBY);
  180. assert (mvShapeMVP.iMVX != NOT_MV && mvShapeMVP.iMVY != NOT_MV);
  181. // mvShapeMVP = CMotionVector ((mvShapeMVP.iMVX * 2 + mvShapeMVP.iHalfX) / 2,  //rounding
  182. // (mvShapeMVP.iMVY * 2 + mvShapeMVP.iHalfY) / 2);
  183. motionCompBY ((PixelC*) m_puciPredBAB->pixels (),
  184.   (PixelC*) pvopcRefQ->getPlane (BY_PLANE)->pixels (),
  185.   mvShapeMVP.iMVX + iX - 1,
  186.   mvShapeMVP.iMVY + iY - 1); //-1 due to 18x18 motion comp
  187. if (!isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
  188.   m_puciPredBAB->pixels (), m_rgiSubBlkIndx18x18, 18, pmbmd))
  189. // zero mvd is ok
  190. *pmvBY = mvShapeMVP;
  191. else
  192. {
  193. // do block matching
  194. CMotionVector mvShape;
  195. blkmatchForShape (pvopcRefQ,&mvShape, mvShapeMVP.trueMVHalfPel (), iX, iY);
  196. assert (mvShape.iMVX != NOT_MV && mvShape.iMVY != NOT_MV);
  197. *pmvBY = mvShape;
  198. mvBYD = mvShape - mvShapeMVP;
  199. motionCompBY ((PixelC*) m_puciPredBAB->pixels (),
  200.   (PixelC*) pvopcRefQ->getPlane (BY_PLANE)->pixels (),
  201.   mvShape.iMVX + iX - 1,
  202.   mvShape.iMVY + iY - 1); //-1 due to 18x18 motion comp
  203. }
  204. // check status of motion compensated prediction BAB
  205. PixelC *ppxlcPredBAB = (PixelC *)m_puciPredBAB->pixels()+MC_BAB_SIZE*MC_BAB_BORDER;
  206. Int iXX,iYY,iOpaqueCount = 0;
  207. for(iYY=MC_BAB_BORDER;iYY<MC_BAB_SIZE-MC_BAB_BORDER;iYY++,ppxlcPredBAB+=MC_BAB_SIZE)
  208. for(iXX=MC_BAB_BORDER;iXX<MC_BAB_SIZE-MC_BAB_BORDER;iXX++)
  209. if(ppxlcPredBAB[iXX] == opaqueValue)
  210. iOpaqueCount++;
  211. if(iOpaqueCount==0 || isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
  212. m_puciPredBAB->pixels (), m_rgiSubBlkIndx18x18, 18, pmbmd))
  213. {
  214. // MC BAB is all transparent or not acceptable, so code.
  215. round(ppxlcSrcFrm, pmbmd);
  216. if(mvBYD.isZero())
  217. pmbmd->m_shpmd = INTER_CAE_MVDZ;
  218. else
  219. pmbmd->m_shpmd = INTER_CAE_MVDNZ;
  220. }
  221. else if(pmbmd->m_shpmd==ALL_OPAQUE && !mvBYD.isZero())
  222. ;
  223. else if(pmbmd->m_rgTranspStatus[0] == NONE && iOpaqueCount!=MB_SQUARE_SIZE)
  224. pmbmd->m_shpmd=ALL_OPAQUE;
  225. else if(mvBYD.isZero())
  226. pmbmd->m_shpmd = MVDZ_NOUPDT;
  227. else
  228. pmbmd->m_shpmd = MVDNZ_NOUPDT;
  229. }
  230. switch(pmbmd->m_shpmd)
  231. {
  232. case ALL_OPAQUE:
  233. #ifdef __TRACE_AND_STATS_
  234. m_pbitstrmOut->trace ("MB_ALL_OPAQUE");
  235. #endif // __TRACE_AND_STATS_
  236. pmvBY->iMVX = NOT_MV;
  237. pmvBY->iMVY = NOT_MV;
  238. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, MPEG4_OPAQUE);
  239. return (codeShapeModeInter (ALL_OPAQUE, shpmdColocatedMB));
  240. case ALL_TRANSP:
  241. #ifdef __TRACE_AND_STATS_
  242. m_pbitstrmOut->trace ("MB_ALL_TRANSP");
  243. #endif // __TRACE_AND_STATS_
  244. pmvBY->iMVX = NOT_MV;
  245. pmvBY->iMVY = NOT_MV;
  246. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, MPEG4_TRANSPARENT);
  247. return (codeShapeModeInter (ALL_TRANSP, shpmdColocatedMB));
  248. case INTER_CAE_MVDZ:
  249. case INTER_CAE_MVDNZ:
  250. {
  251. if (m_bNoShapeChg)
  252. copyReconShapeToRef (ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
  253. else
  254. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, BAB_BORDER);
  255. #ifdef __TRACE_AND_STATS_
  256. m_pbitstrmOut->trace ((PixelC *)m_puciPredBAB->pixels(), MC_BAB_SIZE, MC_BAB_SIZE, "MB_MC_PRED_BAB");
  257. m_pbitstrmOut->trace (m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE, TOTAL_BAB_SIZE, "MB_RECON_BAB (Ignore Borders)");
  258. m_pbitstrmOut->trace (m_rgpxlcCaeSymbol, m_iWidthCurrBAB , m_iWidthCurrBAB , "MB_ENCODED_BAB");
  259. #endif // __TRACE_AND_STATS_
  260. m_pbitstrmShapeMBOut->setBookmark ();
  261. // try intra
  262. UInt nBitsModeIntra = codeShapeModeInter (INTRA_CAE, shpmdColocatedMB);
  263. #ifdef __TRACE_AND_STATS_
  264. m_pbitstrmOut->trace ("MB_CAE_INTRA_HORIZONTAL_CODING (TRIAL)");
  265. #endif // __TRACE_AND_STATS_
  266. UInt nBitsHIntra = encodeCAEIntra (INTRA_CAE, HORIZONTAL);
  267. #ifdef __TRACE_AND_STATS_
  268. m_pbitstrmOut->trace ("MB_CAE_INTRA_VERTICAL_CODING (TRIAL)");
  269. #endif // __TRACE_AND_STATS_
  270. UInt nBitsVIntra = encodeCAEIntra (INTRA_CAE, VERTICAL);
  271. UInt nBitsIntra = nBitsModeIntra + min (nBitsVIntra, nBitsHIntra);
  272. // try inter
  273. UInt nBitsMV=0;
  274. UInt nBitsModeInter = codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
  275. if(pmbmd->m_shpmd==INTER_CAE_MVDNZ)
  276. nBitsMV = encodeMVDS (mvBYD);
  277. #ifdef __TRACE_AND_STATS_
  278. m_pbitstrmOut->trace ("MB_CAE_INTER_VERTICAL_CODING (TRIAL)");
  279. #endif // __TRACE_AND_STATS_
  280. UInt nBitsVInter = encodeCAEInter (pmbmd->m_shpmd, VERTICAL);
  281. #ifdef __TRACE_AND_STATS_
  282. m_pbitstrmOut->trace ("MB_CAE_INTER_HORIZONTAL_CODING (TRIAL)");
  283. #endif // __TRACE_AND_STATS_
  284. UInt nBitsHInter = encodeCAEInter (pmbmd->m_shpmd, HORIZONTAL);
  285. UInt nBitsInter = nBitsModeInter + nBitsMV + min (nBitsVInter, nBitsHInter);
  286. m_pbitstrmShapeMBOut->gotoBookmark ();
  287. if (nBitsInter < nBitsIntra)
  288. {
  289. // choose inter coding
  290. #ifdef __TRACE_AND_STATS_
  291. m_pbitstrmOut->trace ("MB_CAE_INTER_CODING (REAL)");
  292. m_pbitstrmOut->trace (mvShapeMVP, "MB_SHP_MV_PRED (half pel)");
  293. m_pbitstrmOut->trace (*pmvBY, "MB_SHP_MV (half pel)");
  294. m_pbitstrmOut->trace (mvBYD, "MB_SHP_MVD (half pel)");
  295. #endif // __TRACE_AND_STATS_
  296. codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
  297. if(pmbmd->m_shpmd==INTER_CAE_MVDNZ)
  298. encodeMVDS (mvBYD);
  299. if(nBitsVInter<nBitsHInter)
  300. encodeCAEInter (pmbmd->m_shpmd, VERTICAL);
  301. else
  302. encodeCAEInter (pmbmd->m_shpmd, HORIZONTAL);
  303. return nBitsInter;
  304. }
  305. else
  306. {
  307. // choose intra coding
  308. #ifdef __TRACE_AND_STATS_
  309. m_pbitstrmOut->trace ("MB_CAE_INTRA_CODING (REAL)");
  310. #endif // __TRACE_AND_STATS_
  311. pmvBY->iMVX = NOT_MV;
  312. pmvBY->iMVY = NOT_MV;
  313. pmbmd->m_shpmd = INTRA_CAE;
  314. codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
  315. if(nBitsVIntra<nBitsHIntra)
  316. encodeCAEIntra (pmbmd->m_shpmd, VERTICAL);
  317. else
  318. encodeCAEIntra (pmbmd->m_shpmd, HORIZONTAL);
  319. return nBitsIntra;
  320. }
  321. }
  322. case MVDZ_NOUPDT:
  323. case MVDNZ_NOUPDT:
  324. {
  325. #ifdef __TRACE_AND_STATS_
  326. m_pbitstrmOut->trace ("MB_CAE_INTER_CODING_NO_UPDATE");
  327. m_pbitstrmOut->trace (mvShapeMVP, "MB_SHP_MV_PRED (half pel)");
  328. m_pbitstrmOut->trace (*pmvBY, "MB_SHP_MV (half pel)");
  329. m_pbitstrmOut->trace (mvBYD, "MB_SHP_MVD (half pel)");
  330. #endif // __TRACE_AND_STATS_
  331. copyReconShapeToMbAndRef (m_ppxlcCurrMBBY, ppxlcSrcFrm, m_puciPredBAB->pixels (), MC_BAB_SIZE, MC_BAB_BORDER);
  332. #ifdef __TRACE_AND_STATS_
  333. m_pbitstrmOut->trace ((PixelC *)m_puciPredBAB->pixels(), MC_BAB_SIZE, MC_BAB_SIZE, "MB_MC_PRED_BAB");
  334. #endif // __TRACE_AND_STATS_
  335. Int nBits = codeShapeModeInter (pmbmd->m_shpmd, shpmdColocatedMB);
  336. if(pmbmd->m_shpmd==MVDNZ_NOUPDT)
  337. nBits += encodeMVDS (mvBYD);
  338. return nBits;
  339. }
  340. default:
  341. assert(FALSE);
  342. return 0;
  343. }
  344. }
  345. UInt CVideoObjectEncoder::codeShapeModeIntra (ShapeMode shpmd, const CMBMode* pmbmd, Int iMBX, Int iMBY)
  346. {
  347. UInt nBits = 0;
  348. assert (shpmd == ALL_TRANSP || shpmd == ALL_OPAQUE || shpmd == INTRA_CAE);
  349. //static Int iLeftTopMostMB = 0;
  350. //Int iRightMostMB = m_iNumMBX - 1;
  351. //get previous shape codes; 
  352. Bool bLeftBndry, bRightTopBndry, bTopBndry, bLeftTopBndry;
  353. Int iMBnum = VPMBnum(iMBX, iMBY);
  354. bLeftBndry = bVPNoLeft(iMBnum, iMBX);
  355. bTopBndry = bVPNoTop(iMBnum);
  356. bRightTopBndry = bVPNoRightTop(iMBnum, iMBX);
  357. bLeftTopBndry = bVPNoLeftTop(iMBnum, iMBX);
  358. ShapeMode shpmdTop = ALL_TRANSP;
  359. ShapeMode shpmdTopRight = ALL_TRANSP;
  360. ShapeMode shpmdTopLeft = ALL_TRANSP;
  361. ShapeMode shpmdLeft = ALL_TRANSP;
  362. // Modified for error resilient mode by Toshiba(1997-11-14)
  363. if (!bTopBndry)
  364. shpmdTop = (pmbmd - m_iNumMBX)->m_shpmd;
  365. if (!bRightTopBndry)
  366. shpmdTopRight = (pmbmd - m_iNumMBX + 1)->m_shpmd;
  367. if (!bLeftBndry)
  368. shpmdLeft = (pmbmd - 1)->m_shpmd;
  369. if (!bLeftTopBndry)
  370. shpmdTopLeft = (pmbmd - m_iNumMBX - 1)->m_shpmd;
  371. //if (iMBY > iLeftTopMostMB) {
  372. // shpmdTop = (pmbmd - m_iNumMBX)->m_shpmd;
  373. // if (iMBX < iRightMostMB)
  374. // shpmdTopRight = (pmbmd - m_iNumMBX + 1)->m_shpmd;
  375. //}
  376. //if (iMBX > iLeftTopMostMB) {
  377. // shpmdLeft = (pmbmd - 1)->m_shpmd;
  378. // if (iMBY > iLeftTopMostMB)
  379. // shpmdTopLeft = (pmbmd - m_iNumMBX - 1)->m_shpmd;
  380. //}
  381. // End Toshiba(1997-11-14)
  382. assert (shpmdTop != UNKNOWN && shpmdTopRight != UNKNOWN && 
  383. shpmdTopLeft != UNKNOWN && shpmdLeft != UNKNOWN);
  384. //get code and its size
  385. UInt uiTblIndex = shpmdTopLeft * 81 +  shpmdTop * 27 +
  386.   shpmdTopRight * 9 + shpmdLeft * 3 + shpmd;
  387. assert (uiTblIndex >= 0 && uiTblIndex < 243);
  388. assert (grgchFirstShpCd [uiTblIndex] == 0 || grgchFirstShpCd [uiTblIndex] == 2 || 
  389. grgchFirstShpCd [uiTblIndex] == 3);
  390. // Modified for error resilient mode by Toshiba(1997-11-14)
  391. UInt nCodeSize = (grgchFirstShpCd [uiTblIndex] == 0) ? 1
  392.  : grgchFirstShpCd [uiTblIndex];
  393. #ifdef __TRACE_AND_STATS_
  394. m_pbitstrmOut->trace ((Int) shpmd, "MB_Curr_ShpMd");
  395. #endif // __TRACE_AND_STATS_
  396. m_pbitstrmShapeMBOut->putBits ((Int) 1, nCodeSize, "MB_Shape_Mode");
  397. // End Toshiba(1997-11-14)
  398. nBits += nCodeSize;
  399. return nBits;
  400. }
  401. UInt CVideoObjectEncoder::codeShapeModeInter (const ShapeMode& shpmd, const ShapeMode& shpmdColocatedMB)
  402. {
  403. assert (shpmdColocatedMB != UNKNOWN && shpmd != UNKNOWN);
  404. UInt nBits = 0;
  405. CEntropyEncoder* pentrenc = m_pentrencSet->m_ppentrencShapeMode [shpmdColocatedMB];
  406. #ifdef __TRACE_AND_STATS_
  407. m_pbitstrmOut->trace ((Int) shpmdColocatedMB, "MB_Colocated_ShpMd");
  408. m_pbitstrmOut->trace ((Int) shpmd, "MB_Curr_ShpMd");
  409. #endif // __TRACE_AND_STATS_
  410. pentrenc->attachStream(*m_pbitstrmShapeMBOut);
  411. nBits += pentrenc->encodeSymbol (shpmd, "MB_Shape_Mode");
  412. pentrenc->attachStream(*m_pbitstrmOut);
  413. return nBits;
  414. }
  415. // find appropriate size for coded babs
  416. ShapeMode CVideoObjectEncoder::round (PixelC* ppxlcSrcFrm, const CMBMode* pmbmd) //only to partial BABs
  417. {
  418. ShapeMode shpmd;
  419. Bool bIsErrorLarge;
  420. if (m_volmd.bNoCrChange == FALSE)
  421. {
  422. // attempt to reduce bab size
  423. m_bNoShapeChg = FALSE;
  424. #define iThreshD4  (7 * MPEG4_OPAQUE)
  425. // reduce by factor 4
  426. downSampleShape (m_ppxlcCurrMBBY, 
  427.    m_rgiSubBlkIndx16x16,
  428.    m_ppxlcCurrMBBYDown4, 
  429.    m_rgiPxlIndx8x8,
  430.    4, iThreshD4, 16);
  431. // see if this size is acceptable
  432. shpmd = INTRA_CAE;
  433. m_iInverseCR = 4;
  434. m_iWidthCurrBAB = 8;
  435. // subsample border before upsample to original size
  436. subsampleLeftTopBorderFromVOP (ppxlcSrcFrm, m_ppxlcCurrMBBYDown4);
  437. makeRightBottomBorder (m_ppxlcCurrMBBYDown4, 8);
  438. upSampleShape(ppxlcSrcFrm,m_ppxlcCurrMBBYDown4,m_ppxlcReconCurrBAB);
  439. // check if approximation is acceptable
  440. bIsErrorLarge = isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
  441. m_ppxlcReconCurrBAB, m_rgiSubBlkIndx20x20, 20, pmbmd);
  442. if(!bIsErrorLarge)
  443. {
  444. // ok, so assign encoding buffer
  445. m_rgpxlcCaeSymbol = m_ppxlcCurrMBBYDown4; 
  446. return shpmd;
  447. }
  448. #define iThreshD2 (MPEG4_OPAQUE)
  449. // factor 4 failed, so try to reduce by factor 2
  450. downSampleShape (m_ppxlcCurrMBBY, 
  451.    m_rgiSSubBlkIndx16x16,
  452.    m_ppxlcCurrMBBYDown2, 
  453.    m_rgiPxlIndx12x12,
  454.    2, iThreshD2, 64);
  455. // mixed, so see if this size is acceptable
  456. shpmd = INTRA_CAE;
  457. m_iInverseCR = 2;
  458. m_iWidthCurrBAB = 12;
  459. // subsample border before upsample to original size
  460. subsampleLeftTopBorderFromVOP (ppxlcSrcFrm, m_ppxlcCurrMBBYDown2);
  461. makeRightBottomBorder (m_ppxlcCurrMBBYDown2, 12);
  462. upSampleShape(ppxlcSrcFrm,m_ppxlcCurrMBBYDown2, m_ppxlcReconCurrBAB);
  463. // check if approximation is acceptable
  464. bIsErrorLarge = isErrorLarge (m_ppxlcCurrMBBY, m_rgiSubBlkIndx16x16, 16,
  465. m_ppxlcReconCurrBAB, m_rgiSubBlkIndx20x20, 20, pmbmd);
  466. if(!bIsErrorLarge)
  467. {
  468. // ok, so assign encoding buffer
  469. m_rgpxlcCaeSymbol = m_ppxlcCurrMBBYDown2; 
  470. return shpmd;
  471. }
  472. }
  473. // has to be original size
  474. m_bNoShapeChg = TRUE;
  475. shpmd = INTRA_CAE;
  476. m_iInverseCR = 1;
  477. m_iWidthCurrBAB = BAB_SIZE;
  478. // copy data to ReconCurrBAB
  479. PixelC* ppxlcDst = m_ppxlcReconCurrBAB + BAB_BORDER + BAB_BORDER * TOTAL_BAB_SIZE;
  480. PixelC* ppxlcSrc = m_ppxlcCurrMBBY;
  481. Int iUnit = sizeof(PixelC); // NBIT: for memcpy
  482. Int i;
  483. for (i = 0; i < MB_SIZE; i++) {
  484. memcpy (ppxlcDst, ppxlcSrc, MB_SIZE*iUnit);
  485. ppxlcSrc += MB_SIZE;
  486. ppxlcDst += BAB_SIZE;
  487. }
  488. // make borders
  489. copyLeftTopBorderFromVOP (ppxlcSrcFrm, m_ppxlcReconCurrBAB);
  490. makeRightBottomBorder (m_ppxlcReconCurrBAB, TOTAL_BAB_SIZE);
  491. // assign encoding buffer
  492. m_rgpxlcCaeSymbol = m_ppxlcReconCurrBAB;
  493. return shpmd;
  494. }
  495. Int CVideoObjectEncoder::downSampleShape (const PixelC* ppxlcSrc, 
  496.    Int* rgiSrcSubBlk,
  497.    PixelC* ppxlcDst, 
  498.    Int* piDstPxl, 
  499.    Int iRate,
  500.    Int iThreshold,
  501.    Int nSubBlk)
  502. {
  503. Int nOpaquePixel = 0, iSum = 0;
  504. Int iSubBlk;
  505. for (iSubBlk = 0; iSubBlk < nSubBlk; iSubBlk++) {
  506. Int i = rgiSrcSubBlk [iSubBlk];
  507. iSum = 0;
  508. for (CoordI iY = 0; iY < iRate; iY++) {
  509. for (CoordI iX = 0; iX < iRate; iX++)  {
  510. iSum += abs (ppxlcSrc [i++]);  //abs???
  511. }
  512. i += MB_SIZE - iRate;
  513. }
  514. ppxlcDst [*piDstPxl] = (iSum > iThreshold) ? MPEG4_OPAQUE : MPEG4_TRANSPARENT;
  515. nOpaquePixel += ppxlcDst [*piDstPxl];
  516. piDstPxl++;
  517. }
  518. return (nOpaquePixel /= MPEG4_OPAQUE);
  519. }
  520. Bool CVideoObjectEncoder::isErrorLarge (const PixelC* rgppxlcSrc, const Int* rgiSubBlkIndx, Int iWidthSrc, PixelC pxlcRecon, const CMBMode* pmbmd)
  521. {
  522. if (pmbmd->m_bhas4MVForward == TRUE) {
  523. if (!sameBlockTranspStatus (pmbmd, pxlcRecon))
  524. return TRUE;
  525. //check error in each 4x4 subblock
  526. Int iSubBlk;
  527. Int iError = 0;
  528. for (iSubBlk = 0; iSubBlk < 16; iSubBlk++) {
  529. Int i = rgiSubBlkIndx [iSubBlk];
  530. for (CoordI iY = 0; iY < 4; iY++) {
  531. for (CoordI iX = 0; iX < 4; iX++)  {
  532. iError += abs (rgppxlcSrc [i++] - pxlcRecon);
  533. }
  534. if (iError > m_volmd.iBinaryAlphaTH) 
  535. return TRUE;
  536. i += iWidthSrc - 4;
  537. }
  538. }
  539. return FALSE;
  540. }
  541. Bool CVideoObjectEncoder::isErrorLarge (const PixelC* rgppxlcSrc, const Int* rgiSubBlkIndxSrc, const Int iSizeSrc,
  542. const PixelC* rgppxlcDst, const Int* rgiSubBlkIndxDst, const Int iSizeDst, const CMBMode* pmbmd)
  543. {
  544. if (pmbmd->m_bhas4MVForward == TRUE) {
  545. if (!sameBlockTranspStatus (pmbmd, rgppxlcDst, iSizeDst))
  546. return TRUE;
  547. //check error in each 4x4 subblock
  548. Int iSubBlk;
  549. Int iError = 0;
  550. for (iSubBlk = 0; iSubBlk < 16; iSubBlk++) {
  551. Int iSrc = rgiSubBlkIndxSrc [iSubBlk];
  552. Int iDst = rgiSubBlkIndxDst [iSubBlk];
  553. for (CoordI iY = 0; iY < 4; iY++) {
  554. for (CoordI iX = 0; iX < 4; iX++)  {
  555. iError += abs (rgppxlcSrc [iSrc] - rgppxlcDst [iDst]);
  556. iSrc++;
  557. iDst++;
  558. }
  559. if (iError > m_volmd.iBinaryAlphaTH)
  560. return TRUE;
  561. iSrc += iSizeSrc - 4;
  562. iDst += iSizeDst - 4;
  563. }
  564. }
  565. return FALSE;
  566. }
  567. UInt CVideoObjectEncoder::encodeCAEIntra (ShapeMode shpmd, CAEScanDirection shpdir)
  568. {
  569. assert (shpmd == INTRA_CAE);
  570. // m_pbitstrmOut->trace (m_rgiCurrShp, TOTAL_BAB_SQUARE_SIZE, "MB_BAB");
  571. UInt nBits = 0;
  572. nBits += codeCrAndSt (shpdir, m_iInverseCR);
  573. //the real arithmatic encoding
  574. StartArCoder (m_parcodec);
  575. if (shpdir == HORIZONTAL) {
  576. const PixelC* ppxlcSrcRow = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
  577. for (Int iRow = BAB_BORDER; iRow < m_iWidthCurrBAB - BAB_BORDER; iRow++) {
  578. const PixelC* ppxlcSrc = ppxlcSrcRow;
  579. for (Int iCol = BAB_BORDER; iCol < m_iWidthCurrBAB - BAB_BORDER; iCol++) {
  580. Int iContext = contextIntra (ppxlcSrc);
  581. #ifdef __TRACE_AND_STATS_
  582. // m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
  583. #endif // __TRACE_AND_STATS_
  584. ArCodeSymbol ((*ppxlcSrc == MPEG4_OPAQUE), gCAEintraProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
  585. ppxlcSrc++;
  586. }
  587. ppxlcSrcRow += m_iWidthCurrBAB;
  588. }
  589. }
  590. else {
  591. const PixelC* ppxlcSrcCol = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
  592. for (Int iCol = BAB_BORDER; iCol < m_iWidthCurrBAB - BAB_BORDER; iCol++) {
  593. const PixelC* ppxlcSrc = ppxlcSrcCol;
  594. for (Int iRow = BAB_BORDER; iRow < m_iWidthCurrBAB - BAB_BORDER; iRow++) {
  595. Int iContext = contextIntraTranspose (ppxlcSrc);
  596. #ifdef __TRACE_AND_STATS_
  597. //m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
  598. #endif // __TRACE_AND_STATS_
  599. ArCodeSymbol ((*ppxlcSrc == MPEG4_OPAQUE), gCAEintraProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
  600. ppxlcSrc += m_iWidthCurrBAB ;
  601. }
  602. ppxlcSrcCol++;
  603. }
  604. }
  605. StopArCoder (m_parcodec, m_pbitstrmShapeMBOut);
  606. nBits += m_parcodec->nBits;
  607. return nBits;
  608. }
  609. UInt CVideoObjectEncoder::encodeCAEInter (ShapeMode shpmd, CAEScanDirection shpdir)
  610. {
  611. assert (shpmd == INTER_CAE_MVDNZ || shpmd == INTER_CAE_MVDZ);
  612. // m_pbitstrmOut->trace (m_rgiCurrShp, TOTAL_BAB_SQUARE_SIZE, "MB_BAB");
  613. UInt nBits = 0;
  614. nBits += codeCrAndSt (shpdir, m_iInverseCR);
  615. const PixelC *ppxlcPredBAB = m_puciPredBAB->pixels();
  616. Int iSizeMB = m_iWidthCurrBAB-BAB_BORDER*2;
  617. Int iSizePredBAB = iSizeMB+MC_BAB_BORDER*2;
  618. if(m_iInverseCR==2)
  619. {
  620. downSampleShapeMCPred(ppxlcPredBAB,m_ppxlcPredBABDown2,2);
  621. ppxlcPredBAB = m_ppxlcPredBABDown2;
  622. }
  623. else if(m_iInverseCR==4)
  624. {
  625. downSampleShapeMCPred(ppxlcPredBAB,m_ppxlcPredBABDown4,4);
  626. ppxlcPredBAB = m_ppxlcPredBABDown4;
  627. }
  628. //the real arithmatic encoding
  629. StartArCoder (m_parcodec);
  630. if (shpdir == HORIZONTAL) {
  631. const PixelC* ppxlcSrcRow  = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
  632. const PixelC* ppxlcPredRow = ppxlcPredBAB + iSizePredBAB * MC_BAB_BORDER + MC_BAB_BORDER;
  633. for (Int iRow = 0; iRow < iSizeMB; iRow++) {
  634. const PixelC* ppxlcSrc = ppxlcSrcRow;
  635. const PixelC* ppxlcPred = ppxlcPredRow;
  636. for (Int iCol = 0; iCol < iSizeMB; iCol++) {
  637. Int iContext = contextInter (ppxlcSrc, ppxlcPred);
  638. #ifdef __TRACE_AND_STATS_
  639. //m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
  640. #endif // __TRACE_AND_STATS_
  641. ArCodeSymbol ((*ppxlcSrc == MPEG4_OPAQUE), gCAEinterProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
  642. ppxlcSrc++;
  643. ppxlcPred++;
  644. }
  645. ppxlcSrcRow += m_iWidthCurrBAB;
  646. ppxlcPredRow += iSizePredBAB;
  647. }
  648. }
  649. else {
  650. const PixelC* ppxlcSrcCol  = m_rgpxlcCaeSymbol + m_iWidthCurrBAB * BAB_BORDER + BAB_BORDER;
  651. const PixelC* ppxlcPredCol = ppxlcPredBAB + iSizePredBAB * MC_BAB_BORDER + MC_BAB_BORDER;
  652. for (Int iCol = 0; iCol < iSizeMB; iCol++) {
  653. const PixelC* ppxlcSrc = ppxlcSrcCol;
  654. const PixelC* ppxlcPred = ppxlcPredCol;
  655. for (Int iRow = 0; iRow < iSizeMB; iRow++) {
  656. Int iContext = contextInterTranspose (ppxlcSrc, ppxlcPred);
  657. #ifdef __TRACE_AND_STATS_
  658. //m_pbitstrmOut->trace (iContext, "MB_CAE_Context");
  659. #endif // __TRACE_AND_STATS_
  660. ArCodeSymbol ((*ppxlcSrc == MPEG4_OPAQUE), gCAEinterProb [iContext], m_parcodec, m_pbitstrmShapeMBOut);
  661. ppxlcSrc += m_iWidthCurrBAB;
  662. ppxlcPred += iSizePredBAB;
  663. }
  664. ppxlcSrcCol++;
  665. ppxlcPredCol++;
  666. }
  667. }
  668. StopArCoder (m_parcodec, m_pbitstrmShapeMBOut);
  669. nBits += m_parcodec->nBits;
  670. return nBits;
  671. }
  672. UInt CVideoObjectEncoder::encodeMVDS (CMotionVector mvBYD)
  673. {
  674. assert (!mvBYD.isZero());
  675. m_pentrencSet->m_pentrencShapeMV1->attachStream(*m_pbitstrmShapeMBOut);
  676. m_pentrencSet->m_pentrencShapeMV2->attachStream(*m_pbitstrmShapeMBOut);
  677. UInt nBits = 0;
  678. nBits += m_pentrencSet->m_pentrencShapeMV1->encodeSymbol (abs (mvBYD.iMVX), "MB_SHP_MVDX");
  679. if (mvBYD.iMVX != 0) {
  680. m_pbitstrmShapeMBOut->putBits (signOf(mvBYD.iMVX), (UInt) 1, "MB_SHP_MVDX_Sign");
  681. nBits++;
  682. nBits += m_pentrencSet->m_pentrencShapeMV1->encodeSymbol (abs (mvBYD.iMVY), "MB_SHP_MVDY");
  683. }
  684. else 
  685. nBits += m_pentrencSet->m_pentrencShapeMV2->encodeSymbol (abs (mvBYD.iMVY) - 1, "MB_SHP_MVDY");
  686. if (mvBYD.iMVY != 0) {
  687. m_pbitstrmShapeMBOut->putBits (signOf(mvBYD.iMVY), (UInt) 1, "MB_SHP_MVDY_Sign");
  688. nBits++;
  689. }
  690. m_pentrencSet->m_pentrencShapeMV1->attachStream(*m_pbitstrmOut);
  691. m_pentrencSet->m_pentrencShapeMV2->attachStream(*m_pbitstrmOut);
  692. return nBits;
  693. }
  694. Bool CVideoObjectEncoder::sameBlockTranspStatus (const CMBMode* pmbmd, PixelC pxlcRecon) //assume src is 16 x 16 buffer
  695. {
  696. if (pxlcRecon == opaqueValue)
  697. return ((pmbmd->m_rgTranspStatus [Y_BLOCK1] != ALL) && //if recon is all opaque
  698. (pmbmd->m_rgTranspStatus [Y_BLOCK2] != ALL) && //then each orig. blk has to be not all transp
  699. (pmbmd->m_rgTranspStatus [Y_BLOCK3] != ALL) &&
  700. (pmbmd->m_rgTranspStatus [Y_BLOCK4] != ALL));
  701. return TRUE;
  702. }
  703. Bool CVideoObjectEncoder::sameBlockTranspStatus (const CMBMode* pmbmd, const PixelC* pxlcRecon, Int iSizeRecon) //src: 16x16 Recon: 18 x 18 || 20 x 20
  704. {
  705. Int iBorder = (iSizeRecon == 18) ? 1 : 2;
  706. const PixelC* ppxlcBlk1 = pxlcRecon + iBorder + iBorder * iSizeRecon;
  707. const PixelC* ppxlcBlk2 = ppxlcBlk1 + BLOCK_SIZE;
  708. const PixelC* ppxlcBlk3 = pxlcRecon + iSizeRecon * iSizeRecon / 2 + iBorder;
  709. const PixelC* ppxlcBlk4 = ppxlcBlk3 + BLOCK_SIZE;
  710. static PixelC rgnOpaquePixels [4];
  711. rgnOpaquePixels [0] = rgnOpaquePixels [1] = rgnOpaquePixels [2] = rgnOpaquePixels [3] = 0;
  712. CoordI ix, iy;
  713. for (iy = 0; iy < BLOCK_SIZE; iy++) {
  714. for (ix = 0; ix < BLOCK_SIZE; ix++) {
  715. rgnOpaquePixels [0] += ppxlcBlk1 [ix];
  716. rgnOpaquePixels [1] += ppxlcBlk2 [ix];
  717. rgnOpaquePixels [2] += ppxlcBlk3 [ix];
  718. rgnOpaquePixels [3] += ppxlcBlk4 [ix];
  719. }
  720. ppxlcBlk1 += iSizeRecon;
  721. ppxlcBlk2 += iSizeRecon;
  722. ppxlcBlk3 += iSizeRecon;
  723. ppxlcBlk4 += iSizeRecon;
  724. }
  725. Int iBlk;
  726. for (iBlk = Y_BLOCK1; iBlk <= Y_BLOCK4; iBlk++)
  727. if (pmbmd->m_rgTranspStatus [iBlk] == ALL) //if org. blk is all transp, the recon can be otherwise
  728. if (rgnOpaquePixels [iBlk - 1] != 0)
  729. return FALSE;
  730. return TRUE;
  731. }
  732. UInt CVideoObjectEncoder::codeCrAndSt (CAEScanDirection shpdir, Int iInverseCR)
  733. {
  734. UInt nBits = 0;
  735. if (m_volmd.bNoCrChange == FALSE) {
  736. UInt nBitsCR = (iInverseCR == 1) ? 1 : 2;
  737. Int iCode = (iInverseCR == 1) ? 0 : (iInverseCR == 2) ? 2 : 3;
  738. m_pbitstrmShapeMBOut->putBits (iCode, nBitsCR, "MB_CR");
  739. nBits += nBitsCR;
  740. }
  741. //Scan direction
  742. m_pbitstrmShapeMBOut->putBits ((shpdir == HORIZONTAL) ? 1 : 0, (UInt) 1, "MB_ST");
  743. nBits++;
  744. return nBits;
  745. }
  746. Void CVideoObjectEncoder::copyReconShapeToRef (PixelC* ppxlcRefFrm, PixelC pxlcSrc) //no need to reset MB buffer
  747. {
  748. for (Int i = 0; i < MB_SIZE; i++) {
  749. pxlcmemset (ppxlcRefFrm, pxlcSrc, MB_SIZE);
  750. ppxlcRefFrm+= m_iFrameWidthY;
  751. }
  752. }
  753. Void CVideoObjectEncoder::copyReconShapeToRef (PixelC* ppxlcRefFrm, 
  754.    const PixelC* ppxlcSrc, Int iSrcWidth, Int iBorder)
  755. {
  756. ppxlcSrc += iSrcWidth * iBorder + iBorder;
  757. Int iUnit = sizeof(PixelC); // NBIT: for memcpy
  758. for (Int i = 0; i < MB_SIZE; i++) {
  759. memcpy (ppxlcRefFrm, ppxlcSrc, MB_SIZE*iUnit);
  760. ppxlcRefFrm += m_iFrameWidthY;
  761. ppxlcSrc += iSrcWidth;
  762. }
  763. }
  764. Int CVideoObjectEncoder::sadForShape (const PixelC* ppxlcRefBY) const
  765. {
  766. Int iInitSAD = 0;
  767. CoordI ix, iy;
  768. const PixelC* ppxlcCurrBY = m_ppxlcCurrMBBY;
  769. for (iy = 0; iy < MB_SIZE; iy++) {
  770. for (ix = 0; ix < MB_SIZE; ix++)
  771. iInitSAD += abs (ppxlcCurrBY [ix] - ppxlcRefBY [ix]);
  772. ppxlcCurrBY += MB_SIZE;
  773. ppxlcRefBY += m_iFrameWidthY;
  774. }
  775. return iInitSAD;
  776. }
  777. Void CVideoObjectEncoder::blkmatchForShape (
  778. CVOPU8YUVBA* pvopcRefQ,
  779. CMotionVector* pmv,
  780. const CVector& mvPredHalfPel,
  781. CoordI iX, CoordI iY
  782. )
  783. {
  784. Int mbDiff;
  785. CoordI x = iX + (mvPredHalfPel.x >> 1), y = iY + (mvPredHalfPel.y >> 1); 
  786. Int iXDest = x, iYDest = y;
  787. CoordI ix, iy;
  788. const PixelC* ppxlcRefMBY = pvopcRefQ->pixelsBY () + m_rctRefFrameY.offset (x, y);
  789. Int iMinSAD = sadForShape (ppxlcRefMBY);
  790. pmv->iMVX = pmv->iMVY = 0;
  791. Int uiPosInLoop, iLoop;
  792. // Spiral Search for the rest
  793. for (iLoop = 1; iLoop <= 16; iLoop++) {
  794. x++;
  795. y++;
  796. ppxlcRefMBY += m_iFrameWidthY + 1;
  797. for (uiPosInLoop = 0; uiPosInLoop < (iLoop << 3); uiPosInLoop++) {
  798. // inside each spiral loop 
  799. if (
  800. x >= m_rctRefVOPY0.left && y >= m_rctRefVOPY0.top && 
  801. x <= m_rctRefVOPY0.right - MB_SIZE && y <= m_rctRefVOPY0.bottom - MB_SIZE
  802. ) {
  803. const PixelC* ppxlcTmpC = m_ppxlcCurrMBBY;
  804. const PixelC* ppxlcRefMB = ppxlcRefMBY;
  805. mbDiff = 0;
  806. for (iy = 0; iy < MB_SIZE; iy++) {
  807. for (ix = 0; ix < MB_SIZE; ix++)
  808. mbDiff += abs (ppxlcTmpC [ix] - ppxlcRefMB [ix]);
  809. if (mbDiff >= iMinSAD)
  810. goto NEXT_POSITION; // skip the current position
  811. ppxlcRefMB += m_iFrameWidthY;
  812. ppxlcTmpC += MB_SIZE;
  813. }
  814. iMinSAD = mbDiff;
  815. iXDest = x;
  816. iYDest = y;
  817. }
  818. NEXT_POSITION:
  819. if (uiPosInLoop < (iLoop << 1)) {
  820. ppxlcRefMBY--;
  821. x--;
  822. }
  823. else if (uiPosInLoop < (iLoop << 2)) {
  824. ppxlcRefMBY -= m_iFrameWidthY;
  825. y--;
  826. }
  827. else if (uiPosInLoop < (iLoop * 6)) {
  828. ppxlcRefMBY++;   
  829. x++;
  830. }
  831. else {
  832. ppxlcRefMBY += m_iFrameWidthY;
  833. y++;
  834. }
  835. }
  836. }
  837. *pmv = CMotionVector (iXDest - iX, iYDest - iY);
  838. }