Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / theora-old / lib / dct_encode.c
blob63a28e575a3a9ddc239641c9ce448be65df29cc3
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 <stdlib.h>
19 #include "codec_internal.h"
20 #include "dsp.h"
23 static int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 };
25 static unsigned char TokenizeDctValue (ogg_int16_t DataValue,
26 ogg_uint32_t * TokenListPtr ){
27 unsigned char tokens_added = 0;
28 ogg_uint32_t AbsDataVal = abs( (ogg_int32_t)DataValue );
30 /* Values are tokenised as category value and a number of additional
31 bits that define the position within the category. */
33 if ( DataValue == 0 ) return 0;
35 if ( AbsDataVal == 1 ){
36 if ( DataValue == 1 )
37 TokenListPtr[0] = ONE_TOKEN;
38 else
39 TokenListPtr[0] = MINUS_ONE_TOKEN;
40 tokens_added = 1;
41 } else if ( AbsDataVal == 2 ) {
42 if ( DataValue == 2 )
43 TokenListPtr[0] = TWO_TOKEN;
44 else
45 TokenListPtr[0] = MINUS_TWO_TOKEN;
46 tokens_added = 1;
47 } else if ( AbsDataVal <= MAX_SINGLE_TOKEN_VALUE ) {
48 TokenListPtr[0] = LOW_VAL_TOKENS + (AbsDataVal - DCT_VAL_CAT2_MIN);
49 if ( DataValue > 0 )
50 TokenListPtr[1] = 0;
51 else
52 TokenListPtr[1] = 1;
53 tokens_added = 2;
54 } else if ( AbsDataVal <= 8 ) {
55 /* Bit 1 determines sign, Bit 0 the value */
56 TokenListPtr[0] = DCT_VAL_CATEGORY3;
57 if ( DataValue > 0 )
58 TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT3_MIN);
59 else
60 TokenListPtr[1] = (0x02) + (AbsDataVal - DCT_VAL_CAT3_MIN);
61 tokens_added = 2;
62 } else if ( AbsDataVal <= 12 ) {
63 /* Bit 2 determines sign, Bit 0-2 the value */
64 TokenListPtr[0] = DCT_VAL_CATEGORY4;
65 if ( DataValue > 0 )
66 TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT4_MIN);
67 else
68 TokenListPtr[1] = (0x04) + (AbsDataVal - DCT_VAL_CAT4_MIN);
69 tokens_added = 2;
70 } else if ( AbsDataVal <= 20 ) {
71 /* Bit 3 determines sign, Bit 0-2 the value */
72 TokenListPtr[0] = DCT_VAL_CATEGORY5;
73 if ( DataValue > 0 )
74 TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT5_MIN);
75 else
76 TokenListPtr[1] = (0x08) + (AbsDataVal - DCT_VAL_CAT5_MIN);
77 tokens_added = 2;
78 } else if ( AbsDataVal <= 36 ) {
79 /* Bit 4 determines sign, Bit 0-3 the value */
80 TokenListPtr[0] = DCT_VAL_CATEGORY6;
81 if ( DataValue > 0 )
82 TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT6_MIN);
83 else
84 TokenListPtr[1] = (0x010) + (AbsDataVal - DCT_VAL_CAT6_MIN);
85 tokens_added = 2;
86 } else if ( AbsDataVal <= 68 ) {
87 /* Bit 5 determines sign, Bit 0-4 the value */
88 TokenListPtr[0] = DCT_VAL_CATEGORY7;
89 if ( DataValue > 0 )
90 TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT7_MIN);
91 else
92 TokenListPtr[1] = (0x20) + (AbsDataVal - DCT_VAL_CAT7_MIN);
93 tokens_added = 2;
94 } else if ( AbsDataVal <= 511 ) {
95 /* Bit 9 determines sign, Bit 0-8 the value */
96 TokenListPtr[0] = DCT_VAL_CATEGORY8;
97 if ( DataValue > 0 )
98 TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT8_MIN);
99 else
100 TokenListPtr[1] = (0x200) + (AbsDataVal - DCT_VAL_CAT8_MIN);
101 tokens_added = 2;
102 } else {
103 TokenListPtr[0] = DCT_VAL_CATEGORY8;
104 if ( DataValue > 0 )
105 TokenListPtr[1] = (511 - DCT_VAL_CAT8_MIN);
106 else
107 TokenListPtr[1] = (0x200) + (511 - DCT_VAL_CAT8_MIN);
108 tokens_added = 2;
111 /* Return the total number of tokens added */
112 return tokens_added;
115 static unsigned char TokenizeDctRunValue (unsigned char RunLength,
116 ogg_int16_t DataValue,
117 ogg_uint32_t * TokenListPtr ){
118 unsigned char tokens_added = 0;
119 ogg_uint32_t AbsDataVal = abs( (ogg_int32_t)DataValue );
121 /* Values are tokenised as category value and a number of additional
122 bits that define the category. */
123 if ( DataValue == 0 ) return 0;
124 if ( AbsDataVal == 1 ) {
125 /* Zero runs of 1-5 */
126 if ( RunLength <= 5 ) {
127 TokenListPtr[0] = DCT_RUN_CATEGORY1 + (RunLength - 1);
128 if ( DataValue > 0 )
129 TokenListPtr[1] = 0;
130 else
131 TokenListPtr[1] = 1;
132 } else if ( RunLength <= 9 ) {
133 /* Zero runs of 6-9 */
134 TokenListPtr[0] = DCT_RUN_CATEGORY1B;
135 if ( DataValue > 0 )
136 TokenListPtr[1] = (RunLength - 6);
137 else
138 TokenListPtr[1] = 0x04 + (RunLength - 6);
139 } else {
140 /* Zero runs of 10-17 */
141 TokenListPtr[0] = DCT_RUN_CATEGORY1C;
142 if ( DataValue > 0 )
143 TokenListPtr[1] = (RunLength - 10);
144 else
145 TokenListPtr[1] = 0x08 + (RunLength - 10);
147 tokens_added = 2;
148 } else if ( AbsDataVal <= 3 ) {
149 if ( RunLength == 1 ) {
150 TokenListPtr[0] = DCT_RUN_CATEGORY2;
152 /* Extra bits token bit 1 indicates sign, bit 0 indicates value */
153 if ( DataValue > 0 )
154 TokenListPtr[1] = (AbsDataVal - 2);
155 else
156 TokenListPtr[1] = (0x02) + (AbsDataVal - 2);
157 tokens_added = 2;
158 }else{
159 TokenListPtr[0] = DCT_RUN_CATEGORY2 + 1;
161 /* Extra bits token. */
162 /* bit 2 indicates sign, bit 1 indicates value, bit 0 indicates
163 run length */
164 if ( DataValue > 0 )
165 TokenListPtr[1] = ((AbsDataVal - 2) << 1) + (RunLength - 2);
166 else
167 TokenListPtr[1] = (0x04) + ((AbsDataVal - 2) << 1) + (RunLength - 2);
168 tokens_added = 2;
170 } else {
171 tokens_added = 2; /* ERROR */
172 /*IssueWarning( "Bad Input to TokenizeDctRunValue" );*/
175 /* Return the total number of tokens added */
176 return tokens_added;
179 static unsigned char TokenizeDctBlock (ogg_int16_t * RawData,
180 ogg_uint32_t * TokenListPtr ) {
181 ogg_uint32_t i;
182 unsigned char run_count;
183 unsigned char token_count = 0; /* Number of tokens crated. */
184 ogg_uint32_t AbsData;
187 /* Tokenize the block */
188 for( i = 0; i < BLOCK_SIZE; i++ ){
189 run_count = 0;
191 /* Look for a zero run. */
192 /* NOTE the use of & instead of && which is faster (and
193 equivalent) in this instance. */
194 /* NO, NO IT ISN'T --Monty */
195 while( (i < BLOCK_SIZE) && (!RawData[i]) ){
196 run_count++;
197 i++;
200 /* If we have reached the end of the block then code EOB */
201 if ( i == BLOCK_SIZE ){
202 TokenListPtr[token_count] = DCT_EOB_TOKEN;
203 token_count++;
204 }else{
205 /* If we have a short zero run followed by a low data value code
206 the two as a composite token. */
207 if ( run_count ){
208 AbsData = abs(RawData[i]);
210 if ( ((AbsData == 1) && (run_count <= 17)) ||
211 ((AbsData <= 3) && (run_count <= 3)) ) {
212 /* Tokenise the run and subsequent value combination value */
213 token_count += TokenizeDctRunValue( run_count,
214 RawData[i],
215 &TokenListPtr[token_count] );
216 }else{
218 /* Else if we have a long non-EOB run or a run followed by a
219 value token > MAX_RUN_VAL then code the run and token
220 seperately */
221 if ( run_count <= 8 )
222 TokenListPtr[token_count] = DCT_SHORT_ZRL_TOKEN;
223 else
224 TokenListPtr[token_count] = DCT_ZRL_TOKEN;
226 token_count++;
227 TokenListPtr[token_count] = run_count - 1;
228 token_count++;
230 /* Now tokenize the value */
231 token_count += TokenizeDctValue( RawData[i],
232 &TokenListPtr[token_count] );
234 }else{
235 /* Else there was NO zero run. */
236 /* Tokenise the value */
237 token_count += TokenizeDctValue( RawData[i],
238 &TokenListPtr[token_count] );
243 /* Return the total number of tokens (including additional bits
244 tokens) used. */
245 return token_count;
248 ogg_uint32_t DPCMTokenizeBlock (CP_INSTANCE *cpi,
249 ogg_int32_t FragIndex){
250 ogg_uint32_t token_count;
252 if ( GetFrameType(&cpi->pb) == KEY_FRAME ){
253 /* Key frame so code block in INTRA mode. */
254 cpi->pb.CodingMode = CODE_INTRA;
255 }else{
256 /* Get Motion vector and mode for this block. */
257 cpi->pb.CodingMode = cpi->pb.FragCodingMethod[FragIndex];
260 /* Tokenise the dct data. */
261 token_count = TokenizeDctBlock( cpi->pb.QFragData[FragIndex],
262 cpi->pb.TokenList[FragIndex] );
264 cpi->FragTokenCounts[FragIndex] = token_count;
265 cpi->TotTokenCount += token_count;
267 /* Return number of pixels coded (i.e. 8x8). */
268 return BLOCK_SIZE;
271 static int AllZeroDctData( Q_LIST_ENTRY * QuantList ){
272 ogg_uint32_t i;
274 for ( i = 0; i < 64; i ++ )
275 if ( QuantList[i] != 0 )
276 return 0;
278 return 1;
281 static void MotionBlockDifference (CP_INSTANCE * cpi, unsigned char * FiltPtr,
282 ogg_int16_t *DctInputPtr, ogg_int32_t MvDevisor,
283 unsigned char* old_ptr1, unsigned char* new_ptr1,
284 ogg_uint32_t FragIndex,ogg_uint32_t PixelsPerLine,
285 ogg_uint32_t ReconPixelsPerLine) {
287 ogg_int32_t MvShift;
288 ogg_int32_t MvModMask;
289 ogg_int32_t AbsRefOffset;
290 ogg_int32_t AbsXOffset;
291 ogg_int32_t AbsYOffset;
292 ogg_int32_t MVOffset; /* Baseline motion vector offset */
293 ogg_int32_t ReconPtr2Offset; /* Offset for second reconstruction in
294 half pixel MC */
295 unsigned char *ReconPtr1; /* DCT reconstructed image pointers */
296 unsigned char *ReconPtr2; /* Pointer used in half pixel MC */
299 switch(MvDevisor) {
300 case 2:
301 MvShift = 1;
302 MvModMask = 1;
303 break;
304 case 4:
305 MvShift = 2;
306 MvModMask = 3;
307 break;
308 default:
309 break;
312 cpi->MVector.x = cpi->pb.FragMVect[FragIndex].x;
313 cpi->MVector.y = cpi->pb.FragMVect[FragIndex].y;
315 /* Set up the baseline offset for the motion vector. */
316 MVOffset = ((cpi->MVector.y / MvDevisor) * ReconPixelsPerLine) +
317 (cpi->MVector.x / MvDevisor);
319 /* Work out the offset of the second reference position for 1/2
320 pixel interpolation. For the U and V planes the MV specifies 1/4
321 pixel accuracy. This is adjusted to 1/2 pixel as follows ( 0->0,
322 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */
323 ReconPtr2Offset = 0;
324 AbsXOffset = cpi->MVector.x % MvDevisor;
325 AbsYOffset = cpi->MVector.y % MvDevisor;
327 if ( AbsXOffset ) {
328 if ( cpi->MVector.x > 0 )
329 ReconPtr2Offset += 1;
330 else
331 ReconPtr2Offset -= 1;
334 if ( AbsYOffset ) {
335 if ( cpi->MVector.y > 0 )
336 ReconPtr2Offset += ReconPixelsPerLine;
337 else
338 ReconPtr2Offset -= ReconPixelsPerLine;
341 if ( cpi->pb.CodingMode==CODE_GOLDEN_MV ) {
342 ReconPtr1 = &cpi->
343 pb.GoldenFrame[cpi->pb.recon_pixel_index_table[FragIndex]];
344 } else {
345 ReconPtr1 = &cpi->
346 pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[FragIndex]];
349 ReconPtr1 += MVOffset;
350 ReconPtr2 = ReconPtr1 + ReconPtr2Offset;
352 AbsRefOffset = abs((int)(ReconPtr1 - ReconPtr2));
354 /* Is the MV offset exactly pixel alligned */
355 if ( AbsRefOffset == 0 ){
356 dsp_sub8x8(cpi->dsp, FiltPtr, ReconPtr1, DctInputPtr,
357 PixelsPerLine, ReconPixelsPerLine);
358 dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine);
359 } else {
360 /* Fractional pixel MVs. */
361 /* Note that we only use two pixel values even for the diagonal */
362 dsp_sub8x8avg2(cpi->dsp, FiltPtr, ReconPtr1,ReconPtr2,DctInputPtr,
363 PixelsPerLine, ReconPixelsPerLine);
364 dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine);
368 void TransformQuantizeBlock (CP_INSTANCE *cpi, ogg_int32_t FragIndex,
369 ogg_uint32_t PixelsPerLine ) {
370 unsigned char *new_ptr1; /* Pointers into current frame */
371 unsigned char *old_ptr1; /* Pointers into old frame */
372 unsigned char *FiltPtr; /* Pointers to srf filtered pixels */
373 ogg_int16_t *DctInputPtr; /* Pointer into buffer containing input to DCT */
374 int LeftEdge; /* Flag if block at left edge of component */
375 ogg_uint32_t ReconPixelsPerLine; /* Line length for recon buffers. */
377 unsigned char *ReconPtr1; /* DCT reconstructed image pointers */
378 ogg_int32_t MvDevisor; /* Defines MV resolution (2 = 1/2
379 pixel for Y or 4 = 1/4 for UV) */
381 new_ptr1 = &cpi->yuv1ptr[cpi->pb.pixel_index_table[FragIndex]];
382 old_ptr1 = &cpi->yuv0ptr[cpi->pb.pixel_index_table[FragIndex]];
383 DctInputPtr = cpi->DCTDataBuffer;
385 /* Set plane specific values */
386 if (FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments){
387 ReconPixelsPerLine = cpi->pb.YStride;
388 MvDevisor = 2; /* 1/2 pixel accuracy in Y */
389 }else{
390 ReconPixelsPerLine = cpi->pb.UVStride;
391 MvDevisor = 4; /* UV planes at 1/2 resolution of Y */
394 /* adjusted / filtered pointers */
395 FiltPtr = &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]];
397 if ( GetFrameType(&cpi->pb) == KEY_FRAME ) {
398 /* Key frame so code block in INTRA mode. */
399 cpi->pb.CodingMode = CODE_INTRA;
400 }else{
401 /* Get Motion vector and mode for this block. */
402 cpi->pb.CodingMode = cpi->pb.FragCodingMethod[FragIndex];
405 /* Selection of Quantiser matrix and set other plane related values. */
406 if ( FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments ){
407 LeftEdge = !(FragIndex%cpi->pb.HFragments);
409 /* Select the appropriate Y quantiser matrix */
410 if ( cpi->pb.CodingMode == CODE_INTRA )
411 select_quantiser(&cpi->pb, BLOCK_Y);
412 else
413 select_quantiser(&cpi->pb, BLOCK_INTER_Y);
414 } else {
415 LeftEdge = !((FragIndex-cpi->pb.YPlaneFragments)%(cpi->pb.HFragments>>1));
417 if(FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments + (ogg_int32_t)cpi->pb.UVPlaneFragments) {
418 /* U plane */
419 if ( cpi->pb.CodingMode == CODE_INTRA )
420 select_quantiser(&cpi->pb, BLOCK_U);
421 else
422 select_quantiser(&cpi->pb, BLOCK_INTER_U);
423 } else {
424 /* V plane */
425 if ( cpi->pb.CodingMode == CODE_INTRA )
426 select_quantiser(&cpi->pb, BLOCK_V);
427 else
428 select_quantiser(&cpi->pb, BLOCK_INTER_V);
432 if ( ModeUsesMC[cpi->pb.CodingMode] ){
434 MotionBlockDifference(cpi, FiltPtr, DctInputPtr, MvDevisor,
435 old_ptr1, new_ptr1, FragIndex, PixelsPerLine,
436 ReconPixelsPerLine);
438 } else if ( (cpi->pb.CodingMode==CODE_INTER_NO_MV ) ||
439 ( cpi->pb.CodingMode==CODE_USING_GOLDEN ) ) {
440 if ( cpi->pb.CodingMode==CODE_INTER_NO_MV ) {
441 ReconPtr1 = &cpi->
442 pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[FragIndex]];
443 } else {
444 ReconPtr1 = &cpi->
445 pb.GoldenFrame[cpi->pb.recon_pixel_index_table[FragIndex]];
448 dsp_sub8x8(cpi->dsp, FiltPtr, ReconPtr1, DctInputPtr,
449 PixelsPerLine, ReconPixelsPerLine);
450 dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine);
451 } else if ( cpi->pb.CodingMode==CODE_INTRA ) {
452 dsp_sub8x8_128(cpi->dsp, FiltPtr, DctInputPtr, PixelsPerLine);
453 dsp_copy8x8 (cpi->dsp, new_ptr1, old_ptr1, PixelsPerLine);
456 /* Proceed to encode the data into the encode buffer if the encoder
457 is enabled. */
458 /* Perform a 2D DCT transform on the data. */
459 dsp_fdct_short(cpi->dsp, cpi->DCTDataBuffer, cpi->DCT_codes );
461 /* Quantize that transform data. */
462 quantize ( &cpi->pb, cpi->DCT_codes, cpi->pb.QFragData[FragIndex] );
464 if ( (cpi->pb.CodingMode == CODE_INTER_NO_MV) &&
465 ( AllZeroDctData(cpi->pb.QFragData[FragIndex]) ) ) {
466 cpi->pb.display_fragments[FragIndex] = 0;