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 ********************************************************************
14 last mod: $Id: dct_decode.c 11442 2006-05-27 17:28:08Z giles $
16 ********************************************************************/
20 #include "codec_internal.h"
24 #include <sys/types.h>
25 #include <sys/fcntl.h>
27 #define GOLDEN_FRAME_THRESH_Q 50
32 #define HIGHBITDUPPED(X) (((signed short) X) >> 15)
34 /* in-loop filter tables. one of these is used in dct_decode.c */
36 static const unsigned char LoopFilterLimitValuesV1
[Q_TABLE_SIZE
] = {
37 30, 25, 20, 20, 15, 15, 14, 14,
38 13, 13, 12, 12, 11, 11, 10, 10,
39 9, 9, 8, 8, 7, 7, 7, 7,
40 6, 6, 6, 6, 5, 5, 5, 5,
41 4, 4, 4, 4, 3, 3, 3, 3,
42 2, 2, 2, 2, 2, 2, 2, 2,
43 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 0, 0
47 static const unsigned char LoopFilterLimitValuesV2
[Q_TABLE_SIZE
] = {
48 30, 25, 20, 20, 15, 15, 14, 14,
49 13, 13, 12, 12, 11, 11, 10, 10,
50 9, 9, 8, 8, 7, 7, 7, 7,
51 6, 6, 6, 6, 5, 5, 5, 5,
52 4, 4, 4, 4, 3, 3, 3, 3,
53 2, 2, 2, 2, 2, 2, 2, 2,
54 2, 2, 2, 2, 2, 2, 2, 2,
55 1, 1, 1, 1, 1, 1, 1, 1
58 static const int ModeUsesMC
[MAX_MODES
] = { 0, 0, 1, 1, 1, 0, 1, 1 };
60 static void SetupBoundingValueArray_Generic(PB_INSTANCE
*pbi
,
63 ogg_int32_t
* BoundingValuePtr
= pbi
->FiltBoundingValue
+256;
66 /* Set up the bounding value array. */
67 memset ( pbi
->FiltBoundingValue
, 0, (512*sizeof(*pbi
->FiltBoundingValue
)) );
68 for ( i
= 0; i
< FLimit
; i
++ ){
69 BoundingValuePtr
[-i
-FLimit
] = (-FLimit
+i
);
70 BoundingValuePtr
[-i
] = -i
;
71 BoundingValuePtr
[i
] = i
;
72 BoundingValuePtr
[i
+FLimit
] = FLimit
-i
;
76 /* handle the in-loop filter limit value table */
78 void WriteFilterTables(PB_INSTANCE
*pbi
, oggpack_buffer
*opb
){
81 oggpackB_write(opb
, bits
, 3);
82 for(i
=0;i
<Q_TABLE_SIZE
;i
++)
83 oggpackB_write(opb
, pbi
->LoopFilterLimits
[i
],bits
);
86 int ReadFilterTables(codec_setup_info
*ci
, oggpack_buffer
*opb
){
90 theora_read(opb
, 3, &bits
);
91 for(i
=0;i
<Q_TABLE_SIZE
;i
++){
92 theora_read(opb
,bits
,&value
);
93 ci
->LoopFilterLimitValues
[i
]=value
;
95 if(bits
<0)return OC_BADHEADER
;
100 /* copy in-loop filter limits from the bitstream header into our instance */
101 void CopyFilterTables(PB_INSTANCE
*pbi
, codec_setup_info
*ci
){
102 memcpy(pbi
->LoopFilterLimits
, ci
->LoopFilterLimitValues
, Q_TABLE_SIZE
);
105 /* initialize the filter limits from our static table */
106 void InitFilterTables(PB_INSTANCE
*pbi
){
107 memcpy(pbi
->LoopFilterLimits
, LoopFilterLimitValuesV1
, Q_TABLE_SIZE
);
110 void SetupLoopFilter(PB_INSTANCE
*pbi
){
113 /* nb: this was using the V2 values rather than V1
114 we think is was a mistake; the results were not used */
115 FLimit
= pbi
->LoopFilterLimits
[pbi
->FrameQIndex
];
116 SetupBoundingValueArray_Generic(pbi
, FLimit
);
119 static void ExpandKFBlock ( PB_INSTANCE
*pbi
, ogg_int32_t FragmentNumber
){
120 ogg_uint32_t ReconPixelsPerLine
;
121 ogg_int32_t ReconPixelIndex
;
123 /* Select the appropriate inverse Q matrix and line stride */
124 if ( FragmentNumber
<(ogg_int32_t
)pbi
->YPlaneFragments
){
125 ReconPixelsPerLine
= pbi
->YStride
;
126 pbi
->dequant_coeffs
= pbi
->dequant_Y_coeffs
;
127 }else if ( FragmentNumber
<(ogg_int32_t
)(pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
) ){
128 ReconPixelsPerLine
= pbi
->UVStride
;
129 pbi
->dequant_coeffs
= pbi
->dequant_U_coeffs
;
131 ReconPixelsPerLine
= pbi
->UVStride
;
132 pbi
->dequant_coeffs
= pbi
->dequant_V_coeffs
;
135 /* Set up pointer into the quantisation buffer. */
136 pbi
->quantized_list
= &pbi
->QFragData
[FragmentNumber
][0];
138 /* Invert quantisation and DCT to get pixel data. */
139 switch(pbi
->FragCoefEOB
[FragmentNumber
]){
141 IDct1( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
143 case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10:
144 IDct10( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
147 IDctSlow( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
150 /* Convert fragment number to a pixel offset in a reconstruction buffer. */
151 ReconPixelIndex
= pbi
->recon_pixel_index_table
[FragmentNumber
];
153 /* Get the pixel index for the first pixel in the fragment. */
154 dsp_recon_intra8x8 (pbi
->dsp
, (unsigned char *)(&pbi
->ThisFrameRecon
[ReconPixelIndex
]),
155 (ogg_int16_t
*)pbi
->ReconDataBuffer
, ReconPixelsPerLine
);
159 static void ExpandBlock ( PB_INSTANCE
*pbi
, ogg_int32_t FragmentNumber
){
160 unsigned char *LastFrameRecPtr
; /* Pointer into previous frame
162 unsigned char *LastFrameRecPtr2
; /* Pointer into previous frame
163 reconstruction for 1/2 pixel MC. */
165 ogg_uint32_t ReconPixelsPerLine
; /* Pixels per line */
166 ogg_int32_t ReconPixelIndex
; /* Offset for block into a
167 reconstruction buffer */
168 ogg_int32_t ReconPtr2Offset
; /* Offset for second
169 reconstruction in half pixel
171 ogg_int32_t MVOffset
; /* Baseline motion vector offset */
172 ogg_int32_t MvShift
; /* Shift to correct to 1/2 or 1/4 pixel */
173 ogg_int32_t MvModMask
; /* Mask to determine whether 1/2
176 /* Get coding mode for this block */
177 if ( GetFrameType(pbi
) == KEY_FRAME
){
178 pbi
->CodingMode
= CODE_INTRA
;
180 /* Get Motion vector and mode for this block. */
181 pbi
->CodingMode
= pbi
->FragCodingMethod
[FragmentNumber
];
184 /* Select the appropriate inverse Q matrix and line stride */
185 if ( FragmentNumber
<(ogg_int32_t
)pbi
->YPlaneFragments
) {
186 ReconPixelsPerLine
= pbi
->YStride
;
188 MvModMask
= 0x00000001;
190 /* Select appropriate dequantiser matrix. */
191 if ( pbi
->CodingMode
== CODE_INTRA
)
192 pbi
->dequant_coeffs
= pbi
->dequant_Y_coeffs
;
194 pbi
->dequant_coeffs
= pbi
->dequant_InterY_coeffs
;
196 ReconPixelsPerLine
= pbi
->UVStride
;
198 MvModMask
= 0x00000003;
200 /* Select appropriate dequantiser matrix. */
201 if ( pbi
->CodingMode
== CODE_INTRA
)
202 if ( FragmentNumber
<
203 (ogg_int32_t
)(pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
) )
204 pbi
->dequant_coeffs
= pbi
->dequant_U_coeffs
;
206 pbi
->dequant_coeffs
= pbi
->dequant_V_coeffs
;
208 if ( FragmentNumber
<
209 (ogg_int32_t
)(pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
) )
210 pbi
->dequant_coeffs
= pbi
->dequant_InterU_coeffs
;
212 pbi
->dequant_coeffs
= pbi
->dequant_InterV_coeffs
;
215 /* Set up pointer into the quantisation buffer. */
216 pbi
->quantized_list
= &pbi
->QFragData
[FragmentNumber
][0];
218 /* Invert quantisation and DCT to get pixel data. */
219 switch(pbi
->FragCoefEOB
[FragmentNumber
]){
221 IDct1( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
223 case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10:
224 IDct10( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
227 IDctSlow( pbi
->quantized_list
, pbi
->dequant_coeffs
, pbi
->ReconDataBuffer
);
230 /* Convert fragment number to a pixel offset in a reconstruction buffer. */
231 ReconPixelIndex
= pbi
->recon_pixel_index_table
[FragmentNumber
];
233 /* Action depends on decode mode. */
234 if ( pbi
->CodingMode
== CODE_INTER_NO_MV
){
235 /* Inter with no motion vector */
236 /* Reconstruct the pixel data using the last frame reconstruction
237 and change data when the motion vector is (0,0), the recon is
238 based on the lastframe without loop filtering---- for testing */
239 dsp_recon_inter8x8 (pbi
->dsp
, &pbi
->ThisFrameRecon
[ReconPixelIndex
],
240 &pbi
->LastFrameRecon
[ReconPixelIndex
],
241 pbi
->ReconDataBuffer
, ReconPixelsPerLine
);
242 }else if ( ModeUsesMC
[pbi
->CodingMode
] ) {
243 /* The mode uses a motion vector. */
244 /* Get vector from list */
245 pbi
->MVector
.x
= pbi
->FragMVect
[FragmentNumber
].x
;
246 pbi
->MVector
.y
= pbi
->FragMVect
[FragmentNumber
].y
;
248 /* Work out the base motion vector offset and the 1/2 pixel offset
249 if any. For the U and V planes the MV specifies 1/4 pixel
250 accuracy. This is adjusted to 1/2 pixel as follows ( 0->0,
251 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */
254 if ( pbi
->MVector
.x
> 0 ){
255 MVOffset
= pbi
->MVector
.x
>> MvShift
;
256 if ( pbi
->MVector
.x
& MvModMask
)
257 ReconPtr2Offset
+= 1;
258 } else if ( pbi
->MVector
.x
< 0 ) {
259 MVOffset
-= (-pbi
->MVector
.x
) >> MvShift
;
260 if ( (-pbi
->MVector
.x
) & MvModMask
)
261 ReconPtr2Offset
-= 1;
264 if ( pbi
->MVector
.y
> 0 ){
265 MVOffset
+= (pbi
->MVector
.y
>> MvShift
) * ReconPixelsPerLine
;
266 if ( pbi
->MVector
.y
& MvModMask
)
267 ReconPtr2Offset
+= ReconPixelsPerLine
;
268 } else if ( pbi
->MVector
.y
< 0 ){
269 MVOffset
-= ((-pbi
->MVector
.y
) >> MvShift
) * ReconPixelsPerLine
;
270 if ( (-pbi
->MVector
.y
) & MvModMask
)
271 ReconPtr2Offset
-= ReconPixelsPerLine
;
274 /* Set up the first of the two reconstruction buffer pointers. */
275 if ( pbi
->CodingMode
==CODE_GOLDEN_MV
) {
276 LastFrameRecPtr
= &pbi
->GoldenFrame
[ReconPixelIndex
] + MVOffset
;
278 LastFrameRecPtr
= &pbi
->LastFrameRecon
[ReconPixelIndex
] + MVOffset
;
281 /* Set up the second of the two reconstruction pointers. */
282 LastFrameRecPtr2
= LastFrameRecPtr
+ ReconPtr2Offset
;
284 /* Select the appropriate reconstruction function */
285 if ( (int)(LastFrameRecPtr
- LastFrameRecPtr2
) == 0 ) {
286 /* Reconstruct the pixel dats from the reference frame and change data
287 (no half pixel in this case as the two references were the same. */
288 dsp_recon_inter8x8 (pbi
->dsp
,
289 &pbi
->ThisFrameRecon
[ReconPixelIndex
],
290 LastFrameRecPtr
, pbi
->ReconDataBuffer
,
293 /* Fractional pixel reconstruction. */
294 /* Note that we only use two pixels per reconstruction even for
296 dsp_recon_inter8x8_half(pbi
->dsp
, &pbi
->ThisFrameRecon
[ReconPixelIndex
],
297 LastFrameRecPtr
, LastFrameRecPtr2
,
298 pbi
->ReconDataBuffer
, ReconPixelsPerLine
);
300 } else if ( pbi
->CodingMode
== CODE_USING_GOLDEN
){
301 /* Golden frame with motion vector */
302 /* Reconstruct the pixel data using the golden frame
303 reconstruction and change data */
304 dsp_recon_inter8x8 (pbi
->dsp
, &pbi
->ThisFrameRecon
[ReconPixelIndex
],
305 &pbi
->GoldenFrame
[ ReconPixelIndex
],
306 pbi
->ReconDataBuffer
, ReconPixelsPerLine
);
308 /* Simple Intra coding */
309 /* Get the pixel index for the first pixel in the fragment. */
310 dsp_recon_intra8x8 (pbi
->dsp
, &pbi
->ThisFrameRecon
[ReconPixelIndex
],
311 pbi
->ReconDataBuffer
, ReconPixelsPerLine
);
315 static void UpdateUMV_HBorders( PB_INSTANCE
*pbi
,
316 unsigned char * DestReconPtr
,
317 ogg_uint32_t PlaneFragOffset
) {
319 ogg_uint32_t PixelIndex
;
321 ogg_uint32_t PlaneStride
;
322 ogg_uint32_t BlockVStep
;
323 ogg_uint32_t PlaneFragments
;
324 ogg_uint32_t LineFragments
;
325 ogg_uint32_t PlaneBorderWidth
;
327 unsigned char *SrcPtr1
;
328 unsigned char *SrcPtr2
;
329 unsigned char *DestPtr1
;
330 unsigned char *DestPtr2
;
332 /* Work out various plane specific values */
333 if ( PlaneFragOffset
== 0 ) {
335 BlockVStep
= (pbi
->YStride
*
337 PlaneStride
= pbi
->YStride
;
338 PlaneBorderWidth
= UMV_BORDER
;
339 PlaneFragments
= pbi
->YPlaneFragments
;
340 LineFragments
= pbi
->HFragments
;
343 BlockVStep
= (pbi
->UVStride
*
345 PlaneStride
= pbi
->UVStride
;
346 PlaneBorderWidth
= UMV_BORDER
/ 2;
347 PlaneFragments
= pbi
->UVPlaneFragments
;
348 LineFragments
= pbi
->HFragments
/ 2;
351 /* Setup the source and destination pointers for the top and bottom
353 PixelIndex
= pbi
->recon_pixel_index_table
[PlaneFragOffset
];
354 SrcPtr1
= &DestReconPtr
[ PixelIndex
- PlaneBorderWidth
];
355 DestPtr1
= SrcPtr1
- (PlaneBorderWidth
* PlaneStride
);
357 PixelIndex
= pbi
->recon_pixel_index_table
[PlaneFragOffset
+
358 PlaneFragments
- LineFragments
] +
360 SrcPtr2
= &DestReconPtr
[ PixelIndex
- PlaneBorderWidth
];
361 DestPtr2
= SrcPtr2
+ PlaneStride
;
363 /* Now copy the top and bottom source lines into each line of the
364 respective borders */
365 for ( i
= 0; i
< PlaneBorderWidth
; i
++ ) {
366 memcpy( DestPtr1
, SrcPtr1
, PlaneStride
);
367 memcpy( DestPtr2
, SrcPtr2
, PlaneStride
);
368 DestPtr1
+= PlaneStride
;
369 DestPtr2
+= PlaneStride
;
373 static void UpdateUMV_VBorders( PB_INSTANCE
*pbi
,
374 unsigned char * DestReconPtr
,
375 ogg_uint32_t PlaneFragOffset
){
377 ogg_uint32_t PixelIndex
;
379 ogg_uint32_t PlaneStride
;
380 ogg_uint32_t LineFragments
;
381 ogg_uint32_t PlaneBorderWidth
;
382 ogg_uint32_t PlaneHeight
;
384 unsigned char *SrcPtr1
;
385 unsigned char *SrcPtr2
;
386 unsigned char *DestPtr1
;
387 unsigned char *DestPtr2
;
389 /* Work out various plane specific values */
390 if ( PlaneFragOffset
== 0 ) {
392 PlaneStride
= pbi
->YStride
;
393 PlaneBorderWidth
= UMV_BORDER
;
394 LineFragments
= pbi
->HFragments
;
395 PlaneHeight
= pbi
->info
.height
;
398 PlaneStride
= pbi
->UVStride
;
399 PlaneBorderWidth
= UMV_BORDER
/ 2;
400 LineFragments
= pbi
->HFragments
/ 2;
401 PlaneHeight
= pbi
->info
.height
/ 2;
404 /* Setup the source data values and destination pointers for the
405 left and right edge borders */
406 PixelIndex
= pbi
->recon_pixel_index_table
[PlaneFragOffset
];
407 SrcPtr1
= &DestReconPtr
[ PixelIndex
];
408 DestPtr1
= &DestReconPtr
[ PixelIndex
- PlaneBorderWidth
];
410 PixelIndex
= pbi
->recon_pixel_index_table
[PlaneFragOffset
+
413 SrcPtr2
= &DestReconPtr
[ PixelIndex
];
414 DestPtr2
= &DestReconPtr
[ PixelIndex
+ 1 ];
416 /* Now copy the top and bottom source lines into each line of the
417 respective borders */
418 for ( i
= 0; i
< PlaneHeight
; i
++ ) {
419 memset( DestPtr1
, SrcPtr1
[0], PlaneBorderWidth
);
420 memset( DestPtr2
, SrcPtr2
[0], PlaneBorderWidth
);
421 SrcPtr1
+= PlaneStride
;
422 SrcPtr2
+= PlaneStride
;
423 DestPtr1
+= PlaneStride
;
424 DestPtr2
+= PlaneStride
;
428 void UpdateUMVBorder( PB_INSTANCE
*pbi
,
429 unsigned char * DestReconPtr
) {
430 ogg_uint32_t PlaneFragOffset
;
434 UpdateUMV_VBorders( pbi
, DestReconPtr
, PlaneFragOffset
);
435 UpdateUMV_HBorders( pbi
, DestReconPtr
, PlaneFragOffset
);
437 /* Then the U and V Planes */
438 PlaneFragOffset
= pbi
->YPlaneFragments
;
439 UpdateUMV_VBorders( pbi
, DestReconPtr
, PlaneFragOffset
);
440 UpdateUMV_HBorders( pbi
, DestReconPtr
, PlaneFragOffset
);
442 PlaneFragOffset
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
443 UpdateUMV_VBorders( pbi
, DestReconPtr
, PlaneFragOffset
);
444 UpdateUMV_HBorders( pbi
, DestReconPtr
, PlaneFragOffset
);
447 static void CopyRecon( PB_INSTANCE
*pbi
, unsigned char * DestReconPtr
,
448 unsigned char * SrcReconPtr
) {
450 ogg_uint32_t PlaneLineStep
; /* Pixels per line */
451 ogg_uint32_t PixelIndex
;
453 unsigned char *SrcPtr
; /* Pointer to line of source image data */
454 unsigned char *DestPtr
; /* Pointer to line of destination image data */
456 /* Copy over only updated blocks.*/
459 PlaneLineStep
= pbi
->YStride
;
460 for ( i
= 0; i
< pbi
->YPlaneFragments
; i
++ ) {
461 if ( pbi
->display_fragments
[i
] ) {
462 PixelIndex
= pbi
->recon_pixel_index_table
[i
];
463 SrcPtr
= &SrcReconPtr
[ PixelIndex
];
464 DestPtr
= &DestReconPtr
[ PixelIndex
];
466 dsp_copy8x8 (pbi
->dsp
, SrcPtr
, DestPtr
, PlaneLineStep
);
471 PlaneLineStep
= pbi
->UVStride
;
472 for ( i
= pbi
->YPlaneFragments
; i
< pbi
->UnitFragments
; i
++ ) {
473 if ( pbi
->display_fragments
[i
] ) {
474 PixelIndex
= pbi
->recon_pixel_index_table
[i
];
475 SrcPtr
= &SrcReconPtr
[ PixelIndex
];
476 DestPtr
= &DestReconPtr
[ PixelIndex
];
478 dsp_copy8x8 (pbi
->dsp
, SrcPtr
, DestPtr
, PlaneLineStep
);
484 static void CopyNotRecon( PB_INSTANCE
*pbi
, unsigned char * DestReconPtr
,
485 unsigned char * SrcReconPtr
) {
487 ogg_uint32_t PlaneLineStep
; /* Pixels per line */
488 ogg_uint32_t PixelIndex
;
490 unsigned char *SrcPtr
; /* Pointer to line of source image data */
491 unsigned char *DestPtr
; /* Pointer to line of destination image data*/
493 /* Copy over only updated blocks. */
496 PlaneLineStep
= pbi
->YStride
;
497 for ( i
= 0; i
< pbi
->YPlaneFragments
; i
++ ) {
498 if ( !pbi
->display_fragments
[i
] ) {
499 PixelIndex
= pbi
->recon_pixel_index_table
[i
];
500 SrcPtr
= &SrcReconPtr
[ PixelIndex
];
501 DestPtr
= &DestReconPtr
[ PixelIndex
];
503 dsp_copy8x8 (pbi
->dsp
, SrcPtr
, DestPtr
, PlaneLineStep
);
508 PlaneLineStep
= pbi
->UVStride
;
509 for ( i
= pbi
->YPlaneFragments
; i
< pbi
->UnitFragments
; i
++ ) {
510 if ( !pbi
->display_fragments
[i
] ) {
511 PixelIndex
= pbi
->recon_pixel_index_table
[i
];
512 SrcPtr
= &SrcReconPtr
[ PixelIndex
];
513 DestPtr
= &DestReconPtr
[ PixelIndex
];
515 dsp_copy8x8 (pbi
->dsp
, SrcPtr
, DestPtr
, PlaneLineStep
);
521 void ExpandToken( Q_LIST_ENTRY
* ExpandedBlock
,
522 unsigned char * CoeffIndex
, ogg_uint32_t Token
,
523 ogg_int32_t ExtraBits
){
524 /* Is the token is a combination run and value token. */
525 if ( Token
>= DCT_RUN_CATEGORY1
){
526 /* Expand the token and additional bits to a zero run length and
528 if ( Token
< DCT_RUN_CATEGORY2
) {
529 /* Decoding method depends on token */
530 if ( Token
< DCT_RUN_CATEGORY1B
) {
531 /* Step on by the zero run length */
532 *CoeffIndex
+= (unsigned char)((Token
- DCT_RUN_CATEGORY1
) + 1);
534 /* The extra bit determines the sign. */
535 if ( ExtraBits
& 0x01 )
536 ExpandedBlock
[*CoeffIndex
] = -1;
538 ExpandedBlock
[*CoeffIndex
] = 1;
539 } else if ( Token
== DCT_RUN_CATEGORY1B
) {
540 /* Bits 0-1 determines the zero run length */
541 *CoeffIndex
+= (6 + (ExtraBits
& 0x03));
543 /* Bit 2 determines the sign */
544 if ( ExtraBits
& 0x04 )
545 ExpandedBlock
[*CoeffIndex
] = -1;
547 ExpandedBlock
[*CoeffIndex
] = 1;
549 /* Bits 0-2 determines the zero run length */
550 *CoeffIndex
+= (10 + (ExtraBits
& 0x07));
552 /* Bit 3 determines the sign */
553 if ( ExtraBits
& 0x08 )
554 ExpandedBlock
[*CoeffIndex
] = -1;
556 ExpandedBlock
[*CoeffIndex
] = 1;
559 /* If token == DCT_RUN_CATEGORY2 we have a single 0 followed by
561 if ( Token
== DCT_RUN_CATEGORY2
){
562 /* Step on by the zero run length */
565 /* Bit 1 determines sign, bit 0 the value */
566 if ( ExtraBits
& 0x02 )
567 ExpandedBlock
[*CoeffIndex
] = -(2 + (ExtraBits
& 0x01));
569 ExpandedBlock
[*CoeffIndex
] = 2 + (ExtraBits
& 0x01);
571 /* else we have 2->3 zeros followed by a value */
572 /* Bit 0 determines the zero run length */
573 *CoeffIndex
+= 2 + (ExtraBits
& 0x01);
575 /* Bit 2 determines the sign, bit 1 the value */
576 if ( ExtraBits
& 0x04 )
577 ExpandedBlock
[*CoeffIndex
] = -(2 + ((ExtraBits
& 0x02) >> 1));
579 ExpandedBlock
[*CoeffIndex
] = 2 + ((ExtraBits
& 0x02) >> 1);
583 /* Step on over value */
586 } else if ( Token
== DCT_SHORT_ZRL_TOKEN
) {
587 /* Token is a ZRL token so step on by the appropriate number of zeros */
588 *CoeffIndex
+= ExtraBits
+ 1;
589 } else if ( Token
== DCT_ZRL_TOKEN
) {
590 /* Token is a ZRL token so step on by the appropriate number of zeros */
591 *CoeffIndex
+= ExtraBits
+ 1;
592 } else if ( Token
< LOW_VAL_TOKENS
) {
593 /* Token is a small single value token. */
596 ExpandedBlock
[*CoeffIndex
] = 1;
598 case MINUS_ONE_TOKEN
:
599 ExpandedBlock
[*CoeffIndex
] = -1;
602 ExpandedBlock
[*CoeffIndex
] = 2;
604 case MINUS_TWO_TOKEN
:
605 ExpandedBlock
[*CoeffIndex
] = -2;
609 /* Step on the coefficient index. */
612 /* Token is a larger single value token */
613 /* Expand the token and additional bits to a data value. */
614 if ( Token
< DCT_VAL_CATEGORY3
) {
615 /* Offset from LOW_VAL_TOKENS determines value */
616 Token
= Token
- LOW_VAL_TOKENS
;
618 /* Extra bit determines sign */
620 ExpandedBlock
[*CoeffIndex
] =
621 -((Q_LIST_ENTRY
)(Token
+ DCT_VAL_CAT2_MIN
));
623 ExpandedBlock
[*CoeffIndex
] =
624 (Q_LIST_ENTRY
)(Token
+ DCT_VAL_CAT2_MIN
);
625 } else if ( Token
== DCT_VAL_CATEGORY3
) {
626 /* Bit 1 determines sign, Bit 0 the value */
627 if ( ExtraBits
& 0x02 )
628 ExpandedBlock
[*CoeffIndex
] = -(DCT_VAL_CAT3_MIN
+ (ExtraBits
& 0x01));
630 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT3_MIN
+ (ExtraBits
& 0x01);
631 } else if ( Token
== DCT_VAL_CATEGORY4
) {
632 /* Bit 2 determines sign, Bit 0-1 the value */
633 if ( ExtraBits
& 0x04 )
634 ExpandedBlock
[*CoeffIndex
] = -(DCT_VAL_CAT4_MIN
+ (ExtraBits
& 0x03));
636 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT4_MIN
+ (ExtraBits
& 0x03);
637 } else if ( Token
== DCT_VAL_CATEGORY5
) {
638 /* Bit 3 determines sign, Bit 0-2 the value */
639 if ( ExtraBits
& 0x08 )
640 ExpandedBlock
[*CoeffIndex
] = -(DCT_VAL_CAT5_MIN
+ (ExtraBits
& 0x07));
642 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT5_MIN
+ (ExtraBits
& 0x07);
643 } else if ( Token
== DCT_VAL_CATEGORY6
) {
644 /* Bit 4 determines sign, Bit 0-3 the value */
645 if ( ExtraBits
& 0x10 )
646 ExpandedBlock
[*CoeffIndex
] = -(DCT_VAL_CAT6_MIN
+ (ExtraBits
& 0x0F));
648 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT6_MIN
+ (ExtraBits
& 0x0F);
649 } else if ( Token
== DCT_VAL_CATEGORY7
) {
650 /* Bit 5 determines sign, Bit 0-4 the value */
651 if ( ExtraBits
& 0x20 )
652 ExpandedBlock
[*CoeffIndex
] = -(DCT_VAL_CAT7_MIN
+ (ExtraBits
& 0x1F));
654 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT7_MIN
+ (ExtraBits
& 0x1F);
655 } else if ( Token
== DCT_VAL_CATEGORY8
) {
656 /* Bit 9 determines sign, Bit 0-8 the value */
657 if ( ExtraBits
& 0x200 )
658 ExpandedBlock
[*CoeffIndex
] = -(DCT_VAL_CAT8_MIN
+ (ExtraBits
& 0x1FF));
660 ExpandedBlock
[*CoeffIndex
] = DCT_VAL_CAT8_MIN
+ (ExtraBits
& 0x1FF);
663 /* Step on the coefficient index. */
668 void ClearDownQFragData(PB_INSTANCE
*pbi
){
670 Q_LIST_ENTRY
* QFragPtr
;
672 for ( i
= 0; i
< pbi
->CodedBlockIndex
; i
++ ) {
673 /* Get the linear index for the current fragment. */
674 QFragPtr
= pbi
->QFragData
[pbi
->CodedBlockList
[i
]];
675 memset(QFragPtr
, 0, 64*sizeof(Q_LIST_ENTRY
));
679 static void FilterHoriz(unsigned char * PixelPtr
,
680 ogg_int32_t LineLength
,
681 ogg_int32_t
*BoundingValuePtr
){
685 for ( j
= 0; j
< 8; j
++ ){
688 ( PixelPtr
[1] * 3 ) +
689 ( PixelPtr
[2] * 3 ) -
692 FiltVal
= *(BoundingValuePtr
+((FiltVal
+ 4) >> 3));
694 PixelPtr
[1] = clamp255(PixelPtr
[1] + FiltVal
);
695 PixelPtr
[2] = clamp255(PixelPtr
[2] - FiltVal
);
697 PixelPtr
+= LineLength
;
701 static void FilterVert(unsigned char * PixelPtr
,
702 ogg_int32_t LineLength
,
703 ogg_int32_t
*BoundingValuePtr
){
707 /* the math was correct, but negative array indicies are forbidden
708 by ANSI/C99 and will break optimization on several modern
711 PixelPtr
-= 2*LineLength
;
713 for ( j
= 0; j
< 8; j
++ ) {
714 FiltVal
= ( (ogg_int32_t
)PixelPtr
[0] ) -
715 ( (ogg_int32_t
)PixelPtr
[LineLength
] * 3 ) +
716 ( (ogg_int32_t
)PixelPtr
[2 * LineLength
] * 3 ) -
717 ( (ogg_int32_t
)PixelPtr
[3 * LineLength
] );
719 FiltVal
= *(BoundingValuePtr
+((FiltVal
+ 4) >> 3));
721 PixelPtr
[LineLength
] = clamp255(PixelPtr
[LineLength
] + FiltVal
);
722 PixelPtr
[2 * LineLength
] = clamp255(PixelPtr
[2*LineLength
] - FiltVal
);
728 void LoopFilter(PB_INSTANCE
*pbi
){
731 ogg_int32_t
* BoundingValuePtr
=pbi
->FiltBoundingValue
+256;
732 int FragsAcross
=pbi
->HFragments
;
733 int FromFragment
,ToFragment
;
734 int FragsDown
= pbi
->VFragments
;
735 ogg_int32_t LineFragments
;
736 ogg_int32_t LineLength
;
741 /* Set the limit value for the loop filter based upon the current
743 QIndex
= Q_TABLE_SIZE
- 1;
744 while ( QIndex
>= 0 ) {
745 if ( (QIndex
== 0) ||
746 ( pbi
->QThreshTable
[QIndex
] >= pbi
->ThisFrameQualityValue
) )
751 FLimit
= pbi
->LoopFilterLimits
[QIndex
];
752 if ( FLimit
== 0 ) return;
753 SetupBoundingValueArray_Generic(pbi
, FLimit
);
755 for ( j
= 0; j
< 3 ; j
++){
759 ToFragment
= pbi
->YPlaneFragments
;
760 FragsAcross
= pbi
->HFragments
;
761 FragsDown
= pbi
->VFragments
;
762 LineLength
= pbi
->YStride
;
763 LineFragments
= pbi
->HFragments
;
766 FromFragment
= pbi
->YPlaneFragments
;
767 ToFragment
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
768 FragsAcross
= pbi
->HFragments
>> 1;
769 FragsDown
= pbi
->VFragments
>> 1;
770 LineLength
= pbi
->UVStride
;
771 LineFragments
= pbi
->HFragments
/ 2;
775 FromFragment
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
776 ToFragment
= pbi
->YPlaneFragments
+ (2 * pbi
->UVPlaneFragments
) ;
777 FragsAcross
= pbi
->HFragments
>> 1;
778 FragsDown
= pbi
->VFragments
>> 1;
779 LineLength
= pbi
->UVStride
;
780 LineFragments
= pbi
->HFragments
/ 2;
786 /**************************************************************
788 **************************************************************/
789 /* first column conditions */
790 /* only do 2 prediction if fragment coded and on non intra or if
791 all fragments are intra */
792 if( pbi
->display_fragments
[i
]){
793 /* Filter right hand border only if the block to the right is
795 if ( !pbi
->display_fragments
[ i
+ 1 ] ){
796 FilterHoriz(pbi
->LastFrameRecon
+
797 pbi
->recon_pixel_index_table
[i
]+6,
798 LineLength
,BoundingValuePtr
);
801 /* Bottom done if next row set */
802 if( !pbi
->display_fragments
[ i
+ LineFragments
] ){
803 FilterVert(pbi
->LastFrameRecon
+
804 pbi
->recon_pixel_index_table
[i
+LineFragments
],
805 LineLength
, BoundingValuePtr
);
810 /***************************************************************/
812 for ( n
= 1 ; n
< FragsAcross
- 1 ; n
++, i
++) {
813 if( pbi
->display_fragments
[i
]){
814 /* Filter Left edge always */
815 FilterHoriz(pbi
->LastFrameRecon
+
816 pbi
->recon_pixel_index_table
[i
]-2,
817 LineLength
, BoundingValuePtr
);
819 /* Filter right hand border only if the block to the right is
821 if ( !pbi
->display_fragments
[ i
+ 1 ] ){
822 FilterHoriz(pbi
->LastFrameRecon
+
823 pbi
->recon_pixel_index_table
[i
]+6,
824 LineLength
, BoundingValuePtr
);
827 /* Bottom done if next row set */
828 if( !pbi
->display_fragments
[ i
+ LineFragments
] ){
829 FilterVert(pbi
->LastFrameRecon
+
830 pbi
->recon_pixel_index_table
[i
+ LineFragments
],
831 LineLength
, BoundingValuePtr
);
837 /***************************************************************/
839 if( pbi
->display_fragments
[i
]){
840 /* Filter Left edge always */
841 FilterHoriz(pbi
->LastFrameRecon
+
842 pbi
->recon_pixel_index_table
[i
] - 2 ,
843 LineLength
, BoundingValuePtr
);
845 /* Bottom done if next row set */
846 if( !pbi
->display_fragments
[ i
+ LineFragments
] ){
847 FilterVert(pbi
->LastFrameRecon
+
848 pbi
->recon_pixel_index_table
[i
+ LineFragments
],
849 LineLength
, BoundingValuePtr
);
854 /***************************************************************/
856 /***************************************************************/
857 for ( m
= 1 ; m
< FragsDown
-1 ; m
++) {
859 /*****************************************************************/
860 /* first column conditions */
861 /* only do 2 prediction if fragment coded and on non intra or if
862 all fragments are intra */
863 if( pbi
->display_fragments
[i
]){
864 /* TopRow is always done */
865 FilterVert(pbi
->LastFrameRecon
+
866 pbi
->recon_pixel_index_table
[i
],
867 LineLength
, BoundingValuePtr
);
869 /* Filter right hand border only if the block to the right is
871 if ( !pbi
->display_fragments
[ i
+ 1 ] ){
872 FilterHoriz(pbi
->LastFrameRecon
+
873 pbi
->recon_pixel_index_table
[i
] + 6,
874 LineLength
, BoundingValuePtr
);
877 /* Bottom done if next row set */
878 if( !pbi
->display_fragments
[ i
+ LineFragments
] ){
879 FilterVert(pbi
->LastFrameRecon
+
880 pbi
->recon_pixel_index_table
[i
+ LineFragments
],
881 LineLength
, BoundingValuePtr
);
886 /*****************************************************************/
888 for ( n
= 1 ; n
< FragsAcross
- 1 ; n
++, i
++){
889 if( pbi
->display_fragments
[i
]){
890 /* Filter Left edge always */
891 FilterHoriz(pbi
->LastFrameRecon
+
892 pbi
->recon_pixel_index_table
[i
] - 2,
893 LineLength
, BoundingValuePtr
);
895 /* TopRow is always done */
896 FilterVert(pbi
->LastFrameRecon
+
897 pbi
->recon_pixel_index_table
[i
],
898 LineLength
, BoundingValuePtr
);
900 /* Filter right hand border only if the block to the right
902 if ( !pbi
->display_fragments
[ i
+ 1 ] ){
903 FilterHoriz(pbi
->LastFrameRecon
+
904 pbi
->recon_pixel_index_table
[i
] + 6,
905 LineLength
, BoundingValuePtr
);
908 /* Bottom done if next row set */
909 if( !pbi
->display_fragments
[ i
+ LineFragments
] ){
910 FilterVert(pbi
->LastFrameRecon
+
911 pbi
->recon_pixel_index_table
[i
+ LineFragments
],
912 LineLength
, BoundingValuePtr
);
917 /******************************************************************/
919 if( pbi
->display_fragments
[i
]){
920 /* Filter Left edge always*/
921 FilterHoriz(pbi
->LastFrameRecon
+
922 pbi
->recon_pixel_index_table
[i
] - 2,
923 LineLength
, BoundingValuePtr
);
925 /* TopRow is always done */
926 FilterVert(pbi
->LastFrameRecon
+
927 pbi
->recon_pixel_index_table
[i
],
928 LineLength
, BoundingValuePtr
);
930 /* Bottom done if next row set */
931 if( !pbi
->display_fragments
[ i
+ LineFragments
] ){
932 FilterVert(pbi
->LastFrameRecon
+
933 pbi
->recon_pixel_index_table
[i
+ LineFragments
],
934 LineLength
, BoundingValuePtr
);
941 /*******************************************************************/
944 /* first column conditions */
945 /* only do 2 prediction if fragment coded and on non intra or if
946 all fragments are intra */
947 if( pbi
->display_fragments
[i
]){
949 /* TopRow is always done */
950 FilterVert(pbi
->LastFrameRecon
+
951 pbi
->recon_pixel_index_table
[i
],
952 LineLength
, BoundingValuePtr
);
954 /* Filter right hand border only if the block to the right is
956 if ( !pbi
->display_fragments
[ i
+ 1 ] ){
957 FilterHoriz(pbi
->LastFrameRecon
+
958 pbi
->recon_pixel_index_table
[i
] + 6,
959 LineLength
, BoundingValuePtr
);
964 /******************************************************************/
966 for ( n
= 1 ; n
< FragsAcross
- 1 ; n
++, i
++){
967 if( pbi
->display_fragments
[i
]){
968 /* Filter Left edge always */
969 FilterHoriz(pbi
->LastFrameRecon
+
970 pbi
->recon_pixel_index_table
[i
] - 2,
971 LineLength
, BoundingValuePtr
);
973 /* TopRow is always done */
974 FilterVert(pbi
->LastFrameRecon
+
975 pbi
->recon_pixel_index_table
[i
],
976 LineLength
, BoundingValuePtr
);
978 /* Filter right hand border only if the block to the right is
980 if ( !pbi
->display_fragments
[ i
+ 1 ] ){
981 FilterHoriz(pbi
->LastFrameRecon
+
982 pbi
->recon_pixel_index_table
[i
] + 6,
983 LineLength
, BoundingValuePtr
);
988 /******************************************************************/
990 if( pbi
->display_fragments
[i
]){
991 /* Filter Left edge always */
992 FilterHoriz(pbi
->LastFrameRecon
+
993 pbi
->recon_pixel_index_table
[i
] - 2,
994 LineLength
, BoundingValuePtr
);
996 /* TopRow is always done */
997 FilterVert(pbi
->LastFrameRecon
+
998 pbi
->recon_pixel_index_table
[i
],
999 LineLength
, BoundingValuePtr
);
1009 int read
; // Driver read on Theora Hardware
1010 int wrote
; // Driver wrote on Theora Hardware
1011 int data
; // Read or transmitted data
1017 int flag_theora
= 0;
1019 void write_theoradriver(int pf
, int data
) {
1021 do ioctl(pf
, 0, &dt
); while (dt
.read
== 0);
1024 void ReconRefFrames (PB_INSTANCE
*pbi
){
1026 unsigned char *SwapReconBuffersTemp
;
1028 /* predictor multiplier up-left, up, up-right,left, shift
1029 Entries are packed in the order L, UL, U, UR, with missing entries
1030 moved to the end (before the shift parameters). */
1031 static const ogg_int16_t pc
[16][6]={
1033 {1,0,0,0,0,0}, /* PL */
1034 {1,0,0,0,0,0}, /* PUL */
1035 {1,0,0,0,0,0}, /* PUL|PL */
1036 {1,0,0,0,0,0}, /* PU */
1037 {1,1,0,0,1,1}, /* PU|PL */
1038 {0,1,0,0,0,0}, /* PU|PUL */
1039 {29,-26,29,0,5,31}, /* PU|PUL|PL */
1040 {1,0,0,0,0,0}, /* PUR */
1041 {75,53,0,0,7,127}, /* PUR|PL */
1042 {1,1,0,0,1,1}, /* PUR|PUL */
1043 {75,0,53,0,7,127}, /* PUR|PUL|PL */
1044 {1,0,0,0,0,0}, /* PUR|PU */
1045 {75,0,53,0,7,127}, /* PUR|PU|PL */
1046 {3,10,3,0,4,15}, /* PUR|PU|PUL */
1047 {29,-26,29,0,5,31} /* PUR|PU|PUL|PL */
1050 /* boundary case bit masks. */
1051 static const int bc_mask
[8]={
1052 /* normal case no boundary condition */
1058 /* top row, left column */
1062 /* right and left column */
1064 /* top row, right column */
1066 /* top row, right and left column */
1070 /* value left value up-left, value up, value up-right, missing
1074 /* fragment number left, up-left, up, up-right */
1077 /* predictor count. */
1081 static const short Mode2Frame
[] = {
1082 1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */
1083 0, /* CODE_INTRA 1 => DCT Encoded Block */
1084 1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */
1085 1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */
1086 1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */
1087 2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */
1088 2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */
1089 1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */
1093 int FragsAcross
=pbi
->HFragments
;
1094 int FromFragment
,ToFragment
;
1095 int FragsDown
= pbi
->VFragments
;
1101 void (*ExpandBlockA
) ( PB_INSTANCE
*pbi
, ogg_int32_t FragmentNumber
);
1103 int int1
, int2
, int3
, int4
;
1105 static int flag_first_time
= 1;
1106 int flag_first_iteration
= 1;
1112 pf
= open("/dev/theora",O_RDONLY
|O_WRONLY
|O_TRUNC
|O_CREAT
);
1116 // if ( GetFrameType(pbi) == KEY_FRAME )
1117 // ExpandBlockA=ExpandKFBlock;
1119 ExpandBlockA
=ExpandBlock
;
1121 SetupLoopFilter(pbi
);
1123 if (flag_first_time
) {
1124 flag_first_time
= 0;
1126 write_theoradriver(pf
, 0);
1127 write_theoradriver(pf
, pbi
->ReconYPlaneSize
+ 2 * pbi
->ReconUVPlaneSize
);
1128 write_theoradriver(pf
, pbi
->HFragments
);
1129 write_theoradriver(pf
, pbi
->YPlaneFragments
);
1130 write_theoradriver(pf
, pbi
->YStride
);
1131 write_theoradriver(pf
, pbi
->UVPlaneFragments
);
1132 write_theoradriver(pf
, pbi
->UVStride
);
1133 write_theoradriver(pf
, pbi
->VFragments
);
1134 write_theoradriver(pf
, pbi
->ReconYDataOffset
);
1135 write_theoradriver(pf
, pbi
->ReconUDataOffset
);
1136 write_theoradriver(pf
, pbi
->ReconVDataOffset
);
1137 write_theoradriver(pf
, pbi
->UnitFragments
);
1140 for (int1
= 0; int1
< 64; int1
++) {
1141 write_theoradriver(pf
, pbi
->QThreshTable
[int1
]);
1144 /* LoopFilterLimits */
1145 for (int1
= 0; int1
< 64; int1
=int1
+4) {
1147 for (int3
= 0; int3
< 4; int3
++) {
1149 int2
= int2
+ ((unsigned int)pbi
->LoopFilterLimits
[int1
+ int3
]);
1151 write_theoradriver(pf
, int2
);
1154 write_theoradriver(pf
, pbi
->info
.height
);
1159 for ( j
= 0; j
< 3 ; j
++) {
1160 /* pick which fragments based on Y, U, V */
1164 ToFragment
= pbi
->YPlaneFragments
;
1165 FragsAcross
= pbi
->HFragments
;
1166 FragsDown
= pbi
->VFragments
;
1169 FromFragment
= pbi
->YPlaneFragments
;
1170 ToFragment
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
1171 FragsAcross
= pbi
->HFragments
>> 1;
1172 FragsDown
= pbi
->VFragments
>> 1;
1176 FromFragment
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
1177 ToFragment
= pbi
->YPlaneFragments
+ (2 * pbi
->UVPlaneFragments
) ;
1178 FragsAcross
= pbi
->HFragments
>> 1;
1179 FragsDown
= pbi
->VFragments
>> 1;
1183 /* initialize our array of last used DC Components */
1189 /* do prediction on all of Y, U or V */
1190 for ( m
= 0 ; m
< FragsDown
; m
++) {
1191 for ( n
= 0 ; n
< FragsAcross
; n
++, i
++){
1193 /* only do 2 prediction if fragment coded and on non intra or
1194 if all fragments are intra */
1195 if( pbi
->display_fragments
[i
] || (GetFrameType(pbi
) == KEY_FRAME
) ){
1196 /* Type of Fragment */
1197 WhichFrame
= Mode2Frame
[pbi
->FragCodingMethod
[i
]];
1199 /* Check Borderline Cases */
1200 WhichCase
= (n
==0) + ((m
==0) << 1) + ((n
+1 == FragsAcross
) << 2);
1203 fn
[1]=i
-FragsAcross
-1;
1204 fn
[2]=i
-FragsAcross
;
1205 fn
[3]=i
-FragsAcross
+1;
1207 /* fragment valid for prediction use if coded and it comes
1208 from same frame as the one we are predicting */
1209 for(k
=pcount
=wpc
=0; k
<4; k
++) {
1212 if((bc_mask
[WhichCase
]&pflag
) &&
1213 pbi
->display_fragments
[fn
[k
]] &&
1214 (Mode2Frame
[pbi
->FragCodingMethod
[fn
[k
]]] == WhichFrame
)){
1215 v
[pcount
]=pbi
->QFragData
[fn
[k
]][0];
1222 /* fall back to the last coded fragment */
1223 pbi
->QFragData
[i
][0] += Last
[WhichFrame
];
1227 /* don't do divide if divisor is 1 or 0 */
1228 PredictedDC
= pc
[wpc
][0]*v
[0];
1229 for(k
=1; k
<pcount
; k
++){
1230 PredictedDC
+= pc
[wpc
][k
]*v
[k
];
1233 /* if we need to do a shift */
1234 if(pc
[wpc
][4] != 0 ){
1236 /* If negative add in the negative correction factor */
1237 PredictedDC
+= (HIGHBITDUPPED(PredictedDC
) & pc
[wpc
][5]);
1239 /* Shift in lieu of a divide */
1240 PredictedDC
>>= pc
[wpc
][4];
1243 /* check for outranging on the two predictors that can outrange */
1244 if((wpc
&(PU
|PUL
|PL
)) == (PU
|PUL
|PL
)){
1245 if( abs(PredictedDC
- v
[2]) > 128) {
1247 } else if( abs(PredictedDC
- v
[0]) > 128) {
1249 } else if( abs(PredictedDC
- v
[1]) > 128) {
1254 pbi
->QFragData
[i
][0] += PredictedDC
;
1258 /* Save the last fragment coded for whatever frame we are
1260 Last
[WhichFrame
] = pbi
->QFragData
[i
][0];
1262 if (flag_first_iteration
) {
1263 flag_first_iteration
= 0;
1264 write_theoradriver(pf
, pbi
->CodedBlockIndex
);
1265 for (int1
= 0; int1
< 64; int1
++)
1266 write_theoradriver(pf
, pbi
->dequant_Y_coeffs
[int1
]);
1267 for (int1
= 0; int1
< 64; int1
++)
1268 write_theoradriver(pf
, pbi
->dequant_U_coeffs
[int1
]);
1269 for (int1
= 0; int1
< 64; int1
++)
1270 write_theoradriver(pf
, pbi
->dequant_V_coeffs
[int1
]);
1271 for (int1
= 0; int1
< 64; int1
++)
1272 write_theoradriver(pf
, pbi
->dequant_InterY_coeffs
[int1
]);
1273 for (int1
= 0; int1
< 64; int1
++)
1274 write_theoradriver(pf
, pbi
->dequant_InterU_coeffs
[int1
]);
1275 for (int1
= 0; int1
< 64; int1
++)
1276 write_theoradriver(pf
, pbi
->dequant_InterV_coeffs
[int1
]);
1277 write_theoradriver(pf
, pbi
->FrameType
);
1280 for (int1
= 0; int1
< 64; int1
++)
1281 write_theoradriver(pf
, pbi
->QFragData
[i
][int1
]);
1282 write_theoradriver(pf
, pbi
->FragCodingMethod
[i
]);
1283 write_theoradriver(pf
, pbi
->FragCoefEOB
[i
]);
1284 write_theoradriver(pf
, pbi
->FragMVect
[i
].x
);
1285 write_theoradriver(pf
, pbi
->FragMVect
[i
].y
);
1286 write_theoradriver(pf
, i
);
1288 /* Inverse DCT and reconstitute buffer in thisframe */
1289 //ExpandBlockA( pbi, i );
1298 int2
= pbi
->UnitFragments
/ 32;
1299 for (int3
= 0; int3
< int2
; int3
++) {
1300 for (int4
= 0; int4
< 32; int4
++)
1301 int1
= (int1
<< 1) + pbi
->display_fragments
[int3
*32 + int4
];
1302 write_theoradriver(pf
, int1
);
1305 for (int1
= 0, int3
= 0; int3
< (pbi
->UnitFragments
% 32); int3
++)
1306 int1
= (int1
<< 1) + pbi
->display_fragments
[int2
*32 + int3
];
1308 if (pbi
->UnitFragments
% 32)
1309 write_theoradriver(pf
, (int1
<< (32 - (pbi
->UnitFragments
% 32))));
1311 write_theoradriver(pf
, pbi
->ThisFrameQualityValue
);
1313 /* display_fragments */
1315 /* Copy the current reconstruction back to the last frame recon buffer. */
1317 if(pbi->CodedBlockIndex > (ogg_int32_t) (pbi->UnitFragments >> 1)){
1318 SwapReconBuffersTemp = pbi->ThisFrameRecon;
1319 pbi->ThisFrameRecon = pbi->LastFrameRecon;
1320 pbi->LastFrameRecon = SwapReconBuffersTemp;
1321 CopyNotRecon( pbi, pbi->LastFrameRecon, pbi->ThisFrameRecon );
1323 CopyRecon( pbi
, pbi
->LastFrameRecon
, pbi
->ThisFrameRecon
);
1326 /* Apply a loop filter to edge pixels of updated blocks */
1329 /* We may need to update the UMV border */
1330 UpdateUMVBorder(pbi
, pbi
->LastFrameRecon
);
1332 /* Reconstruct the golden frame if necessary.
1333 For VFW codec only on key frames */
1334 if ( GetFrameType(pbi
) == KEY_FRAME
){
1335 CopyRecon( pbi
, pbi
->GoldenFrame
, pbi
->LastFrameRecon
);
1336 /* We may need to update the UMV border */
1337 UpdateUMVBorder(pbi
, pbi
->GoldenFrame
);
1340 // Reading the outputs from driver
1341 //Matriz LastFrameRecon
1342 for (int1
= 0; int1
< pbi
->LastFraRecLen
; int1
=int1
+4) {
1344 for (int2
= 0; int2
< 4; int2
++) {
1346 int3
= int3
+ ((unsigned int)pbi
->LastFrameRecon
[int1
+ int2
]);
1352 if (ioctl(pf
, 1, &dt
) < 0) {
1353 printf("ERROR: ioctl(0,&a) failed\n");
1356 } while (dt
.wrote
== 0);
1357 printf("saida = soft %d : hard %d\n", int3
, dt
.data
);