misc_common.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 *
  9. * by the Xiph.Org Foundation http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function:
  13. last mod: $Id: misc_common.c 15323 2008-09-19 19:43:59Z giles $
  14. ********************************************************************/
  15. #include <string.h>
  16. #include "codec_internal.h"
  17. #include "block_inline.h"
  18. #define FIXED_Q 150
  19. #define MAX_UP_REG_LOOPS 2
  20. /* Gives the initial bytes per block estimate for each Q value */
  21. static const double BpbTable[Q_TABLE_SIZE] = {
  22. 0.42, 0.45, 0.46, 0.49, 0.51, 0.53, 0.56, 0.58,
  23. 0.61, 0.64, 0.68, 0.71, 0.74, 0.77, 0.80, 0.84,
  24. 0.89, 0.92, 0.98, 1.01, 1.04, 1.13, 1.17, 1.23,
  25. 1.28, 1.34, 1.41, 1.45, 1.51, 1.59, 1.69, 1.80,
  26. 1.84, 1.94, 2.02, 2.15, 2.23, 2.34, 2.44, 2.50,
  27. 2.69, 2.80, 2.87, 3.04, 3.16, 3.29, 3.59, 3.66,
  28. 3.86, 3.94, 4.22, 4.50, 4.64, 4.70, 5.24, 5.34,
  29. 5.61, 5.87, 6.11, 6.41, 6.71, 6.99, 7.36, 7.69
  30. };
  31. static const double KfBpbTable[Q_TABLE_SIZE] = {
  32. 0.74, 0.81, 0.88, 0.94, 1.00, 1.06, 1.14, 1.19,
  33. 1.27, 1.34, 1.42, 1.49, 1.54, 1.59, 1.66, 1.73,
  34. 1.80, 1.87, 1.97, 2.01, 2.08, 2.21, 2.25, 2.36,
  35. 2.39, 2.50, 2.55, 2.65, 2.71, 2.82, 2.95, 3.01,
  36. 3.11, 3.19, 3.31, 3.42, 3.58, 3.66, 3.78, 3.89,
  37. 4.11, 4.26, 4.36, 4.39, 4.63, 4.76, 4.85, 5.04,
  38. 5.26, 5.29, 5.47, 5.64, 5.76, 6.05, 6.35, 6.67,
  39. 6.91, 7.17, 7.40, 7.56, 8.02, 8.45, 8.86, 9.38
  40. };
  41. double GetEstimatedBpb( CP_INSTANCE *cpi, ogg_uint32_t TargetQ ){
  42. ogg_uint32_t i;
  43. ogg_int32_t ThreshTableIndex = Q_TABLE_SIZE - 1;
  44. double BytesPerBlock;
  45. /* Search for the Q table index that matches the given Q. */
  46. for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
  47. if ( TargetQ >= cpi->pb.QThreshTable[i] ) {
  48. ThreshTableIndex = i;
  49. break;
  50. }
  51. }
  52. /* Adjust according to Q shift and type of frame */
  53. if ( cpi->pb.FrameType == KEY_FRAME ) {
  54. /* Get primary prediction */
  55. BytesPerBlock = KfBpbTable[ThreshTableIndex];
  56. } else {
  57. /* Get primary prediction */
  58. BytesPerBlock = BpbTable[ThreshTableIndex];
  59. BytesPerBlock = BytesPerBlock * cpi->BpbCorrectionFactor;
  60. }
  61. return BytesPerBlock;
  62. }
  63. static void UpRegulateMB( CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
  64. ogg_uint32_t SB, ogg_uint32_t MB, int NoCheck ) {
  65. ogg_int32_t FragIndex;
  66. ogg_uint32_t B;
  67. /* Variables used in calculating corresponding row,col and index in
  68. UV planes */
  69. ogg_uint32_t UVRow;
  70. ogg_uint32_t UVColumn;
  71. ogg_uint32_t UVFragOffset;
  72. /* There may be MB's lying out of frame which must be ignored. For
  73. these MB's Top left block will have a negative Fragment Index. */
  74. if ( QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ) >= 0 ) {
  75. /* Up regulate the component blocks Y then UV. */
  76. for ( B=0; B<4; B++ ){
  77. FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B );
  78. if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
  79. ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ){
  80. cpi->pb.display_fragments[FragIndex] = 1;
  81. cpi->extra_fragments[FragIndex] = 1;
  82. cpi->FragmentLastQ[FragIndex] = RegulationQ;
  83. cpi->MotionScore++;
  84. }
  85. }
  86. /* Check the two UV blocks */
  87. FragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB );
  88. UVRow = (FragIndex / (cpi->pb.HFragments * 2));
  89. UVColumn = (FragIndex % cpi->pb.HFragments) / 2;
  90. UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn;
  91. FragIndex = cpi->pb.YPlaneFragments + UVFragOffset;
  92. if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
  93. ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) {
  94. cpi->pb.display_fragments[FragIndex] = 1;
  95. cpi->extra_fragments[FragIndex] = 1;
  96. cpi->FragmentLastQ[FragIndex] = RegulationQ;
  97. cpi->MotionScore++;
  98. }
  99. FragIndex += cpi->pb.UVPlaneFragments;
  100. if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
  101. ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) {
  102. cpi->pb.display_fragments[FragIndex] = 1;
  103. cpi->extra_fragments[FragIndex] = 1;
  104. cpi->FragmentLastQ[FragIndex] = RegulationQ;
  105. cpi->MotionScore++;
  106. }
  107. }
  108. }
  109. static void UpRegulateBlocks (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
  110. ogg_int32_t RecoveryBlocks,
  111. ogg_uint32_t * LastSB, ogg_uint32_t * LastMB ) {
  112. ogg_uint32_t LoopTimesRound = 0;
  113. ogg_uint32_t MaxSB = cpi->pb.YSBRows *
  114. cpi->pb.YSBCols; /* Tot super blocks in image */
  115. ogg_uint32_t SB, MB; /* Super-Block and macro block indices. */
  116. /* First scan for blocks for which a residue update is outstanding. */
  117. while ( (cpi->MotionScore < RecoveryBlocks) &&
  118. (LoopTimesRound < MAX_UP_REG_LOOPS) ) {
  119. LoopTimesRound++;
  120. for ( SB = (*LastSB); SB < MaxSB; SB++ ) {
  121. /* Check its four Macro-Blocks */
  122. for ( MB=(*LastMB); MB<4; MB++ ) {
  123. /* Mark relevant blocks for update */
  124. UpRegulateMB( cpi, RegulationQ, SB, MB, 0 );
  125. /* Keep track of the last refresh MB. */
  126. (*LastMB) += 1;
  127. if ( (*LastMB) == 4 )
  128. (*LastMB) = 0;
  129. /* Termination clause */
  130. if (cpi->MotionScore >= RecoveryBlocks) {
  131. /* Make sure we don't stall at SB level */
  132. if ( *LastMB == 0 )
  133. SB++;
  134. break;
  135. }
  136. }
  137. /* Termination clause */
  138. if (cpi->MotionScore >= RecoveryBlocks)
  139. break;
  140. }
  141. /* Update super block start index */
  142. if ( SB >= MaxSB){
  143. (*LastSB) = 0;
  144. }else{
  145. (*LastSB) = SB;
  146. }
  147. }
  148. }
  149. void UpRegulateDataStream (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
  150. ogg_int32_t RecoveryBlocks ) {
  151. ogg_uint32_t LastPassMBPos = 0;
  152. ogg_uint32_t StdLastMBPos = 0;
  153. ogg_uint32_t MaxSB = cpi->pb.YSBRows *
  154. cpi->pb.YSBCols; /* Tot super blocks in image */
  155. ogg_uint32_t SB=0; /* Super-Block index */
  156. ogg_uint32_t MB; /* Macro-Block index */
  157. /* Decduct the number of blocks in an MB / 2 from the recover block count.
  158. This will compensate for the fact that once we start checking an MB
  159. we test every block in that macro block */
  160. if ( RecoveryBlocks > 3 )
  161. RecoveryBlocks -= 3;
  162. /* Up regulate blocks last coded at higher Q */
  163. UpRegulateBlocks( cpi, RegulationQ, RecoveryBlocks,
  164. &cpi->LastEndSB, &StdLastMBPos );
  165. /* If we have still not used up the minimum number of blocks and are
  166. at the minimum Q then run through a final pass of the data to
  167. insure that each block gets a final refresh. */
  168. if ( (RegulationQ == VERY_BEST_Q) &&
  169. (cpi->MotionScore < RecoveryBlocks) ) {
  170. if ( cpi->FinalPassLastPos < MaxSB ) {
  171. for ( SB = cpi->FinalPassLastPos; SB < MaxSB; SB++ ) {
  172. /* Check its four Macro-Blocks */
  173. for ( MB=LastPassMBPos; MB<4; MB++ ) {
  174. /* Mark relevant blocks for update */
  175. UpRegulateMB( cpi, RegulationQ, SB, MB, 1 );
  176. /* Keep track of the last refresh MB. */
  177. LastPassMBPos += 1;
  178. if ( LastPassMBPos == 4 ) {
  179. LastPassMBPos = 0;
  180. /* Increment SB index */
  181. cpi->FinalPassLastPos += 1;
  182. }
  183. /* Termination clause */
  184. if (cpi->MotionScore >= RecoveryBlocks)
  185. break;
  186. }
  187. /* Termination clause */
  188. if (cpi->MotionScore >= RecoveryBlocks)
  189. break;
  190. }
  191. }
  192. }
  193. }
  194. void RegulateQ( CP_INSTANCE *cpi, ogg_int32_t UpdateScore ) {
  195. double PredUnitScoreBytes;
  196. ogg_uint32_t QIndex = Q_TABLE_SIZE - 1;
  197. ogg_uint32_t i;
  198. if ( UpdateScore > 0 ) {
  199. double TargetUnitScoreBytes = (double)cpi->ThisFrameTargetBytes /
  200. (double)UpdateScore;
  201. double LastBitError = 10000.0; /* Silly high number */
  202. /* Search for the best Q for the target bitrate. */
  203. for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
  204. PredUnitScoreBytes = GetEstimatedBpb( cpi, cpi->pb.QThreshTable[i] );
  205. if ( PredUnitScoreBytes > TargetUnitScoreBytes ) {
  206. if ( (PredUnitScoreBytes - TargetUnitScoreBytes) <= LastBitError ) {
  207. QIndex = i;
  208. } else {
  209. QIndex = i - 1;
  210. }
  211. break;
  212. } else {
  213. LastBitError = TargetUnitScoreBytes - PredUnitScoreBytes;
  214. }
  215. }
  216. }
  217. /* QIndex should now indicate the optimal Q. */
  218. cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[QIndex];
  219. /* Apply range restrictions for key frames. */
  220. if ( cpi->pb.FrameType == KEY_FRAME ) {
  221. if ( cpi->pb.ThisFrameQualityValue > cpi->pb.QThreshTable[20] )
  222. cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[20];
  223. else if ( cpi->pb.ThisFrameQualityValue < cpi->pb.QThreshTable[50] )
  224. cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[50];
  225. }
  226. /* Limit the Q value to the maximum available value */
  227. if (cpi->pb.ThisFrameQualityValue >
  228. cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) {
  229. cpi->pb.ThisFrameQualityValue =
  230. (ogg_uint32_t)cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ];
  231. }
  232. if(cpi->FixedQ) {
  233. if ( cpi->pb.FrameType == KEY_FRAME ) {
  234. cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[43];
  235. cpi->pb.ThisFrameQualityValue = cpi->FixedQ;
  236. } else {
  237. cpi->pb.ThisFrameQualityValue = cpi->FixedQ;
  238. }
  239. }
  240. /* If the quantizer value has changed then re-initialise it */
  241. if ( cpi->pb.ThisFrameQualityValue != cpi->pb.LastFrameQualityValue ) {
  242. /* Initialise quality tables. */
  243. UpdateQC( cpi, cpi->pb.ThisFrameQualityValue );
  244. cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue;
  245. }
  246. }
  247. void CopyBackExtraFrags(CP_INSTANCE *cpi){
  248. ogg_uint32_t i,j;
  249. unsigned char * SrcPtr;
  250. unsigned char * DestPtr;
  251. ogg_uint32_t PlaneLineStep;
  252. ogg_uint32_t PixelIndex;
  253. /* Copy back for Y plane. */
  254. PlaneLineStep = cpi->pb.info.width;
  255. for ( i = 0; i < cpi->pb.YPlaneFragments; i++ ) {
  256. /* We are only interested in updated fragments. */
  257. if ( cpi->extra_fragments[i] ) {
  258. /* Get the start index for the fragment. */
  259. PixelIndex = cpi->pb.pixel_index_table[i];
  260. SrcPtr = &cpi->yuv1ptr[PixelIndex];
  261. DestPtr = &cpi->ConvDestBuffer[PixelIndex];
  262. for ( j = 0; j < VFRAGPIXELS; j++ ) {
  263. memcpy( DestPtr, SrcPtr, HFRAGPIXELS);
  264. SrcPtr += PlaneLineStep;
  265. DestPtr += PlaneLineStep;
  266. }
  267. }
  268. }
  269. /* Now the U and V planes */
  270. PlaneLineStep = cpi->pb.info.width / 2;
  271. for ( i = cpi->pb.YPlaneFragments;
  272. i < (cpi->pb.YPlaneFragments + (2 * cpi->pb.UVPlaneFragments)) ;
  273. i++ ) {
  274. /* We are only interested in updated fragments. */
  275. if ( cpi->extra_fragments[i] ) {
  276. /* Get the start index for the fragment. */
  277. PixelIndex = cpi->pb.pixel_index_table[i];
  278. SrcPtr = &cpi->yuv1ptr[PixelIndex];
  279. DestPtr = &cpi->ConvDestBuffer[PixelIndex];
  280. for ( j = 0; j < VFRAGPIXELS; j++ ) {
  281. memcpy( DestPtr, SrcPtr, HFRAGPIXELS);
  282. SrcPtr += PlaneLineStep;
  283. DestPtr += PlaneLineStep;
  284. }
  285. }
  286. }
  287. }