Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / theora-old / lib / dct_decode.c
blob5b1cebddfd2f0e4314170aa62d2e845642075f06
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 <string.h>
20 #include "codec_internal.h"
23 #define GOLDEN_FRAME_THRESH_Q 50
24 #define PUR 8
25 #define PU 4
26 #define PUL 2
27 #define PL 1
28 #define HIGHBITDUPPED(X) (((signed short) X) >> 15)
30 /* in-loop filter tables. */
32 static const unsigned char LoopFilterLimitValuesV1[Q_TABLE_SIZE] = {
33 30, 25, 20, 20, 15, 15, 14, 14,
34 13, 13, 12, 12, 11, 11, 10, 10,
35 9, 9, 8, 8, 7, 7, 7, 7,
36 6, 6, 6, 6, 5, 5, 5, 5,
37 4, 4, 4, 4, 3, 3, 3, 3,
38 2, 2, 2, 2, 2, 2, 2, 2,
39 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0
43 static const int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 };
45 static void SetupBoundingValueArray_Generic(PB_INSTANCE *pbi,
46 ogg_int32_t FLimit){
48 ogg_int16_t * BoundingValuePtr = pbi->FiltBoundingValue+127;
49 ogg_int32_t i;
51 /* Set up the bounding value array. */
52 memset ( pbi->FiltBoundingValue, 0, (256*sizeof(*pbi->FiltBoundingValue)) );
53 for ( i = 0; i < FLimit; i++ ){
54 BoundingValuePtr[-i-FLimit] = (-FLimit+i);
55 BoundingValuePtr[-i] = -i;
56 BoundingValuePtr[i] = i;
57 BoundingValuePtr[i+FLimit] = FLimit-i;
61 /* handle the in-loop filter limit value table */
63 void WriteFilterTables(PB_INSTANCE *pbi, oggpack_buffer *opb){
64 int i;
65 int bits=5;
66 oggpackB_write(opb, bits, 3);
67 for(i=0;i<Q_TABLE_SIZE;i++)
68 oggpackB_write(opb, pbi->LoopFilterLimits[i],bits);
71 int ReadFilterTables(codec_setup_info *ci, oggpack_buffer *opb){
72 int i;
73 int bits, value;
75 theora_read(opb, 3, &bits);
76 for(i=0;i<Q_TABLE_SIZE;i++){
77 theora_read(opb,bits,&value);
78 ci->LoopFilterLimitValues[i]=value;
80 if(bits<0)return OC_BADHEADER;
82 return 0;
85 /* copy in-loop filter limits from the bitstream header into our instance */
86 void CopyFilterTables(PB_INSTANCE *pbi, codec_setup_info *ci){
87 memcpy(pbi->LoopFilterLimits, ci->LoopFilterLimitValues, Q_TABLE_SIZE);
90 /* initialize the filter limits from our static table */
91 void InitFilterTables(PB_INSTANCE *pbi){
92 memcpy(pbi->LoopFilterLimits, LoopFilterLimitValuesV1, Q_TABLE_SIZE);
95 void SetupLoopFilter(PB_INSTANCE *pbi){
96 ogg_int32_t FLimit;
98 FLimit = pbi->LoopFilterLimits[pbi->FrameQIndex];
99 SetupBoundingValueArray_Generic(pbi, FLimit);
102 static void ExpandKFBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){
103 ogg_uint32_t ReconPixelsPerLine;
104 ogg_int32_t ReconPixelIndex;
106 /* Select the appropriate inverse Q matrix and line stride */
107 if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ){
108 ReconPixelsPerLine = pbi->YStride;
109 pbi->dequant_coeffs = pbi->dequant_Y_coeffs;
110 }else if ( FragmentNumber<(ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ){
111 ReconPixelsPerLine = pbi->UVStride;
112 pbi->dequant_coeffs = pbi->dequant_U_coeffs;
113 }else{
114 ReconPixelsPerLine = pbi->UVStride;
115 pbi->dequant_coeffs = pbi->dequant_V_coeffs;
118 /* Set up pointer into the quantisation buffer. */
119 pbi->quantized_list = &pbi->QFragData[FragmentNumber][0];
121 /* Invert quantisation and DCT to get pixel data. */
122 switch(pbi->FragCoefEOB[FragmentNumber]){
123 case 0:case 1:
124 IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
125 break;
126 case 2: case 3:
127 dsp_IDct3(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
128 break;
129 case 4:case 5:case 6:case 7:case 8: case 9:case 10:
130 dsp_IDct10(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
131 break;
132 default:
133 dsp_IDctSlow(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
136 /* Convert fragment number to a pixel offset in a reconstruction buffer. */
137 ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber];
139 /* Get the pixel index for the first pixel in the fragment. */
140 dsp_recon_intra8x8 (pbi->dsp, (unsigned char *)(&pbi->ThisFrameRecon[ReconPixelIndex]),
141 (ogg_int16_t *)pbi->ReconDataBuffer, ReconPixelsPerLine);
145 static void ExpandBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){
146 unsigned char *LastFrameRecPtr; /* Pointer into previous frame
147 reconstruction. */
148 unsigned char *LastFrameRecPtr2; /* Pointer into previous frame
149 reconstruction for 1/2 pixel MC. */
151 ogg_uint32_t ReconPixelsPerLine; /* Pixels per line */
152 ogg_int32_t ReconPixelIndex; /* Offset for block into a
153 reconstruction buffer */
154 ogg_int32_t ReconPtr2Offset; /* Offset for second
155 reconstruction in half pixel
156 MC */
157 ogg_int32_t MVOffset; /* Baseline motion vector offset */
158 ogg_int32_t MvShift ; /* Shift to correct to 1/2 or 1/4 pixel */
159 ogg_int32_t MvModMask; /* Mask to determine whether 1/2
160 pixel is used */
162 /* Get coding mode for this block */
163 if ( GetFrameType(pbi) == KEY_FRAME ){
164 pbi->CodingMode = CODE_INTRA;
165 }else{
166 /* Get Motion vector and mode for this block. */
167 pbi->CodingMode = pbi->FragCodingMethod[FragmentNumber];
170 /* Select the appropriate inverse Q matrix and line stride */
171 if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ) {
172 ReconPixelsPerLine = pbi->YStride;
173 MvShift = 1;
174 MvModMask = 0x00000001;
176 /* Select appropriate dequantiser matrix. */
177 if ( pbi->CodingMode == CODE_INTRA )
178 pbi->dequant_coeffs = pbi->dequant_Y_coeffs;
179 else
180 pbi->dequant_coeffs = pbi->dequant_InterY_coeffs;
181 }else{
182 ReconPixelsPerLine = pbi->UVStride;
183 MvShift = 2;
184 MvModMask = 0x00000003;
186 /* Select appropriate dequantiser matrix. */
187 if ( pbi->CodingMode == CODE_INTRA )
188 if ( FragmentNumber <
189 (ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) )
190 pbi->dequant_coeffs = pbi->dequant_U_coeffs;
191 else
192 pbi->dequant_coeffs = pbi->dequant_V_coeffs;
193 else
194 if ( FragmentNumber <
195 (ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) )
196 pbi->dequant_coeffs = pbi->dequant_InterU_coeffs;
197 else
198 pbi->dequant_coeffs = pbi->dequant_InterV_coeffs;
201 /* Set up pointer into the quantisation buffer. */
202 pbi->quantized_list = &pbi->QFragData[FragmentNumber][0];
204 /* Invert quantisation and DCT to get pixel data. */
205 switch(pbi->FragCoefEOB[FragmentNumber]){
206 case 0:case 1:
207 IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
208 break;
209 case 2: case 3:
210 dsp_IDct3(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
211 break;
212 case 4:case 5:case 6:case 7:case 8: case 9:case 10:
213 dsp_IDct10(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
214 break;
215 default:
216 dsp_IDctSlow(pbi->dsp, pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
219 /* Convert fragment number to a pixel offset in a reconstruction buffer. */
220 ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber];
222 /* Action depends on decode mode. */
223 if ( pbi->CodingMode == CODE_INTER_NO_MV ){
224 /* Inter with no motion vector */
225 /* Reconstruct the pixel data using the last frame reconstruction
226 and change data when the motion vector is (0,0), the recon is
227 based on the lastframe without loop filtering---- for testing */
228 dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex],
229 &pbi->LastFrameRecon[ReconPixelIndex],
230 pbi->ReconDataBuffer, ReconPixelsPerLine);
231 }else if ( ModeUsesMC[pbi->CodingMode] ) {
232 /* The mode uses a motion vector. */
233 /* Get vector from list */
234 pbi->MVector.x = pbi->FragMVect[FragmentNumber].x;
235 pbi->MVector.y = pbi->FragMVect[FragmentNumber].y;
237 /* Work out the base motion vector offset and the 1/2 pixel offset
238 if any. For the U and V planes the MV specifies 1/4 pixel
239 accuracy. This is adjusted to 1/2 pixel as follows ( 0->0,
240 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */
241 MVOffset = 0;
242 ReconPtr2Offset = 0;
243 if ( pbi->MVector.x > 0 ){
244 MVOffset = pbi->MVector.x >> MvShift;
245 if ( pbi->MVector.x & MvModMask )
246 ReconPtr2Offset += 1;
247 } else if ( pbi->MVector.x < 0 ) {
248 MVOffset -= (-pbi->MVector.x) >> MvShift;
249 if ( (-pbi->MVector.x) & MvModMask )
250 ReconPtr2Offset -= 1;
253 if ( pbi->MVector.y > 0 ){
254 MVOffset += (pbi->MVector.y >> MvShift) * ReconPixelsPerLine;
255 if ( pbi->MVector.y & MvModMask )
256 ReconPtr2Offset += ReconPixelsPerLine;
257 } else if ( pbi->MVector.y < 0 ){
258 MVOffset -= ((-pbi->MVector.y) >> MvShift) * ReconPixelsPerLine;
259 if ( (-pbi->MVector.y) & MvModMask )
260 ReconPtr2Offset -= ReconPixelsPerLine;
263 /* Set up the first of the two reconstruction buffer pointers. */
264 if ( pbi->CodingMode==CODE_GOLDEN_MV ) {
265 LastFrameRecPtr = &pbi->GoldenFrame[ReconPixelIndex] + MVOffset;
266 }else{
267 LastFrameRecPtr = &pbi->LastFrameRecon[ReconPixelIndex] + MVOffset;
270 /* Set up the second of the two reconstruction pointers. */
271 LastFrameRecPtr2 = LastFrameRecPtr + ReconPtr2Offset;
273 /* Select the appropriate reconstruction function */
274 if ( (int)(LastFrameRecPtr - LastFrameRecPtr2) == 0 ) {
275 /* Reconstruct the pixel dats from the reference frame and change data
276 (no half pixel in this case as the two references were the same. */
277 dsp_recon_inter8x8 (pbi->dsp,
278 &pbi->ThisFrameRecon[ReconPixelIndex],
279 LastFrameRecPtr, pbi->ReconDataBuffer,
280 ReconPixelsPerLine);
281 }else{
282 /* Fractional pixel reconstruction. */
283 /* Note that we only use two pixels per reconstruction even for
284 the diagonal. */
285 dsp_recon_inter8x8_half(pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex],
286 LastFrameRecPtr, LastFrameRecPtr2,
287 pbi->ReconDataBuffer, ReconPixelsPerLine);
289 } else if ( pbi->CodingMode == CODE_USING_GOLDEN ){
290 /* Golden frame with motion vector */
291 /* Reconstruct the pixel data using the golden frame
292 reconstruction and change data */
293 dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex],
294 &pbi->GoldenFrame[ ReconPixelIndex ],
295 pbi->ReconDataBuffer, ReconPixelsPerLine);
296 } else {
297 /* Simple Intra coding */
298 /* Get the pixel index for the first pixel in the fragment. */
299 dsp_recon_intra8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex],
300 pbi->ReconDataBuffer, ReconPixelsPerLine);
304 static void UpdateUMV_HBorders( PB_INSTANCE *pbi,
305 unsigned char * DestReconPtr,
306 ogg_uint32_t PlaneFragOffset ) {
307 ogg_uint32_t i;
308 ogg_uint32_t PixelIndex;
310 ogg_uint32_t PlaneStride;
311 ogg_uint32_t BlockVStep;
312 ogg_uint32_t PlaneFragments;
313 ogg_uint32_t LineFragments;
314 ogg_uint32_t PlaneBorderWidth;
316 unsigned char *SrcPtr1;
317 unsigned char *SrcPtr2;
318 unsigned char *DestPtr1;
319 unsigned char *DestPtr2;
321 /* Work out various plane specific values */
322 if ( PlaneFragOffset == 0 ) {
323 /* Y Plane */
324 BlockVStep = (pbi->YStride *
325 (VFRAGPIXELS - 1));
326 PlaneStride = pbi->YStride;
327 PlaneBorderWidth = UMV_BORDER;
328 PlaneFragments = pbi->YPlaneFragments;
329 LineFragments = pbi->HFragments;
330 }else{
331 /* U or V plane. */
332 BlockVStep = (pbi->UVStride *
333 (VFRAGPIXELS - 1));
334 PlaneStride = pbi->UVStride;
335 PlaneBorderWidth = UMV_BORDER / 2;
336 PlaneFragments = pbi->UVPlaneFragments;
337 LineFragments = pbi->HFragments / 2;
340 /* Setup the source and destination pointers for the top and bottom
341 borders */
342 PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset];
343 SrcPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ];
344 DestPtr1 = SrcPtr1 - (PlaneBorderWidth * PlaneStride);
346 PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset +
347 PlaneFragments - LineFragments] +
348 BlockVStep;
349 SrcPtr2 = &DestReconPtr[ PixelIndex - PlaneBorderWidth];
350 DestPtr2 = SrcPtr2 + PlaneStride;
352 /* Now copy the top and bottom source lines into each line of the
353 respective borders */
354 for ( i = 0; i < PlaneBorderWidth; i++ ) {
355 memcpy( DestPtr1, SrcPtr1, PlaneStride );
356 memcpy( DestPtr2, SrcPtr2, PlaneStride );
357 DestPtr1 += PlaneStride;
358 DestPtr2 += PlaneStride;
362 static void UpdateUMV_VBorders( PB_INSTANCE *pbi,
363 unsigned char * DestReconPtr,
364 ogg_uint32_t PlaneFragOffset ){
365 ogg_uint32_t i;
366 ogg_uint32_t PixelIndex;
368 ogg_uint32_t PlaneStride;
369 ogg_uint32_t LineFragments;
370 ogg_uint32_t PlaneBorderWidth;
371 ogg_uint32_t PlaneHeight;
373 unsigned char *SrcPtr1;
374 unsigned char *SrcPtr2;
375 unsigned char *DestPtr1;
376 unsigned char *DestPtr2;
378 /* Work out various plane specific values */
379 if ( PlaneFragOffset == 0 ) {
380 /* Y Plane */
381 PlaneStride = pbi->YStride;
382 PlaneBorderWidth = UMV_BORDER;
383 LineFragments = pbi->HFragments;
384 PlaneHeight = pbi->info.height;
385 }else{
386 /* U or V plane. */
387 PlaneStride = pbi->UVStride;
388 PlaneBorderWidth = UMV_BORDER / 2;
389 LineFragments = pbi->HFragments / 2;
390 PlaneHeight = pbi->info.height / 2;
393 /* Setup the source data values and destination pointers for the
394 left and right edge borders */
395 PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset];
396 SrcPtr1 = &DestReconPtr[ PixelIndex ];
397 DestPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ];
399 PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset +
400 LineFragments - 1] +
401 (HFRAGPIXELS - 1);
402 SrcPtr2 = &DestReconPtr[ PixelIndex ];
403 DestPtr2 = &DestReconPtr[ PixelIndex + 1 ];
405 /* Now copy the top and bottom source lines into each line of the
406 respective borders */
407 for ( i = 0; i < PlaneHeight; i++ ) {
408 memset( DestPtr1, SrcPtr1[0], PlaneBorderWidth );
409 memset( DestPtr2, SrcPtr2[0], PlaneBorderWidth );
410 SrcPtr1 += PlaneStride;
411 SrcPtr2 += PlaneStride;
412 DestPtr1 += PlaneStride;
413 DestPtr2 += PlaneStride;
417 void UpdateUMVBorder( PB_INSTANCE *pbi,
418 unsigned char * DestReconPtr ) {
419 ogg_uint32_t PlaneFragOffset;
421 /* Y plane */
422 PlaneFragOffset = 0;
423 UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset );
424 UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset );
426 /* Then the U and V Planes */
427 PlaneFragOffset = pbi->YPlaneFragments;
428 UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset );
429 UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset );
431 PlaneFragOffset = pbi->YPlaneFragments + pbi->UVPlaneFragments;
432 UpdateUMV_VBorders( pbi, DestReconPtr, PlaneFragOffset );
433 UpdateUMV_HBorders( pbi, DestReconPtr, PlaneFragOffset );
436 static void CopyRecon( PB_INSTANCE *pbi, unsigned char * DestReconPtr,
437 unsigned char * SrcReconPtr ) {
438 ogg_uint32_t i;
439 ogg_uint32_t PlaneLineStep; /* Pixels per line */
440 ogg_uint32_t PixelIndex;
442 unsigned char *SrcPtr; /* Pointer to line of source image data */
443 unsigned char *DestPtr; /* Pointer to line of destination image data */
445 /* Copy over only updated blocks.*/
447 /* First Y plane */
448 PlaneLineStep = pbi->YStride;
449 for ( i = 0; i < pbi->YPlaneFragments; i++ ) {
450 if ( pbi->display_fragments[i] ) {
451 PixelIndex = pbi->recon_pixel_index_table[i];
452 SrcPtr = &SrcReconPtr[ PixelIndex ];
453 DestPtr = &DestReconPtr[ PixelIndex ];
455 dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep);
459 /* Then U and V */
460 PlaneLineStep = pbi->UVStride;
461 for ( i = pbi->YPlaneFragments; i < pbi->UnitFragments; i++ ) {
462 if ( pbi->display_fragments[i] ) {
463 PixelIndex = pbi->recon_pixel_index_table[i];
464 SrcPtr = &SrcReconPtr[ PixelIndex ];
465 DestPtr = &DestReconPtr[ PixelIndex ];
467 dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep);
473 static void CopyNotRecon( PB_INSTANCE *pbi, unsigned char * DestReconPtr,
474 unsigned char * SrcReconPtr ) {
475 ogg_uint32_t i;
476 ogg_uint32_t PlaneLineStep; /* Pixels per line */
477 ogg_uint32_t PixelIndex;
479 unsigned char *SrcPtr; /* Pointer to line of source image data */
480 unsigned char *DestPtr; /* Pointer to line of destination image data*/
482 /* Copy over only updated blocks. */
484 /* First Y plane */
485 PlaneLineStep = pbi->YStride;
486 for ( i = 0; i < pbi->YPlaneFragments; i++ ) {
487 if ( !pbi->display_fragments[i] ) {
488 PixelIndex = pbi->recon_pixel_index_table[i];
489 SrcPtr = &SrcReconPtr[ PixelIndex ];
490 DestPtr = &DestReconPtr[ PixelIndex ];
492 dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep);
496 /* Then U and V */
497 PlaneLineStep = pbi->UVStride;
498 for ( i = pbi->YPlaneFragments; i < pbi->UnitFragments; i++ ) {
499 if ( !pbi->display_fragments[i] ) {
500 PixelIndex = pbi->recon_pixel_index_table[i];
501 SrcPtr = &SrcReconPtr[ PixelIndex ];
502 DestPtr = &DestReconPtr[ PixelIndex ];
504 dsp_copy8x8 (pbi->dsp, SrcPtr, DestPtr, PlaneLineStep);
510 void ExpandToken( Q_LIST_ENTRY * ExpandedBlock,
511 unsigned char * CoeffIndex, ogg_uint32_t Token,
512 ogg_int32_t ExtraBits ){
513 /* Is the token is a combination run and value token. */
514 if ( Token >= DCT_RUN_CATEGORY1 ){
515 /* Expand the token and additional bits to a zero run length and
516 data value. */
517 if ( Token < DCT_RUN_CATEGORY2 ) {
518 /* Decoding method depends on token */
519 if ( Token < DCT_RUN_CATEGORY1B ) {
520 /* Step on by the zero run length */
521 *CoeffIndex += (unsigned char)((Token - DCT_RUN_CATEGORY1) + 1);
523 /* The extra bit determines the sign. */
524 if ( ExtraBits & 0x01 )
525 ExpandedBlock[*CoeffIndex] = -1;
526 else
527 ExpandedBlock[*CoeffIndex] = 1;
528 } else if ( Token == DCT_RUN_CATEGORY1B ) {
529 /* Bits 0-1 determines the zero run length */
530 *CoeffIndex += (6 + (ExtraBits & 0x03));
532 /* Bit 2 determines the sign */
533 if ( ExtraBits & 0x04 )
534 ExpandedBlock[*CoeffIndex] = -1;
535 else
536 ExpandedBlock[*CoeffIndex] = 1;
537 }else{
538 /* Bits 0-2 determines the zero run length */
539 *CoeffIndex += (10 + (ExtraBits & 0x07));
541 /* Bit 3 determines the sign */
542 if ( ExtraBits & 0x08 )
543 ExpandedBlock[*CoeffIndex] = -1;
544 else
545 ExpandedBlock[*CoeffIndex] = 1;
547 }else{
548 /* If token == DCT_RUN_CATEGORY2 we have a single 0 followed by
549 a value */
550 if ( Token == DCT_RUN_CATEGORY2 ){
551 /* Step on by the zero run length */
552 *CoeffIndex += 1;
554 /* Bit 1 determines sign, bit 0 the value */
555 if ( ExtraBits & 0x02 )
556 ExpandedBlock[*CoeffIndex] = -(2 + (ExtraBits & 0x01));
557 else
558 ExpandedBlock[*CoeffIndex] = 2 + (ExtraBits & 0x01);
559 }else{
560 /* else we have 2->3 zeros followed by a value */
561 /* Bit 0 determines the zero run length */
562 *CoeffIndex += 2 + (ExtraBits & 0x01);
564 /* Bit 2 determines the sign, bit 1 the value */
565 if ( ExtraBits & 0x04 )
566 ExpandedBlock[*CoeffIndex] = -(2 + ((ExtraBits & 0x02) >> 1));
567 else
568 ExpandedBlock[*CoeffIndex] = 2 + ((ExtraBits & 0x02) >> 1);
572 /* Step on over value */
573 *CoeffIndex += 1;
575 } else if ( Token == DCT_SHORT_ZRL_TOKEN ) {
576 /* Token is a ZRL token so step on by the appropriate number of zeros */
577 *CoeffIndex += ExtraBits + 1;
578 } else if ( Token == DCT_ZRL_TOKEN ) {
579 /* Token is a ZRL token so step on by the appropriate number of zeros */
580 *CoeffIndex += ExtraBits + 1;
581 } else if ( Token < LOW_VAL_TOKENS ) {
582 /* Token is a small single value token. */
583 switch ( Token ) {
584 case ONE_TOKEN:
585 ExpandedBlock[*CoeffIndex] = 1;
586 break;
587 case MINUS_ONE_TOKEN:
588 ExpandedBlock[*CoeffIndex] = -1;
589 break;
590 case TWO_TOKEN:
591 ExpandedBlock[*CoeffIndex] = 2;
592 break;
593 case MINUS_TWO_TOKEN:
594 ExpandedBlock[*CoeffIndex] = -2;
595 break;
598 /* Step on the coefficient index. */
599 *CoeffIndex += 1;
600 }else{
601 /* Token is a larger single value token */
602 /* Expand the token and additional bits to a data value. */
603 if ( Token < DCT_VAL_CATEGORY3 ) {
604 /* Offset from LOW_VAL_TOKENS determines value */
605 Token = Token - LOW_VAL_TOKENS;
607 /* Extra bit determines sign */
608 if ( ExtraBits )
609 ExpandedBlock[*CoeffIndex] =
610 -((Q_LIST_ENTRY)(Token + DCT_VAL_CAT2_MIN));
611 else
612 ExpandedBlock[*CoeffIndex] =
613 (Q_LIST_ENTRY)(Token + DCT_VAL_CAT2_MIN);
614 } else if ( Token == DCT_VAL_CATEGORY3 ) {
615 /* Bit 1 determines sign, Bit 0 the value */
616 if ( ExtraBits & 0x02 )
617 ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT3_MIN + (ExtraBits & 0x01));
618 else
619 ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT3_MIN + (ExtraBits & 0x01);
620 } else if ( Token == DCT_VAL_CATEGORY4 ) {
621 /* Bit 2 determines sign, Bit 0-1 the value */
622 if ( ExtraBits & 0x04 )
623 ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT4_MIN + (ExtraBits & 0x03));
624 else
625 ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT4_MIN + (ExtraBits & 0x03);
626 } else if ( Token == DCT_VAL_CATEGORY5 ) {
627 /* Bit 3 determines sign, Bit 0-2 the value */
628 if ( ExtraBits & 0x08 )
629 ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT5_MIN + (ExtraBits & 0x07));
630 else
631 ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT5_MIN + (ExtraBits & 0x07);
632 } else if ( Token == DCT_VAL_CATEGORY6 ) {
633 /* Bit 4 determines sign, Bit 0-3 the value */
634 if ( ExtraBits & 0x10 )
635 ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT6_MIN + (ExtraBits & 0x0F));
636 else
637 ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT6_MIN + (ExtraBits & 0x0F);
638 } else if ( Token == DCT_VAL_CATEGORY7 ) {
639 /* Bit 5 determines sign, Bit 0-4 the value */
640 if ( ExtraBits & 0x20 )
641 ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT7_MIN + (ExtraBits & 0x1F));
642 else
643 ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT7_MIN + (ExtraBits & 0x1F);
644 } else if ( Token == DCT_VAL_CATEGORY8 ) {
645 /* Bit 9 determines sign, Bit 0-8 the value */
646 if ( ExtraBits & 0x200 )
647 ExpandedBlock[*CoeffIndex] = -(DCT_VAL_CAT8_MIN + (ExtraBits & 0x1FF));
648 else
649 ExpandedBlock[*CoeffIndex] = DCT_VAL_CAT8_MIN + (ExtraBits & 0x1FF);
652 /* Step on the coefficient index. */
653 *CoeffIndex += 1;
657 void ClearDownQFragData(PB_INSTANCE *pbi){
658 ogg_int32_t i;
659 Q_LIST_ENTRY * QFragPtr;
661 for ( i = 0; i < pbi->CodedBlockIndex; i++ ) {
662 /* Get the linear index for the current fragment. */
663 QFragPtr = pbi->QFragData[pbi->CodedBlockList[i]];
664 memset(QFragPtr, 0, 64*sizeof(Q_LIST_ENTRY));
668 static void FilterHoriz__c(unsigned char * PixelPtr,
669 ogg_int32_t LineLength,
670 ogg_int16_t *BoundingValuePtr){
671 ogg_int32_t j;
672 ogg_int32_t FiltVal;
674 for ( j = 0; j < 8; j++ ){
675 FiltVal =
676 ( PixelPtr[0] ) -
677 ( PixelPtr[1] * 3 ) +
678 ( PixelPtr[2] * 3 ) -
679 ( PixelPtr[3] );
681 FiltVal = *(BoundingValuePtr+((FiltVal + 4) >> 3));
683 PixelPtr[1] = clamp255(PixelPtr[1] + FiltVal);
684 PixelPtr[2] = clamp255(PixelPtr[2] - FiltVal);
686 PixelPtr += LineLength;
690 static void FilterVert__c(unsigned char * PixelPtr,
691 ogg_int32_t LineLength,
692 ogg_int16_t *BoundingValuePtr){
693 ogg_int32_t j;
694 ogg_int32_t FiltVal;
695 PixelPtr -= 2*LineLength;
696 /* the math was correct, but negative array indicies are forbidden
697 by ANSI/C99 and will break optimization on several modern
698 compilers */
700 for ( j = 0; j < 8; j++ ) {
701 FiltVal = ( (ogg_int32_t)PixelPtr[0] ) -
702 ( (ogg_int32_t)PixelPtr[LineLength] * 3 ) +
703 ( (ogg_int32_t)PixelPtr[2 * LineLength] * 3 ) -
704 ( (ogg_int32_t)PixelPtr[3 * LineLength] );
706 FiltVal = *(BoundingValuePtr+((FiltVal + 4) >> 3));
708 PixelPtr[LineLength] = clamp255(PixelPtr[LineLength] + FiltVal);
709 PixelPtr[2 * LineLength] = clamp255(PixelPtr[2*LineLength] - FiltVal);
711 PixelPtr ++;
715 void LoopFilter(PB_INSTANCE *pbi){
716 ogg_int32_t i;
718 ogg_int16_t * BoundingValuePtr=pbi->FiltBoundingValue+127;
719 int FragsAcross=pbi->HFragments;
720 int FromFragment,ToFragment;
721 int FragsDown = pbi->VFragments;
722 ogg_int32_t LineFragments;
723 ogg_int32_t LineLength;
724 ogg_int32_t FLimit;
725 int QIndex;
726 int j,m,n;
728 /* Set the limit value for the loop filter based upon the current
729 quantizer. */
730 QIndex = Q_TABLE_SIZE - 1;
731 while ( QIndex >= 0 ) {
732 if ( (QIndex == 0) ||
733 ( pbi->QThreshTable[QIndex] >= pbi->ThisFrameQualityValue) )
734 break;
735 QIndex --;
738 FLimit = pbi->LoopFilterLimits[QIndex];
739 if ( FLimit == 0 ) return;
740 SetupBoundingValueArray_Generic(pbi, FLimit);
742 for ( j = 0; j < 3 ; j++){
743 switch(j) {
744 case 0: /* y */
745 FromFragment = 0;
746 ToFragment = pbi->YPlaneFragments;
747 FragsAcross = pbi->HFragments;
748 FragsDown = pbi->VFragments;
749 LineLength = pbi->YStride;
750 LineFragments = pbi->HFragments;
751 break;
752 case 1: /* u */
753 FromFragment = pbi->YPlaneFragments;
754 ToFragment = pbi->YPlaneFragments + pbi->UVPlaneFragments ;
755 FragsAcross = pbi->HFragments >> 1;
756 FragsDown = pbi->VFragments >> 1;
757 LineLength = pbi->UVStride;
758 LineFragments = pbi->HFragments / 2;
759 break;
760 /*case 2: v */
761 default:
762 FromFragment = pbi->YPlaneFragments + pbi->UVPlaneFragments;
763 ToFragment = pbi->YPlaneFragments + (2 * pbi->UVPlaneFragments) ;
764 FragsAcross = pbi->HFragments >> 1;
765 FragsDown = pbi->VFragments >> 1;
766 LineLength = pbi->UVStride;
767 LineFragments = pbi->HFragments / 2;
768 break;
771 i=FromFragment;
773 /**************************************************************
774 First Row
775 **************************************************************/
776 /* first column conditions */
777 /* only do 2 prediction if fragment coded and on non intra or if
778 all fragments are intra */
779 if( pbi->display_fragments[i]){
780 /* Filter right hand border only if the block to the right is
781 not coded */
782 if ( !pbi->display_fragments[ i + 1 ] ){
783 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
784 pbi->recon_pixel_index_table[i]+6,
785 LineLength,BoundingValuePtr);
788 /* Bottom done if next row set */
789 if( !pbi->display_fragments[ i + LineFragments] ){
790 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
791 pbi->recon_pixel_index_table[i+LineFragments],
792 LineLength, BoundingValuePtr);
795 i++;
797 /***************************************************************/
798 /* middle columns */
799 for ( n = 1 ; n < FragsAcross - 1 ; n++, i++) {
800 if( pbi->display_fragments[i]){
801 /* Filter Left edge always */
802 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
803 pbi->recon_pixel_index_table[i]-2,
804 LineLength, BoundingValuePtr);
806 /* Filter right hand border only if the block to the right is
807 not coded */
808 if ( !pbi->display_fragments[ i + 1 ] ){
809 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
810 pbi->recon_pixel_index_table[i]+6,
811 LineLength, BoundingValuePtr);
814 /* Bottom done if next row set */
815 if( !pbi->display_fragments[ i + LineFragments] ){
816 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
817 pbi->recon_pixel_index_table[i + LineFragments],
818 LineLength, BoundingValuePtr);
824 /***************************************************************/
825 /* Last Column */
826 if( pbi->display_fragments[i]){
827 /* Filter Left edge always */
828 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
829 pbi->recon_pixel_index_table[i] - 2 ,
830 LineLength, BoundingValuePtr);
832 /* Bottom done if next row set */
833 if( !pbi->display_fragments[ i + LineFragments] ){
834 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
835 pbi->recon_pixel_index_table[i + LineFragments],
836 LineLength, BoundingValuePtr);
839 i++;
841 /***************************************************************/
842 /* Middle Rows */
843 /***************************************************************/
844 for ( m = 1 ; m < FragsDown-1 ; m++) {
846 /*****************************************************************/
847 /* first column conditions */
848 /* only do 2 prediction if fragment coded and on non intra or if
849 all fragments are intra */
850 if( pbi->display_fragments[i]){
851 /* TopRow is always done */
852 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
853 pbi->recon_pixel_index_table[i],
854 LineLength, BoundingValuePtr);
856 /* Filter right hand border only if the block to the right is
857 not coded */
858 if ( !pbi->display_fragments[ i + 1 ] ){
859 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
860 pbi->recon_pixel_index_table[i] + 6,
861 LineLength, BoundingValuePtr);
864 /* Bottom done if next row set */
865 if( !pbi->display_fragments[ i + LineFragments] ){
866 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
867 pbi->recon_pixel_index_table[i + LineFragments],
868 LineLength, BoundingValuePtr);
871 i++;
873 /*****************************************************************/
874 /* middle columns */
875 for ( n = 1 ; n < FragsAcross - 1 ; n++, i++){
876 if( pbi->display_fragments[i]){
877 /* Filter Left edge always */
878 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
879 pbi->recon_pixel_index_table[i] - 2,
880 LineLength, BoundingValuePtr);
882 /* TopRow is always done */
883 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
884 pbi->recon_pixel_index_table[i],
885 LineLength, BoundingValuePtr);
887 /* Filter right hand border only if the block to the right
888 is not coded */
889 if ( !pbi->display_fragments[ i + 1 ] ){
890 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
891 pbi->recon_pixel_index_table[i] + 6,
892 LineLength, BoundingValuePtr);
895 /* Bottom done if next row set */
896 if( !pbi->display_fragments[ i + LineFragments] ){
897 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
898 pbi->recon_pixel_index_table[i + LineFragments],
899 LineLength, BoundingValuePtr);
904 /******************************************************************/
905 /* Last Column */
906 if( pbi->display_fragments[i]){
907 /* Filter Left edge always*/
908 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
909 pbi->recon_pixel_index_table[i] - 2,
910 LineLength, BoundingValuePtr);
912 /* TopRow is always done */
913 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
914 pbi->recon_pixel_index_table[i],
915 LineLength, BoundingValuePtr);
917 /* Bottom done if next row set */
918 if( !pbi->display_fragments[ i + LineFragments] ){
919 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
920 pbi->recon_pixel_index_table[i + LineFragments],
921 LineLength, BoundingValuePtr);
924 i++;
928 /*******************************************************************/
929 /* Last Row */
931 /* first column conditions */
932 /* only do 2 prediction if fragment coded and on non intra or if
933 all fragments are intra */
934 if( pbi->display_fragments[i]){
936 /* TopRow is always done */
937 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
938 pbi->recon_pixel_index_table[i],
939 LineLength, BoundingValuePtr);
941 /* Filter right hand border only if the block to the right is
942 not coded */
943 if ( !pbi->display_fragments[ i + 1 ] ){
944 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
945 pbi->recon_pixel_index_table[i] + 6,
946 LineLength, BoundingValuePtr);
949 i++;
951 /******************************************************************/
952 /* middle columns */
953 for ( n = 1 ; n < FragsAcross - 1 ; n++, i++){
954 if( pbi->display_fragments[i]){
955 /* Filter Left edge always */
956 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
957 pbi->recon_pixel_index_table[i] - 2,
958 LineLength, BoundingValuePtr);
960 /* TopRow is always done */
961 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
962 pbi->recon_pixel_index_table[i],
963 LineLength, BoundingValuePtr);
965 /* Filter right hand border only if the block to the right is
966 not coded */
967 if ( !pbi->display_fragments[ i + 1 ] ){
968 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
969 pbi->recon_pixel_index_table[i] + 6,
970 LineLength, BoundingValuePtr);
975 /******************************************************************/
976 /* Last Column */
977 if( pbi->display_fragments[i]){
978 /* Filter Left edge always */
979 dsp_FilterHoriz(pbi->dsp,pbi->LastFrameRecon+
980 pbi->recon_pixel_index_table[i] - 2,
981 LineLength, BoundingValuePtr);
983 /* TopRow is always done */
984 dsp_FilterVert(pbi->dsp,pbi->LastFrameRecon+
985 pbi->recon_pixel_index_table[i],
986 LineLength, BoundingValuePtr);
989 i++;
993 void ReconRefFrames (PB_INSTANCE *pbi){
994 ogg_int32_t i;
995 unsigned char *SwapReconBuffersTemp;
997 /* predictor multiplier up-left, up, up-right,left, shift
998 Entries are packed in the order L, UL, U, UR, with missing entries
999 moved to the end (before the shift parameters). */
1000 static const ogg_int16_t pc[16][6]={
1001 {0,0,0,0,0,0},
1002 {1,0,0,0,0,0}, /* PL */
1003 {1,0,0,0,0,0}, /* PUL */
1004 {1,0,0,0,0,0}, /* PUL|PL */
1005 {1,0,0,0,0,0}, /* PU */
1006 {1,1,0,0,1,1}, /* PU|PL */
1007 {0,1,0,0,0,0}, /* PU|PUL */
1008 {29,-26,29,0,5,31}, /* PU|PUL|PL */
1009 {1,0,0,0,0,0}, /* PUR */
1010 {75,53,0,0,7,127}, /* PUR|PL */
1011 {1,1,0,0,1,1}, /* PUR|PUL */
1012 {75,0,53,0,7,127}, /* PUR|PUL|PL */
1013 {1,0,0,0,0,0}, /* PUR|PU */
1014 {75,0,53,0,7,127}, /* PUR|PU|PL */
1015 {3,10,3,0,4,15}, /* PUR|PU|PUL */
1016 {29,-26,29,0,5,31} /* PUR|PU|PUL|PL */
1019 /* boundary case bit masks. */
1020 static const int bc_mask[8]={
1021 /* normal case no boundary condition */
1022 PUR|PU|PUL|PL,
1023 /* left column */
1024 PUR|PU,
1025 /* top row */
1027 /* top row, left column */
1029 /* right column */
1030 PU|PUL|PL,
1031 /* right and left column */
1033 /* top row, right column */
1035 /* top row, right and left column */
1039 /* value left value up-left, value up, value up-right, missing
1040 values skipped. */
1041 int v[4];
1043 /* fragment number left, up-left, up, up-right */
1044 int fn[4];
1046 /* predictor count. */
1047 int pcount;
1049 short wpc;
1050 static const short Mode2Frame[] = {
1051 1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */
1052 0, /* CODE_INTRA 1 => DCT Encoded Block */
1053 1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */
1054 1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */
1055 1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */
1056 2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */
1057 2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */
1058 1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */
1060 short Last[3];
1061 short PredictedDC;
1062 int FragsAcross=pbi->HFragments;
1063 int FromFragment,ToFragment;
1064 int FragsDown = pbi->VFragments;
1066 int WhichFrame;
1067 int WhichCase;
1068 int j,k,m,n;
1070 void (*ExpandBlockA) ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber );
1072 if ( GetFrameType(pbi) == KEY_FRAME )
1073 ExpandBlockA=ExpandKFBlock;
1074 else
1075 ExpandBlockA=ExpandBlock;
1077 SetupLoopFilter(pbi);
1079 /* for y,u,v */
1080 for ( j = 0; j < 3 ; j++) {
1081 /* pick which fragments based on Y, U, V */
1082 switch(j){
1083 case 0: /* y */
1084 FromFragment = 0;
1085 ToFragment = pbi->YPlaneFragments;
1086 FragsAcross = pbi->HFragments;
1087 FragsDown = pbi->VFragments;
1088 break;
1089 case 1: /* u */
1090 FromFragment = pbi->YPlaneFragments;
1091 ToFragment = pbi->YPlaneFragments + pbi->UVPlaneFragments ;
1092 FragsAcross = pbi->HFragments >> 1;
1093 FragsDown = pbi->VFragments >> 1;
1094 break;
1095 /*case 2: v */
1096 default:
1097 FromFragment = pbi->YPlaneFragments + pbi->UVPlaneFragments;
1098 ToFragment = pbi->YPlaneFragments + (2 * pbi->UVPlaneFragments) ;
1099 FragsAcross = pbi->HFragments >> 1;
1100 FragsDown = pbi->VFragments >> 1;
1101 break;
1104 /* initialize our array of last used DC Components */
1105 for(k=0;k<3;k++)
1106 Last[k]=0;
1108 i=FromFragment;
1110 /* do prediction on all of Y, U or V */
1111 for ( m = 0 ; m < FragsDown ; m++) {
1112 for ( n = 0 ; n < FragsAcross ; n++, i++){
1114 /* only do 2 prediction if fragment coded and on non intra or
1115 if all fragments are intra */
1116 if( pbi->display_fragments[i] || (GetFrameType(pbi) == KEY_FRAME) ){
1117 /* Type of Fragment */
1118 WhichFrame = Mode2Frame[pbi->FragCodingMethod[i]];
1120 /* Check Borderline Cases */
1121 WhichCase = (n==0) + ((m==0) << 1) + ((n+1 == FragsAcross) << 2);
1123 fn[0]=i-1;
1124 fn[1]=i-FragsAcross-1;
1125 fn[2]=i-FragsAcross;
1126 fn[3]=i-FragsAcross+1;
1128 /* fragment valid for prediction use if coded and it comes
1129 from same frame as the one we are predicting */
1130 for(k=pcount=wpc=0; k<4; k++) {
1131 int pflag;
1132 pflag=1<<k;
1133 if((bc_mask[WhichCase]&pflag) &&
1134 pbi->display_fragments[fn[k]] &&
1135 (Mode2Frame[pbi->FragCodingMethod[fn[k]]] == WhichFrame)){
1136 v[pcount]=pbi->QFragData[fn[k]][0];
1137 wpc|=pflag;
1138 pcount++;
1142 if(wpc==0){
1143 /* fall back to the last coded fragment */
1144 pbi->QFragData[i][0] += Last[WhichFrame];
1146 }else{
1148 /* don't do divide if divisor is 1 or 0 */
1149 PredictedDC = pc[wpc][0]*v[0];
1150 for(k=1; k<pcount; k++){
1151 PredictedDC += pc[wpc][k]*v[k];
1154 /* if we need to do a shift */
1155 if(pc[wpc][4] != 0 ){
1157 /* If negative add in the negative correction factor */
1158 PredictedDC += (HIGHBITDUPPED(PredictedDC) & pc[wpc][5]);
1160 /* Shift in lieu of a divide */
1161 PredictedDC >>= pc[wpc][4];
1164 /* check for outranging on the two predictors that can outrange */
1165 if((wpc&(PU|PUL|PL)) == (PU|PUL|PL)){
1166 if( abs(PredictedDC - v[2]) > 128) {
1167 PredictedDC = v[2];
1168 } else if( abs(PredictedDC - v[0]) > 128) {
1169 PredictedDC = v[0];
1170 } else if( abs(PredictedDC - v[1]) > 128) {
1171 PredictedDC = v[1];
1175 pbi->QFragData[i][0] += PredictedDC;
1179 /* Save the last fragment coded for whatever frame we are
1180 predicting from */
1181 Last[WhichFrame] = pbi->QFragData[i][0];
1183 /* Inverse DCT and reconstitute buffer in thisframe */
1184 ExpandBlockA( pbi, i );
1191 /* Copy the current reconstruction back to the last frame recon buffer. */
1192 if(pbi->CodedBlockIndex > (ogg_int32_t) (pbi->UnitFragments >> 1)){
1193 SwapReconBuffersTemp = pbi->ThisFrameRecon;
1194 pbi->ThisFrameRecon = pbi->LastFrameRecon;
1195 pbi->LastFrameRecon = SwapReconBuffersTemp;
1196 CopyNotRecon( pbi, pbi->LastFrameRecon, pbi->ThisFrameRecon );
1197 }else{
1198 CopyRecon( pbi, pbi->LastFrameRecon, pbi->ThisFrameRecon );
1201 /* Apply a loop filter to edge pixels of updated blocks */
1202 LoopFilter(pbi);
1204 /* We may need to update the UMV border */
1205 UpdateUMVBorder(pbi, pbi->LastFrameRecon);
1207 /* Reconstruct the golden frame if necessary.
1208 For VFW codec only on key frames */
1209 if ( GetFrameType(pbi) == KEY_FRAME ){
1210 CopyRecon( pbi, pbi->GoldenFrame, pbi->LastFrameRecon );
1211 /* We may need to update the UMV border */
1212 UpdateUMVBorder(pbi, pbi->GoldenFrame);
1216 void dsp_dct_decode_init (DspFunctions *funcs, ogg_uint32_t cpu_flags)
1218 funcs->FilterVert = FilterVert__c;
1219 funcs->FilterHoriz = FilterHoriz__c;
1220 #if defined(USE_ASM)
1221 if (cpu_flags & CPU_X86_MMX) {
1222 dsp_mmx_dct_decode_init(funcs);
1224 #endif