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