1 /********************************************************************
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. *
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
16 ********************************************************************/
20 #include "codec_internal.h"
23 #define GOLDEN_FRAME_THRESH_Q 50
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
,
48 ogg_int16_t
* BoundingValuePtr
= pbi
->FiltBoundingValue
+127;
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
){
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
){
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
;
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
){
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
;
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
]){
124 IDct1( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
127 dsp_IDct3(pbi
->dsp
, pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
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
);
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
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
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
162 /* Get coding mode for this block */
163 if ( GetFrameType(pbi
) == KEY_FRAME
){
164 pbi
->CodingMode
= CODE_INTRA
;
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
;
174 MvModMask
= 0x00000001;
176 /* Select appropriate dequantiser matrix. */
177 if ( pbi
->CodingMode
== CODE_INTRA
)
178 pbi
->dequant_coeffs
= pbi
->dequant_Y_coeffs
;
180 pbi
->dequant_coeffs
= pbi
->dequant_InterY_coeffs
;
182 ReconPixelsPerLine
= pbi
->UVStride
;
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
;
192 pbi
->dequant_coeffs
= pbi
->dequant_V_coeffs
;
194 if ( FragmentNumber
<
195 (ogg_int32_t
)(pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
) )
196 pbi
->dequant_coeffs
= pbi
->dequant_InterU_coeffs
;
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
]){
207 IDct1( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
210 dsp_IDct3(pbi
->dsp
, pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
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
);
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 ). */
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
;
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
,
282 /* Fractional pixel reconstruction. */
283 /* Note that we only use two pixels per reconstruction even for
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
);
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
) {
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 ) {
324 BlockVStep
= (pbi
->YStride
*
326 PlaneStride
= pbi
->YStride
;
327 PlaneBorderWidth
= UMV_BORDER
;
328 PlaneFragments
= pbi
->YPlaneFragments
;
329 LineFragments
= pbi
->HFragments
;
332 BlockVStep
= (pbi
->UVStride
*
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
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
] +
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
){
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 ) {
381 PlaneStride
= pbi
->YStride
;
382 PlaneBorderWidth
= UMV_BORDER
;
383 LineFragments
= pbi
->HFragments
;
384 PlaneHeight
= pbi
->info
.height
;
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
+
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
;
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
) {
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.*/
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
);
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
) {
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. */
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
);
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
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;
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;
536 ExpandedBlock
[*CoeffIndex
] = 1;
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;
545 ExpandedBlock
[*CoeffIndex
] = 1;
548 /* If token == DCT_RUN_CATEGORY2 we have a single 0 followed by
550 if ( Token
== DCT_RUN_CATEGORY2
){
551 /* Step on by the zero run length */
554 /* Bit 1 determines sign, bit 0 the value */
555 if ( ExtraBits
& 0x02 )
556 ExpandedBlock
[*CoeffIndex
] = -(2 + (ExtraBits
& 0x01));
558 ExpandedBlock
[*CoeffIndex
] = 2 + (ExtraBits
& 0x01);
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));
568 ExpandedBlock
[*CoeffIndex
] = 2 + ((ExtraBits
& 0x02) >> 1);
572 /* Step on over value */
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. */
585 ExpandedBlock
[*CoeffIndex
] = 1;
587 case MINUS_ONE_TOKEN
:
588 ExpandedBlock
[*CoeffIndex
] = -1;
591 ExpandedBlock
[*CoeffIndex
] = 2;
593 case MINUS_TWO_TOKEN
:
594 ExpandedBlock
[*CoeffIndex
] = -2;
598 /* Step on the coefficient index. */
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 */
609 ExpandedBlock
[*CoeffIndex
] =
610 -((Q_LIST_ENTRY
)(Token
+ DCT_VAL_CAT2_MIN
));
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));
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));
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));
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));
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));
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));
649 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT8_MIN
+ (ExtraBits
& 0x1FF);
652 /* Step on the coefficient index. */
657 void ClearDownQFragData(PB_INSTANCE
*pbi
){
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
){
674 for ( j
= 0; j
< 8; j
++ ){
677 ( PixelPtr
[1] * 3 ) +
678 ( PixelPtr
[2] * 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
){
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
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
);
715 void LoopFilter(PB_INSTANCE
*pbi
){
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
;
728 /* Set the limit value for the loop filter based upon the current
730 QIndex
= Q_TABLE_SIZE
- 1;
731 while ( QIndex
>= 0 ) {
732 if ( (QIndex
== 0) ||
733 ( pbi
->QThreshTable
[QIndex
] >= pbi
->ThisFrameQualityValue
) )
738 FLimit
= pbi
->LoopFilterLimits
[QIndex
];
739 if ( FLimit
== 0 ) return;
740 SetupBoundingValueArray_Generic(pbi
, FLimit
);
742 for ( j
= 0; j
< 3 ; j
++){
746 ToFragment
= pbi
->YPlaneFragments
;
747 FragsAcross
= pbi
->HFragments
;
748 FragsDown
= pbi
->VFragments
;
749 LineLength
= pbi
->YStride
;
750 LineFragments
= pbi
->HFragments
;
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;
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;
773 /**************************************************************
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
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
);
797 /***************************************************************/
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
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 /***************************************************************/
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
);
841 /***************************************************************/
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
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
);
873 /*****************************************************************/
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
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 /******************************************************************/
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
);
928 /*******************************************************************/
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
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
);
951 /******************************************************************/
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
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 /******************************************************************/
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
);
993 void ReconRefFrames (PB_INSTANCE
*pbi
){
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]={
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 */
1027 /* top row, left column */
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
1043 /* fragment number left, up-left, up, up-right */
1046 /* predictor count. */
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 */
1062 int FragsAcross
=pbi
->HFragments
;
1063 int FromFragment
,ToFragment
;
1064 int FragsDown
= pbi
->VFragments
;
1070 void (*ExpandBlockA
) ( PB_INSTANCE
*pbi
, ogg_int32_t FragmentNumber
);
1072 if ( GetFrameType(pbi
) == KEY_FRAME
)
1073 ExpandBlockA
=ExpandKFBlock
;
1075 ExpandBlockA
=ExpandBlock
;
1077 SetupLoopFilter(pbi
);
1080 for ( j
= 0; j
< 3 ; j
++) {
1081 /* pick which fragments based on Y, U, V */
1085 ToFragment
= pbi
->YPlaneFragments
;
1086 FragsAcross
= pbi
->HFragments
;
1087 FragsDown
= pbi
->VFragments
;
1090 FromFragment
= pbi
->YPlaneFragments
;
1091 ToFragment
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
1092 FragsAcross
= pbi
->HFragments
>> 1;
1093 FragsDown
= pbi
->VFragments
>> 1;
1097 FromFragment
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
1098 ToFragment
= pbi
->YPlaneFragments
+ (2 * pbi
->UVPlaneFragments
) ;
1099 FragsAcross
= pbi
->HFragments
>> 1;
1100 FragsDown
= pbi
->VFragments
>> 1;
1104 /* initialize our array of last used DC Components */
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);
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
++) {
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];
1143 /* fall back to the last coded fragment */
1144 pbi
->QFragData
[i
][0] += Last
[WhichFrame
];
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) {
1168 } else if( abs(PredictedDC
- v
[0]) > 128) {
1170 } else if( abs(PredictedDC
- v
[1]) > 128) {
1175 pbi
->QFragData
[i
][0] += PredictedDC
;
1179 /* Save the last fragment coded for whatever frame we are
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
);
1198 CopyRecon( pbi
, pbi
->LastFrameRecon
, pbi
->ThisFrameRecon
);
1201 /* Apply a loop filter to edge pixels of updated blocks */
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
);