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

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*************************************************************************
  2. This software module was originally developed by 
  3. Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
  4. Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
  5. Bruce Lin (blin@microsoft.com), Microsoft Corporation
  6. Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
  7. Simon Winder (swinder@microsoft.com), Microsoft Corporation
  8. (date: March, 1996)
  9. in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). 
  10. This software module is an implementation of a part of one or more MPEG-4 Video tools 
  11. as specified by the MPEG-4 Video. 
  12. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications 
  13. thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. 
  14. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. 
  15. The original developer of this software module and his/her company, 
  16. the subsequent editors and their companies, 
  17. and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. 
  18. Copyright is not released for non MPEG-4 Video conforming products. 
  19. Microsoft retains full right to use the code for his/her own purpose, 
  20. assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. 
  21. This copyright notice must be included in all copies or derivative works. 
  22. Copyright (c) 1996, 1997.
  23. Module Name:
  24. mode.h
  25. Abstract:
  26. basic coding modes for VOP and MB
  27. Revision History:
  28. Dec. 12, 1997: Interlaced tools added by NextLevel Systems
  29.         May. 9   1998:  add boundary by Hyundai Electronics
  30.                                   Cheol-Soo Park (cspark@super5.hyundai.co.kr)
  31.         May. 9   1998:  add field based MC padding by Hyundai Electronics
  32.                                   Cheol-Soo Park (cspark@super5.hyundai.co.kr)
  33. May 9, 1999: tm5 rate control by DemoGraFX, duhoff@mediaone.net
  34. *************************************************************************/
  35. #include <string.h>
  36. #include <iostream.h>
  37. #include <math.h>
  38. #include "typeapi.h"
  39. #include "mode.hpp"
  40. #include "warp.hpp"
  41. #ifdef __MFC_
  42. #ifdef _DEBUG
  43. #undef THIS_FILE
  44. static char BASED_CODE THIS_FILE[] = __FILE__;
  45. #endif
  46. #define new DEBUG_NEW    
  47. #endif // __MFC_
  48. // only works for 4:2:0
  49. #define MAX_NUM_MV 4
  50. UInt uiNumBlks = 10;
  51. //#define uiNumBlks 10
  52. CMBMode::~CMBMode ()
  53. delete [] m_rgbCodedBlockPattern; 
  54. delete [] m_rgfltMinErrors; 
  55. }
  56. CMBMode::CMBMode ()
  57. {
  58. UInt i;
  59. for (i = 0; i < uiNumBlks + 1; i++) {
  60. m_rgTranspStatus [i] = NONE;
  61. m_rgNumNonTranspPixels [i] = 0;
  62. }
  63. /*BBM// Added for Boundary by Hyundai(1998-5-9)
  64.         for (i = 0; i < uiNumBlks + 1; i++)
  65.                 m_rgTranspStatusBBM[i] = NONE;
  66.         memset (m_bMerged, FALSE, 7 * sizeof(Bool));
  67. // End of Hyundai(1998-5-9)*/
  68. // Added for field based MC padding by Hyundai(1998-5-9)
  69.         for (i = 0; i < 5; i++)
  70. m_rgFieldTranspStatus [i] = ALL;
  71. memset (m_rgbFieldPadded, 0, 5 * sizeof(Bool));
  72. // End of Hyundai(1998-5-9)
  73. m_rgbCodedBlockPattern = new Bool [uiNumBlks];
  74. memset (m_rgbCodedBlockPattern, FALSE, uiNumBlks * sizeof (Bool));
  75. m_rgfltMinErrors = new Float [uiNumBlks];
  76. memset (m_rgfltMinErrors, 0, uiNumBlks * sizeof (Float));
  77. m_bPadded = FALSE;
  78. m_bSkip = FALSE;
  79. m_dctMd = INTRA;
  80. m_shpmd = UNKNOWN;
  81. m_mbType = FORWARD;
  82. m_intStepDelta = 0;
  83. m_bhas4MVForward = FALSE; 
  84. m_bhas4MVBackward = FALSE;
  85. m_bFieldMV = FALSE;
  86. m_bForwardTop = FALSE;   
  87. m_bForwardBottom = FALSE;
  88. m_bBackwardTop = FALSE;
  89. m_bBackwardBottom = FALSE;
  90. m_bFieldDCT = FALSE;
  91. m_bPerspectiveForward = FALSE;
  92. m_bPerspectiveBackward = FALSE;
  93. m_stepSize = 0;
  94. m_stepSizeDelayed = 0;
  95. m_stepSizeAlpha = 0;
  96. m_bACPrediction = FALSE;
  97. m_bInterShapeCoding = FALSE;
  98. m_bColocatedMBSkip = FALSE;
  99. m_iVideoPacketNumber = 0;
  100. m_vctDirectDeltaMV = CVector (0, 0);
  101. }
  102. CMBMode::CMBMode (const CMBMode& md)
  103. {
  104. memcpy (m_rgTranspStatus, md.m_rgTranspStatus, (uiNumBlks + 1)  * sizeof (TransparentStatus));
  105. memcpy (m_rgNumNonTranspPixels, md.m_rgNumNonTranspPixels, (uiNumBlks + 1)  * sizeof (UInt));
  106. memcpy (m_preddir,md.m_preddir,uiNumBlks * sizeof(IntraPredDirection));
  107. /*BBM// Added for Boundary by Hyundai(1998-5-9)
  108.         memcpy (m_rgTranspStatusBBM, md.m_rgTranspStatusBBM, (uiNumBlks + 1)  * sizeof (TransparentStatus));
  109.         memcpy (m_bMerged, md.m_bMerged, 7 * sizeof (Bool));
  110. // End of Hyundai(1998-5-9)*/
  111. // Added for field based MC padding by Hyundai(1998-5-9)
  112.         memcpy (m_rgFieldTranspStatus, md.m_rgFieldTranspStatus, 5  * sizeof (TransparentStatus));
  113. memcpy (m_rgbFieldPadded, md.m_rgbFieldPadded, 5 * sizeof (Bool));
  114. // End of Hyundai(1998-5-9)
  115. m_bPadded = md.m_bPadded;
  116. m_bSkip = md.m_bSkip;
  117. m_CODAlpha = md.m_CODAlpha;
  118. m_mbType = md.m_mbType;
  119. m_dctMd = md.m_dctMd;
  120. m_shpmd = md.m_shpmd ;
  121. m_intStepDelta = md.m_intStepDelta;
  122. m_bhas4MVForward = md.m_bhas4MVForward; 
  123. m_bhas4MVBackward = md.m_bhas4MVBackward; 
  124. m_bPerspectiveForward = md.m_bPerspectiveForward;
  125. m_bPerspectiveBackward = md.m_bPerspectiveBackward;
  126. m_stepSize = md.m_stepSize;
  127. m_stepSizeDelayed = md.m_stepSizeDelayed;
  128. m_stepSizeAlpha = md.m_stepSizeAlpha;
  129. m_bACPrediction = md.m_bACPrediction;
  130. m_bACPredictionAlpha = md.m_bACPredictionAlpha;
  131. m_bInterShapeCoding = md.m_bInterShapeCoding;
  132. m_bCodeDcAsAc = md.m_bCodeDcAsAc;
  133. m_bCodeDcAsAcAlpha = md.m_bCodeDcAsAcAlpha;
  134. m_bColocatedMBSkip = md.m_bColocatedMBSkip;
  135. m_iVideoPacketNumber = md.m_iVideoPacketNumber;
  136. m_rgbCodedBlockPattern = new Bool [uiNumBlks];
  137. memcpy (m_rgbCodedBlockPattern, md.m_rgbCodedBlockPattern, uiNumBlks * sizeof (Bool));
  138. m_rgfltMinErrors = new Float [uiNumBlks];
  139. memcpy (m_rgfltMinErrors, md.m_rgfltMinErrors, uiNumBlks * sizeof (Float));
  140. }
  141. Void CMBMode::operator = (const CMBMode& md)
  142. {
  143. memcpy (m_rgTranspStatus, md.m_rgTranspStatus, (uiNumBlks + 1) * sizeof (TransparentStatus));
  144. memcpy (m_rgNumNonTranspPixels, md.m_rgNumNonTranspPixels, (uiNumBlks + 1) * sizeof (UInt));
  145. memcpy (m_preddir,md.m_preddir,uiNumBlks * sizeof(IntraPredDirection));
  146. /*BBM// Added for Boundary by Hyundai(1998-5-9)
  147. memcpy (m_rgTranspStatusBBM, md.m_rgTranspStatusBBM, (uiNumBlks + 1)  * sizeof (TransparentStatus));
  148.         memcpy (m_bMerged, md.m_bMerged, 7 * sizeof (Bool));
  149. // End of Hyundai(1998-5-9)*/
  150. // Added for field based MC padding by Hyundai(1998-5-9)
  151.         memcpy (m_rgFieldTranspStatus, md.m_rgFieldTranspStatus, 5  * sizeof (TransparentStatus));
  152.         memcpy (m_rgbFieldPadded, md.m_rgbFieldPadded, 5 * sizeof (Bool));
  153. // End of Hyundai(1998-5-9)
  154. m_bPadded = md.m_bPadded;
  155. m_bSkip = md.m_bSkip;
  156. m_CODAlpha = md.m_CODAlpha;
  157. m_mbType = md.m_mbType;
  158. m_dctMd = md.m_dctMd;
  159. m_shpmd = md.m_shpmd ;
  160. m_intStepDelta = md.m_intStepDelta;
  161. m_bhas4MVForward = md.m_bhas4MVForward; 
  162. m_bhas4MVBackward = md.m_bhas4MVBackward; 
  163. m_bPerspectiveForward = md.m_bPerspectiveForward;
  164. m_bPerspectiveBackward = md.m_bPerspectiveBackward;
  165. m_stepSize = md.m_stepSize;
  166. m_stepSizeDelayed = md.m_stepSizeDelayed;
  167. m_stepSizeAlpha = md.m_stepSizeAlpha;
  168. m_bACPrediction = md.m_bACPrediction;
  169. m_bACPredictionAlpha = md.m_bACPredictionAlpha;
  170. m_bInterShapeCoding = md.m_bInterShapeCoding;
  171. m_bCodeDcAsAc = md.m_bCodeDcAsAc;
  172. m_bCodeDcAsAcAlpha = md.m_bCodeDcAsAcAlpha;
  173. m_bColocatedMBSkip = md.m_bColocatedMBSkip;
  174. m_iVideoPacketNumber = md.m_iVideoPacketNumber;
  175. memcpy (m_rgbCodedBlockPattern, md.m_rgbCodedBlockPattern, uiNumBlks * sizeof (Bool));
  176. memcpy (m_rgfltMinErrors, md.m_rgfltMinErrors, uiNumBlks * sizeof (Float));
  177. }
  178. Void CMBMode::setCodedBlockPattern (const Bool* rgbblockNum)
  179. for (UInt i = 0; i < uiNumBlks; i++)
  180. m_rgbCodedBlockPattern[i] = rgbblockNum [i];
  181. }
  182. Void CMBMode::setMinError (const Float* pfltminError)
  183. {
  184. for (UInt i = 0; i < uiNumBlks; i++)
  185. m_rgfltMinErrors[i] = pfltminError [i];
  186. }
  187. CDirectModeData::~CDirectModeData ()
  188. {
  189. destroyMem ();
  190. }
  191. CDirectModeData::CDirectModeData ()
  192. {
  193. m_ppmbmd = NULL;
  194. m_prgmv = NULL;
  195. }
  196. Bool CDirectModeData::inBound (UInt iMbIdx) const
  197. {
  198. if (iMbIdx >= m_uiNumMB)
  199. return FALSE;
  200. else
  201. return TRUE;
  202. }
  203. Bool CDirectModeData::inBound (UInt idX, UInt idY) const
  204. {
  205. if (idX >= m_uiNumMBX || idY >= m_uiNumMBY || idX * idY >= m_uiNumMB)
  206. return FALSE;
  207. else
  208. return TRUE;
  209. }
  210. Void CDirectModeData::reassign (UInt numMBX, UInt numMBY)
  211. {
  212. destroyMem ();
  213. m_uiNumMBX = numMBX;
  214. m_uiNumMBY = numMBY;
  215. m_uiNumMB = m_uiNumMBX * m_uiNumMBY;
  216. m_ppmbmd = new CMBMode* [m_uiNumMB];
  217. m_prgmv = new CMotionVector* [m_uiNumMB];
  218. for (UInt i = 0; i < m_uiNumMB; i++) {
  219. m_ppmbmd [i] = new CMBMode;
  220. m_prgmv [i] = new CMotionVector [5];
  221. }
  222. }
  223. Void CDirectModeData::assign (UInt imb, const CMBMode& mbmd, const CMotionVector* rgmv)
  224. {
  225. assert (inBound (imb));
  226. *(m_ppmbmd [imb]) = mbmd;
  227. memcpy (m_prgmv [imb], rgmv, 5 * sizeof (CMotionVector));
  228. }
  229. Void CDirectModeData::destroyMem ()
  230. {
  231. if (m_ppmbmd != NULL) {
  232. for (UInt i = 0; i < m_uiNumMB; i++)
  233. delete m_ppmbmd [i];
  234. delete [] m_ppmbmd;
  235. }
  236. if (m_prgmv != NULL) {
  237. for (UInt i = 0; i < m_uiNumMB; i++)
  238. delete [] m_prgmv [i];
  239. delete [] m_prgmv;
  240. }
  241. }
  242. CStatistics::CStatistics ()
  243. {
  244. reset ();
  245. }
  246. Void CStatistics::print (Bool bVOPPrint)
  247. {
  248. (Void) total ();
  249. if (bVOPPrint)
  250. cout << "t" << "VOP overhead:" << "tt" << nBitsHead << "n";
  251. cout << "t" << "Y:" << "ttt" << nBitsY << "n";
  252. cout << "t" << "Cr:" << "ttt" << nBitsCr << "n";
  253. cout << "t" << "Cb:" << "ttt" << nBitsCb << "n";
  254. cout << "t" << "A:" << "ttt" << nBitsA << "n";
  255. // cout << "t" << "1st Shape Code:" << "tt" << nBits1stShpCode << "n";
  256. cout << "t" << "CBPY:" << "ttt" << nBitsCBPY << "n";
  257. cout << "t" << "MCBPC:" << "ttt" << nBitsMCBPC << "n";
  258. cout << "t" << "DQUANT:" << "ttt" << nBitsDQUANT << "n";
  259. cout << "t" << "nBitsMODB:" << "tt" << nBitsMODB << "n";
  260. cout << "t" << "nBitsCBPB:" << "tt" << nBitsCBPB << "n";
  261. cout << "t" << "nBitsMBTYPE:" << "tt" << nBitsMBTYPE << "n";
  262. cout << "t" << "nBitsIntraPred:" << "tt" << nBitsIntraPred << "n";
  263. cout << "t" << "nBitsNoDCT:" << "tt" << nBitsNoDCT << "n";
  264. cout << "t" << "nBitsCODA:" << "tt" << nBitsCODA << "n";
  265. cout << "t" << "nBitsCBPA:" << "tt" << nBitsCBPA << "n";
  266. cout << "t" << "nBitsMODBA:" << "tt" << nBitsMODBA << "n";
  267. cout << "t" << "nBitsCBPBA:" << "tt" << nBitsCBPBA << "n";
  268. cout << "t" << "nBitsInterlace:" << "tt" << nBitsInterlace << "n";
  269. cout << "t" << "nBitsSTUFFING:" << "tt" << nBitsStuffing << "n";
  270. cout << "t" << "# of Skipped MB:" << "t" << nSkipMB << "n";
  271. cout << "t" << "# of Inter MB:" << "tt" << nInterMB << "n";
  272. cout << "t" << "# of Inter4V MB:" << "t" << nInter4VMB << "n";
  273. cout << "t" << "# of Intra MB:" << "tt" << nIntraMB << "n";
  274. cout << "t" << "# of Direct MB:" << "tt" << nDirectMB << "n";
  275. cout << "t" << "# of Forward MB:" << "t" << nForwardMB << "n";
  276. cout << "t" << "# of Backward MB:" << "t" << nBackwardMB << "n";
  277. cout << "t" << "# of Interpolate MB:" << "t" << nInterpolateMB << "n";
  278. cout << "t" << "# of Field Fwd MB:" << "t" << nFieldForwardMB << "n";
  279. cout << "t" << "# of Field Back MB:" << "t" << nFieldBackwardMB << "n";
  280. cout << "t" << "# of Field Ave MB:" << "t" << nFieldInterpolateMB << "n";
  281. cout << "t" << "# of Field Direct MB:" << "t" << nFieldDirectMB << "n";
  282. cout << "t" << "# of Field DCT MBs:" << "t" << nFieldDCTMB << "n";
  283. cout << "t" << "Motion:" << "ttt" << nBitsMV << "n";
  284. cout << "t" << "Texture:" << "tt" << nBitsTexture << "n";
  285. // if (bVOPPrint)
  286. cout << "t" << "Shape:" << "ttt" << nBitsShape << "n";
  287. cout << "t" << "Total:" << "ttt" << nBitsTotal << "n";
  288. cout << "t" << "SNR Y:" << "ttt" << dSNRY / nVOPs << " dBn";
  289. cout << "t" << "SNR U:" << "ttt" << dSNRU / nVOPs << " dBn";
  290. cout << "t" << "SNR V:" << "ttt" << dSNRV / nVOPs << " dBn";
  291. cout << "t" << "SNR A:" << "ttt" << dSNRA / nVOPs << " dBnn";
  292. cout << "t" << "average Qp:" << "tt" << (Double)nQp / nQMB << "nn";
  293. cout.flush ();
  294. }
  295. Void CStatistics::operator += (const CStatistics& statSrc)
  296. {
  297. nBitsHead += statSrc.nBitsHead;
  298. nBitsY += statSrc.nBitsY;
  299. nBitsCr += statSrc.nBitsCr;
  300. nBitsCb += statSrc.nBitsCb;
  301. nBitsA += statSrc.nBitsA;
  302. // nBits1stShpCode += statSrc.nBits1stShpCode;
  303. nBitsCOD += statSrc.nBitsCOD;
  304. nBitsCBPY += statSrc.nBitsCBPY;
  305. nBitsMCBPC += statSrc.nBitsMCBPC;
  306. nBitsDQUANT += statSrc.nBitsDQUANT;
  307. nBitsMODB += statSrc.nBitsMODB;
  308. nBitsCBPB += statSrc.nBitsCBPB;
  309. nBitsMBTYPE += statSrc.nBitsMBTYPE;
  310. nBitsIntraPred += statSrc.nBitsIntraPred;
  311. nBitsNoDCT += statSrc.nBitsNoDCT;
  312. nBitsCODA += statSrc.nBitsCODA;
  313. nBitsCBPA += statSrc.nBitsCBPA;
  314. nBitsMODBA += statSrc.nBitsMODBA;
  315. nBitsCBPBA += statSrc.nBitsCBPBA;
  316. nBitsStuffing += statSrc.nBitsStuffing;
  317. nSkipMB += statSrc.nSkipMB;
  318. nInterMB += statSrc.nInterMB;
  319. nInter4VMB += statSrc.nInter4VMB;
  320. nIntraMB += statSrc.nIntraMB;
  321. nDirectMB += statSrc.nDirectMB;
  322. nForwardMB += statSrc.nForwardMB;
  323. nBackwardMB += statSrc.nBackwardMB;
  324. nInterpolateMB += statSrc.nInterpolateMB;
  325. nBitsInterlace += statSrc.nBitsInterlace;
  326. nFieldForwardMB += statSrc.nFieldForwardMB;
  327. nFieldBackwardMB += statSrc.nFieldBackwardMB;
  328. nFieldInterpolateMB += statSrc.nFieldInterpolateMB;
  329. nFieldDirectMB += statSrc.nFieldDirectMB;
  330. nFieldDCTMB += statSrc.nFieldDCTMB;
  331. nVOPs += statSrc.nVOPs;
  332. nBitsMV += statSrc.nBitsMV;
  333. nBitsTexture += statSrc.nBitsTexture;
  334. nBitsShape += statSrc.nBitsShape;
  335. nBitsTotal += statSrc.nBitsTotal;
  336. dSNRY += statSrc.dSNRY;
  337. dSNRU += statSrc.dSNRU;
  338. dSNRV += statSrc.dSNRV;
  339. dSNRA += statSrc.dSNRA;
  340. nQMB += statSrc.nQMB;
  341. nQp += statSrc.nQp;
  342. }
  343. Void CStatistics::reset ()
  344. {
  345. nBitsHead = 0;
  346. nBitsY = 0;
  347. nBitsCr = 0;
  348. nBitsCb = 0;
  349. nBitsA = 0;
  350. // nBits1stShpCode = 0;
  351. nBitsCOD = 0;
  352. nBitsCBPY = 0;
  353. nBitsMCBPC = 0;
  354. nBitsDQUANT = 0;
  355. nBitsMODB = 0;
  356. nBitsCBPB = 0;
  357. nBitsMBTYPE = 0;
  358. nBitsIntraPred = 0;
  359. nBitsNoDCT = 0;
  360. nBitsCODA = 0;
  361. nBitsCBPA = 0;
  362. nBitsMODBA = 0;
  363. nBitsCBPBA = 0;
  364. nBitsStuffing = 0;
  365. nSkipMB = 0;
  366. nInterMB = 0;
  367. nInter4VMB = 0;
  368. nIntraMB = 0;
  369. nDirectMB = 0;
  370. nForwardMB = 0;
  371. nBackwardMB = 0;
  372. nInterpolateMB = 0;
  373. nBitsInterlace = 0;
  374. nFieldForwardMB = 0;
  375. nFieldBackwardMB = 0;
  376. nFieldInterpolateMB = 0;
  377. nFieldDirectMB = 0;
  378. nFieldDCTMB = 0;
  379. nVOPs = 0;
  380. nBitsMV = 0;
  381. nBitsTexture = 0;
  382. nBitsShape = 0;
  383. nBitsTotal = 0;
  384. dSNRY = 0;
  385. dSNRU = 0;
  386. dSNRV = 0;
  387. dSNRA = 0;
  388. nQMB = 0;
  389. nQp = 0;
  390. }
  391. CStatistics& CStatistics::operator = (const CStatistics& statSrc)
  392. {
  393. nBitsHead = statSrc.nBitsHead;
  394. nBitsY = statSrc.nBitsY;
  395. nBitsCr = statSrc.nBitsCr;
  396. nBitsCb = statSrc.nBitsCb;
  397. nBitsA = statSrc.nBitsA;
  398. // nBits1stShpCode = statSrc.nBits1stShpCode;
  399. nBitsCOD = statSrc.nBitsCOD;
  400. nBitsCBPY = statSrc.nBitsCBPY;
  401. nBitsMCBPC = statSrc.nBitsMCBPC;
  402. nBitsDQUANT = statSrc.nBitsDQUANT;
  403. nBitsMODB = statSrc.nBitsMODB;
  404. nBitsCBPB = statSrc.nBitsCBPB;
  405. nBitsMBTYPE = statSrc.nBitsMBTYPE;
  406. nBitsIntraPred = statSrc.nBitsIntraPred;
  407. nBitsNoDCT = statSrc.nBitsNoDCT;
  408. nBitsCODA = statSrc.nBitsCODA;
  409. nBitsCBPA = statSrc.nBitsCBPA;
  410. nBitsMODBA = statSrc.nBitsMODBA;
  411. nBitsCBPBA = statSrc.nBitsCBPBA;
  412. nBitsStuffing = statSrc.nBitsStuffing;
  413. nSkipMB = statSrc.nSkipMB;
  414. nInterMB = statSrc.nInterMB;
  415. nInter4VMB = statSrc.nInter4VMB;
  416. nIntraMB = statSrc.nIntraMB;
  417. nDirectMB = statSrc.nDirectMB;
  418. nForwardMB = statSrc.nForwardMB;
  419. nBackwardMB = statSrc.nBackwardMB;
  420. nInterpolateMB = statSrc.nInterpolateMB;
  421. nBitsInterlace = statSrc.nBitsInterlace;
  422. nFieldForwardMB = statSrc.nFieldForwardMB;
  423. nFieldBackwardMB = statSrc.nFieldBackwardMB;
  424. nFieldInterpolateMB = statSrc.nFieldInterpolateMB;
  425. nFieldDirectMB = statSrc.nFieldDirectMB;
  426. nFieldDCTMB = statSrc.nFieldDCTMB;
  427. nVOPs = statSrc.nVOPs;
  428. nBitsMV = statSrc.nBitsMV;
  429. nBitsTexture = statSrc.nBitsTexture;
  430. nBitsShape = statSrc.nBitsShape;
  431. nBitsTotal = statSrc.nBitsTotal;
  432. dSNRY = statSrc.dSNRY;
  433. dSNRU = statSrc.dSNRU;
  434. dSNRV = statSrc.dSNRV;
  435. dSNRA = statSrc.dSNRA;
  436. nQMB = statSrc.nQMB;
  437. nQp = statSrc.nQp;
  438. return *this;
  439. }
  440. UInt CStatistics::total ()
  441. {
  442. nBitsTexture = nBitsY + nBitsCr + nBitsCb + nBitsA + nBitsCOD
  443. + nBitsCBPY + nBitsMCBPC + nBitsDQUANT
  444. + nBitsMODB + nBitsCBPB + nBitsMBTYPE 
  445. + nBitsIntraPred + nBitsNoDCT
  446. + nBitsInterlace
  447. + nBitsCODA + nBitsCBPA + nBitsMODBA + nBitsCBPBA;
  448. nBitsTotal = nBitsHead + nBitsTexture + nBitsMV + nBitsShape + nBitsStuffing;
  449. return nBitsTotal;
  450. }
  451. UInt CStatistics::head ()
  452. {
  453. /*
  454. UInt bitsHead = nBitsCr + nBitsCb + nBitsA + nBitsCOD
  455. + nBitsCBPY + nBitsMCBPC + nBitsDQUANT
  456. + nBitsMODB + nBitsCBPB + nBitsMBTYPE 
  457. + nBitsIntraPred + nBitsNoDCT
  458. + nBitsInterlace
  459. + nBitsCODA + nBitsCBPA + nBitsMODBA + nBitsCBPBA;
  460. bitsHead +=  nBitsHead + nBitsMV + nBitsShape + nBitsStuffing;
  461. */
  462. UInt bitsHead = nBitsTotal - nBitsTexture;
  463. return bitsHead;
  464. }
  465. Void CRCMode::reset (UInt uiFirstFrame, UInt uiLastFrame, UInt uiTemporalRate, 
  466.    UInt uiBufferSize, Double mad, UInt uiBitsFirstFrame, Double dFrameHz)
  467. {
  468. m_Ts = (uiLastFrame - uiFirstFrame + 1) / 30.0;
  469. m_Rs = (UInt) (uiBufferSize / m_Ts);
  470. m_Ns = uiTemporalRate;
  471. m_X1 = m_Rs * m_Ns / 2.0; // 1st order coefficient transient
  472. m_X2 = 0.0; // 2nd order coeeficient transient
  473. m_Nr = (uiLastFrame - uiFirstFrame + 1) / m_Ns - 1;
  474. m_Nc = 0;
  475. m_Rf = uiBitsFirstFrame;
  476. m_Rc = uiBitsFirstFrame;
  477. m_S = uiBitsFirstFrame;
  478. m_Qc = 15;
  479. m_Qp = 15; // a simple solution (assumption)
  480. m_Rr = (UInt) (m_Ts * m_Rs) - m_Rf; // total number of bits available for this segment
  481. m_Rp = m_Rr / m_Nr; // average bits to be removed from the buffer
  482. m_Bs = m_Rs / 2; // assumed buffer size
  483. m_B = m_Rs / 4; // current buffer level containing the bits for first frame
  484. for (UInt i = 0; i < RC_MAX_SLIDING_WINDOW; i++) {// if 0, don't use that frame (rejected outliers)
  485. m_rgQp[i] = 0;
  486. m_rgRp[i] = 0.0;
  487. }
  488. m_Ec = mad; 
  489. m_skipNextFrame = FALSE;
  490. }
  491. UInt CRCMode::updateQuanStepsize ()
  492. {
  493. // Target bit calculation 
  494. m_T = (UInt) max (m_Rs / 30.0, m_Rr / m_Nr * (1.0 - RC_PAST_PERCENT) + m_S * RC_PAST_PERCENT); // a minimum of Rs/30 is assigned to each frame
  495. m_T = (UInt) (m_T * (m_B + 2.0 * (m_Bs - m_B)) / (2.0 * m_B + (m_Bs - m_B))); // increase if less than half, decrease if more than half, don't change if half
  496. if ((m_B + m_T) > (1.0 - RC_SAFETY_MARGIN) * m_Bs)
  497. m_T = (UInt) max (m_Rs / 30.0, (1.0 - RC_SAFETY_MARGIN) * m_Bs - m_B); // to avoid buffer overflow
  498. else if ((m_B - m_Rp + m_T) < RC_SAFETY_MARGIN * m_Bs)
  499. m_T = m_Rp - m_B + (UInt) (RC_SAFETY_MARGIN * m_Bs);   // to avoid buffer underflow
  500. m_T = min (m_T, (UInt)m_Rr);
  501. // Quantization level calculation
  502. m_T = max (m_Rp / 3 + m_Hp, m_T);
  503. Double dtmp = m_Ec * m_X1 * m_Ec * m_X1 + 4 * m_X2 * m_Ec * (m_T - m_Hp);
  504. if ((m_X2 == 0.0) || (dtmp < 0) || ((sqrt (dtmp) - m_X1 * m_Ec) <= 0.0)) // fall back 1st order mode
  505. m_Qc = (UInt) (m_X1 * m_Ec / (Double) (m_T - m_Hp));
  506. else // 2nd order mode
  507. m_Qc = (UInt) ((2 * m_X2 * m_Ec) / (sqrt (dtmp) - m_X1 * m_Ec));
  508. m_Qc = (UInt) min (ceil(m_Qp * (1.0 + RC_MAX_Q_INCREASE)), (Double) m_Qc); // control variation
  509. m_Qc = min (m_Qc, RC_MAX_QUANT); // clipping
  510. m_Qc = (UInt) max (ceil(m_Qp * (1.0 - RC_MAX_Q_INCREASE)), (Double) m_Qc); // control variation
  511. m_Qc = max (m_Qc, RC_MIN_QUANT); // clipping
  512. return m_Qc;
  513. }
  514. Void CRCMode::updateRCModel (UInt uiBitsTotalCurr, UInt uiBitsHeadCurr)
  515. {
  516. UInt n_windowSize;
  517. m_Rc = uiBitsTotalCurr; // total bits used for the current frame 
  518. m_B += m_Rc - m_Rp; // update buffer fillness
  519. m_Rr -= m_Rc; // update the remaining bits
  520. if (m_Nr != 1) 
  521. assert (m_Rr > 0.0); // check if there is any bits left, except the last frame
  522. m_S = m_Rc; // update the previous bits
  523. m_Hc = uiBitsHeadCurr; // update the current header and motion bits
  524. m_Hp = m_Hc; // update the previous header and motion bits
  525. m_Qp = m_Qc; // update the previous qunatization level
  526. m_Nr--; // update the frame counter
  527. m_Nc++;
  528. Int i;
  529. for (i = RC_MAX_SLIDING_WINDOW - 1; i > 0; i--) {// update the history
  530. m_rgQp[i] = m_rgQp[i - 1];
  531. m_rgRp[i] = m_rgRp[i - 1];
  532. }
  533. m_rgQp[0] = m_Qc;
  534. m_rgRp[0] = (m_Rc - m_Hc) / m_Ec;
  535. n_windowSize = (m_Ep > m_Ec) ? (UInt) (m_Ec / m_Ep * 20) : (UInt) (m_Ep / m_Ec * 20);
  536. n_windowSize = max (n_windowSize, 1);
  537. n_windowSize = min (n_windowSize, m_Nc);
  538. for (i = 0; i < RC_MAX_SLIDING_WINDOW; i++) {
  539. m_rgRejected[i] = FALSE;
  540. }
  541. // initial RD model estimator
  542. RCModelEstimator (n_windowSize);
  543. // remove outlier
  544. Double error[20], std = 0.0, threshold;
  545. for (i = 0; i < (Int) n_windowSize; i++) {
  546. error[i] = m_X1 / m_rgQp[i] + m_X2 / (m_rgQp[i] * m_rgQp[i]) - m_rgRp[i];
  547. std += error[i] * error[i];
  548. }
  549. threshold = (n_windowSize == 2) ? 0 : sqrt (std / n_windowSize);
  550. for (i = 0; i < (Int) n_windowSize; i++) {
  551. if (fabs(error[i]) > threshold)
  552. m_rgRejected[i] = TRUE;
  553. }
  554.     // always include the last data point
  555. m_rgRejected[0] = FALSE;
  556. // second RD model estimator
  557. RCModelEstimator (n_windowSize);
  558. }
  559. Bool CRCMode::skipThisFrame ()
  560. {
  561. if (m_B > (Int) ((RC_SKIP_MARGIN / 100.0) * m_Bs)) { // buffer full!
  562. m_skipNextFrame = TRUE; // set the status
  563. m_Nr--; // skip one frame
  564. m_B -= m_Rp; // decrease current buffer level
  565. } else
  566. m_skipNextFrame = FALSE;
  567. return m_skipNextFrame;
  568. }
  569. Void CRCMode::RCModelEstimator (UInt n_windowSize)
  570. {
  571. UInt n_realSize = n_windowSize;
  572. UInt i;
  573. for (i = 0; i < n_windowSize; i++) {// find the number of samples which are not rejected
  574. if (m_rgRejected[i])
  575. n_realSize--;
  576. }
  577. // default RD model estimation results
  578. Bool estimateX2 = FALSE;
  579. m_X1 = m_X2 = 0.0;
  580. Double oneSampleQ = 0.0;
  581. for (i = 0; i < n_windowSize; i++) {
  582. if (!m_rgRejected[i])
  583. oneSampleQ = m_rgQp[i];
  584. }
  585. for (i = 0; i < n_windowSize; i++) {// if all non-rejected Q are the same, take 1st order model
  586. if ((m_rgQp[i] != oneSampleQ) && !m_rgRejected[i])
  587. estimateX2 = TRUE;
  588. if (!m_rgRejected[i])
  589. m_X1 += (m_rgQp[i] * m_rgRp[i]) / n_realSize;
  590. }
  591. // take 2nd order model to estimate X1 and X2
  592. if ((n_realSize >= RC_START_RATE_CONTROL) && estimateX2) {
  593. Double a00 = 0.0, a01 = 0.0, a10 = 0.0, a11 = 0.0, b0 = 0.0, b1 = 0.0;
  594. for (UInt i = 0; i < n_windowSize; i++) {
  595. if (!m_rgRejected[i]) {
  596. a00 = a00 + 1.0;
  597. a01 += 1.0 / m_rgQp[i];
  598. a10 = a01;
  599. a11 += 1.0 / (m_rgQp[i] * m_rgQp[i]);
  600. b0 += m_rgQp[i] * m_rgRp[i];
  601. b1 += m_rgRp[i];
  602. }
  603. }
  604. // solve the equation of AX = B
  605. CMatrix2x2D A = CMatrix2x2D (a00, a01, a10, a11);
  606. CMatrix2x2D AInv = A.inverse ();
  607. CVector2D B = CVector2D (b0, b1);
  608. CVector2D solution = AInv.apply (B);
  609. if (solution.x != 0.0) {
  610. m_X1 = solution.x;
  611. m_X2 = solution.y;
  612. }
  613. }
  614. }