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"
21 #include "encoder_lookup.h"
22 #include "block_inline.h"
28 #define HIGHBITDUPPED(X) (((ogg_int16_t) X) >> 15)
30 static ogg_uint32_t
QuadCodeComponent ( CP_INSTANCE
*cpi
,
34 ogg_uint32_t PixelsPerLine
){
36 ogg_int32_t FragIndex
; /* Fragment number */
37 ogg_uint32_t MB
, B
; /* Macro-Block, Block indices */
38 ogg_uint32_t SBrow
; /* Super-Block row number */
39 ogg_uint32_t SBcol
; /* Super-Block row number */
40 ogg_uint32_t SB
=FirstSB
; /* Super-Block index, initialised to first
42 ogg_uint32_t coded_pixels
=0; /* Number of pixels coded */
45 /* actually transform and quantize the image now that we've decided
46 on the modes Parse in quad-tree ordering */
49 for ( SBrow
=0; SBrow
<SBRows
; SBrow
++ ) {
50 for ( SBcol
=0; SBcol
<SBCols
; SBcol
++ ) {
51 /* Check its four Macro-Blocks */
52 for ( MB
=0; MB
<4; MB
++ ) {
54 if ( QuadMapToMBTopLeft(cpi
->pb
.BlockMap
,SB
,MB
) >= 0 ) {
58 /* Now actually code the blocks */
59 for ( B
=0; B
<4; B
++ ) {
60 FragIndex
= QuadMapToIndex1( cpi
->pb
.BlockMap
, SB
, MB
, B
);
62 /* Does Block lie in frame: */
63 if ( FragIndex
>= 0 ) {
64 /* In Frame: Is it coded: */
65 if ( cpi
->pb
.display_fragments
[FragIndex
] ) {
67 /* transform and quantize block */
68 TransformQuantizeBlock( cpi
, FragIndex
, PixelsPerLine
);
70 /* Has the block got struck off (no MV and no data
71 generated after DCT) If not then mark it and the
72 assosciated MB as coded. */
73 if ( cpi
->pb
.display_fragments
[FragIndex
] ) {
74 /* Create linear list of coded block indices */
75 cpi
->pb
.CodedBlockList
[cpi
->pb
.CodedBlockIndex
] = FragIndex
;
76 cpi
->pb
.CodedBlockIndex
++;
78 /* MB is still coded */
80 cpi
->MBCodingMode
= cpi
->pb
.FragCodingMethod
[FragIndex
];
86 /* If the MB is marked as coded and we are in the Y plane then */
87 /* the mode list needs to be updated. */
88 if ( MBCodedFlag
&& (FirstSB
== 0) ){
89 /* Make a note of the selected mode in the mode list */
90 cpi
->ModeList
[cpi
->ModeListCount
] = cpi
->MBCodingMode
;
101 /* Return number of pixels coded */
105 static void EncodeDcTokenList (CP_INSTANCE
*cpi
) {
108 ogg_uint32_t ExtraBitsToken
;
109 ogg_uint32_t HuffIndex
;
111 ogg_uint32_t BestDcBits
;
112 ogg_uint32_t DcHuffChoice
[2];
113 ogg_uint32_t EntropyTableBits
[2][DC_HUFF_CHOICES
];
115 oggpack_buffer
*opb
=cpi
->oggbuffer
;
117 /* Clear table data structure */
118 memset ( EntropyTableBits
, 0, sizeof(ogg_uint32_t
)*DC_HUFF_CHOICES
*2 );
120 /* Analyse token list to see which is the best entropy table to use */
121 for ( i
= 0; i
< cpi
->OptimisedTokenCount
; i
++ ) {
122 /* Count number of bits for each table option */
123 Token
= (ogg_uint32_t
)cpi
->OptimisedTokenList
[i
];
124 for ( j
= 0; j
< DC_HUFF_CHOICES
; j
++ ){
125 EntropyTableBits
[cpi
->OptimisedTokenListPl
[i
]][j
] +=
126 cpi
->pb
.HuffCodeLengthArray_VP3x
[DC_HUFF_OFFSET
+ j
][Token
];
130 /* Work out which table option is best for Y */
131 BestDcBits
= EntropyTableBits
[0][0];
133 for ( j
= 1; j
< DC_HUFF_CHOICES
; j
++ ) {
134 if ( EntropyTableBits
[0][j
] < BestDcBits
) {
135 BestDcBits
= EntropyTableBits
[0][j
];
140 /* Add the DC huffman table choice to the bitstream */
141 oggpackB_write( opb
, DcHuffChoice
[0], DC_HUFF_CHOICE_BITS
);
143 /* Work out which table option is best for UV */
144 BestDcBits
= EntropyTableBits
[1][0];
146 for ( j
= 1; j
< DC_HUFF_CHOICES
; j
++ ) {
147 if ( EntropyTableBits
[1][j
] < BestDcBits
) {
148 BestDcBits
= EntropyTableBits
[1][j
];
153 /* Add the DC huffman table choice to the bitstream */
154 oggpackB_write( opb
, DcHuffChoice
[1], DC_HUFF_CHOICE_BITS
);
156 /* Encode the token list */
157 for ( i
= 0; i
< cpi
->OptimisedTokenCount
; i
++ ) {
159 /* Get the token and extra bits */
160 Token
= (ogg_uint32_t
)cpi
->OptimisedTokenList
[i
];
161 ExtraBitsToken
= (ogg_uint32_t
)cpi
->OptimisedTokenListEb
[i
];
163 /* Select the huffman table */
164 if ( cpi
->OptimisedTokenListPl
[i
] == 0)
165 HuffIndex
= (ogg_uint32_t
)DC_HUFF_OFFSET
+ (ogg_uint32_t
)DcHuffChoice
[0];
167 HuffIndex
= (ogg_uint32_t
)DC_HUFF_OFFSET
+ (ogg_uint32_t
)DcHuffChoice
[1];
169 /* Add the bits to the encode holding buffer. */
170 cpi
->FrameBitCount
+= cpi
->pb
.HuffCodeLengthArray_VP3x
[HuffIndex
][Token
];
171 oggpackB_write( opb
, cpi
->pb
.HuffCodeArray_VP3x
[HuffIndex
][Token
],
173 pb
.HuffCodeLengthArray_VP3x
[HuffIndex
][Token
] );
175 /* If the token is followed by an extra bits token then code it */
176 if ( cpi
->pb
.ExtraBitLengths_VP3x
[Token
] > 0 ) {
177 /* Add the bits to the encode holding buffer. */
178 cpi
->FrameBitCount
+= cpi
->pb
.ExtraBitLengths_VP3x
[Token
];
179 oggpackB_write( opb
, ExtraBitsToken
,
180 (ogg_uint32_t
)cpi
->pb
.ExtraBitLengths_VP3x
[Token
] );
184 /* Reset the count of second order optimised tokens */
185 cpi
->OptimisedTokenCount
= 0;
188 static void EncodeAcTokenList (CP_INSTANCE
*cpi
) {
191 ogg_uint32_t ExtraBitsToken
;
192 ogg_uint32_t HuffIndex
;
194 ogg_uint32_t BestAcBits
;
195 ogg_uint32_t AcHuffChoice
[2];
196 ogg_uint32_t EntropyTableBits
[2][AC_HUFF_CHOICES
];
198 oggpack_buffer
*opb
=cpi
->oggbuffer
;
200 memset ( EntropyTableBits
, 0, sizeof(ogg_uint32_t
)*AC_HUFF_CHOICES
*2 );
202 /* Analyse token list to see which is the best entropy table to use */
203 for ( i
= 0; i
< cpi
->OptimisedTokenCount
; i
++ ) {
204 /* Count number of bits for each table option */
205 Token
= (ogg_uint32_t
)cpi
->OptimisedTokenList
[i
];
206 HuffIndex
= cpi
->OptimisedTokenListHi
[i
];
207 for ( j
= 0; j
< AC_HUFF_CHOICES
; j
++ ) {
208 EntropyTableBits
[cpi
->OptimisedTokenListPl
[i
]][j
] +=
209 cpi
->pb
.HuffCodeLengthArray_VP3x
[HuffIndex
+ j
][Token
];
213 /* Select the best set of AC tables for Y */
214 BestAcBits
= EntropyTableBits
[0][0];
216 for ( j
= 1; j
< AC_HUFF_CHOICES
; j
++ ) {
217 if ( EntropyTableBits
[0][j
] < BestAcBits
) {
218 BestAcBits
= EntropyTableBits
[0][j
];
223 /* Add the AC-Y huffman table choice to the bitstream */
224 oggpackB_write( opb
, AcHuffChoice
[0], AC_HUFF_CHOICE_BITS
);
226 /* Select the best set of AC tables for UV */
227 BestAcBits
= EntropyTableBits
[1][0];
229 for ( j
= 1; j
< AC_HUFF_CHOICES
; j
++ ) {
230 if ( EntropyTableBits
[1][j
] < BestAcBits
) {
231 BestAcBits
= EntropyTableBits
[1][j
];
236 /* Add the AC-UV huffman table choice to the bitstream */
237 oggpackB_write( opb
, AcHuffChoice
[1], AC_HUFF_CHOICE_BITS
);
239 /* Encode the token list */
240 for ( i
= 0; i
< cpi
->OptimisedTokenCount
; i
++ ) {
241 /* Get the token and extra bits */
242 Token
= (ogg_uint32_t
)cpi
->OptimisedTokenList
[i
];
243 ExtraBitsToken
= (ogg_uint32_t
)cpi
->OptimisedTokenListEb
[i
];
245 /* Select the huffman table */
246 HuffIndex
= (ogg_uint32_t
)cpi
->OptimisedTokenListHi
[i
] +
247 AcHuffChoice
[cpi
->OptimisedTokenListPl
[i
]];
249 /* Add the bits to the encode holding buffer. */
250 cpi
->FrameBitCount
+= cpi
->pb
.HuffCodeLengthArray_VP3x
[HuffIndex
][Token
];
251 oggpackB_write( opb
, cpi
->pb
.HuffCodeArray_VP3x
[HuffIndex
][Token
],
253 pb
.HuffCodeLengthArray_VP3x
[HuffIndex
][Token
] );
255 /* If the token is followed by an extra bits token then code it */
256 if ( cpi
->pb
.ExtraBitLengths_VP3x
[Token
] > 0 ) {
257 /* Add the bits to the encode holding buffer. */
258 cpi
->FrameBitCount
+= cpi
->pb
.ExtraBitLengths_VP3x
[Token
];
259 oggpackB_write( opb
, ExtraBitsToken
,
260 (ogg_uint32_t
)cpi
->pb
.ExtraBitLengths_VP3x
[Token
] );
264 /* Reset the count of second order optimised tokens */
265 cpi
->OptimisedTokenCount
= 0;
268 static void PackModes (CP_INSTANCE
*cpi
) {
270 unsigned char ModeIndex
;
271 unsigned char *SchemeList
;
273 unsigned char BestModeSchemes
[MAX_MODES
];
274 ogg_int32_t ModeCount
[MAX_MODES
];
275 ogg_int32_t TmpFreq
= -1;
276 ogg_int32_t TmpIndex
= -1;
278 ogg_uint32_t BestScheme
;
279 ogg_uint32_t BestSchemeScore
;
280 ogg_uint32_t SchemeScore
;
282 oggpack_buffer
*opb
=cpi
->oggbuffer
;
284 /* Build a frequency map for the modes in this frame */
285 memset( ModeCount
, 0, MAX_MODES
*sizeof(ogg_int32_t
) );
286 for ( i
= 0; i
< cpi
->ModeListCount
; i
++ )
287 ModeCount
[cpi
->ModeList
[i
]] ++;
289 /* Order the modes from most to least frequent. Store result as
291 for ( j
= 0; j
< MAX_MODES
; j
++ ) {
292 TmpFreq
= -1; /* need to re-initialize for each loop */
293 /* Find the most frequent */
294 for ( i
= 0; i
< MAX_MODES
; i
++ ) {
295 /* Is this the best scheme so far ??? */
296 if ( ModeCount
[i
] > TmpFreq
) {
297 TmpFreq
= ModeCount
[i
];
301 /* I don't know if the above loop ever fails to match, but it's
302 better safe than sorry. Plus this takes care of gcc warning */
303 if ( TmpIndex
!= -1 ) {
304 ModeCount
[TmpIndex
] = -1;
305 BestModeSchemes
[TmpIndex
] = (unsigned char)j
;
309 /* Default/ fallback scheme uses MODE_BITS bits per mode entry */
310 BestScheme
= (MODE_METHODS
- 1);
311 BestSchemeScore
= cpi
->ModeListCount
* 3;
312 /* Get a bit score for the available schemes. */
313 for ( j
= 0; j
< (MODE_METHODS
- 1); j
++ ) {
315 /* Reset the scheme score */
317 /* Scheme 0 additional cost of sending frequency order */
319 SchemeList
= BestModeSchemes
;
322 SchemeList
= ModeSchemes
[j
-1];
325 /* Find the total bits to code using each avaialable scheme */
326 for ( i
= 0; i
< cpi
->ModeListCount
; i
++ )
327 SchemeScore
+= ModeBitLengths
[SchemeList
[cpi
->ModeList
[i
]]];
329 /* Is this the best scheme so far ??? */
330 if ( SchemeScore
< BestSchemeScore
) {
331 BestSchemeScore
= SchemeScore
;
336 /* Encode the best scheme. */
337 oggpackB_write( opb
, BestScheme
, (ogg_uint32_t
)MODE_METHOD_BITS
);
339 /* If the chosen schems is scheme 0 send details of the mode
341 if ( BestScheme
== 0 ) {
342 for ( j
= 0; j
< MAX_MODES
; j
++ )
343 /* Note that the last two entries are implicit */
344 oggpackB_write( opb
, BestModeSchemes
[j
], (ogg_uint32_t
)MODE_BITS
);
345 SchemeList
= BestModeSchemes
;
348 SchemeList
= ModeSchemes
[BestScheme
-1];
351 /* Are we using one of the alphabet based schemes or the fallback scheme */
352 if ( BestScheme
< (MODE_METHODS
- 1)) {
353 /* Pack and encode the Mode list */
354 for ( i
= 0; i
< cpi
->ModeListCount
; i
++ ) {
355 /* Add the appropriate mode entropy token. */
356 ModeIndex
= SchemeList
[cpi
->ModeList
[i
]];
357 oggpackB_write( opb
, ModeBitPatterns
[ModeIndex
],
358 (ogg_uint32_t
)ModeBitLengths
[ModeIndex
] );
361 /* Fall back to MODE_BITS per entry */
362 for ( i
= 0; i
< cpi
->ModeListCount
; i
++ ) {
363 /* Add the appropriate mode entropy token. */
364 oggpackB_write( opb
, cpi
->ModeList
[i
], MODE_BITS
);
369 static void PackMotionVectors (CP_INSTANCE
*cpi
) {
371 ogg_uint32_t MethodBits
[2] = {0,0};
372 ogg_uint32_t
* MvBitsPtr
;
373 ogg_uint32_t
* MvPatternPtr
;
375 oggpack_buffer
*opb
=cpi
->oggbuffer
;
377 /* Choose the coding method */
378 MvBitsPtr
= &MvBits
[MAX_MV_EXTENT
];
379 for ( i
= 0; i
< (ogg_int32_t
)cpi
->MvListCount
; i
++ ) {
380 MethodBits
[0] += MvBitsPtr
[cpi
->MVList
[i
].x
];
381 MethodBits
[0] += MvBitsPtr
[cpi
->MVList
[i
].y
];
382 MethodBits
[1] += 12; /* Simple six bits per mv component fallback
386 /* Select entropy table */
387 if ( MethodBits
[0] < MethodBits
[1] ) {
388 oggpackB_write( opb
, 0, 1 );
389 MvBitsPtr
= &MvBits
[MAX_MV_EXTENT
];
390 MvPatternPtr
= &MvPattern
[MAX_MV_EXTENT
];
392 oggpackB_write( opb
, 1, 1 );
393 MvBitsPtr
= &MvBits2
[MAX_MV_EXTENT
];
394 MvPatternPtr
= &MvPattern2
[MAX_MV_EXTENT
];
397 /* Pack and encode the motion vectors */
398 for ( i
= 0; i
< (ogg_int32_t
)cpi
->MvListCount
; i
++ ) {
399 oggpackB_write( opb
, MvPatternPtr
[cpi
->MVList
[i
].x
],
400 (ogg_uint32_t
)MvBitsPtr
[cpi
->MVList
[i
].x
] );
401 oggpackB_write( opb
, MvPatternPtr
[cpi
->MVList
[i
].y
],
402 (ogg_uint32_t
)MvBitsPtr
[cpi
->MVList
[i
].y
] );
406 static void PackEOBRun( CP_INSTANCE
*cpi
) {
407 if(cpi
->RunLength
== 0)
410 /* Note the appropriate EOB or EOB run token and any extra bits in
411 the optimised token list. Use the huffman index assosciated with
412 the first token in the run */
414 /* Mark out which plane the block belonged to */
415 cpi
->OptimisedTokenListPl
[cpi
->OptimisedTokenCount
] =
416 (unsigned char)cpi
->RunPlaneIndex
;
418 /* Note the huffman index to be used */
419 cpi
->OptimisedTokenListHi
[cpi
->OptimisedTokenCount
] =
420 (unsigned char)cpi
->RunHuffIndex
;
422 if ( cpi
->RunLength
<= 3 ) {
423 if ( cpi
->RunLength
== 1 ) {
424 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] = DCT_EOB_TOKEN
;
425 } else if ( cpi
->RunLength
== 2 ) {
426 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] = DCT_EOB_PAIR_TOKEN
;
428 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] = DCT_EOB_TRIPLE_TOKEN
;
435 /* Choose a token appropriate to the run length. */
436 if ( cpi
->RunLength
< 8 ) {
437 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] =
438 DCT_REPEAT_RUN_TOKEN
;
439 cpi
->OptimisedTokenListEb
[cpi
->OptimisedTokenCount
] =
442 } else if ( cpi
->RunLength
< 16 ) {
443 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] =
444 DCT_REPEAT_RUN2_TOKEN
;
445 cpi
->OptimisedTokenListEb
[cpi
->OptimisedTokenCount
] =
448 } else if ( cpi
->RunLength
< 32 ) {
449 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] =
450 DCT_REPEAT_RUN3_TOKEN
;
451 cpi
->OptimisedTokenListEb
[cpi
->OptimisedTokenCount
] =
454 } else if ( cpi
->RunLength
< 4096) {
455 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] =
456 DCT_REPEAT_RUN4_TOKEN
;
457 cpi
->OptimisedTokenListEb
[cpi
->OptimisedTokenCount
] =
464 cpi
->OptimisedTokenCount
++;
465 /* Reset run EOB length */
469 static void PackToken ( CP_INSTANCE
*cpi
, ogg_int32_t FragmentNumber
,
470 ogg_uint32_t HuffIndex
) {
472 cpi
->pb
.TokenList
[FragmentNumber
][cpi
->FragTokens
[FragmentNumber
]];
473 ogg_uint32_t ExtraBitsToken
=
474 cpi
->pb
.TokenList
[FragmentNumber
][cpi
->FragTokens
[FragmentNumber
] + 1];
475 ogg_uint32_t OneOrTwo
;
476 ogg_uint32_t OneOrZero
;
478 /* Update the record of what coefficient we have got up to for this
479 block and unpack the encoded token back into the quantised data
481 if ( Token
== DCT_EOB_TOKEN
)
482 cpi
->pb
.FragCoeffs
[FragmentNumber
] = BLOCK_SIZE
;
484 ExpandToken( cpi
->pb
.QFragData
[FragmentNumber
],
485 &cpi
->pb
.FragCoeffs
[FragmentNumber
],
486 Token
, ExtraBitsToken
);
488 /* Update record of tokens coded and where we are in this fragment. */
489 /* Is there an extra bits token */
490 OneOrTwo
= 1 + ( cpi
->pb
.ExtraBitLengths_VP3x
[Token
] > 0 );
491 /* Advance to the next real token. */
492 cpi
->FragTokens
[FragmentNumber
] += (unsigned char)OneOrTwo
;
494 /* Update the counts of tokens coded */
495 cpi
->TokensCoded
+= OneOrTwo
;
496 cpi
->TokensToBeCoded
-= OneOrTwo
;
498 OneOrZero
= ( FragmentNumber
< (ogg_int32_t
)cpi
->pb
.YPlaneFragments
);
500 if ( Token
== DCT_EOB_TOKEN
) {
501 if ( cpi
->RunLength
== 0 ) {
502 cpi
->RunHuffIndex
= HuffIndex
;
503 cpi
->RunPlaneIndex
= 1 - OneOrZero
;
507 /* we have exceeded our longest run length xmit an eob run token; */
508 if ( cpi
->RunLength
== 4095 ) PackEOBRun(cpi
);
512 /* If we have an EOB run then code it up first */
513 if ( cpi
->RunLength
> 0 ) PackEOBRun( cpi
);
515 /* Mark out which plane the block belonged to */
516 cpi
->OptimisedTokenListPl
[cpi
->OptimisedTokenCount
] =
517 (unsigned char)(1 - OneOrZero
);
519 /* Note the token, extra bits and hufman table in the optimised
521 cpi
->OptimisedTokenList
[cpi
->OptimisedTokenCount
] =
522 (unsigned char)Token
;
523 cpi
->OptimisedTokenListEb
[cpi
->OptimisedTokenCount
] =
525 cpi
->OptimisedTokenListHi
[cpi
->OptimisedTokenCount
] =
526 (unsigned char)HuffIndex
;
528 cpi
->OptimisedTokenCount
++;
532 static ogg_uint32_t
GetBlockReconErrorSlow( CP_INSTANCE
*cpi
,
533 ogg_int32_t BlockIndex
) {
534 ogg_uint32_t ErrorVal
;
536 unsigned char * SrcDataPtr
=
537 &cpi
->ConvDestBuffer
[cpi
->pb
.pixel_index_table
[BlockIndex
]];
538 unsigned char * RecDataPtr
=
539 &cpi
->pb
.LastFrameRecon
[cpi
->pb
.recon_pixel_index_table
[BlockIndex
]];
540 ogg_int32_t SrcStride
;
541 ogg_int32_t RecStride
;
543 /* Is the block a Y block or a UV block. */
544 if ( BlockIndex
< (ogg_int32_t
)cpi
->pb
.YPlaneFragments
) {
545 SrcStride
= cpi
->pb
.info
.width
;
546 RecStride
= cpi
->pb
.YStride
;
548 SrcStride
= cpi
->pb
.info
.width
>> 1;
549 RecStride
= cpi
->pb
.UVStride
;
552 ErrorVal
= dsp_sad8x8 (cpi
->dsp
, SrcDataPtr
, SrcStride
, RecDataPtr
, RecStride
);
557 static void PackCodedVideo (CP_INSTANCE
*cpi
) {
559 ogg_int32_t EncodedCoeffs
= 1;
560 ogg_int32_t FragIndex
;
561 ogg_uint32_t HuffIndex
; /* Index to group of tables used to code a token */
563 /* Reset the count of second order optimised tokens */
564 cpi
->OptimisedTokenCount
= 0;
566 cpi
->TokensToBeCoded
= cpi
->TotTokenCount
;
567 cpi
->TokensCoded
= 0;
569 /* Calculate the bit rate at which this frame should be capped. */
570 cpi
->MaxBitTarget
= (ogg_uint32_t
)((double)(cpi
->ThisFrameTargetBytes
* 8) *
571 cpi
->BitRateCapFactor
);
573 /* Blank the various fragment data structures before we start. */
574 memset(cpi
->pb
.FragCoeffs
, 0, cpi
->pb
.UnitFragments
);
575 memset(cpi
->FragTokens
, 0, cpi
->pb
.UnitFragments
);
577 /* Clear down the QFragData structure for all coded blocks. */
578 ClearDownQFragData(&cpi
->pb
);
580 /* The tree is not needed (implicit) for key frames */
581 if ( GetFrameType(&cpi
->pb
) != KEY_FRAME
){
582 /* Pack the quad tree fragment mapping. */
583 PackAndWriteDFArray( cpi
);
586 /* Note the number of bits used to code the tree itself. */
587 cpi
->FrameBitCount
= oggpackB_bytes(cpi
->oggbuffer
) << 3;
589 /* Mode and MV data not needed for key frames. */
590 if ( GetFrameType(&cpi
->pb
) != KEY_FRAME
){
591 /* Pack and code the mode list. */
593 /* Pack the motion vectors */
594 PackMotionVectors (cpi
);
597 cpi
->FrameBitCount
= oggpackB_bytes(cpi
->oggbuffer
) << 3;
599 /* Optimise the DC tokens */
600 for ( i
= 0; i
< cpi
->pb
.CodedBlockIndex
; i
++ ) {
601 /* Get the linear index for the current fragment. */
602 FragIndex
= cpi
->pb
.CodedBlockList
[i
];
604 cpi
->pb
.FragCoefEOB
[FragIndex
]=(unsigned char)EncodedCoeffs
;
605 PackToken(cpi
, FragIndex
, DC_HUFF_OFFSET
);
609 /* Pack any outstanding EOB tokens */
612 /* Now output the optimised DC token list using the appropriate
614 EncodeDcTokenList(cpi
);
616 /* Work out the number of DC bits coded */
618 /* Optimise the AC tokens */
619 while ( EncodedCoeffs
< 64 ) {
620 /* Huffman table adjustment based upon coefficient number. */
621 if ( EncodedCoeffs
<= AC_TABLE_2_THRESH
)
622 HuffIndex
= AC_HUFF_OFFSET
;
623 else if ( EncodedCoeffs
<= AC_TABLE_3_THRESH
)
624 HuffIndex
= AC_HUFF_OFFSET
+ AC_HUFF_CHOICES
;
625 else if ( EncodedCoeffs
<= AC_TABLE_4_THRESH
)
626 HuffIndex
= AC_HUFF_OFFSET
+ (AC_HUFF_CHOICES
* 2);
628 HuffIndex
= AC_HUFF_OFFSET
+ (AC_HUFF_CHOICES
* 3);
630 /* Repeatedly scan through the list of blocks. */
631 for ( i
= 0; i
< cpi
->pb
.CodedBlockIndex
; i
++ ) {
632 /* Get the linear index for the current fragment. */
633 FragIndex
= cpi
->pb
.CodedBlockList
[i
];
635 /* Should we code a token for this block on this pass. */
636 if ( cpi
->FragTokens
[FragIndex
] < cpi
->FragTokenCounts
[FragIndex
]
637 && cpi
->pb
.FragCoeffs
[FragIndex
] <= EncodedCoeffs
) {
638 /* Bit pack and a token for this block */
639 cpi
->pb
.FragCoefEOB
[FragIndex
]=(unsigned char)EncodedCoeffs
;
640 PackToken( cpi
, FragIndex
, HuffIndex
);
647 /* Pack any outstanding EOB tokens */
650 /* Now output the optimised AC token list using the appropriate
652 EncodeAcTokenList(cpi
);
656 static ogg_uint32_t
QuadCodeDisplayFragments (CP_INSTANCE
*cpi
) {
658 ogg_uint32_t coded_pixels
=0;
662 /* predictor multiplier up-left, up, up-right,left, shift
663 Entries are packed in the order L, UL, U, UR, with missing entries
664 moved to the end (before the shift parameters). */
665 static const ogg_int16_t pc
[16][6]={
667 {1,0,0,0,0,0}, /* PL */
668 {1,0,0,0,0,0}, /* PUL */
669 {1,0,0,0,0,0}, /* PUL|PL */
670 {1,0,0,0,0,0}, /* PU */
671 {1,1,0,0,1,1}, /* PU|PL */
672 {0,1,0,0,0,0}, /* PU|PUL */
673 {29,-26,29,0,5,31}, /* PU|PUL|PL */
674 {1,0,0,0,0,0}, /* PUR */
675 {75,53,0,0,7,127}, /* PUR|PL */
676 {1,1,0,0,1,1}, /* PUR|PUL */
677 {75,0,53,0,7,127}, /* PUR|PUL|PL */
678 {1,0,0,0,0,0}, /* PUR|PU */
679 {75,0,53,0,7,127}, /* PUR|PU|PL */
680 {3,10,3,0,4,15}, /* PUR|PU|PUL */
681 {29,-26,29,0,5,31} /* PUR|PU|PUL|PL */
684 /* boundary case bit masks. */
685 static const int bc_mask
[8]={
686 /* normal case no boundary condition */
692 /* top row, left column */
696 /* right and left column */
698 /* top row, right column */
700 /* top row, right and left column */
704 /* value left value up-left, value up, value up-right, missing
708 /* fragment number left, up-left, up, up-right */
711 /* predictor count. */
714 /*which predictor constants to use */
717 /* last used inter predictor (Raster Order) */
718 ogg_int16_t Last
[3]; /* last value used for given frame */
720 int FragsAcross
=cpi
->pb
.HFragments
;
721 int FragsDown
= cpi
->pb
.VFragments
;
722 int FromFragment
,ToFragment
;
723 ogg_int32_t FragIndex
;
727 static const ogg_int16_t Mode2Frame
[] = {
728 1, /* CODE_INTER_NO_MV 0 => Encoded diff from same MB last frame */
729 0, /* CODE_INTRA 1 => DCT Encoded Block */
730 1, /* CODE_INTER_PLUS_MV 2 => Encoded diff from included MV MB last frame */
731 1, /* CODE_INTER_LAST_MV 3 => Encoded diff from MRU MV MB last frame */
732 1, /* CODE_INTER_PRIOR_MV 4 => Encoded diff from included 4 separate MV blocks */
733 2, /* CODE_USING_GOLDEN 5 => Encoded diff from same MB golden frame */
734 2, /* CODE_GOLDEN_MV 6 => Encoded diff from included MV MB golden frame */
735 1 /* CODE_INTER_FOUR_MV 7 => Encoded diff from included 4 separate MV blocks */
738 ogg_int16_t PredictedDC
;
740 /* Initialise the coded block indices variables. These allow
741 subsequent linear access to the quad tree ordered list of coded
743 cpi
->pb
.CodedBlockIndex
= 0;
745 /* Set the inter/intra descision control variables. */
746 QIndex
= Q_TABLE_SIZE
- 1;
747 while ( QIndex
>= 0 ) {
748 if ( (QIndex
== 0) ||
749 ( cpi
->pb
.QThreshTable
[QIndex
] >= cpi
->pb
.ThisFrameQualityValue
) )
755 /* Encode and tokenise the Y, U and V components */
756 coded_pixels
= QuadCodeComponent(cpi
, 0, cpi
->pb
.YSBRows
, cpi
->pb
.YSBCols
,
757 cpi
->pb
.info
.width
);
758 coded_pixels
+= QuadCodeComponent(cpi
, cpi
->pb
.YSuperBlocks
,
761 cpi
->pb
.info
.width
>>1 );
762 coded_pixels
+= QuadCodeComponent(cpi
,
763 cpi
->pb
.YSuperBlocks
+cpi
->pb
.UVSuperBlocks
,
764 cpi
->pb
.UVSBRows
, cpi
->pb
.UVSBCols
,
765 cpi
->pb
.info
.width
>>1 );
768 for ( j
= 0; j
< 3 ; j
++) {
769 /* pick which fragments based on Y, U, V */
773 ToFragment
= cpi
->pb
.YPlaneFragments
;
774 FragsAcross
= cpi
->pb
.HFragments
;
775 FragsDown
= cpi
->pb
.VFragments
;
778 FromFragment
= cpi
->pb
.YPlaneFragments
;
779 ToFragment
= cpi
->pb
.YPlaneFragments
+ cpi
->pb
.UVPlaneFragments
;
780 FragsAcross
= cpi
->pb
.HFragments
>> 1;
781 FragsDown
= cpi
->pb
.VFragments
>> 1;
785 FromFragment
= cpi
->pb
.YPlaneFragments
+ cpi
->pb
.UVPlaneFragments
;
786 ToFragment
= cpi
->pb
.YPlaneFragments
+ (2 * cpi
->pb
.UVPlaneFragments
) ;
787 FragsAcross
= cpi
->pb
.HFragments
>> 1;
788 FragsDown
= cpi
->pb
.VFragments
>> 1;
792 /* initialize our array of last used DC Components */
793 for(k
=0;k
<3;k
++)Last
[k
]=0;
796 /* do prediction on all of Y, U or V */
797 for ( m
= 0 ; m
< FragsDown
; m
++) {
798 for ( n
= 0 ; n
< FragsAcross
; n
++, i
++) {
799 cpi
->OriginalDC
[i
] = cpi
->pb
.QFragData
[i
][0];
801 /* only do 2 prediction if fragment coded and on non intra or
802 if all fragments are intra */
803 if( cpi
->pb
.display_fragments
[i
] ||
804 (GetFrameType(&cpi
->pb
) == KEY_FRAME
) ) {
805 /* Type of Fragment */
806 WhichFrame
= Mode2Frame
[cpi
->pb
.FragCodingMethod
[i
]];
808 /* Check Borderline Cases */
809 WhichCase
= (n
==0) + ((m
==0) << 1) + ((n
+1 == FragsAcross
) << 2);
812 fn
[1]=i
-FragsAcross
-1;
814 fn
[3]=i
-FragsAcross
+1;
816 /* fragment valid for prediction use if coded and it comes
817 from same frame as the one we are predicting */
818 for(k
=pcount
=wpc
=0; k
<4; k
++) {
821 if((bc_mask
[WhichCase
]&pflag
) &&
822 cpi
->pb
.display_fragments
[fn
[k
]] &&
823 (Mode2Frame
[cpi
->pb
.FragCodingMethod
[fn
[k
]]] == WhichFrame
)){
824 v
[pcount
]=cpi
->OriginalDC
[fn
[k
]];
832 /* fall back to the last coded fragment */
833 cpi
->pb
.QFragData
[i
][0] -= Last
[WhichFrame
];
837 /* don't do divide if divisor is 1 or 0 */
838 PredictedDC
= pc
[wpc
][0]*v
[0];
839 for(k
=1; k
<pcount
; k
++){
840 PredictedDC
+= pc
[wpc
][k
]*v
[k
];
843 /* if we need to do a shift */
844 if(pc
[wpc
][4] != 0 ) {
846 /* If negative add in the negative correction factor */
847 PredictedDC
+= (HIGHBITDUPPED(PredictedDC
) & pc
[wpc
][5]);
848 /* Shift in lieu of a divide */
849 PredictedDC
>>= pc
[wpc
][4];
853 /* check for outranging on the two predictors that can outrange */
854 if((wpc
&(PU
|PUL
|PL
)) == (PU
|PUL
|PL
)){
855 if( abs(PredictedDC
- v
[2]) > 128) {
857 } else if( abs(PredictedDC
- v
[0]) > 128) {
859 } else if( abs(PredictedDC
- v
[1]) > 128) {
864 cpi
->pb
.QFragData
[i
][0] -= PredictedDC
;
867 /* Save the last fragment coded for whatever frame we are
870 Last
[WhichFrame
] = cpi
->OriginalDC
[i
];
877 /* Pack DC tokens and adjust the ones we couldn't predict 2d */
878 for ( i
= 0; i
< cpi
->pb
.CodedBlockIndex
; i
++ ) {
879 /* Get the linear index for the current coded fragment. */
880 FragIndex
= cpi
->pb
.CodedBlockList
[i
];
881 coded_pixels
+= DPCMTokenizeBlock ( cpi
, FragIndex
);
886 /* Bit pack the video data data */
889 /* End the bit packing run. */
890 /* EndAddBitsToBuffer(cpi); */
892 /* Reconstruct the reference frames */
893 ReconRefFrames(&cpi
->pb
);
895 UpdateFragQIndex(&cpi
->pb
);
897 /* Measure the inter reconstruction error for all the blocks that
899 /* for use as part of the recovery monitoring process in subsequent frames. */
900 for ( i
= 0; i
< cpi
->pb
.CodedBlockIndex
; i
++ ) {
901 cpi
->LastCodedErrorScore
[ cpi
->pb
.CodedBlockList
[i
] ] =
902 GetBlockReconErrorSlow( cpi
, cpi
->pb
.CodedBlockList
[i
] );
906 /* Return total number of coded pixels */
910 ogg_uint32_t
EncodeData(CP_INSTANCE
*cpi
){
911 ogg_uint32_t coded_pixels
= 0;
913 /* Zero the count of tokens so far this frame. */
914 cpi
->TotTokenCount
= 0;
916 /* Zero the mode and MV list indices. */
917 cpi
->ModeListCount
= 0;
919 /* Zero Decoder EOB run count */
922 dsp_save_fpu (cpi
->dsp
);
924 /* Encode any fragments coded using DCT. */
925 coded_pixels
+= QuadCodeDisplayFragments (cpi
);
927 dsp_restore_fpu (cpi
->dsp
);
933 ogg_uint32_t
PickIntra( CP_INSTANCE
*cpi
,
935 ogg_uint32_t SBCols
){
937 ogg_int32_t FragIndex
; /* Fragment number */
938 ogg_uint32_t MB
, B
; /* Macro-Block, Block indices */
939 ogg_uint32_t SBrow
; /* Super-Block row number */
940 ogg_uint32_t SBcol
; /* Super-Block row number */
941 ogg_uint32_t SB
=0; /* Super-Block index, initialised to first of
945 ogg_uint32_t UVColumn
;
946 ogg_uint32_t UVFragOffset
;
948 /* decide what block type and motion vectors to use on all of the frames */
949 for ( SBrow
=0; SBrow
<SBRows
; SBrow
++ ) {
950 for ( SBcol
=0; SBcol
<SBCols
; SBcol
++ ) {
951 /* Check its four Macro-Blocks */
952 for ( MB
=0; MB
<4; MB
++ ) {
953 /* There may be MB's lying out of frame which must be
954 ignored. For these MB's Top left block will have a negative
956 if ( QuadMapToMBTopLeft(cpi
->pb
.BlockMap
,SB
,MB
) >= 0 ) {
958 cpi
->MBCodingMode
= CODE_INTRA
;
960 /* Now actually code the blocks. */
961 for ( B
=0; B
<4; B
++ ) {
962 FragIndex
= QuadMapToIndex1( cpi
->pb
.BlockMap
, SB
, MB
, B
);
963 cpi
->pb
.FragCodingMethod
[FragIndex
] = cpi
->MBCodingMode
;
966 /* Matching fragments in the U and V planes */
967 UVRow
= (FragIndex
/ (cpi
->pb
.HFragments
* 2));
968 UVColumn
= (FragIndex
% cpi
->pb
.HFragments
) / 2;
969 UVFragOffset
= (UVRow
* (cpi
->pb
.HFragments
/ 2)) + UVColumn
;
971 cpi
->pb
.FragCodingMethod
[cpi
->pb
.YPlaneFragments
+ UVFragOffset
] =
973 cpi
->pb
.FragCodingMethod
[cpi
->pb
.YPlaneFragments
+
974 cpi
->pb
.UVPlaneFragments
+ UVFragOffset
] =
980 /* Next Super-Block */
987 static void AddMotionVector(CP_INSTANCE
*cpi
,
988 MOTION_VECTOR
*ThisMotionVector
) {
989 cpi
->MVList
[cpi
->MvListCount
].x
= ThisMotionVector
->x
;
990 cpi
->MVList
[cpi
->MvListCount
].y
= ThisMotionVector
->y
;
994 static void SetFragMotionVectorAndMode(CP_INSTANCE
*cpi
,
995 ogg_int32_t FragIndex
,
996 MOTION_VECTOR
*ThisMotionVector
){
997 /* Note the coding mode and vector for each block */
998 cpi
->pb
.FragMVect
[FragIndex
].x
= ThisMotionVector
->x
;
999 cpi
->pb
.FragMVect
[FragIndex
].y
= ThisMotionVector
->y
;
1000 cpi
->pb
.FragCodingMethod
[FragIndex
] = cpi
->MBCodingMode
;
1003 static void SetMBMotionVectorsAndMode(CP_INSTANCE
*cpi
,
1004 ogg_int32_t YFragIndex
,
1005 ogg_int32_t UFragIndex
,
1006 ogg_int32_t VFragIndex
,
1007 MOTION_VECTOR
*ThisMotionVector
){
1008 SetFragMotionVectorAndMode(cpi
, YFragIndex
, ThisMotionVector
);
1009 SetFragMotionVectorAndMode(cpi
, YFragIndex
+ 1, ThisMotionVector
);
1010 SetFragMotionVectorAndMode(cpi
, YFragIndex
+ cpi
->pb
.HFragments
,
1012 SetFragMotionVectorAndMode(cpi
, YFragIndex
+ cpi
->pb
.HFragments
+ 1,
1014 SetFragMotionVectorAndMode(cpi
, UFragIndex
, ThisMotionVector
);
1015 SetFragMotionVectorAndMode(cpi
, VFragIndex
, ThisMotionVector
);
1018 ogg_uint32_t
PickModes(CP_INSTANCE
*cpi
,
1019 ogg_uint32_t SBRows
, ogg_uint32_t SBCols
,
1020 ogg_uint32_t PixelsPerLine
,
1021 ogg_uint32_t
*InterError
, ogg_uint32_t
*IntraError
) {
1022 ogg_int32_t YFragIndex
;
1023 ogg_int32_t UFragIndex
;
1024 ogg_int32_t VFragIndex
;
1025 ogg_uint32_t MB
, B
; /* Macro-Block, Block indices */
1026 ogg_uint32_t SBrow
; /* Super-Block row number */
1027 ogg_uint32_t SBcol
; /* Super-Block row number */
1028 ogg_uint32_t SB
=0; /* Super-Block index, initialised to first
1029 of this component */
1031 ogg_uint32_t MBIntraError
; /* Intra error for macro block */
1032 ogg_uint32_t MBGFError
; /* Golden frame macro block error */
1033 ogg_uint32_t MBGF_MVError
; /* Golden frame plus MV error */
1034 ogg_uint32_t LastMBGF_MVError
; /* Golden frame error with
1037 ogg_uint32_t MBInterError
; /* Inter no MV macro block error */
1038 ogg_uint32_t MBLastInterError
; /* Inter with last used MV */
1039 ogg_uint32_t MBPriorLastInterError
; /* Inter with prior last MV */
1040 ogg_uint32_t MBInterMVError
; /* Inter MV macro block error */
1041 ogg_uint32_t MBInterMVExError
; /* Inter MV (exhaustive
1042 search) macro block error */
1043 ogg_uint32_t MBInterFOURMVError
; /* Inter MV error when using 4
1044 motion vectors per macro
1046 ogg_uint32_t BestError
; /* Best error so far. */
1048 MOTION_VECTOR FourMVect
[6]; /* storage for last used vectors (one
1049 entry for each block in MB) */
1050 MOTION_VECTOR LastInterMVect
; /* storage for last used Inter frame
1052 MOTION_VECTOR PriorLastInterMVect
; /* storage for prior last used
1053 Inter frame MB motion vector */
1054 MOTION_VECTOR TmpMVect
; /* Temporary MV storage */
1055 MOTION_VECTOR LastGFMVect
; /* storage for last used Golden
1056 Frame MB motion vector */
1057 MOTION_VECTOR InterMVect
; /* storage for motion vector */
1058 MOTION_VECTOR InterMVectEx
; /* storage for motion vector result
1059 from exhaustive search */
1060 MOTION_VECTOR GFMVect
; /* storage for motion vector */
1061 MOTION_VECTOR ZeroVect
;
1064 ogg_uint32_t UVColumn
;
1065 ogg_uint32_t UVFragOffset
;
1068 unsigned char QIndex
;
1070 /* initialize error scores */
1074 /* clear down the default motion vector. */
1075 cpi
->MvListCount
= 0;
1088 LastInterMVect
.x
= 0;
1089 LastInterMVect
.y
= 0;
1090 PriorLastInterMVect
.x
= 0;
1091 PriorLastInterMVect
.y
= 0;
1102 QIndex
= (unsigned char)cpi
->pb
.FrameQIndex
;
1106 /* change the quatization matrix to the one at best Q to compute the
1108 cpi
->MinImprovementForNewMV
= (MvThreshTable
[QIndex
] << 12);
1109 cpi
->InterTripOutThresh
= (5000<<12);
1110 cpi
->MVChangeFactor
= MVChangeFactorTable
[QIndex
]; /* 0.9 */
1112 if ( cpi
->pb
.info
.quick_p
) {
1113 cpi
->ExhaustiveSearchThresh
= (1000<<12);
1114 cpi
->FourMVThreshold
= (2500<<12);
1116 cpi
->ExhaustiveSearchThresh
= (250<<12);
1117 cpi
->FourMVThreshold
= (500<<12);
1119 cpi
->MinImprovementForFourMV
= cpi
->MinImprovementForNewMV
* 4;
1121 if(cpi
->MinImprovementForFourMV
< (40<<12))
1122 cpi
->MinImprovementForFourMV
= (40<<12);
1124 cpi
->FourMvChangeFactor
= 8; /* cpi->MVChangeFactor - 0.05; */
1126 /* decide what block type and motion vectors to use on all of the frames */
1127 for ( SBrow
=0; SBrow
<SBRows
; SBrow
++ ) {
1128 for ( SBcol
=0; SBcol
<SBCols
; SBcol
++ ) {
1129 /* Check its four Macro-Blocks */
1130 for ( MB
=0; MB
<4; MB
++ ) {
1131 /* There may be MB's lying out of frame which must be
1132 ignored. For these MB's Top left block will have a negative
1134 if ( QuadMapToMBTopLeft(cpi
->pb
.BlockMap
,SB
,MB
) < 0 ) continue;
1136 /* Is the current macro block coded (in part or in whole) */
1138 for ( B
=0; B
<4; B
++ ) {
1139 YFragIndex
= QuadMapToIndex1( cpi
->pb
.BlockMap
, SB
, MB
, B
);
1141 /* Does Block lie in frame: */
1142 if ( YFragIndex
>= 0 ) {
1143 /* In Frame: Is it coded: */
1144 if ( cpi
->pb
.display_fragments
[YFragIndex
] ) {
1152 /* This one isn't coded go to the next one */
1153 if(!MBCodedFlag
) continue;
1155 /* Calculate U and V FragIndex from YFragIndex */
1156 YFragIndex
= QuadMapToMBTopLeft(cpi
->pb
.BlockMap
, SB
,MB
);
1157 UVRow
= (YFragIndex
/ (cpi
->pb
.HFragments
* 2));
1158 UVColumn
= (YFragIndex
% cpi
->pb
.HFragments
) / 2;
1159 UVFragOffset
= (UVRow
* (cpi
->pb
.HFragments
/ 2)) + UVColumn
;
1160 UFragIndex
= cpi
->pb
.YPlaneFragments
+ UVFragOffset
;
1161 VFragIndex
= cpi
->pb
.YPlaneFragments
+ cpi
->pb
.UVPlaneFragments
+
1165 /**************************************************************
1166 Find the block choice with the lowest error
1168 NOTE THAT if U or V is coded but no Y from a macro block then
1169 the mode will be CODE_INTER_NO_MV as this is the default
1170 state to which the mode data structure is initialised in
1171 encoder and decoder at the start of each frame. */
1173 BestError
= HUGE_ERROR
;
1176 /* Look at the intra coding error. */
1177 MBIntraError
= GetMBIntraError( cpi
, YFragIndex
, PixelsPerLine
);
1178 BestError
= (BestError
> MBIntraError
) ? MBIntraError
: BestError
;
1180 /* Get the golden frame error */
1181 MBGFError
= GetMBInterError( cpi
, cpi
->ConvDestBuffer
,
1182 cpi
->pb
.GoldenFrame
, YFragIndex
,
1183 0, 0, PixelsPerLine
);
1184 BestError
= (BestError
> MBGFError
) ? MBGFError
: BestError
;
1186 /* Calculate the 0,0 case. */
1187 MBInterError
= GetMBInterError( cpi
, cpi
->ConvDestBuffer
,
1188 cpi
->pb
.LastFrameRecon
,
1189 YFragIndex
, 0, 0, PixelsPerLine
);
1190 BestError
= (BestError
> MBInterError
) ? MBInterError
: BestError
;
1192 /* Measure error for last MV */
1193 MBLastInterError
= GetMBInterError( cpi
, cpi
->ConvDestBuffer
,
1194 cpi
->pb
.LastFrameRecon
,
1195 YFragIndex
, LastInterMVect
.x
,
1196 LastInterMVect
.y
, PixelsPerLine
);
1197 BestError
= (BestError
> MBLastInterError
) ?
1198 MBLastInterError
: BestError
;
1200 /* Measure error for prior last MV */
1201 MBPriorLastInterError
= GetMBInterError( cpi
, cpi
->ConvDestBuffer
,
1202 cpi
->pb
.LastFrameRecon
,
1204 PriorLastInterMVect
.x
,
1205 PriorLastInterMVect
.y
,
1207 BestError
= (BestError
> MBPriorLastInterError
) ?
1208 MBPriorLastInterError
: BestError
;
1210 /* Temporarily force usage of no motionvector blocks */
1211 MBInterMVError
= HUGE_ERROR
;
1212 InterMVect
.x
= 0; /* Set 0,0 motion vector */
1215 /* If the best error is above the required threshold search
1216 for a new inter MV */
1217 if ( BestError
> cpi
->MinImprovementForNewMV
) {
1218 /* Use a mix of heirachical and exhaustive searches for
1220 if ( cpi
->pb
.info
.quick_p
) {
1221 MBInterMVError
= GetMBMVInterError( cpi
, cpi
->pb
.LastFrameRecon
,
1222 YFragIndex
, PixelsPerLine
,
1223 cpi
->MVPixelOffsetY
,
1226 /* If we still do not have a good match try an exhaustive
1228 if ( (MBInterMVError
> cpi
->ExhaustiveSearchThresh
) &&
1229 (BestError
> cpi
->ExhaustiveSearchThresh
) ) {
1232 GetMBMVExhaustiveSearch( cpi
, cpi
->pb
.LastFrameRecon
,
1233 YFragIndex
, PixelsPerLine
,
1236 /* Is the Variance measure for the EX search
1237 better... If so then use it. */
1238 if ( MBInterMVExError
< MBInterMVError
) {
1239 MBInterMVError
= MBInterMVExError
;
1240 InterMVect
.x
= InterMVectEx
.x
;
1241 InterMVect
.y
= InterMVectEx
.y
;
1245 /* Use an exhaustive search */
1247 GetMBMVExhaustiveSearch( cpi
, cpi
->pb
.LastFrameRecon
,
1248 YFragIndex
, PixelsPerLine
,
1253 /* Is the improvement, if any, good enough to justify a new MV */
1254 if ( (16 * MBInterMVError
< (BestError
* cpi
->MVChangeFactor
)) &&
1255 ((MBInterMVError
+ cpi
->MinImprovementForNewMV
) < BestError
) ){
1256 BestError
= MBInterMVError
;
1261 /* If the best error is still above the required threshold
1262 search for a golden frame MV */
1263 MBGF_MVError
= HUGE_ERROR
;
1264 GFMVect
.x
= 0; /* Set 0,0 motion vector */
1266 if ( BestError
> cpi
->MinImprovementForNewMV
) {
1267 /* Do an MV search in the golden reference frame */
1268 MBGF_MVError
= GetMBMVInterError( cpi
, cpi
->pb
.GoldenFrame
,
1269 YFragIndex
, PixelsPerLine
,
1270 cpi
->MVPixelOffsetY
, &GFMVect
);
1272 /* Measure error for last GFMV */
1273 LastMBGF_MVError
= GetMBInterError( cpi
, cpi
->ConvDestBuffer
,
1274 cpi
->pb
.GoldenFrame
,
1275 YFragIndex
, LastGFMVect
.x
,
1276 LastGFMVect
.y
, PixelsPerLine
);
1278 /* Check against last GF motion vector and reset if the
1279 search has thrown a worse result. */
1280 if ( LastMBGF_MVError
< MBGF_MVError
) {
1281 GFMVect
.x
= LastGFMVect
.x
;
1282 GFMVect
.y
= LastGFMVect
.y
;
1283 MBGF_MVError
= LastMBGF_MVError
;
1285 LastGFMVect
.x
= GFMVect
.x
;
1286 LastGFMVect
.y
= GFMVect
.y
;
1289 /* Is the improvement, if any, good enough to justify a new MV */
1290 if ( (16 * MBGF_MVError
< (BestError
* cpi
->MVChangeFactor
)) &&
1291 ((MBGF_MVError
+ cpi
->MinImprovementForNewMV
) < BestError
) ) {
1292 BestError
= MBGF_MVError
;
1296 /* Finally... If the best error is still to high then consider
1298 MBInterFOURMVError
= HUGE_ERROR
;
1299 if ( BestError
> cpi
->FourMVThreshold
) {
1300 /* Get the 4MV error. */
1301 MBInterFOURMVError
=
1302 GetFOURMVExhaustiveSearch( cpi
, cpi
->pb
.LastFrameRecon
,
1303 YFragIndex
, PixelsPerLine
, FourMVect
);
1305 /* If the improvement is great enough then use the four MV mode */
1306 if ( ((MBInterFOURMVError
+ cpi
->MinImprovementForFourMV
) <
1307 BestError
) && (16 * MBInterFOURMVError
<
1308 (BestError
* cpi
->FourMvChangeFactor
))) {
1309 BestError
= MBInterFOURMVError
;
1313 /********************************************************
1314 end finding the best error
1315 *******************************************************
1317 Figure out what to do with the block we chose
1319 Over-ride and force intra if error high and Intra error similar
1320 Now choose a mode based on lowest error (with bias towards no MV) */
1322 if ( (BestError
> cpi
->InterTripOutThresh
) &&
1323 (10 * BestError
> MBIntraError
* 7 ) ) {
1324 cpi
->MBCodingMode
= CODE_INTRA
;
1325 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1326 VFragIndex
,&ZeroVect
);
1327 } else if ( BestError
== MBInterError
) {
1328 cpi
->MBCodingMode
= CODE_INTER_NO_MV
;
1329 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1330 VFragIndex
,&ZeroVect
);
1331 } else if ( BestError
== MBGFError
) {
1332 cpi
->MBCodingMode
= CODE_USING_GOLDEN
;
1333 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1334 VFragIndex
,&ZeroVect
);
1335 } else if ( BestError
== MBLastInterError
) {
1336 cpi
->MBCodingMode
= CODE_INTER_LAST_MV
;
1337 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1338 VFragIndex
,&LastInterMVect
);
1339 } else if ( BestError
== MBPriorLastInterError
) {
1340 cpi
->MBCodingMode
= CODE_INTER_PRIOR_LAST
;
1341 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1342 VFragIndex
,&PriorLastInterMVect
);
1344 /* Swap the prior and last MV cases over */
1345 TmpMVect
.x
= PriorLastInterMVect
.x
;
1346 TmpMVect
.y
= PriorLastInterMVect
.y
;
1347 PriorLastInterMVect
.x
= LastInterMVect
.x
;
1348 PriorLastInterMVect
.y
= LastInterMVect
.y
;
1349 LastInterMVect
.x
= TmpMVect
.x
;
1350 LastInterMVect
.y
= TmpMVect
.y
;
1352 } else if ( BestError
== MBInterMVError
) {
1354 cpi
->MBCodingMode
= CODE_INTER_PLUS_MV
;
1355 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1356 VFragIndex
,&InterMVect
);
1358 /* Update Prior last mv with last mv */
1359 PriorLastInterMVect
.x
= LastInterMVect
.x
;
1360 PriorLastInterMVect
.y
= LastInterMVect
.y
;
1362 /* Note last inter MV for future use */
1363 LastInterMVect
.x
= InterMVect
.x
;
1364 LastInterMVect
.y
= InterMVect
.y
;
1366 AddMotionVector( cpi
, &InterMVect
);
1368 } else if ( BestError
== MBGF_MVError
) {
1370 cpi
->MBCodingMode
= CODE_GOLDEN_MV
;
1371 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1372 VFragIndex
,&GFMVect
);
1374 /* Note last inter GF MV for future use */
1375 LastGFMVect
.x
= GFMVect
.x
;
1376 LastGFMVect
.y
= GFMVect
.y
;
1378 AddMotionVector( cpi
, &GFMVect
);
1379 } else if ( BestError
== MBInterFOURMVError
) {
1380 cpi
->MBCodingMode
= CODE_INTER_FOURMV
;
1382 /* Calculate the UV vectors as the average of the Y plane ones. */
1383 /* First .x component */
1384 FourMVect
[4].x
= FourMVect
[0].x
+ FourMVect
[1].x
+
1385 FourMVect
[2].x
+ FourMVect
[3].x
;
1386 if ( FourMVect
[4].x
>= 0 )
1387 FourMVect
[4].x
= (FourMVect
[4].x
+ 2) / 4;
1389 FourMVect
[4].x
= (FourMVect
[4].x
- 2) / 4;
1390 FourMVect
[5].x
= FourMVect
[4].x
;
1392 /* Then .y component */
1393 FourMVect
[4].y
= FourMVect
[0].y
+ FourMVect
[1].y
+
1394 FourMVect
[2].y
+ FourMVect
[3].y
;
1395 if ( FourMVect
[4].y
>= 0 )
1396 FourMVect
[4].y
= (FourMVect
[4].y
+ 2) / 4;
1398 FourMVect
[4].y
= (FourMVect
[4].y
- 2) / 4;
1399 FourMVect
[5].y
= FourMVect
[4].y
;
1401 SetFragMotionVectorAndMode(cpi
, YFragIndex
, &FourMVect
[0]);
1402 SetFragMotionVectorAndMode(cpi
, YFragIndex
+ 1, &FourMVect
[1]);
1403 SetFragMotionVectorAndMode(cpi
, YFragIndex
+ cpi
->pb
.HFragments
,
1405 SetFragMotionVectorAndMode(cpi
, YFragIndex
+ cpi
->pb
.HFragments
+ 1,
1407 SetFragMotionVectorAndMode(cpi
, UFragIndex
, &FourMVect
[4]);
1408 SetFragMotionVectorAndMode(cpi
, VFragIndex
, &FourMVect
[5]);
1410 /* Note the four MVs values for current macro-block. */
1411 AddMotionVector( cpi
, &FourMVect
[0]);
1412 AddMotionVector( cpi
, &FourMVect
[1]);
1413 AddMotionVector( cpi
, &FourMVect
[2]);
1414 AddMotionVector( cpi
, &FourMVect
[3]);
1416 /* Update Prior last mv with last mv */
1417 PriorLastInterMVect
.x
= LastInterMVect
.x
;
1418 PriorLastInterMVect
.y
= LastInterMVect
.y
;
1420 /* Note last inter MV for future use */
1421 LastInterMVect
.x
= FourMVect
[3].x
;
1422 LastInterMVect
.y
= FourMVect
[3].y
;
1426 cpi
->MBCodingMode
= CODE_INTRA
;
1427 SetMBMotionVectorsAndMode(cpi
,YFragIndex
,UFragIndex
,
1428 VFragIndex
,&ZeroVect
);
1432 /* setting up mode specific block types
1433 *******************************************************/
1435 *InterError
+= (BestError
>>8);
1436 *IntraError
+= (MBIntraError
>>8);
1445 /* Return number of pixels coded */
1449 void WriteFrameHeader( CP_INSTANCE
*cpi
) {
1451 oggpack_buffer
*opb
=cpi
->oggbuffer
;
1453 /* Output the frame type (base/key frame or inter frame) */
1454 oggpackB_write( opb
, cpi
->pb
.FrameType
, 1 );
1456 /* Write out details of the current value of Q... variable resolution. */
1457 for ( i
= 0; i
< Q_TABLE_SIZE
; i
++ ) {
1458 if ( cpi
->pb
.ThisFrameQualityValue
== cpi
->pb
.QThreshTable
[i
] ) {
1459 oggpackB_write( opb
, i
, 6 );
1464 if ( i
== Q_TABLE_SIZE
) {
1465 /* An invalid DCT value was specified. */
1466 /*IssueWarning( "Invalid Q Multiplier" );*/
1467 oggpackB_write( opb
, 31, 6 );
1470 /* we only support one Q index per frame */
1471 oggpackB_write( opb
, 0, 1 );
1473 /* If the frame was a base frame then write out the frame dimensions. */
1474 if ( cpi
->pb
.FrameType
== KEY_FRAME
) {
1475 /* Key frame type / method */
1476 oggpackB_write( opb
, cpi
->pb
.KeyFrameType
, 1 );
1478 /* Spare configuration bits */
1479 oggpackB_write( opb
, 0, 2 );