Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / theora-old / lib / misc_common.c
blob057be2f8fd3821a791d558e5ace0be60c4ed2d51
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-2003 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
10 * *
11 ********************************************************************
13 function:
14 last mod: $Id$
16 ********************************************************************/
18 #include <string.h>
19 #include "codec_internal.h"
20 #include "block_inline.h"
22 #define FIXED_Q 150
23 #define MAX_UP_REG_LOOPS 2
25 /* Gives the initial bytes per block estimate for each Q value */
26 double BpbTable[Q_TABLE_SIZE] = {
27 0.42, 0.45, 0.46, 0.49, 0.51, 0.53, 0.56, 0.58,
28 0.61, 0.64, 0.68, 0.71, 0.74, 0.77, 0.80, 0.84,
29 0.89, 0.92, 0.98, 1.01, 1.04, 1.13, 1.17, 1.23,
30 1.28, 1.34, 1.41, 1.45, 1.51, 1.59, 1.69, 1.80,
31 1.84, 1.94, 2.02, 2.15, 2.23, 2.34, 2.44, 2.50,
32 2.69, 2.80, 2.87, 3.04, 3.16, 3.29, 3.59, 3.66,
33 3.86, 3.94, 4.22, 4.50, 4.64, 4.70, 5.24, 5.34,
34 5.61, 5.87, 6.11, 6.41, 6.71, 6.99, 7.36, 7.69
37 double KfBpbTable[Q_TABLE_SIZE] = {
38 0.74, 0.81, 0.88, 0.94, 1.00, 1.06, 1.14, 1.19,
39 1.27, 1.34, 1.42, 1.49, 1.54, 1.59, 1.66, 1.73,
40 1.80, 1.87, 1.97, 2.01, 2.08, 2.21, 2.25, 2.36,
41 2.39, 2.50, 2.55, 2.65, 2.71, 2.82, 2.95, 3.01,
42 3.11, 3.19, 3.31, 3.42, 3.58, 3.66, 3.78, 3.89,
43 4.11, 4.26, 4.36, 4.39, 4.63, 4.76, 4.85, 5.04,
44 5.26, 5.29, 5.47, 5.64, 5.76, 6.05, 6.35, 6.67,
45 6.91, 7.17, 7.40, 7.56, 8.02, 8.45, 8.86, 9.38
48 double GetEstimatedBpb( CP_INSTANCE *cpi, ogg_uint32_t TargetQ ){
49 ogg_uint32_t i;
50 ogg_int32_t ThreshTableIndex = Q_TABLE_SIZE - 1;
51 double BytesPerBlock;
53 /* Search for the Q table index that matches the given Q. */
54 for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
55 if ( TargetQ >= cpi->pb.QThreshTable[i] ) {
56 ThreshTableIndex = i;
57 break;
61 /* Adjust according to Q shift and type of frame */
62 if ( GetFrameType(&cpi->pb) == KEY_FRAME ) {
63 /* Get primary prediction */
64 BytesPerBlock = KfBpbTable[ThreshTableIndex];
65 } else {
66 /* Get primary prediction */
67 BytesPerBlock = BpbTable[ThreshTableIndex];
68 BytesPerBlock = BytesPerBlock * cpi->BpbCorrectionFactor;
71 return BytesPerBlock;
74 static void UpRegulateMB( CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
75 ogg_uint32_t SB, ogg_uint32_t MB, int NoCheck ) {
76 ogg_int32_t FragIndex;
77 ogg_uint32_t B;
79 /* Variables used in calculating corresponding row,col and index in
80 UV planes */
81 ogg_uint32_t UVRow;
82 ogg_uint32_t UVColumn;
83 ogg_uint32_t UVFragOffset;
85 /* There may be MB's lying out of frame which must be ignored. For
86 these MB's Top left block will have a negative Fragment Index. */
87 if ( QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ) >= 0 ) {
88 /* Up regulate the component blocks Y then UV. */
89 for ( B=0; B<4; B++ ){
90 FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B );
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++;
101 /* Check the two UV blocks */
102 FragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB );
104 UVRow = (FragIndex / (cpi->pb.HFragments * 2));
105 UVColumn = (FragIndex % cpi->pb.HFragments) / 2;
106 UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn;
108 FragIndex = cpi->pb.YPlaneFragments + UVFragOffset;
109 if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
110 ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) {
111 cpi->pb.display_fragments[FragIndex] = 1;
112 cpi->extra_fragments[FragIndex] = 1;
113 cpi->FragmentLastQ[FragIndex] = RegulationQ;
114 cpi->MotionScore++;
117 FragIndex += cpi->pb.UVPlaneFragments;
118 if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
119 ( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) {
120 cpi->pb.display_fragments[FragIndex] = 1;
121 cpi->extra_fragments[FragIndex] = 1;
122 cpi->FragmentLastQ[FragIndex] = RegulationQ;
123 cpi->MotionScore++;
128 static void UpRegulateBlocks (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
129 ogg_int32_t RecoveryBlocks,
130 ogg_uint32_t * LastSB, ogg_uint32_t * LastMB ) {
132 ogg_uint32_t LoopTimesRound = 0;
133 ogg_uint32_t MaxSB = cpi->pb.YSBRows *
134 cpi->pb.YSBCols; /* Tot super blocks in image */
135 ogg_uint32_t SB, MB; /* Super-Block and macro block indices. */
137 /* First scan for blocks for which a residue update is outstanding. */
138 while ( (cpi->MotionScore < RecoveryBlocks) &&
139 (LoopTimesRound < MAX_UP_REG_LOOPS) ) {
140 LoopTimesRound++;
142 for ( SB = (*LastSB); SB < MaxSB; SB++ ) {
143 /* Check its four Macro-Blocks */
144 for ( MB=(*LastMB); MB<4; MB++ ) {
145 /* Mark relevant blocks for update */
146 UpRegulateMB( cpi, RegulationQ, SB, MB, 0 );
148 /* Keep track of the last refresh MB. */
149 (*LastMB) += 1;
150 if ( (*LastMB) == 4 )
151 (*LastMB) = 0;
153 /* Termination clause */
154 if (cpi->MotionScore >= RecoveryBlocks) {
155 /* Make sure we don't stall at SB level */
156 if ( *LastMB == 0 )
157 SB++;
158 break;
162 /* Termination clause */
163 if (cpi->MotionScore >= RecoveryBlocks)
164 break;
167 /* Update super block start index */
168 if ( SB >= MaxSB){
169 (*LastSB) = 0;
170 }else{
171 (*LastSB) = SB;
176 void UpRegulateDataStream (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
177 ogg_int32_t RecoveryBlocks ) {
178 ogg_uint32_t LastPassMBPos = 0;
179 ogg_uint32_t StdLastMBPos = 0;
181 ogg_uint32_t MaxSB = cpi->pb.YSBRows *
182 cpi->pb.YSBCols; /* Tot super blocks in image */
184 ogg_uint32_t SB=0; /* Super-Block index */
185 ogg_uint32_t MB; /* Macro-Block index */
187 /* Decduct the number of blocks in an MB / 2 from the recover block count.
188 This will compensate for the fact that once we start checking an MB
189 we test every block in that macro block */
190 if ( RecoveryBlocks > 3 )
191 RecoveryBlocks -= 3;
193 /* Up regulate blocks last coded at higher Q */
194 UpRegulateBlocks( cpi, RegulationQ, RecoveryBlocks,
195 &cpi->LastEndSB, &StdLastMBPos );
197 /* If we have still not used up the minimum number of blocks and are
198 at the minimum Q then run through a final pass of the data to
199 insure that each block gets a final refresh. */
200 if ( (RegulationQ == VERY_BEST_Q) &&
201 (cpi->MotionScore < RecoveryBlocks) ) {
202 if ( cpi->FinalPassLastPos < MaxSB ) {
203 for ( SB = cpi->FinalPassLastPos; SB < MaxSB; SB++ ) {
204 /* Check its four Macro-Blocks */
205 for ( MB=LastPassMBPos; MB<4; MB++ ) {
206 /* Mark relevant blocks for update */
207 UpRegulateMB( cpi, RegulationQ, SB, MB, 1 );
209 /* Keep track of the last refresh MB. */
210 LastPassMBPos += 1;
211 if ( LastPassMBPos == 4 ) {
212 LastPassMBPos = 0;
214 /* Increment SB index */
215 cpi->FinalPassLastPos += 1;
218 /* Termination clause */
219 if (cpi->MotionScore >= RecoveryBlocks)
220 break;
223 /* Termination clause */
224 if (cpi->MotionScore >= RecoveryBlocks)
225 break;
232 void RegulateQ( CP_INSTANCE *cpi, ogg_int32_t UpdateScore ) {
233 double PredUnitScoreBytes;
234 ogg_uint32_t QIndex = Q_TABLE_SIZE - 1;
235 ogg_uint32_t i;
237 if ( UpdateScore > 0 ) {
238 double TargetUnitScoreBytes = (double)cpi->ThisFrameTargetBytes /
239 (double)UpdateScore;
240 double LastBitError = 10000.0; /* Silly high number */
241 /* Search for the best Q for the target bitrate. */
242 for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
243 PredUnitScoreBytes = GetEstimatedBpb( cpi, cpi->pb.QThreshTable[i] );
244 if ( PredUnitScoreBytes > TargetUnitScoreBytes ) {
245 if ( (PredUnitScoreBytes - TargetUnitScoreBytes) <= LastBitError ) {
246 QIndex = i;
247 } else {
248 QIndex = i - 1;
250 break;
251 } else {
252 LastBitError = TargetUnitScoreBytes - PredUnitScoreBytes;
257 /* QIndex should now indicate the optimal Q. */
258 cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[QIndex];
260 /* Apply range restrictions for key frames. */
261 if ( GetFrameType(&cpi->pb) == KEY_FRAME ) {
262 if ( cpi->pb.ThisFrameQualityValue > cpi->pb.QThreshTable[20] )
263 cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[20];
264 else if ( cpi->pb.ThisFrameQualityValue < cpi->pb.QThreshTable[50] )
265 cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[50];
268 /* Limit the Q value to the maximum available value */
269 if (cpi->pb.ThisFrameQualityValue >
270 cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) {
271 cpi->pb.ThisFrameQualityValue =
272 (ogg_uint32_t)cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ];
275 if(cpi->FixedQ) {
276 if ( GetFrameType(&cpi->pb) == KEY_FRAME ) {
277 cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[43];
278 cpi->pb.ThisFrameQualityValue = cpi->FixedQ;
279 } else {
280 cpi->pb.ThisFrameQualityValue = cpi->FixedQ;
284 /* If the quantizer value has changed then re-initialise it */
285 if ( cpi->pb.ThisFrameQualityValue != cpi->pb.LastFrameQualityValue ) {
286 /* Initialise quality tables. */
287 UpdateQC( cpi, cpi->pb.ThisFrameQualityValue );
288 cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue;
292 void CopyBackExtraFrags(CP_INSTANCE *cpi){
293 ogg_uint32_t i,j;
294 unsigned char * SrcPtr;
295 unsigned char * DestPtr;
296 ogg_uint32_t PlaneLineStep;
297 ogg_uint32_t PixelIndex;
299 /* Copy back for Y plane. */
300 PlaneLineStep = cpi->pb.info.width;
301 for ( i = 0; i < cpi->pb.YPlaneFragments; i++ ) {
302 /* We are only interested in updated fragments. */
303 if ( cpi->extra_fragments[i] ) {
304 /* Get the start index for the fragment. */
305 PixelIndex = cpi->pb.pixel_index_table[i];
306 SrcPtr = &cpi->yuv1ptr[PixelIndex];
307 DestPtr = &cpi->ConvDestBuffer[PixelIndex];
309 for ( j = 0; j < VFRAGPIXELS; j++ ) {
310 memcpy( DestPtr, SrcPtr, HFRAGPIXELS);
312 SrcPtr += PlaneLineStep;
313 DestPtr += PlaneLineStep;
318 /* Now the U and V planes */
319 PlaneLineStep = cpi->pb.info.width / 2;
320 for ( i = cpi->pb.YPlaneFragments;
321 i < (cpi->pb.YPlaneFragments + (2 * cpi->pb.UVPlaneFragments)) ;
322 i++ ) {
324 /* We are only interested in updated fragments. */
325 if ( cpi->extra_fragments[i] ) {
326 /* Get the start index for the fragment. */
327 PixelIndex = cpi->pb.pixel_index_table[i];
328 SrcPtr = &cpi->yuv1ptr[PixelIndex];
329 DestPtr = &cpi->ConvDestBuffer[PixelIndex];
331 for ( j = 0; j < VFRAGPIXELS; j++ ) {
332 memcpy( DestPtr, SrcPtr, HFRAGPIXELS);
333 SrcPtr += PlaneLineStep;
334 DestPtr += PlaneLineStep;