| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /********************************************************************
 | 
					
						
							|  |  |  |  *                                                                  * | 
					
						
							|  |  |  |  * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   * | 
					
						
							|  |  |  |  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     * | 
					
						
							|  |  |  |  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * | 
					
						
							|  |  |  |  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       * | 
					
						
							|  |  |  |  *                                                                  * | 
					
						
							|  |  |  |  * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                * | 
					
						
							|  |  |  |  * by the Xiph.Org Foundation http://www.xiph.org/                  *
 | 
					
						
							|  |  |  |  *                                                                  * | 
					
						
							|  |  |  |  ******************************************************************** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function: | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   last mod: $Id$ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |  ********************************************************************/ | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include "encint.h"
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | #include "dequant.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*The default quantization parameters used by VP3.1.*/ | 
					
						
							|  |  |  | static const int OC_VP31_RANGE_SIZES[1]={63}; | 
					
						
							|  |  |  | static const th_quant_base OC_VP31_BASES_INTRA_Y[2]={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 11, 10, 16, 24, 40, 51, 61, | 
					
						
							|  |  |  |      12, 12, 14, 19, 26, 58, 60, 55, | 
					
						
							|  |  |  |      14, 13, 16, 24, 40, 57, 69, 56, | 
					
						
							|  |  |  |      14, 17, 22, 29, 51, 87, 80, 62, | 
					
						
							|  |  |  |      18, 22, 37, 58, 68,109,103, 77, | 
					
						
							|  |  |  |      24, 35, 55, 64, 81,104,113, 92, | 
					
						
							|  |  |  |      49, 64, 78, 87,103,121,120,101, | 
					
						
							|  |  |  |      72, 92, 95, 98,112,100,103, 99 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 11, 10, 16, 24, 40, 51, 61, | 
					
						
							|  |  |  |      12, 12, 14, 19, 26, 58, 60, 55, | 
					
						
							|  |  |  |      14, 13, 16, 24, 40, 57, 69, 56, | 
					
						
							|  |  |  |      14, 17, 22, 29, 51, 87, 80, 62, | 
					
						
							|  |  |  |      18, 22, 37, 58, 68,109,103, 77, | 
					
						
							|  |  |  |      24, 35, 55, 64, 81,104,113, 92, | 
					
						
							|  |  |  |      49, 64, 78, 87,103,121,120,101, | 
					
						
							|  |  |  |      72, 92, 95, 98,112,100,103, 99 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static const th_quant_base OC_VP31_BASES_INTRA_C[2]={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      17, 18, 24, 47, 99, 99, 99, 99, | 
					
						
							|  |  |  |      18, 21, 26, 66, 99, 99, 99, 99, | 
					
						
							|  |  |  |      24, 26, 56, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      47, 66, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      17, 18, 24, 47, 99, 99, 99, 99, | 
					
						
							|  |  |  |      18, 21, 26, 66, 99, 99, 99, 99, | 
					
						
							|  |  |  |      24, 26, 56, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      47, 66, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static const th_quant_base OC_VP31_BASES_INTER[2]={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 16, 16, 20, 24, 28, 32, 40, | 
					
						
							|  |  |  |      16, 16, 20, 24, 28, 32, 40, 48, | 
					
						
							|  |  |  |      16, 20, 24, 28, 32, 40, 48, 64, | 
					
						
							|  |  |  |      20, 24, 28, 32, 40, 48, 64, 64, | 
					
						
							|  |  |  |      24, 28, 32, 40, 48, 64, 64, 64, | 
					
						
							|  |  |  |      28, 32, 40, 48, 64, 64, 64, 96, | 
					
						
							|  |  |  |      32, 40, 48, 64, 64, 64, 96,128, | 
					
						
							|  |  |  |      40, 48, 64, 64, 64, 96,128,128 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 16, 16, 20, 24, 28, 32, 40, | 
					
						
							|  |  |  |      16, 16, 20, 24, 28, 32, 40, 48, | 
					
						
							|  |  |  |      16, 20, 24, 28, 32, 40, 48, 64, | 
					
						
							|  |  |  |      20, 24, 28, 32, 40, 48, 64, 64, | 
					
						
							|  |  |  |      24, 28, 32, 40, 48, 64, 64, 64, | 
					
						
							|  |  |  |      28, 32, 40, 48, 64, 64, 64, 96, | 
					
						
							|  |  |  |      32, 40, 48, 64, 64, 64, 96,128, | 
					
						
							|  |  |  |      40, 48, 64, 64, 64, 96,128,128 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const th_quant_info TH_VP31_QUANT_INFO={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     220,200,190,180,170,170,160,160, | 
					
						
							|  |  |  |     150,150,140,140,130,130,120,120, | 
					
						
							|  |  |  |     110,110,100,100, 90, 90, 90, 80, | 
					
						
							|  |  |  |      80, 80, 70, 70, 70, 60, 60, 60, | 
					
						
							|  |  |  |      60, 50, 50, 50, 50, 40, 40, 40, | 
					
						
							|  |  |  |      40, 40, 30, 30, 30, 30, 30, 30, | 
					
						
							|  |  |  |      30, 20, 20, 20, 20, 20, 20, 20, | 
					
						
							|  |  |  |      20, 10, 10, 10, 10, 10, 10, 10 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     500,450,400,370,340,310,285,265, | 
					
						
							|  |  |  |     245,225,210,195,185,180,170,160, | 
					
						
							|  |  |  |     150,145,135,130,125,115,110,107, | 
					
						
							|  |  |  |     100, 96, 93, 89, 85, 82, 75, 74, | 
					
						
							|  |  |  |      70, 68, 64, 60, 57, 56, 52, 50, | 
					
						
							|  |  |  |      49, 45, 44, 43, 40, 38, 37, 35, | 
					
						
							|  |  |  |      33, 32, 30, 29, 28, 25, 24, 22, | 
					
						
							|  |  |  |      21, 19, 18, 17, 15, 13, 12, 10 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     30,25,20,20,15,15,14,14, | 
					
						
							|  |  |  |     13,13,12,12,11,11,10,10, | 
					
						
							|  |  |  |      9, 9, 8, 8, 7, 7, 7, 7, | 
					
						
							|  |  |  |      6, 6, 6, 6, 5, 5, 5, 5, | 
					
						
							|  |  |  |      4, 4, 4, 4, 3, 3, 3, 3, | 
					
						
							|  |  |  |      2, 2, 2, 2, 2, 2, 2, 2, | 
					
						
							|  |  |  |      0, 0, 0, 0, 0, 0, 0, 0, | 
					
						
							|  |  |  |      0, 0, 0, 0, 0, 0, 0, 0 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_Y}, | 
					
						
							|  |  |  |       {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C}, | 
					
						
							|  |  |  |       {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C} | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}, | 
					
						
							|  |  |  |       {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}, | 
					
						
							|  |  |  |       {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*The current default quantization parameters.*/ | 
					
						
							|  |  |  | static const int OC_DEF_QRANGE_SIZES[3]={32,16,15}; | 
					
						
							|  |  |  | static const th_quant_base OC_DEF_BASES_INTRA_Y[4]={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |      15, 15, 15, 15, 15, 15, 15, 15, | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      15, 12, 12, 15, 18, 20, 20, 21, | 
					
						
							|  |  |  |      13, 13, 14, 17, 18, 21, 21, 20, | 
					
						
							|  |  |  |      14, 14, 15, 18, 20, 21, 21, 21, | 
					
						
							|  |  |  |      14, 16, 17, 19, 20, 21, 21, 21, | 
					
						
							|  |  |  |      16, 17, 20, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      18, 19, 20, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      20, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 12, 11, 16, 20, 25, 27, 28, | 
					
						
							|  |  |  |      13, 13, 14, 18, 21, 28, 28, 27, | 
					
						
							|  |  |  |      14, 13, 16, 20, 25, 28, 28, 28, | 
					
						
							|  |  |  |      14, 16, 19, 22, 27, 29, 29, 28, | 
					
						
							|  |  |  |      17, 19, 25, 28, 28, 30, 30, 29, | 
					
						
							|  |  |  |      20, 24, 27, 28, 29, 30, 30, 29, | 
					
						
							|  |  |  |      27, 28, 29, 29, 30, 30, 30, 30, | 
					
						
							|  |  |  |      29, 29, 29, 29, 30, 30, 30, 29 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 11, 10, 16, 24, 40, 51, 61, | 
					
						
							|  |  |  |      12, 12, 14, 19, 26, 58, 60, 55, | 
					
						
							|  |  |  |      14, 13, 16, 24, 40, 57, 69, 56, | 
					
						
							|  |  |  |      14, 17, 22, 29, 51, 87, 80, 62, | 
					
						
							|  |  |  |      18, 22, 37, 58, 68,109,103, 77, | 
					
						
							|  |  |  |      24, 35, 55, 64, 81,104,113, 92, | 
					
						
							|  |  |  |      49, 64, 78, 87,103,121,120,101, | 
					
						
							|  |  |  |      72, 92, 95, 98,112,100,103, 99 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static const th_quant_base OC_DEF_BASES_INTRA_C[4]={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19, | 
					
						
							|  |  |  |      19, 19, 19, 19, 19, 19, 19, 19 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      18, 18, 21, 25, 26, 26, 26, 26, | 
					
						
							|  |  |  |      18, 20, 22, 26, 26, 26, 26, 26, | 
					
						
							|  |  |  |      21, 22, 25, 26, 26, 26, 26, 26, | 
					
						
							|  |  |  |      25, 26, 26, 26, 26, 26, 26, 26, | 
					
						
							|  |  |  |      26, 26, 26, 26, 26, 26, 26, 26, | 
					
						
							|  |  |  |      26, 26, 26, 26, 26, 26, 26, 26, | 
					
						
							|  |  |  |      26, 26, 26, 26, 26, 26, 26, 26, | 
					
						
							|  |  |  |      26, 26, 26, 26, 26, 26, 26, 26 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      17, 18, 22, 31, 36, 36, 36, 36, | 
					
						
							|  |  |  |      18, 20, 24, 34, 36, 36, 36, 36, | 
					
						
							|  |  |  |      22, 24, 33, 36, 36, 36, 36, 36, | 
					
						
							|  |  |  |      31, 34, 36, 36, 36, 36, 36, 36, | 
					
						
							|  |  |  |      36, 36, 36, 36, 36, 36, 36, 36, | 
					
						
							|  |  |  |      36, 36, 36, 36, 36, 36, 36, 36, | 
					
						
							|  |  |  |      36, 36, 36, 36, 36, 36, 36, 36, | 
					
						
							|  |  |  |      36, 36, 36, 36, 36, 36, 36, 36 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      17, 18, 24, 47, 99, 99, 99, 99, | 
					
						
							|  |  |  |      18, 21, 26, 66, 99, 99, 99, 99, | 
					
						
							|  |  |  |      24, 26, 56, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      47, 66, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99, | 
					
						
							|  |  |  |      99, 99, 99, 99, 99, 99, 99, 99 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static const th_quant_base OC_DEF_BASES_INTER[4]={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21, | 
					
						
							|  |  |  |      21, 21, 21, 21, 21, 21, 21, 21 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      18, 18, 18, 21, 23, 24, 25, 27, | 
					
						
							|  |  |  |      18, 18, 21, 23, 24, 25, 27, 28, | 
					
						
							|  |  |  |      18, 21, 23, 24, 25, 27, 28, 29, | 
					
						
							|  |  |  |      21, 23, 24, 25, 27, 28, 29, 29, | 
					
						
							|  |  |  |      23, 24, 25, 27, 28, 29, 29, 29, | 
					
						
							|  |  |  |      24, 25, 27, 28, 29, 29, 29, 30, | 
					
						
							|  |  |  |      25, 27, 28, 29, 29, 29, 30, 30, | 
					
						
							|  |  |  |      27, 28, 29, 29, 29, 30, 30, 30 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      17, 17, 17, 20, 23, 26, 28, 32, | 
					
						
							|  |  |  |      17, 17, 20, 23, 26, 28, 32, 34, | 
					
						
							|  |  |  |      17, 20, 23, 26, 28, 32, 34, 37, | 
					
						
							|  |  |  |      20, 23, 26, 28, 32, 34, 37, 37, | 
					
						
							|  |  |  |      23, 26, 28, 32, 34, 37, 37, 37, | 
					
						
							|  |  |  |      26, 28, 32, 34, 37, 37, 37, 41, | 
					
						
							|  |  |  |      28, 32, 34, 37, 37, 37, 41, 42, | 
					
						
							|  |  |  |      32, 34, 37, 37, 37, 41, 42, 42 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |      16, 16, 16, 20, 24, 28, 32, 40, | 
					
						
							|  |  |  |      16, 16, 20, 24, 28, 32, 40, 48, | 
					
						
							|  |  |  |      16, 20, 24, 28, 32, 40, 48, 64, | 
					
						
							|  |  |  |      20, 24, 28, 32, 40, 48, 64, 64, | 
					
						
							|  |  |  |      24, 28, 32, 40, 48, 64, 64, 64, | 
					
						
							|  |  |  |      28, 32, 40, 48, 64, 64, 64, 96, | 
					
						
							|  |  |  |      32, 40, 48, 64, 64, 64, 96,128, | 
					
						
							|  |  |  |      40, 48, 64, 64, 64, 96,128,128 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const th_quant_info TH_DEF_QUANT_INFO={ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     365,348,333,316,300,287,277,265, | 
					
						
							|  |  |  |     252,240,229,219,206,197,189,180, | 
					
						
							|  |  |  |     171,168,160,153,146,139,132,127, | 
					
						
							|  |  |  |     121,115,110,107,101, 97, 94, 89, | 
					
						
							|  |  |  |      85, 83, 78, 73, 72, 67, 66, 62, | 
					
						
							|  |  |  |      60, 59, 56, 53, 52, 48, 47, 43, | 
					
						
							|  |  |  |      42, 40, 36, 35, 34, 33, 31, 30, | 
					
						
							|  |  |  |      28, 25, 24, 22, 20, 17, 14, 10 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     365,348,333,316,300,287,277,265, | 
					
						
							|  |  |  |     252,240,229,219,206,197,189,180, | 
					
						
							|  |  |  |     171,168,160,153,146,139,132,127, | 
					
						
							|  |  |  |     121,115,110,107,101, 97, 94, 89, | 
					
						
							|  |  |  |      85, 83, 78, 73, 72, 67, 66, 62, | 
					
						
							|  |  |  |      60, 59, 56, 53, 52, 48, 47, 43, | 
					
						
							|  |  |  |      42, 40, 36, 35, 34, 33, 31, 30, | 
					
						
							|  |  |  |      28, 25, 24, 22, 20, 17, 14, 10 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |     15,12, 9, 8, 6, 6, 5, 5, | 
					
						
							|  |  |  |      5, 5, 5, 5, 5, 5, 5, 5, | 
					
						
							|  |  |  |      4, 4, 4, 4, 4, 4, 3, 3, | 
					
						
							|  |  |  |      3, 3, 3, 3, 3, 3, 3, 3, | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |      2, 2, 2, 2, 2, 2, 2, 2, | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |      2, 2, 2, 2, 2, 2, 2, 0, | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |      0, 0, 0, 0, 0, 0, 0, 0, | 
					
						
							|  |  |  |      0, 0, 0, 0, 0, 0, 0, 0 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_Y}, | 
					
						
							|  |  |  |       {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_C}, | 
					
						
							|  |  |  |       {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_C} | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER}, | 
					
						
							|  |  |  |       {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER}, | 
					
						
							|  |  |  |       {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*The Huffman codes used for macro block modes.*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const unsigned char OC_MODE_BITS[2][OC_NMODES]={ | 
					
						
							|  |  |  |   /*Codebook 0: a maximally skewed prefix code.*/ | 
					
						
							|  |  |  |   {1,2,3,4,5,6,7,7}, | 
					
						
							|  |  |  |   /*Codebook 1: a fixed-length code.*/ | 
					
						
							|  |  |  |   {3,3,3,3,3,3,3,3} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const unsigned char OC_MODE_CODES[2][OC_NMODES]={ | 
					
						
							|  |  |  |   /*Codebook 0: a maximally skewed prefix code.*/ | 
					
						
							|  |  |  |   {0x00,0x02,0x06,0x0E,0x1E,0x3E,0x7E,0x7F}, | 
					
						
							|  |  |  |   /*Codebook 1: a fixed-length code.*/ | 
					
						
							|  |  |  |   {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*The Huffman codes used for motion vectors.*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const unsigned char OC_MV_BITS[2][64]={ | 
					
						
							|  |  |  |   /*Codebook 0: VLC code.*/ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |       8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, | 
					
						
							|  |  |  |     8,7,7,7,7,7,7,7,7,6,6,6,6,4,4,3, | 
					
						
							|  |  |  |     3, | 
					
						
							|  |  |  |     3,4,4,6,6,6,6,7,7,7,7,7,7,7,7,8, | 
					
						
							|  |  |  |     8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   /*Codebook 1: (5 bit magnitude, 1 bit sign).
 | 
					
						
							|  |  |  |     This wastes a code word (0x01, negative zero), or a bit (0x00, positive | 
					
						
							|  |  |  |      zero, requires only 5 bits to uniquely decode), but is hopefully not used | 
					
						
							|  |  |  |      very often.*/ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | 
					
						
							|  |  |  |     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | 
					
						
							|  |  |  |     6, | 
					
						
							|  |  |  |     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | 
					
						
							|  |  |  |     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const unsigned char OC_MV_CODES[2][64]={ | 
					
						
							|  |  |  |   /*Codebook 0: VLC code.*/ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |          0xFF,0xFD,0xFB,0xF9,0xF7,0xF5,0xF3, | 
					
						
							|  |  |  |     0xF1,0xEF,0xED,0xEB,0xE9,0xE7,0xE5,0xE3, | 
					
						
							|  |  |  |     0xE1,0x6F,0x6D,0x6B,0x69,0x67,0x65,0x63, | 
					
						
							|  |  |  |     0x61,0x2F,0x2D,0x2B,0x29,0x09,0x07,0x02, | 
					
						
							|  |  |  |     0x00, | 
					
						
							|  |  |  |     0x01,0x06,0x08,0x28,0x2A,0x2C,0x2E,0x60, | 
					
						
							|  |  |  |     0x62,0x64,0x66,0x68,0x6A,0x6C,0x6E,0xE0, | 
					
						
							|  |  |  |     0xE2,0xE4,0xE6,0xE8,0xEA,0xEC,0xEE,0xF0, | 
					
						
							|  |  |  |     0xF2,0xF4,0xF6,0xF8,0xFA,0xFC,0xFE | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   /*Codebook 1: (5 bit magnitude, 1 bit sign).*/ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |          0x3F,0x3D,0x3B,0x39,0x37,0x35,0x33, | 
					
						
							|  |  |  |     0x31,0x2F,0x2D,0x2B,0x29,0x27,0x25,0x23, | 
					
						
							|  |  |  |     0x21,0x1F,0x1D,0x1B,0x19,0x17,0x15,0x13, | 
					
						
							|  |  |  |     0x11,0x0F,0x0D,0x0B,0x09,0x07,0x05,0x03, | 
					
						
							|  |  |  |     0x00, | 
					
						
							|  |  |  |     0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x10, | 
					
						
							|  |  |  |     0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20, | 
					
						
							|  |  |  |     0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30, | 
					
						
							|  |  |  |     0x32,0x34,0x36,0x38,0x3A,0x3C,0x3E | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Super block run coding scheme:
 | 
					
						
							|  |  |  |    Codeword             Run Length | 
					
						
							|  |  |  |    0                       1 | 
					
						
							|  |  |  |    10x                     2-3 | 
					
						
							|  |  |  |    110x                    4-5 | 
					
						
							|  |  |  |    1110xx                  6-9 | 
					
						
							|  |  |  |    11110xxx                10-17 | 
					
						
							|  |  |  |    111110xxxx              18-33 | 
					
						
							|  |  |  |    111111xxxxxxxxxxxx      34-4129*/ | 
					
						
							|  |  |  | const ogg_uint16_t    OC_SB_RUN_VAL_MIN[8]={1,2,4,6,10,18,34,4130}; | 
					
						
							|  |  |  | static const unsigned OC_SB_RUN_CODE_PREFIX[7]={ | 
					
						
							|  |  |  |   0,4,0xC,0x38,0xF0,0x3E0,0x3F000 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | const unsigned char   OC_SB_RUN_CODE_NBITS[7]={1,3,4,6,8,10,18}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Writes the bit pattern for the run length of a super block run to the given
 | 
					
						
							|  |  |  |    oggpack_buffer. | 
					
						
							|  |  |  |   _opb:       The buffer to write to. | 
					
						
							|  |  |  |   _run_count: The length of the run, which must be positive. | 
					
						
							|  |  |  |   _flag:      The current flag. | 
					
						
							|  |  |  |   _done:      Whether or not more flags are to be encoded.*/ | 
					
						
							|  |  |  | static void oc_sb_run_pack(oggpack_buffer *_opb,ptrdiff_t _run_count, | 
					
						
							|  |  |  |  int _flag,int _done){ | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   if(_run_count>=4129){ | 
					
						
							|  |  |  |     do{ | 
					
						
							|  |  |  |       oggpackB_write(_opb,0x3FFFF,18); | 
					
						
							|  |  |  |       _run_count-=4129; | 
					
						
							|  |  |  |       if(_run_count>0)oggpackB_write(_opb,_flag,1); | 
					
						
							|  |  |  |       else if(!_done)oggpackB_write(_opb,!_flag,1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     while(_run_count>=4129); | 
					
						
							|  |  |  |     if(_run_count<=0)return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   for(i=0;_run_count>=OC_SB_RUN_VAL_MIN[i+1];i++); | 
					
						
							|  |  |  |   oggpackB_write(_opb,OC_SB_RUN_CODE_PREFIX[i]+_run_count-OC_SB_RUN_VAL_MIN[i], | 
					
						
							|  |  |  |    OC_SB_RUN_CODE_NBITS[i]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Block run coding scheme:
 | 
					
						
							|  |  |  |    Codeword             Run Length | 
					
						
							|  |  |  |    0x                      1-2 | 
					
						
							|  |  |  |    10x                     3-4 | 
					
						
							|  |  |  |    110x                    5-6 | 
					
						
							|  |  |  |    1110xx                  7-10 | 
					
						
							|  |  |  |    11110xx                 11-14 | 
					
						
							|  |  |  |    11111xxxx               15-30*/ | 
					
						
							|  |  |  | const unsigned char OC_BLOCK_RUN_CODE_NBITS[30]={ | 
					
						
							|  |  |  |   2,2,3,3,4,4,6,6,6,6,7,7,7,7,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | static const ogg_uint16_t  OC_BLOCK_RUN_CODE_PATTERN[30]={ | 
					
						
							|  |  |  |         0x000,0x001,0x004,0x005,0x00C,0x00D,0x038, | 
					
						
							|  |  |  |   0x039,0x03A,0x03B,0x078,0x079,0x07A,0x07B,0x1F0, | 
					
						
							|  |  |  |   0x1F1,0x1F2,0x1F3,0x1F4,0x1F5,0x1F6,0x1F7,0x1F8, | 
					
						
							|  |  |  |   0x1F9,0x1FA,0x1FB,0x1FC,0x1FD,0x1FE,0x1FF | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Writes the bit pattern for the run length of a block run to the given
 | 
					
						
							|  |  |  |    oggpack_buffer. | 
					
						
							|  |  |  |   _opb:       The buffer to write to. | 
					
						
							|  |  |  |   _run_count: The length of the run. | 
					
						
							|  |  |  |               This must be positive, and no more than 30.*/ | 
					
						
							|  |  |  | static void oc_block_run_pack(oggpack_buffer *_opb,int _run_count){ | 
					
						
							|  |  |  |   oggpackB_write(_opb,OC_BLOCK_RUN_CODE_PATTERN[_run_count-1], | 
					
						
							|  |  |  |    OC_BLOCK_RUN_CODE_NBITS[_run_count-1]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_frame_header_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   /*Mark this as a data packet.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   /*Output the frame type (key frame or delta frame).*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->state.frame_type,1); | 
					
						
							|  |  |  |   /*Write out the current qi list.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->state.qis[0],6); | 
					
						
							|  |  |  |   if(_enc->state.nqis>1){ | 
					
						
							|  |  |  |     oggpackB_write(&_enc->opb,1,1); | 
					
						
							|  |  |  |     oggpackB_write(&_enc->opb,_enc->state.qis[1],6); | 
					
						
							|  |  |  |     if(_enc->state.nqis>2){ | 
					
						
							|  |  |  |       oggpackB_write(&_enc->opb,1,1); | 
					
						
							|  |  |  |       oggpackB_write(&_enc->opb,_enc->state.qis[2],6); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   if(_enc->state.frame_type==OC_INTRA_FRAME){ | 
					
						
							|  |  |  |     /*Key frames have 3 unused configuration bits, holdovers from the VP3 days.
 | 
					
						
							|  |  |  |       Most of the other unused bits in the VP3 headers were eliminated. | 
					
						
							|  |  |  |       Monty kept these to leave us some wiggle room for future expansion, | 
					
						
							|  |  |  |        though a single bit in all frames would have been far more useful.*/ | 
					
						
							|  |  |  |     oggpackB_write(&_enc->opb,0,3); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Writes the bit flags for whether or not each super block is partially coded
 | 
					
						
							|  |  |  |    or not. | 
					
						
							|  |  |  |   These flags are run-length encoded, with the flag value alternating between | 
					
						
							|  |  |  |    each run. | 
					
						
							|  |  |  |   Return: The number partially coded SBs.*/ | 
					
						
							|  |  |  | static unsigned oc_enc_partial_sb_flags_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   const oc_sb_flags *sb_flags; | 
					
						
							|  |  |  |   unsigned           nsbs; | 
					
						
							|  |  |  |   unsigned           sbi; | 
					
						
							|  |  |  |   unsigned           npartial; | 
					
						
							|  |  |  |   int                flag; | 
					
						
							|  |  |  |   sb_flags=_enc->state.sb_flags; | 
					
						
							|  |  |  |   nsbs=_enc->state.nsbs; | 
					
						
							|  |  |  |   flag=sb_flags[0].coded_partially; | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,flag,1); | 
					
						
							|  |  |  |   sbi=npartial=0; | 
					
						
							|  |  |  |   do{ | 
					
						
							|  |  |  |     unsigned run_count; | 
					
						
							|  |  |  |     for(run_count=0;sbi<nsbs;sbi++){ | 
					
						
							|  |  |  |       if(sb_flags[sbi].coded_partially!=flag)break; | 
					
						
							|  |  |  |       run_count++; | 
					
						
							|  |  |  |       npartial+=flag; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oc_sb_run_pack(&_enc->opb,run_count,flag,sbi>=nsbs); | 
					
						
							|  |  |  |     flag=!flag; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   while(sbi<nsbs); | 
					
						
							|  |  |  |   return npartial; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Writes the coded/not coded flags for each super block that is not partially
 | 
					
						
							|  |  |  |    coded. | 
					
						
							|  |  |  |   These flags are run-length encoded, with the flag value altenating between | 
					
						
							|  |  |  |    each run.*/ | 
					
						
							|  |  |  | static void oc_enc_coded_sb_flags_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   const oc_sb_flags *sb_flags; | 
					
						
							|  |  |  |   unsigned           nsbs; | 
					
						
							|  |  |  |   unsigned           sbi; | 
					
						
							|  |  |  |   int                flag; | 
					
						
							|  |  |  |   sb_flags=_enc->state.sb_flags; | 
					
						
							|  |  |  |   nsbs=_enc->state.nsbs; | 
					
						
							|  |  |  |   /*Skip partially coded super blocks; their flags have already been coded.*/ | 
					
						
							|  |  |  |   for(sbi=0;sb_flags[sbi].coded_partially;sbi++); | 
					
						
							|  |  |  |   flag=sb_flags[sbi].coded_fully; | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,flag,1); | 
					
						
							|  |  |  |   do{ | 
					
						
							|  |  |  |     unsigned run_count; | 
					
						
							|  |  |  |     for(run_count=0;sbi<nsbs;sbi++){ | 
					
						
							|  |  |  |       if(sb_flags[sbi].coded_partially)continue; | 
					
						
							|  |  |  |       if(sb_flags[sbi].coded_fully!=flag)break; | 
					
						
							|  |  |  |       run_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oc_sb_run_pack(&_enc->opb,run_count,flag,sbi>=nsbs); | 
					
						
							|  |  |  |     flag=!flag; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   while(sbi<nsbs); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_coded_flags_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   const oc_sb_map   *sb_maps; | 
					
						
							|  |  |  |   const oc_sb_flags *sb_flags; | 
					
						
							|  |  |  |   unsigned           nsbs; | 
					
						
							|  |  |  |   const oc_fragment *frags; | 
					
						
							|  |  |  |   unsigned           npartial; | 
					
						
							|  |  |  |   int                run_count; | 
					
						
							|  |  |  |   int                flag; | 
					
						
							|  |  |  |   int                pli; | 
					
						
							|  |  |  |   unsigned           sbi; | 
					
						
							|  |  |  |   npartial=oc_enc_partial_sb_flags_pack(_enc); | 
					
						
							|  |  |  |   if(npartial<_enc->state.nsbs)oc_enc_coded_sb_flags_pack(_enc); | 
					
						
							|  |  |  |   sb_maps=(const oc_sb_map *)_enc->state.sb_maps; | 
					
						
							|  |  |  |   sb_flags=_enc->state.sb_flags; | 
					
						
							|  |  |  |   nsbs=_enc->state.nsbs; | 
					
						
							|  |  |  |   frags=_enc->state.frags; | 
					
						
							|  |  |  |   for(sbi=0;sbi<nsbs&&!sb_flags[sbi].coded_partially;sbi++); | 
					
						
							|  |  |  |   /*If there's at least one partial SB, store individual coded block flags.*/ | 
					
						
							|  |  |  |   if(sbi<nsbs){ | 
					
						
							|  |  |  |     flag=frags[sb_maps[sbi][0][0]].coded; | 
					
						
							|  |  |  |     oggpackB_write(&_enc->opb,flag,1); | 
					
						
							|  |  |  |     run_count=0; | 
					
						
							|  |  |  |     nsbs=sbi=0; | 
					
						
							|  |  |  |     for(pli=0;pli<3;pli++){ | 
					
						
							|  |  |  |       nsbs+=_enc->state.fplanes[pli].nsbs; | 
					
						
							|  |  |  |       for(;sbi<nsbs;sbi++){ | 
					
						
							|  |  |  |         int       quadi; | 
					
						
							|  |  |  |         int       bi; | 
					
						
							|  |  |  |         ptrdiff_t fragi; | 
					
						
							|  |  |  |         if(sb_flags[sbi].coded_partially){ | 
					
						
							|  |  |  |           for(quadi=0;quadi<4;quadi++){ | 
					
						
							|  |  |  |             for(bi=0;bi<4;bi++){ | 
					
						
							|  |  |  |               fragi=sb_maps[sbi][quadi][bi]; | 
					
						
							|  |  |  |               if(fragi>=0){ | 
					
						
							|  |  |  |                 if(frags[fragi].coded!=flag){ | 
					
						
							|  |  |  |                   oc_block_run_pack(&_enc->opb,run_count); | 
					
						
							|  |  |  |                   flag=!flag; | 
					
						
							|  |  |  |                   run_count=1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else run_count++; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*Flush any trailing block coded run.*/ | 
					
						
							|  |  |  |     if(run_count>0)oc_block_run_pack(&_enc->opb,run_count); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_mb_modes_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   const unsigned char *mode_codes; | 
					
						
							|  |  |  |   const unsigned char *mode_bits; | 
					
						
							|  |  |  |   const unsigned char *mode_ranks; | 
					
						
							|  |  |  |   unsigned            *coded_mbis; | 
					
						
							|  |  |  |   size_t               ncoded_mbis; | 
					
						
							|  |  |  |   const signed char   *mb_modes; | 
					
						
							|  |  |  |   unsigned             mbii; | 
					
						
							|  |  |  |   int                  scheme; | 
					
						
							|  |  |  |   int                  mb_mode; | 
					
						
							|  |  |  |   scheme=_enc->chooser.scheme_list[0]; | 
					
						
							|  |  |  |   /*Encode the best scheme.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,scheme,3); | 
					
						
							|  |  |  |   /*If the chosen scheme is scheme 0, send the mode frequency ordering.*/ | 
					
						
							|  |  |  |   if(scheme==0){ | 
					
						
							|  |  |  |     for(mb_mode=0;mb_mode<OC_NMODES;mb_mode++){ | 
					
						
							|  |  |  |       oggpackB_write(&_enc->opb,_enc->chooser.scheme0_ranks[mb_mode],3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   mode_ranks=_enc->chooser.mode_ranks[scheme]; | 
					
						
							|  |  |  |   mode_bits=OC_MODE_BITS[scheme+1>>3]; | 
					
						
							|  |  |  |   mode_codes=OC_MODE_CODES[scheme+1>>3]; | 
					
						
							|  |  |  |   coded_mbis=_enc->coded_mbis; | 
					
						
							|  |  |  |   ncoded_mbis=_enc->ncoded_mbis; | 
					
						
							|  |  |  |   mb_modes=_enc->state.mb_modes; | 
					
						
							|  |  |  |   for(mbii=0;mbii<ncoded_mbis;mbii++){ | 
					
						
							|  |  |  |     int rank; | 
					
						
							|  |  |  |     rank=mode_ranks[mb_modes[coded_mbis[mbii]]]; | 
					
						
							|  |  |  |     oggpackB_write(&_enc->opb,mode_codes[rank],mode_bits[rank]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,oc_mv _mv){ | 
					
						
							|  |  |  |   int dx; | 
					
						
							|  |  |  |   int dy; | 
					
						
							|  |  |  |   dx=OC_MV_X(_mv); | 
					
						
							|  |  |  |   dy=OC_MV_Y(_mv); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   oggpackB_write(&_enc->opb, | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |    OC_MV_CODES[_mv_scheme][dx+31],OC_MV_BITS[_mv_scheme][dx+31]); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   oggpackB_write(&_enc->opb, | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |    OC_MV_CODES[_mv_scheme][dy+31],OC_MV_BITS[_mv_scheme][dy+31]); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_mvs_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   const unsigned     *coded_mbis; | 
					
						
							|  |  |  |   size_t              ncoded_mbis; | 
					
						
							|  |  |  |   const oc_mb_map    *mb_maps; | 
					
						
							|  |  |  |   const signed char  *mb_modes; | 
					
						
							|  |  |  |   const oc_fragment  *frags; | 
					
						
							|  |  |  |   const oc_mv        *frag_mvs; | 
					
						
							|  |  |  |   unsigned            mbii; | 
					
						
							|  |  |  |   int                 mv_scheme; | 
					
						
							|  |  |  |   /*Choose the coding scheme.*/ | 
					
						
							|  |  |  |   mv_scheme=_enc->mv_bits[1]<_enc->mv_bits[0]; | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,mv_scheme,1); | 
					
						
							|  |  |  |   /*Encode the motion vectors.
 | 
					
						
							|  |  |  |     Macro blocks are iterated in Hilbert scan order, but the MVs within the | 
					
						
							|  |  |  |      macro block are coded in raster order.*/ | 
					
						
							|  |  |  |   coded_mbis=_enc->coded_mbis; | 
					
						
							|  |  |  |   ncoded_mbis=_enc->ncoded_mbis; | 
					
						
							|  |  |  |   mb_modes=_enc->state.mb_modes; | 
					
						
							|  |  |  |   mb_maps=(const oc_mb_map *)_enc->state.mb_maps; | 
					
						
							|  |  |  |   frags=_enc->state.frags; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   frag_mvs=_enc->state.frag_mvs; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   for(mbii=0;mbii<ncoded_mbis;mbii++){ | 
					
						
							|  |  |  |     ptrdiff_t fragi; | 
					
						
							|  |  |  |     unsigned  mbi; | 
					
						
							|  |  |  |     int       bi; | 
					
						
							|  |  |  |     mbi=coded_mbis[mbii]; | 
					
						
							|  |  |  |     switch(mb_modes[mbi]){ | 
					
						
							|  |  |  |       case OC_MODE_INTER_MV: | 
					
						
							|  |  |  |       case OC_MODE_GOLDEN_MV:{ | 
					
						
							|  |  |  |         for(bi=0;;bi++){ | 
					
						
							|  |  |  |           fragi=mb_maps[mbi][0][bi]; | 
					
						
							|  |  |  |           if(frags[fragi].coded){ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |             oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |             /*Only code a single MV for this macro block.*/ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }break; | 
					
						
							|  |  |  |       case OC_MODE_INTER_MV_FOUR:{ | 
					
						
							|  |  |  |         for(bi=0;bi<4;bi++){ | 
					
						
							|  |  |  |           fragi=mb_maps[mbi][0][bi]; | 
					
						
							|  |  |  |           if(frags[fragi].coded){ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |             oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |             /*Keep coding all the MVs for this macro block.*/ | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_block_qis_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   const oc_fragment *frags; | 
					
						
							|  |  |  |   ptrdiff_t         *coded_fragis; | 
					
						
							|  |  |  |   ptrdiff_t          ncoded_fragis; | 
					
						
							|  |  |  |   ptrdiff_t          fragii; | 
					
						
							|  |  |  |   ptrdiff_t          run_count; | 
					
						
							|  |  |  |   ptrdiff_t          nqi0; | 
					
						
							|  |  |  |   int                flag; | 
					
						
							|  |  |  |   if(_enc->state.nqis<=1)return; | 
					
						
							|  |  |  |   ncoded_fragis=_enc->state.ntotal_coded_fragis; | 
					
						
							|  |  |  |   if(ncoded_fragis<=0)return; | 
					
						
							|  |  |  |   coded_fragis=_enc->state.coded_fragis; | 
					
						
							|  |  |  |   frags=_enc->state.frags; | 
					
						
							|  |  |  |   flag=!!frags[coded_fragis[0]].qii; | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,flag,1); | 
					
						
							|  |  |  |   nqi0=0; | 
					
						
							|  |  |  |   for(fragii=0;fragii<ncoded_fragis;){ | 
					
						
							|  |  |  |     for(run_count=0;fragii<ncoded_fragis;fragii++){ | 
					
						
							|  |  |  |       if(!!frags[coded_fragis[fragii]].qii!=flag)break; | 
					
						
							|  |  |  |       run_count++; | 
					
						
							|  |  |  |       nqi0+=!flag; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oc_sb_run_pack(&_enc->opb,run_count,flag,fragii>=ncoded_fragis); | 
					
						
							|  |  |  |     flag=!flag; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if(_enc->state.nqis<3||nqi0>=ncoded_fragis)return; | 
					
						
							|  |  |  |   for(fragii=0;!frags[coded_fragis[fragii]].qii;fragii++); | 
					
						
							|  |  |  |   flag=frags[coded_fragis[fragii]].qii-1; | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,flag,1); | 
					
						
							|  |  |  |   while(fragii<ncoded_fragis){ | 
					
						
							|  |  |  |     for(run_count=0;fragii<ncoded_fragis;fragii++){ | 
					
						
							|  |  |  |       int qii; | 
					
						
							|  |  |  |       qii=frags[coded_fragis[fragii]].qii; | 
					
						
							|  |  |  |       if(!qii)continue; | 
					
						
							|  |  |  |       if(qii-1!=flag)break; | 
					
						
							|  |  |  |       run_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oc_sb_run_pack(&_enc->opb,run_count,flag,fragii>=ncoded_fragis); | 
					
						
							|  |  |  |     flag=!flag; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Counts the tokens of each type used for the given range of coefficient
 | 
					
						
							|  |  |  |    indices in zig-zag order. | 
					
						
							|  |  |  |   _zzi_start:      The first zig-zag index to include. | 
					
						
							|  |  |  |   _zzi_end:        The first zig-zag index to not include. | 
					
						
							|  |  |  |   _token_counts_y: Returns the token counts for the Y' plane. | 
					
						
							|  |  |  |   _token_counts_c: Returns the token counts for the Cb and Cr planes.*/ | 
					
						
							|  |  |  | static void oc_enc_count_tokens(oc_enc_ctx *_enc,int _zzi_start,int _zzi_end, | 
					
						
							|  |  |  |  ptrdiff_t _token_counts_y[32],ptrdiff_t _token_counts_c[32]){ | 
					
						
							|  |  |  |   const unsigned char *dct_tokens; | 
					
						
							|  |  |  |   ptrdiff_t            ndct_tokens; | 
					
						
							|  |  |  |   int                  pli; | 
					
						
							|  |  |  |   int                  zzi; | 
					
						
							|  |  |  |   ptrdiff_t            ti; | 
					
						
							|  |  |  |   memset(_token_counts_y,0,32*sizeof(*_token_counts_y)); | 
					
						
							|  |  |  |   memset(_token_counts_c,0,32*sizeof(*_token_counts_c)); | 
					
						
							|  |  |  |   for(zzi=_zzi_start;zzi<_zzi_end;zzi++){ | 
					
						
							|  |  |  |     dct_tokens=_enc->dct_tokens[0][zzi]; | 
					
						
							|  |  |  |     ndct_tokens=_enc->ndct_tokens[0][zzi]; | 
					
						
							|  |  |  |     for(ti=_enc->dct_token_offs[0][zzi];ti<ndct_tokens;ti++){ | 
					
						
							|  |  |  |       _token_counts_y[dct_tokens[ti]]++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   for(pli=1;pli<3;pli++){ | 
					
						
							|  |  |  |     for(zzi=_zzi_start;zzi<_zzi_end;zzi++){ | 
					
						
							|  |  |  |       dct_tokens=_enc->dct_tokens[pli][zzi]; | 
					
						
							|  |  |  |       ndct_tokens=_enc->ndct_tokens[pli][zzi]; | 
					
						
							|  |  |  |       for(ti=_enc->dct_token_offs[pli][zzi];ti<ndct_tokens;ti++){ | 
					
						
							|  |  |  |         _token_counts_c[dct_tokens[ti]]++; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Computes the number of bits used for each of the potential Huffman code for
 | 
					
						
							|  |  |  |    the given list of token counts. | 
					
						
							|  |  |  |   The bits are added to whatever the current bit counts are.*/ | 
					
						
							|  |  |  | static void oc_enc_count_bits(oc_enc_ctx *_enc,int _hgi, | 
					
						
							|  |  |  |  const ptrdiff_t _token_counts[32],size_t _bit_counts[16]){ | 
					
						
							|  |  |  |   int huffi; | 
					
						
							|  |  |  |   int huff_offs; | 
					
						
							|  |  |  |   int token; | 
					
						
							|  |  |  |   huff_offs=_hgi<<4; | 
					
						
							|  |  |  |   for(huffi=0;huffi<16;huffi++){ | 
					
						
							|  |  |  |     for(token=0;token<32;token++){ | 
					
						
							|  |  |  |       _bit_counts[huffi]+= | 
					
						
							|  |  |  |        _token_counts[token]*_enc->huff_codes[huffi+huff_offs][token].nbits; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Returns the Huffman index using the fewest number of bits.*/ | 
					
						
							|  |  |  | static int oc_select_huff_idx(size_t _bit_counts[16]){ | 
					
						
							|  |  |  |   int best_huffi; | 
					
						
							|  |  |  |   int huffi; | 
					
						
							|  |  |  |   best_huffi=0; | 
					
						
							|  |  |  |   for(huffi=1;huffi<16;huffi++)if(_bit_counts[huffi]<_bit_counts[best_huffi]){ | 
					
						
							|  |  |  |     best_huffi=huffi; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return best_huffi; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_huff_group_pack(oc_enc_ctx *_enc, | 
					
						
							|  |  |  |  int _zzi_start,int _zzi_end,const int _huff_idxs[2]){ | 
					
						
							|  |  |  |   int zzi; | 
					
						
							|  |  |  |   for(zzi=_zzi_start;zzi<_zzi_end;zzi++){ | 
					
						
							|  |  |  |     int pli; | 
					
						
							|  |  |  |     for(pli=0;pli<3;pli++){ | 
					
						
							|  |  |  |       const unsigned char *dct_tokens; | 
					
						
							|  |  |  |       const ogg_uint16_t  *extra_bits; | 
					
						
							|  |  |  |       ptrdiff_t            ndct_tokens; | 
					
						
							|  |  |  |       const th_huff_code  *huff_codes; | 
					
						
							|  |  |  |       ptrdiff_t            ti; | 
					
						
							|  |  |  |       dct_tokens=_enc->dct_tokens[pli][zzi]; | 
					
						
							|  |  |  |       extra_bits=_enc->extra_bits[pli][zzi]; | 
					
						
							|  |  |  |       ndct_tokens=_enc->ndct_tokens[pli][zzi]; | 
					
						
							|  |  |  |       huff_codes=_enc->huff_codes[_huff_idxs[pli+1>>1]]; | 
					
						
							|  |  |  |       for(ti=_enc->dct_token_offs[pli][zzi];ti<ndct_tokens;ti++){ | 
					
						
							|  |  |  |         int token; | 
					
						
							|  |  |  |         int neb; | 
					
						
							|  |  |  |         token=dct_tokens[ti]; | 
					
						
							|  |  |  |         oggpackB_write(&_enc->opb,huff_codes[token].pattern, | 
					
						
							|  |  |  |          huff_codes[token].nbits); | 
					
						
							|  |  |  |         neb=OC_DCT_TOKEN_EXTRA_BITS[token]; | 
					
						
							|  |  |  |         if(neb)oggpackB_write(&_enc->opb,extra_bits[ti],neb); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_residual_tokens_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   static const unsigned char  OC_HUFF_GROUP_MIN[6]={0,1,6,15,28,64}; | 
					
						
							|  |  |  |   static const unsigned char *OC_HUFF_GROUP_MAX=OC_HUFF_GROUP_MIN+1; | 
					
						
							|  |  |  |   ptrdiff_t token_counts_y[32]; | 
					
						
							|  |  |  |   ptrdiff_t token_counts_c[32]; | 
					
						
							|  |  |  |   size_t    bits_y[16]; | 
					
						
							|  |  |  |   size_t    bits_c[16]; | 
					
						
							|  |  |  |   int       huff_idxs[2]; | 
					
						
							|  |  |  |   int       frame_type; | 
					
						
							|  |  |  |   int       hgi; | 
					
						
							|  |  |  |   frame_type=_enc->state.frame_type; | 
					
						
							|  |  |  |   /*Choose which Huffman tables to use for the DC token list.*/ | 
					
						
							|  |  |  |   oc_enc_count_tokens(_enc,0,1,token_counts_y,token_counts_c); | 
					
						
							|  |  |  |   memset(bits_y,0,sizeof(bits_y)); | 
					
						
							|  |  |  |   memset(bits_c,0,sizeof(bits_c)); | 
					
						
							|  |  |  |   oc_enc_count_bits(_enc,0,token_counts_y,bits_y); | 
					
						
							|  |  |  |   oc_enc_count_bits(_enc,0,token_counts_c,bits_c); | 
					
						
							|  |  |  |   huff_idxs[0]=oc_select_huff_idx(bits_y); | 
					
						
							|  |  |  |   huff_idxs[1]=oc_select_huff_idx(bits_c); | 
					
						
							|  |  |  |   /*Write the DC token list with the chosen tables.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,huff_idxs[0],4); | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,huff_idxs[1],4); | 
					
						
							|  |  |  |   _enc->huff_idxs[frame_type][0][0]=(unsigned char)huff_idxs[0]; | 
					
						
							|  |  |  |   _enc->huff_idxs[frame_type][0][1]=(unsigned char)huff_idxs[1]; | 
					
						
							|  |  |  |   oc_enc_huff_group_pack(_enc,0,1,huff_idxs); | 
					
						
							|  |  |  |   /*Choose which Huffman tables to use for the AC token lists.*/ | 
					
						
							|  |  |  |   memset(bits_y,0,sizeof(bits_y)); | 
					
						
							|  |  |  |   memset(bits_c,0,sizeof(bits_c)); | 
					
						
							|  |  |  |   for(hgi=1;hgi<5;hgi++){ | 
					
						
							|  |  |  |     oc_enc_count_tokens(_enc,OC_HUFF_GROUP_MIN[hgi],OC_HUFF_GROUP_MAX[hgi], | 
					
						
							|  |  |  |      token_counts_y,token_counts_c); | 
					
						
							|  |  |  |     oc_enc_count_bits(_enc,hgi,token_counts_y,bits_y); | 
					
						
							|  |  |  |     oc_enc_count_bits(_enc,hgi,token_counts_c,bits_c); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   huff_idxs[0]=oc_select_huff_idx(bits_y); | 
					
						
							|  |  |  |   huff_idxs[1]=oc_select_huff_idx(bits_c); | 
					
						
							|  |  |  |   /*Write the AC token lists using the chosen tables.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,huff_idxs[0],4); | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,huff_idxs[1],4); | 
					
						
							|  |  |  |   _enc->huff_idxs[frame_type][1][0]=(unsigned char)huff_idxs[0]; | 
					
						
							|  |  |  |   _enc->huff_idxs[frame_type][1][1]=(unsigned char)huff_idxs[1]; | 
					
						
							|  |  |  |   for(hgi=1;hgi<5;hgi++){ | 
					
						
							|  |  |  |     huff_idxs[0]+=16; | 
					
						
							|  |  |  |     huff_idxs[1]+=16; | 
					
						
							|  |  |  |     oc_enc_huff_group_pack(_enc, | 
					
						
							|  |  |  |      OC_HUFF_GROUP_MIN[hgi],OC_HUFF_GROUP_MAX[hgi],huff_idxs); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | /*Packs an explicit drop frame, instead of using the more efficient 0-byte
 | 
					
						
							|  |  |  |    packet. | 
					
						
							|  |  |  |   This is only enabled in VP3-compatibility mode, even though it is not | 
					
						
							|  |  |  |    strictly required for VP3 compatibility (VP3 could be encoded in AVI, which | 
					
						
							|  |  |  |    also supports dropping frames by inserting 0 byte packets). | 
					
						
							|  |  |  |   However, almost every _Theora_ player used to get this wrong (and many still | 
					
						
							|  |  |  |    do), and it wasn't until we started shipping a post-VP3 encoder that | 
					
						
							|  |  |  |    actually used non-VP3 features that this began to be discovered and fixed, | 
					
						
							|  |  |  |    despite being in the standard since 2004. | 
					
						
							|  |  |  |   The pack buffer must be reset before calling this function.*/ | 
					
						
							|  |  |  | static void oc_enc_drop_frame_pack(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   unsigned nsbs; | 
					
						
							|  |  |  |   /*Mark this as a data packet.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   /*Output the frame type (key frame or delta frame).*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,OC_INTER_FRAME,1); | 
					
						
							|  |  |  |   /*Write out the current qi list.
 | 
					
						
							|  |  |  |     We always use just 1 qi, to avoid wasting bits on the others.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->state.qis[0],6); | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   /*Coded block flags: everything is uncoded.*/ | 
					
						
							|  |  |  |   nsbs=_enc->state.nsbs; | 
					
						
							|  |  |  |   /*No partially coded SBs.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   oc_sb_run_pack(&_enc->opb,nsbs,0,1); | 
					
						
							|  |  |  |   /*No fully coded SBs.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,0,1); | 
					
						
							|  |  |  |   oc_sb_run_pack(&_enc->opb,nsbs,0,1); | 
					
						
							|  |  |  |   /*MB modes: just need write which scheme to use.
 | 
					
						
							|  |  |  |     Since we have no coded MBs, we can pick any of them except 0, which would | 
					
						
							|  |  |  |      require writing out an additional mode list.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,7,3); | 
					
						
							|  |  |  |   /*MVs: just need write which scheme to use.
 | 
					
						
							|  |  |  |     We can pick either one, since we have no MVs.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,1,1); | 
					
						
							|  |  |  |   /*Write the chosen DC token tables.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][0],4); | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][1],4); | 
					
						
							|  |  |  |   /*Write the chosen AC token tables.*/ | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][0],4); | 
					
						
							|  |  |  |   oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][1],4); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | static void oc_enc_frame_pack(oc_enc_ctx *_enc){ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*musl libc malloc()/realloc() calls might use floating point, so make sure
 | 
					
						
							|  |  |  |      we've cleared the MMX state for them.*/ | 
					
						
							|  |  |  |   oc_restore_fpu(&_enc->state); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   oggpackB_reset(&_enc->opb); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*Only proceed if we have some coded blocks.*/ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   if(_enc->state.ntotal_coded_fragis>0){ | 
					
						
							|  |  |  |     oc_enc_frame_header_pack(_enc); | 
					
						
							|  |  |  |     if(_enc->state.frame_type==OC_INTER_FRAME){ | 
					
						
							|  |  |  |       /*Coded block flags, MB modes, and MVs are only needed for delta frames.*/ | 
					
						
							|  |  |  |       oc_enc_coded_flags_pack(_enc); | 
					
						
							|  |  |  |       oc_enc_mb_modes_pack(_enc); | 
					
						
							|  |  |  |       oc_enc_mvs_pack(_enc); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oc_enc_block_qis_pack(_enc); | 
					
						
							|  |  |  |     oc_enc_tokenize_finish(_enc); | 
					
						
							|  |  |  |     oc_enc_residual_tokens_pack(_enc); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*If there are no coded blocks, we can drop this frame simply by emitting a
 | 
					
						
							|  |  |  |      0 byte packet. | 
					
						
							|  |  |  |     We emit an inter frame with no coded blocks in VP3-compatibility mode.*/ | 
					
						
							|  |  |  |   else if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   /*Success: Mark the packet as ready to be flushed.*/ | 
					
						
							|  |  |  |   _enc->packet_state=OC_PACKET_READY; | 
					
						
							|  |  |  | #if defined(OC_COLLECT_METRICS)
 | 
					
						
							|  |  |  |   oc_enc_mode_metrics_collect(_enc); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | void oc_enc_accel_init_c(oc_enc_ctx *_enc){ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   /*The implementations prefixed with oc_enc_ are encoder-specific.
 | 
					
						
							|  |  |  |     The rest we re-use from the decoder.*/ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | # if defined(OC_ENC_USE_VTABLE)
 | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->opt_vtable.frag_sad=oc_enc_frag_sad_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_c; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->opt_vtable.frag_intra_sad=oc_enc_frag_intra_sad_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_satd=oc_enc_frag_satd_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_c; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_c; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_border_ssd=oc_enc_frag_border_ssd_c; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_c; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.quantize=oc_enc_quantize_c; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c; | 
					
						
							|  |  |  |   _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_c; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | # endif
 | 
					
						
							|  |  |  |   _enc->opt_data.enquant_table_size=64*sizeof(oc_iquant); | 
					
						
							|  |  |  |   _enc->opt_data.enquant_table_alignment=16; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Initialize the macro block neighbor lists for MC analysis.
 | 
					
						
							|  |  |  |   This assumes that the entire mb_info memory region has been initialized with | 
					
						
							|  |  |  |    zeros.*/ | 
					
						
							|  |  |  | static void oc_enc_mb_info_init(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   oc_mb_enc_info    *embs; | 
					
						
							|  |  |  |   const signed char *mb_modes; | 
					
						
							|  |  |  |   unsigned           nhsbs; | 
					
						
							|  |  |  |   unsigned           nvsbs; | 
					
						
							|  |  |  |   unsigned           nhmbs; | 
					
						
							|  |  |  |   unsigned           nvmbs; | 
					
						
							|  |  |  |   unsigned           sby; | 
					
						
							|  |  |  |   mb_modes=_enc->state.mb_modes; | 
					
						
							|  |  |  |   embs=_enc->mb_info; | 
					
						
							|  |  |  |   nhsbs=_enc->state.fplanes[0].nhsbs; | 
					
						
							|  |  |  |   nvsbs=_enc->state.fplanes[0].nvsbs; | 
					
						
							|  |  |  |   nhmbs=_enc->state.nhmbs; | 
					
						
							|  |  |  |   nvmbs=_enc->state.nvmbs; | 
					
						
							|  |  |  |   for(sby=0;sby<nvsbs;sby++){ | 
					
						
							|  |  |  |     unsigned sbx; | 
					
						
							|  |  |  |     for(sbx=0;sbx<nhsbs;sbx++){ | 
					
						
							|  |  |  |       int quadi; | 
					
						
							|  |  |  |       for(quadi=0;quadi<4;quadi++){ | 
					
						
							|  |  |  |         /*Because of the Hilbert curve ordering the macro blocks are
 | 
					
						
							|  |  |  |            visited in, the available neighbors change depending on where in | 
					
						
							|  |  |  |            a super block the macro block is located. | 
					
						
							|  |  |  |           Only the first three vectors are used in the median calculation | 
					
						
							|  |  |  |            for the optimal predictor, and so the most important should be | 
					
						
							|  |  |  |            listed first. | 
					
						
							|  |  |  |           Additional vectors are used, so there will always be at least 3, | 
					
						
							|  |  |  |            except for in the upper-left most macro block.*/ | 
					
						
							|  |  |  |         /*The number of current neighbors for each macro block position.*/ | 
					
						
							|  |  |  |         static const unsigned char NCNEIGHBORS[4]={4,3,2,4}; | 
					
						
							|  |  |  |         /*The offset of each current neighbor in the X direction.*/ | 
					
						
							|  |  |  |         static const signed char   CDX[4][4]={ | 
					
						
							|  |  |  |           {-1,0,1,-1}, | 
					
						
							|  |  |  |           {-1,0,-1,}, | 
					
						
							|  |  |  |           {-1,-1}, | 
					
						
							|  |  |  |           {-1,0,0,1} | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         /*The offset of each current neighbor in the Y direction.*/ | 
					
						
							|  |  |  |         static const signed char   CDY[4][4]={ | 
					
						
							|  |  |  |           {0,-1,-1,-1}, | 
					
						
							|  |  |  |           {0,-1,-1}, | 
					
						
							|  |  |  |           {0,-1}, | 
					
						
							|  |  |  |           {0,-1,1,-1} | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         /*The offset of each previous neighbor in the X direction.*/ | 
					
						
							|  |  |  |         static const signed char   PDX[4]={-1,0,1,0}; | 
					
						
							|  |  |  |         /*The offset of each previous neighbor in the Y direction.*/ | 
					
						
							|  |  |  |         static const signed char   PDY[4]={0,-1,0,1}; | 
					
						
							|  |  |  |         unsigned mbi; | 
					
						
							|  |  |  |         int      mbx; | 
					
						
							|  |  |  |         int      mby; | 
					
						
							|  |  |  |         unsigned nmbi; | 
					
						
							|  |  |  |         int      nmbx; | 
					
						
							|  |  |  |         int      nmby; | 
					
						
							|  |  |  |         int      ni; | 
					
						
							|  |  |  |         mbi=(sby*nhsbs+sbx<<2)+quadi; | 
					
						
							|  |  |  |         if(mb_modes[mbi]==OC_MODE_INVALID)continue; | 
					
						
							|  |  |  |         mbx=2*sbx+(quadi>>1); | 
					
						
							|  |  |  |         mby=2*sby+(quadi+1>>1&1); | 
					
						
							|  |  |  |         /*Fill in the neighbors with current motion vectors available.*/ | 
					
						
							|  |  |  |         for(ni=0;ni<NCNEIGHBORS[quadi];ni++){ | 
					
						
							|  |  |  |           nmbx=mbx+CDX[quadi][ni]; | 
					
						
							|  |  |  |           nmby=mby+CDY[quadi][ni]; | 
					
						
							|  |  |  |           if(nmbx<0||nmbx>=nhmbs||nmby<0||nmby>=nvmbs)continue; | 
					
						
							|  |  |  |           nmbi=(nmby&~1)*nhmbs+((nmbx&~1)<<1)+OC_MB_MAP[nmby&1][nmbx&1]; | 
					
						
							|  |  |  |           if(mb_modes[nmbi]==OC_MODE_INVALID)continue; | 
					
						
							|  |  |  |           embs[mbi].cneighbors[embs[mbi].ncneighbors++]=nmbi; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /*Fill in the neighbors with previous motion vectors available.*/ | 
					
						
							|  |  |  |         for(ni=0;ni<4;ni++){ | 
					
						
							|  |  |  |           nmbx=mbx+PDX[ni]; | 
					
						
							|  |  |  |           nmby=mby+PDY[ni]; | 
					
						
							|  |  |  |           if(nmbx<0||nmbx>=nhmbs||nmby<0||nmby>=nvmbs)continue; | 
					
						
							|  |  |  |           nmbi=(nmby&~1)*nhmbs+((nmbx&~1)<<1)+OC_MB_MAP[nmby&1][nmbx&1]; | 
					
						
							|  |  |  |           if(mb_modes[nmbi]==OC_MODE_INVALID)continue; | 
					
						
							|  |  |  |           embs[mbi].pneighbors[embs[mbi].npneighbors++]=nmbi; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc, | 
					
						
							|  |  |  |  const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){ | 
					
						
							|  |  |  |   int ret; | 
					
						
							|  |  |  |   if(_enc==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |   if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL; | 
					
						
							|  |  |  |   if(_codes==NULL)_codes=TH_VP31_HUFF_CODES; | 
					
						
							|  |  |  |   /*Validate the codes.*/ | 
					
						
							|  |  |  |   oggpackB_reset(&_enc->opb); | 
					
						
							|  |  |  |   ret=oc_huff_codes_pack(&_enc->opb,_codes); | 
					
						
							|  |  |  |   if(ret<0)return ret; | 
					
						
							|  |  |  |   memcpy(_enc->huff_codes,_codes,sizeof(_enc->huff_codes)); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  | static void oc_enc_enquant_tables_init(oc_enc_ctx *_enc, | 
					
						
							|  |  |  |  const th_quant_info *_qinfo){ | 
					
						
							|  |  |  |   unsigned char *etd; | 
					
						
							|  |  |  |   size_t         ets; | 
					
						
							|  |  |  |   int            align; | 
					
						
							|  |  |  |   int            qii; | 
					
						
							|  |  |  |   int            qi; | 
					
						
							|  |  |  |   int            pli; | 
					
						
							|  |  |  |   int            qti; | 
					
						
							|  |  |  |   for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){ | 
					
						
							|  |  |  |     _enc->state.dequant_tables[qi][pli][qti]= | 
					
						
							|  |  |  |      _enc->state.dequant_table_data[qi][pli][qti]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /*Initialize the dequantization tables.*/ | 
					
						
							|  |  |  |   oc_dequant_tables_init(_enc->state.dequant_tables,NULL,_qinfo); | 
					
						
							|  |  |  |   /*And save off the DC values.*/ | 
					
						
							|  |  |  |   for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){ | 
					
						
							|  |  |  |     _enc->dequant_dc[qi][pli][qti]=_enc->state.dequant_tables[qi][pli][qti][0]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /*Set up storage for the quantization tables.*/ | 
					
						
							|  |  |  |   etd=_enc->enquant_table_data; | 
					
						
							|  |  |  |   ets=_enc->opt_data.enquant_table_size; | 
					
						
							|  |  |  |   align=-(etd-(unsigned char *)0)&_enc->opt_data.enquant_table_alignment-1; | 
					
						
							|  |  |  |   etd+=align; | 
					
						
							|  |  |  |   /*Set up the main tables.*/ | 
					
						
							|  |  |  |   for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){ | 
					
						
							|  |  |  |     _enc->enquant_tables[qi][pli][qti]=etd; | 
					
						
							|  |  |  |     oc_enc_enquant_table_init(_enc,etd, | 
					
						
							|  |  |  |      _enc->state.dequant_tables[qi][pli][qti]); | 
					
						
							|  |  |  |     etd+=ets; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /*Set up storage for the local copies we modify for each frame.*/ | 
					
						
							|  |  |  |   for(pli=0;pli<3;pli++)for(qii=0;qii<3;qii++)for(qti=0;qti<2;qti++){ | 
					
						
							|  |  |  |     _enc->enquant[pli][qii][qti]=etd; | 
					
						
							|  |  |  |     etd+=ets; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Updates the encoder state after the quantization parameters have been
 | 
					
						
							|  |  |  |    changed.*/ | 
					
						
							|  |  |  | static void oc_enc_quant_params_updated(oc_enc_ctx *_enc, | 
					
						
							|  |  |  |  const th_quant_info *_qinfo){ | 
					
						
							|  |  |  |   oc_enc_enquant_tables_init(_enc,_qinfo); | 
					
						
							|  |  |  |   memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits, | 
					
						
							|  |  |  |    sizeof(_enc->state.loop_filter_limits)); | 
					
						
							|  |  |  |   oc_enquant_qavg_init(_enc->log_qavg,_enc->log_plq,_enc->chroma_rd_scale, | 
					
						
							|  |  |  |    _enc->state.dequant_tables,_enc->state.info.pixel_fmt); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*Sets the quantization parameters to use.
 | 
					
						
							|  |  |  |   This may only be called before the setup header is written. | 
					
						
							|  |  |  |   If it is called multiple times, only the last call has any effect. | 
					
						
							|  |  |  |   _qinfo: The quantization parameters. | 
					
						
							|  |  |  |           These are described in more detail in theoraenc.h. | 
					
						
							|  |  |  |           This can be NULL, in which case the default quantization parameters | 
					
						
							|  |  |  |            will be used.*/ | 
					
						
							|  |  |  | static int oc_enc_set_quant_params(oc_enc_ctx *_enc, | 
					
						
							|  |  |  |  const th_quant_info *_qinfo){ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   th_quant_info old_qinfo; | 
					
						
							|  |  |  |   int           ret; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   if(_enc==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |   if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL; | 
					
						
							|  |  |  |   if(_qinfo==NULL)_qinfo=&TH_DEF_QUANT_INFO; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   memcpy(&old_qinfo,&_enc->qinfo,sizeof(old_qinfo)); | 
					
						
							|  |  |  |   ret=oc_quant_params_clone(&_enc->qinfo,_qinfo); | 
					
						
							|  |  |  |   if(ret<0){ | 
					
						
							|  |  |  |     oc_quant_params_clear(&_enc->qinfo); | 
					
						
							|  |  |  |     memcpy(&_enc->qinfo,&old_qinfo,sizeof(old_qinfo)); | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   else oc_quant_params_clear(&old_qinfo); | 
					
						
							|  |  |  |   oc_enc_quant_params_updated(_enc,_qinfo); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_clear(oc_enc_ctx *_enc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){ | 
					
						
							|  |  |  |   th_info   info; | 
					
						
							|  |  |  |   size_t    mcu_nmbs; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   ptrdiff_t mcu_ncfrags; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   ptrdiff_t mcu_nfrags; | 
					
						
							|  |  |  |   int       hdec; | 
					
						
							|  |  |  |   int       vdec; | 
					
						
							|  |  |  |   int       ret; | 
					
						
							|  |  |  |   int       pli; | 
					
						
							|  |  |  |   /*Clean up the requested settings.*/ | 
					
						
							|  |  |  |   memcpy(&info,_info,sizeof(info)); | 
					
						
							|  |  |  |   info.version_major=TH_VERSION_MAJOR; | 
					
						
							|  |  |  |   info.version_minor=TH_VERSION_MINOR; | 
					
						
							|  |  |  |   info.version_subminor=TH_VERSION_SUB; | 
					
						
							|  |  |  |   if(info.quality>63)info.quality=63; | 
					
						
							|  |  |  |   if(info.quality<0)info.quality=32; | 
					
						
							|  |  |  |   if(info.target_bitrate<0)info.target_bitrate=0; | 
					
						
							|  |  |  |   /*Initialize the shared encoder/decoder state.*/ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   ret=oc_state_init(&_enc->state,&info,6); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   if(ret<0)return ret; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   oc_enc_accel_init(_enc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->mb_info=_ogg_calloc(_enc->state.nmbs,sizeof(*_enc->mb_info)); | 
					
						
							|  |  |  |   _enc->frag_dc=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_dc)); | 
					
						
							|  |  |  |   _enc->coded_mbis= | 
					
						
							|  |  |  |    (unsigned *)_ogg_malloc(_enc->state.nmbs*sizeof(*_enc->coded_mbis)); | 
					
						
							|  |  |  |   hdec=!(_enc->state.info.pixel_fmt&1); | 
					
						
							|  |  |  |   vdec=!(_enc->state.info.pixel_fmt&2); | 
					
						
							|  |  |  |   /*If chroma is sub-sampled in the vertical direction, we have to encode two
 | 
					
						
							|  |  |  |      super block rows of Y' for each super block row of Cb and Cr.*/ | 
					
						
							|  |  |  |   _enc->mcu_nvsbs=1<<vdec; | 
					
						
							|  |  |  |   mcu_nmbs=_enc->mcu_nvsbs*_enc->state.fplanes[0].nhsbs*(size_t)4; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   mcu_ncfrags=mcu_nmbs<<3-(hdec+vdec); | 
					
						
							|  |  |  |   mcu_nfrags=4*mcu_nmbs+mcu_ncfrags; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->mcu_skip_ssd=(unsigned *)_ogg_malloc( | 
					
						
							|  |  |  |    mcu_nfrags*sizeof(*_enc->mcu_skip_ssd)); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->mcu_rd_scale=(ogg_uint16_t *)_ogg_malloc( | 
					
						
							|  |  |  |    (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_scale)); | 
					
						
							|  |  |  |   _enc->mcu_rd_iscale=(ogg_uint16_t *)_ogg_malloc( | 
					
						
							|  |  |  |    (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_iscale)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   for(pli=0;pli<3;pli++){ | 
					
						
							|  |  |  |     _enc->dct_tokens[pli]=(unsigned char **)oc_malloc_2d(64, | 
					
						
							|  |  |  |      _enc->state.fplanes[pli].nfrags,sizeof(**_enc->dct_tokens)); | 
					
						
							|  |  |  |     _enc->extra_bits[pli]=(ogg_uint16_t **)oc_malloc_2d(64, | 
					
						
							|  |  |  |      _enc->state.fplanes[pli].nfrags,sizeof(**_enc->extra_bits)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #if defined(OC_COLLECT_METRICS)
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->frag_sad=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_sad)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->frag_satd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_satd)); | 
					
						
							|  |  |  |   _enc->frag_ssd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_ssd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->enquant_table_data=(unsigned char *)_ogg_malloc( | 
					
						
							|  |  |  |    (64+3)*3*2*_enc->opt_data.enquant_table_size | 
					
						
							|  |  |  |    +_enc->opt_data.enquant_table_alignment-1); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->keyframe_frequency_force=1<<_enc->state.info.keyframe_granule_shift; | 
					
						
							|  |  |  |   _enc->state.qis[0]=_enc->state.info.quality; | 
					
						
							|  |  |  |   _enc->state.nqis=1; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->activity_avg=90<<12; | 
					
						
							|  |  |  |   _enc->luma_avg=128<<8; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   oc_rc_state_init(&_enc->rc,_enc); | 
					
						
							|  |  |  |   oggpackB_writeinit(&_enc->opb); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes)); | 
					
						
							|  |  |  |   memset(_enc->qinfo.qi_ranges,0,sizeof(_enc->qinfo.qi_ranges)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   /*Reset the packet-out state machine.*/ | 
					
						
							|  |  |  |   _enc->packet_state=OC_PACKET_INFO_HDR; | 
					
						
							|  |  |  |   _enc->dup_count=0; | 
					
						
							|  |  |  |   _enc->nqueued_dups=0; | 
					
						
							|  |  |  |   _enc->prev_dup_count=0; | 
					
						
							|  |  |  |   /*Enable speed optimizations up through early skip by default.*/ | 
					
						
							|  |  |  |   _enc->sp_level=OC_SP_LEVEL_EARLY_SKIP; | 
					
						
							|  |  |  |   /*Disable VP3 compatibility by default.*/ | 
					
						
							|  |  |  |   _enc->vp3_compatible=0; | 
					
						
							|  |  |  |   /*No INTER frames coded yet.*/ | 
					
						
							|  |  |  |   _enc->coded_inter_frame=0; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL | 
					
						
							|  |  |  |    ||_enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL | 
					
						
							|  |  |  |    ||_enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL | 
					
						
							|  |  |  |    ||_enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL | 
					
						
							|  |  |  |    ||_enc->extra_bits[2]==NULL | 
					
						
							|  |  |  | #if defined(OC_COLLECT_METRICS)
 | 
					
						
							|  |  |  |    ||_enc->frag_sad==NULL||_enc->frag_satd==NULL||_enc->frag_ssd==NULL | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |    ||oc_enc_set_quant_params(_enc,NULL)<0){ | 
					
						
							|  |  |  |     oc_enc_clear(_enc); | 
					
						
							|  |  |  |     return TH_EFAULT; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   oc_mode_scheme_chooser_init(&_enc->chooser); | 
					
						
							|  |  |  |   oc_enc_mb_info_init(_enc); | 
					
						
							|  |  |  |   memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_clear(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   int pli; | 
					
						
							|  |  |  |   oc_rc_state_clear(&_enc->rc); | 
					
						
							|  |  |  |   oggpackB_writeclear(&_enc->opb); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   oc_quant_params_clear(&_enc->qinfo); | 
					
						
							|  |  |  |   _ogg_free(_enc->enquant_table_data); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #if defined(OC_COLLECT_METRICS)
 | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*Save the collected metrics from this run.
 | 
					
						
							|  |  |  |     Use tools/process_modedec_stats to actually generate modedec.h from the | 
					
						
							|  |  |  |      resulting file.*/ | 
					
						
							|  |  |  |   oc_mode_metrics_dump(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _ogg_free(_enc->frag_ssd); | 
					
						
							|  |  |  |   _ogg_free(_enc->frag_satd); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _ogg_free(_enc->frag_sad); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |   for(pli=3;pli-->0;){ | 
					
						
							|  |  |  |     oc_free_2d(_enc->extra_bits[pli]); | 
					
						
							|  |  |  |     oc_free_2d(_enc->dct_tokens[pli]); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _ogg_free(_enc->mcu_rd_iscale); | 
					
						
							|  |  |  |   _ogg_free(_enc->mcu_rd_scale); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _ogg_free(_enc->mcu_skip_ssd); | 
					
						
							|  |  |  |   _ogg_free(_enc->coded_mbis); | 
					
						
							|  |  |  |   _ogg_free(_enc->frag_dc); | 
					
						
							|  |  |  |   _ogg_free(_enc->mb_info); | 
					
						
							|  |  |  |   oc_state_clear(&_enc->state); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_drop_frame(th_enc_ctx *_enc){ | 
					
						
							|  |  |  |   /*Use the previous frame's reconstruction.*/ | 
					
						
							|  |  |  |   _enc->state.ref_frame_idx[OC_FRAME_SELF]= | 
					
						
							|  |  |  |    _enc->state.ref_frame_idx[OC_FRAME_PREV]; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->state.ref_frame_data[OC_FRAME_SELF]= | 
					
						
							|  |  |  |    _enc->state.ref_frame_data[OC_FRAME_PREV]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   /*Flag motion vector analysis about the frame drop.*/ | 
					
						
							|  |  |  |   _enc->prevframe_dropped=1; | 
					
						
							|  |  |  |   /*Zero the packet.*/ | 
					
						
							|  |  |  |   oggpackB_reset(&_enc->opb); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/ | 
					
						
							|  |  |  |   if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_compress_keyframe(oc_enc_ctx *_enc,int _recode){ | 
					
						
							|  |  |  |   if(_enc->state.info.target_bitrate>0){ | 
					
						
							|  |  |  |     _enc->state.qis[0]=oc_enc_select_qi(_enc,OC_INTRA_FRAME, | 
					
						
							|  |  |  |      _enc->state.curframe_num>0); | 
					
						
							|  |  |  |     _enc->state.nqis=1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   oc_enc_calc_lambda(_enc,OC_INTRA_FRAME); | 
					
						
							|  |  |  |   oc_enc_analyze_intra(_enc,_recode); | 
					
						
							|  |  |  |   oc_enc_frame_pack(_enc); | 
					
						
							|  |  |  |   /*On the first frame, the previous call was an initial dry-run to prime
 | 
					
						
							|  |  |  |      feed-forward statistics.*/ | 
					
						
							|  |  |  |   if(!_recode&&_enc->state.curframe_num==0){ | 
					
						
							|  |  |  |     if(_enc->state.info.target_bitrate>0){ | 
					
						
							|  |  |  |       oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3, | 
					
						
							|  |  |  |                              OC_INTRA_FRAME,_enc->state.qis[0],1,0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     oc_enc_compress_keyframe(_enc,1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_enc_compress_frame(oc_enc_ctx *_enc,int _recode){ | 
					
						
							|  |  |  |   if(_enc->state.info.target_bitrate>0){ | 
					
						
							|  |  |  |     _enc->state.qis[0]=oc_enc_select_qi(_enc,OC_INTER_FRAME,1); | 
					
						
							|  |  |  |     _enc->state.nqis=1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   oc_enc_calc_lambda(_enc,OC_INTER_FRAME); | 
					
						
							|  |  |  |   if(oc_enc_analyze_inter(_enc,_enc->rc.twopass!=2,_recode)){ | 
					
						
							|  |  |  |     /*Mode analysis thinks this should have been a keyframe; start over.*/ | 
					
						
							|  |  |  |     oc_enc_compress_keyframe(_enc,1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else{ | 
					
						
							|  |  |  |     oc_enc_frame_pack(_enc); | 
					
						
							|  |  |  |     if(!_enc->coded_inter_frame){ | 
					
						
							|  |  |  |       /*On the first INTER frame, the previous call was an initial dry-run to
 | 
					
						
							|  |  |  |          prime feed-forward statistics.*/ | 
					
						
							|  |  |  |       _enc->coded_inter_frame=1; | 
					
						
							|  |  |  |       if(_enc->state.info.target_bitrate>0){ | 
					
						
							|  |  |  |         /*Rate control also needs to prime.*/ | 
					
						
							|  |  |  |         oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3, | 
					
						
							|  |  |  |          OC_INTER_FRAME,_enc->state.qis[0],1,0); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       oc_enc_compress_frame(_enc,1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Set the granule position for the next packet to output based on the current
 | 
					
						
							|  |  |  |    internal state.*/ | 
					
						
							|  |  |  | static void oc_enc_set_granpos(oc_enc_ctx *_enc){ | 
					
						
							|  |  |  |   unsigned dup_offs; | 
					
						
							|  |  |  |   /*Add an offset for the number of duplicate frames we've emitted so far.*/ | 
					
						
							|  |  |  |   dup_offs=_enc->prev_dup_count-_enc->nqueued_dups; | 
					
						
							|  |  |  |   /*If the current frame was a keyframe, use it for the high part.*/ | 
					
						
							|  |  |  |   if(_enc->state.frame_type==OC_INTRA_FRAME){ | 
					
						
							|  |  |  |     _enc->state.granpos=(_enc->state.curframe_num+_enc->state.granpos_bias<< | 
					
						
							|  |  |  |      _enc->state.info.keyframe_granule_shift)+dup_offs; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /*Otherwise use the last keyframe in the high part and put the current frame
 | 
					
						
							|  |  |  |      in the low part.*/ | 
					
						
							|  |  |  |   else{ | 
					
						
							|  |  |  |     _enc->state.granpos= | 
					
						
							|  |  |  |      (_enc->state.keyframe_num+_enc->state.granpos_bias<< | 
					
						
							|  |  |  |      _enc->state.info.keyframe_granule_shift) | 
					
						
							|  |  |  |      +_enc->state.curframe_num-_enc->state.keyframe_num+dup_offs; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | th_enc_ctx *th_encode_alloc(const th_info *_info){ | 
					
						
							|  |  |  |   oc_enc_ctx *enc; | 
					
						
							|  |  |  |   if(_info==NULL)return NULL; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   enc=oc_aligned_malloc(sizeof(*enc),16); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   if(enc==NULL||oc_enc_init(enc,_info)<0){ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |     oc_aligned_free(enc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return enc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void th_encode_free(th_enc_ctx *_enc){ | 
					
						
							|  |  |  |   if(_enc!=NULL){ | 
					
						
							|  |  |  |     oc_enc_clear(_enc); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |     oc_aligned_free(_enc); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){ | 
					
						
							|  |  |  |   switch(_req){ | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_HUFFMAN_CODES:{ | 
					
						
							|  |  |  |       if(_buf==NULL&&_buf_sz!=0|| | 
					
						
							|  |  |  |        _buf!=NULL&&_buf_sz!=sizeof(th_huff_table)*TH_NHUFFMAN_TABLES){ | 
					
						
							|  |  |  |         return TH_EINVAL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return oc_enc_set_huffman_codes(_enc,(const th_huff_table *)_buf); | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_QUANT_PARAMS:{ | 
					
						
							|  |  |  |       if(_buf==NULL&&_buf_sz!=0|| | 
					
						
							|  |  |  |        _buf!=NULL&&_buf_sz!=sizeof(th_quant_info)){ | 
					
						
							|  |  |  |         return TH_EINVAL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return oc_enc_set_quant_params(_enc,(th_quant_info *)_buf); | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE:{ | 
					
						
							|  |  |  |       ogg_uint32_t keyframe_frequency_force; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(keyframe_frequency_force))return TH_EINVAL; | 
					
						
							|  |  |  |       keyframe_frequency_force=*(ogg_uint32_t *)_buf; | 
					
						
							|  |  |  |       if(keyframe_frequency_force<=0)keyframe_frequency_force=1; | 
					
						
							|  |  |  |       if(_enc->packet_state==OC_PACKET_INFO_HDR){ | 
					
						
							|  |  |  |         /*It's still early enough to enlarge keyframe_granule_shift.*/ | 
					
						
							|  |  |  |         _enc->state.info.keyframe_granule_shift=OC_CLAMPI( | 
					
						
							|  |  |  |          _enc->state.info.keyframe_granule_shift, | 
					
						
							|  |  |  |          OC_ILOG_32(keyframe_frequency_force-1),31); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       _enc->keyframe_frequency_force=OC_MINI(keyframe_frequency_force, | 
					
						
							|  |  |  |        (ogg_uint32_t)1U<<_enc->state.info.keyframe_granule_shift); | 
					
						
							|  |  |  |       *(ogg_uint32_t *)_buf=_enc->keyframe_frequency_force; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_VP3_COMPATIBLE:{ | 
					
						
							|  |  |  |       int vp3_compatible; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |       int ret; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(vp3_compatible))return TH_EINVAL; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |       /*Try this before we change anything else, because it can fail.*/ | 
					
						
							|  |  |  |       ret=oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO); | 
					
						
							|  |  |  |       /*If we can't allocate enough memory, don't change any of the state.*/ | 
					
						
							|  |  |  |       if(ret==TH_EFAULT)return ret; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |       vp3_compatible=*(int *)_buf; | 
					
						
							|  |  |  |       _enc->vp3_compatible=vp3_compatible; | 
					
						
							|  |  |  |       if(oc_enc_set_huffman_codes(_enc,TH_VP31_HUFF_CODES)<0)vp3_compatible=0; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |       if(ret<0)vp3_compatible=0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |       if(_enc->state.info.pixel_fmt!=TH_PF_420|| | 
					
						
							|  |  |  |        _enc->state.info.pic_width<_enc->state.info.frame_width|| | 
					
						
							|  |  |  |        _enc->state.info.pic_height<_enc->state.info.frame_height|| | 
					
						
							|  |  |  |       /*If we have more than 4095 super blocks, VP3's RLE coding might
 | 
					
						
							|  |  |  |          overflow. | 
					
						
							|  |  |  |         We could overcome this by ensuring we flip the coded/not-coded flags on | 
					
						
							|  |  |  |          at least one super block in the frame, but we pick the simple solution | 
					
						
							|  |  |  |          of just telling the user the stream will be incompatible instead. | 
					
						
							|  |  |  |         It's unlikely the old VP3 codec would be able to decode streams at this | 
					
						
							|  |  |  |          resolution in real time in the first place.*/ | 
					
						
							|  |  |  |        _enc->state.nsbs>4095){ | 
					
						
							|  |  |  |         vp3_compatible=0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       *(int *)_buf=vp3_compatible; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_GET_SPLEVEL_MAX:{ | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(int))return TH_EINVAL; | 
					
						
							|  |  |  |       *(int *)_buf=OC_SP_LEVEL_MAX; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_SPLEVEL:{ | 
					
						
							|  |  |  |       int speed; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(speed))return TH_EINVAL; | 
					
						
							|  |  |  |       speed=*(int *)_buf; | 
					
						
							|  |  |  |       if(speed<0||speed>OC_SP_LEVEL_MAX)return TH_EINVAL; | 
					
						
							|  |  |  |       _enc->sp_level=speed; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_GET_SPLEVEL:{ | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(int))return TH_EINVAL; | 
					
						
							|  |  |  |       *(int *)_buf=_enc->sp_level; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_DUP_COUNT:{ | 
					
						
							|  |  |  |       int dup_count; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(dup_count))return TH_EINVAL; | 
					
						
							|  |  |  |       dup_count=*(int *)_buf; | 
					
						
							|  |  |  |       if(dup_count>=_enc->keyframe_frequency_force)return TH_EINVAL; | 
					
						
							|  |  |  |       _enc->dup_count=OC_MAXI(dup_count,0); | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_QUALITY:{ | 
					
						
							|  |  |  |       int qi; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_enc->state.info.target_bitrate>0)return TH_EINVAL; | 
					
						
							|  |  |  |       qi=*(int *)_buf; | 
					
						
							|  |  |  |       if(qi<0||qi>63)return TH_EINVAL; | 
					
						
							|  |  |  |       _enc->state.info.quality=qi; | 
					
						
							|  |  |  |       _enc->state.qis[0]=(unsigned char)qi; | 
					
						
							|  |  |  |       _enc->state.nqis=1; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_BITRATE:{ | 
					
						
							|  |  |  |       long bitrate; | 
					
						
							|  |  |  |       int  reset; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       bitrate=*(long *)_buf; | 
					
						
							|  |  |  |       if(bitrate<=0)return TH_EINVAL; | 
					
						
							|  |  |  |       reset=_enc->state.info.target_bitrate<=0; | 
					
						
							|  |  |  |       _enc->state.info.target_bitrate=bitrate>INT_MAX?INT_MAX:bitrate; | 
					
						
							|  |  |  |       if(reset)oc_rc_state_init(&_enc->rc,_enc); | 
					
						
							|  |  |  |       else oc_enc_rc_resize(_enc); | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_RATE_FLAGS:{ | 
					
						
							|  |  |  |       int set; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(set))return TH_EINVAL; | 
					
						
							|  |  |  |       if(_enc->state.info.target_bitrate<=0)return TH_EINVAL; | 
					
						
							|  |  |  |       set=*(int *)_buf; | 
					
						
							|  |  |  |       _enc->rc.drop_frames=set&TH_RATECTL_DROP_FRAMES; | 
					
						
							|  |  |  |       _enc->rc.cap_overflow=set&TH_RATECTL_CAP_OVERFLOW; | 
					
						
							|  |  |  |       _enc->rc.cap_underflow=set&TH_RATECTL_CAP_UNDERFLOW; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_RATE_BUFFER:{ | 
					
						
							|  |  |  |       int set; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_buf_sz!=sizeof(set))return TH_EINVAL; | 
					
						
							|  |  |  |       if(_enc->state.info.target_bitrate<=0)return TH_EINVAL; | 
					
						
							|  |  |  |       set=*(int *)_buf; | 
					
						
							|  |  |  |       _enc->rc.buf_delay=set; | 
					
						
							|  |  |  |       oc_enc_rc_resize(_enc); | 
					
						
							|  |  |  |       *(int *)_buf=_enc->rc.buf_delay; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_2PASS_OUT:{ | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_enc->state.info.target_bitrate<=0|| | 
					
						
							|  |  |  |        _enc->state.curframe_num>=0&&_enc->rc.twopass!=1|| | 
					
						
							|  |  |  |        _buf_sz!=sizeof(unsigned char *)){ | 
					
						
							|  |  |  |         return TH_EINVAL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return oc_enc_rc_2pass_out(_enc,(unsigned char **)_buf); | 
					
						
							|  |  |  |     }break; | 
					
						
							|  |  |  |     case TH_ENCCTL_2PASS_IN:{ | 
					
						
							|  |  |  |       if(_enc==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_enc->state.info.target_bitrate<=0|| | 
					
						
							|  |  |  |        _enc->state.curframe_num>=0&&_enc->rc.twopass!=2){ | 
					
						
							|  |  |  |         return TH_EINVAL; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return oc_enc_rc_2pass_in(_enc,_buf,_buf_sz); | 
					
						
							|  |  |  |     }break; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |     case TH_ENCCTL_SET_COMPAT_CONFIG:{ | 
					
						
							|  |  |  |       unsigned char buf[7]; | 
					
						
							|  |  |  |       oc_pack_buf   opb; | 
					
						
							|  |  |  |       th_quant_info qinfo; | 
					
						
							|  |  |  |       th_huff_code  huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]; | 
					
						
							|  |  |  |       int           ret; | 
					
						
							|  |  |  |       int           i; | 
					
						
							|  |  |  |       if(_enc==NULL||_buf==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL; | 
					
						
							|  |  |  |       oc_pack_readinit(&opb,_buf,_buf_sz); | 
					
						
							|  |  |  |       /*Validate the setup packet header.*/ | 
					
						
							|  |  |  |       for(i=0;i<7;i++)buf[i]=(unsigned char)oc_pack_read(&opb,8); | 
					
						
							|  |  |  |       if(!(buf[0]&0x80)||memcmp(buf+1,"theora",6)!=0)return TH_ENOTFORMAT; | 
					
						
							|  |  |  |       if(buf[0]!=0x82)return TH_EBADHEADER; | 
					
						
							|  |  |  |       /*Reads its contents.*/ | 
					
						
							|  |  |  |       ret=oc_quant_params_unpack(&opb,&qinfo); | 
					
						
							|  |  |  |       if(ret<0){ | 
					
						
							|  |  |  |         oc_quant_params_clear(&qinfo); | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       ret=oc_huff_codes_unpack(&opb,huff_codes); | 
					
						
							|  |  |  |       if(ret<0){ | 
					
						
							|  |  |  |         oc_quant_params_clear(&qinfo); | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /*Install the new state.*/ | 
					
						
							|  |  |  |       oc_quant_params_clear(&_enc->qinfo); | 
					
						
							|  |  |  |       memcpy(&_enc->qinfo,&qinfo,sizeof(qinfo)); | 
					
						
							|  |  |  |       oc_enc_quant_params_updated(_enc,&qinfo); | 
					
						
							|  |  |  |       memcpy(_enc->huff_codes,huff_codes,sizeof(_enc->huff_codes)); | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #if defined(OC_COLLECT_METRICS)
 | 
					
						
							|  |  |  |     case TH_ENCCTL_SET_METRICS_FILE:{ | 
					
						
							|  |  |  |       OC_MODE_METRICS_FILENAME=(const char *)_buf; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     default:return TH_EIMPL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int th_encode_flushheader(th_enc_ctx *_enc,th_comment *_tc,ogg_packet *_op){ | 
					
						
							|  |  |  |   if(_enc==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |   return oc_state_flushheader(&_enc->state,&_enc->packet_state,&_enc->opb, | 
					
						
							|  |  |  |    &_enc->qinfo,(const th_huff_table *)_enc->huff_codes,th_version_string(), | 
					
						
							|  |  |  |    _tc,_op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void oc_img_plane_copy_pad(th_img_plane *_dst,th_img_plane *_src, | 
					
						
							|  |  |  |  ogg_int32_t _pic_x,ogg_int32_t _pic_y, | 
					
						
							|  |  |  |  ogg_int32_t _pic_width,ogg_int32_t _pic_height){ | 
					
						
							|  |  |  |   unsigned char *dst; | 
					
						
							|  |  |  |   int            dstride; | 
					
						
							|  |  |  |   ogg_uint32_t   frame_width; | 
					
						
							|  |  |  |   ogg_uint32_t   frame_height; | 
					
						
							|  |  |  |   ogg_uint32_t   y; | 
					
						
							|  |  |  |   frame_width=_dst->width; | 
					
						
							|  |  |  |   frame_height=_dst->height; | 
					
						
							|  |  |  |   /*If we have _no_ data, just encode a dull green.*/ | 
					
						
							|  |  |  |   if(_pic_width==0||_pic_height==0){ | 
					
						
							|  |  |  |     dst=_dst->data; | 
					
						
							|  |  |  |     dstride=_dst->stride; | 
					
						
							|  |  |  |     for(y=0;y<frame_height;y++){ | 
					
						
							|  |  |  |       memset(dst,0,frame_width*sizeof(*dst)); | 
					
						
							|  |  |  |       dst+=dstride; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /*Otherwise, copy what we do have, and add our own padding.*/ | 
					
						
							|  |  |  |   else{ | 
					
						
							|  |  |  |     unsigned char *dst_data; | 
					
						
							|  |  |  |     unsigned char *src_data; | 
					
						
							|  |  |  |     unsigned char *src; | 
					
						
							|  |  |  |     int            sstride; | 
					
						
							|  |  |  |     ogg_uint32_t   x; | 
					
						
							|  |  |  |     /*Step 1: Copy the data we do have.*/ | 
					
						
							|  |  |  |     dstride=_dst->stride; | 
					
						
							|  |  |  |     sstride=_src->stride; | 
					
						
							|  |  |  |     dst_data=_dst->data; | 
					
						
							|  |  |  |     src_data=_src->data; | 
					
						
							|  |  |  |     dst=dst_data+_pic_y*(ptrdiff_t)dstride+_pic_x; | 
					
						
							|  |  |  |     src=src_data+_pic_y*(ptrdiff_t)sstride+_pic_x; | 
					
						
							|  |  |  |     for(y=0;y<_pic_height;y++){ | 
					
						
							|  |  |  |       memcpy(dst,src,_pic_width); | 
					
						
							|  |  |  |       dst+=dstride; | 
					
						
							|  |  |  |       src+=sstride; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*Step 2: Perform a low-pass extension into the padding region.*/ | 
					
						
							|  |  |  |     /*Left side.*/ | 
					
						
							|  |  |  |     for(x=_pic_x;x-->0;){ | 
					
						
							|  |  |  |       dst=dst_data+_pic_y*(ptrdiff_t)dstride+x; | 
					
						
							|  |  |  |       for(y=0;y<_pic_height;y++){ | 
					
						
							|  |  |  |         dst[0]=(dst[1]<<1)+(dst-(dstride&-(y>0)))[1] | 
					
						
							|  |  |  |          +(dst+(dstride&-(y+1<_pic_height)))[1]+2>>2; | 
					
						
							|  |  |  |         dst+=dstride; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*Right side.*/ | 
					
						
							|  |  |  |     for(x=_pic_x+_pic_width;x<frame_width;x++){ | 
					
						
							|  |  |  |       dst=dst_data+_pic_y*(ptrdiff_t)dstride+x-1; | 
					
						
							|  |  |  |       for(y=0;y<_pic_height;y++){ | 
					
						
							|  |  |  |         dst[1]=(dst[0]<<1)+(dst-(dstride&-(y>0)))[0] | 
					
						
							|  |  |  |          +(dst+(dstride&-(y+1<_pic_height)))[0]+2>>2; | 
					
						
							|  |  |  |         dst+=dstride; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*Top.*/ | 
					
						
							|  |  |  |     dst=dst_data+_pic_y*(ptrdiff_t)dstride; | 
					
						
							|  |  |  |     for(y=_pic_y;y-->0;){ | 
					
						
							|  |  |  |       for(x=0;x<frame_width;x++){ | 
					
						
							|  |  |  |         (dst-dstride)[x]=(dst[x]<<1)+dst[x-(x>0)] | 
					
						
							|  |  |  |          +dst[x+(x+1<frame_width)]+2>>2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       dst-=dstride; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*Bottom.*/ | 
					
						
							|  |  |  |     dst=dst_data+(_pic_y+_pic_height)*(ptrdiff_t)dstride; | 
					
						
							|  |  |  |     for(y=_pic_y+_pic_height;y<frame_height;y++){ | 
					
						
							|  |  |  |       for(x=0;x<frame_width;x++){ | 
					
						
							|  |  |  |         dst[x]=((dst-dstride)[x]<<1)+(dst-dstride)[x-(x>0)] | 
					
						
							|  |  |  |          +(dst-dstride)[x+(x+1<frame_width)]+2>>2; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       dst+=dstride; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){ | 
					
						
							|  |  |  |   th_ycbcr_buffer img; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   int             frame_width; | 
					
						
							|  |  |  |   int             frame_height; | 
					
						
							|  |  |  |   int             pic_width; | 
					
						
							|  |  |  |   int             pic_height; | 
					
						
							|  |  |  |   int             pic_x; | 
					
						
							|  |  |  |   int             pic_y; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   int             cframe_width; | 
					
						
							|  |  |  |   int             cframe_height; | 
					
						
							|  |  |  |   int             cpic_width; | 
					
						
							|  |  |  |   int             cpic_height; | 
					
						
							|  |  |  |   int             cpic_x; | 
					
						
							|  |  |  |   int             cpic_y; | 
					
						
							|  |  |  |   int             hdec; | 
					
						
							|  |  |  |   int             vdec; | 
					
						
							|  |  |  |   int             pli; | 
					
						
							|  |  |  |   int             refi; | 
					
						
							|  |  |  |   int             drop; | 
					
						
							|  |  |  |   /*Step 1: validate parameters.*/ | 
					
						
							|  |  |  |   if(_enc==NULL||_img==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |   if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL; | 
					
						
							|  |  |  |   if(_enc->rc.twopass&&_enc->rc.twopass_buffer_bytes==0)return TH_EINVAL; | 
					
						
							|  |  |  |   hdec=!(_enc->state.info.pixel_fmt&1); | 
					
						
							|  |  |  |   vdec=!(_enc->state.info.pixel_fmt&2); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   frame_width=_enc->state.info.frame_width; | 
					
						
							|  |  |  |   frame_height=_enc->state.info.frame_height; | 
					
						
							|  |  |  |   pic_x=_enc->state.info.pic_x; | 
					
						
							|  |  |  |   pic_y=_enc->state.info.pic_y; | 
					
						
							|  |  |  |   pic_width=_enc->state.info.pic_width; | 
					
						
							|  |  |  |   pic_height=_enc->state.info.pic_height; | 
					
						
							|  |  |  |   cframe_width=frame_width>>hdec; | 
					
						
							|  |  |  |   cframe_height=frame_height>>vdec; | 
					
						
							|  |  |  |   cpic_x=pic_x>>hdec; | 
					
						
							|  |  |  |   cpic_y=pic_y>>vdec; | 
					
						
							|  |  |  |   cpic_width=(pic_x+pic_width+hdec>>hdec)-cpic_x; | 
					
						
							|  |  |  |   cpic_height=(pic_y+pic_height+vdec>>vdec)-cpic_y; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   /*Flip the input buffer upside down.*/ | 
					
						
							|  |  |  |   oc_ycbcr_buffer_flip(img,_img); | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   if(img[0].width!=frame_width||img[0].height!=frame_height|| | 
					
						
							|  |  |  |    img[1].width!=cframe_width||img[2].width!=cframe_width|| | 
					
						
							|  |  |  |    img[1].height!=cframe_height||img[2].height!=cframe_height){ | 
					
						
							|  |  |  |     /*The buffer does not match the frame size.
 | 
					
						
							|  |  |  |       Check to see if it matches the picture size.*/ | 
					
						
							|  |  |  |     if(img[0].width!=pic_width||img[0].height!=pic_height|| | 
					
						
							|  |  |  |      img[1].width!=cpic_width||img[2].width!=cpic_width|| | 
					
						
							|  |  |  |      img[1].height!=cpic_height||img[2].height!=cpic_height){ | 
					
						
							|  |  |  |       /*It doesn't; we don't know how to handle it.*/ | 
					
						
							|  |  |  |       return TH_EINVAL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*Adjust the pointers to address a full frame.
 | 
					
						
							|  |  |  |       We still only use the picture region, however.*/ | 
					
						
							|  |  |  |     img[0].data-=pic_y*(ptrdiff_t)img[0].stride+pic_x; | 
					
						
							|  |  |  |     img[1].data-=cpic_y*(ptrdiff_t)img[1].stride+cpic_x; | 
					
						
							|  |  |  |     img[2].data-=cpic_y*(ptrdiff_t)img[2].stride+cpic_x; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*Step 2: Update the buffer state.*/ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   if(_enc->state.ref_frame_idx[OC_FRAME_SELF]>=0){ | 
					
						
							|  |  |  |     _enc->state.ref_frame_idx[OC_FRAME_PREV]= | 
					
						
							|  |  |  |      _enc->state.ref_frame_idx[OC_FRAME_SELF]; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |     _enc->state.ref_frame_data[OC_FRAME_PREV]= | 
					
						
							|  |  |  |      _enc->state.ref_frame_data[OC_FRAME_SELF]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     if(_enc->state.frame_type==OC_INTRA_FRAME){ | 
					
						
							|  |  |  |       /*The new frame becomes both the previous and gold reference frames.*/ | 
					
						
							|  |  |  |       _enc->state.keyframe_num=_enc->state.curframe_num; | 
					
						
							|  |  |  |       _enc->state.ref_frame_idx[OC_FRAME_GOLD]= | 
					
						
							|  |  |  |        _enc->state.ref_frame_idx[OC_FRAME_SELF]; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |       _enc->state.ref_frame_data[OC_FRAME_GOLD]= | 
					
						
							|  |  |  |        _enc->state.ref_frame_data[OC_FRAME_SELF]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if(_enc->state.ref_frame_idx[OC_FRAME_IO]>=0&&_enc->prevframe_dropped==0){ | 
					
						
							|  |  |  |     _enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG]= | 
					
						
							|  |  |  |      _enc->state.ref_frame_idx[OC_FRAME_IO]; | 
					
						
							|  |  |  |     _enc->state.ref_frame_data[OC_FRAME_PREV_ORIG]= | 
					
						
							|  |  |  |      _enc->state.ref_frame_data[OC_FRAME_IO]; | 
					
						
							|  |  |  |     if(_enc->state.frame_type==OC_INTRA_FRAME){ | 
					
						
							|  |  |  |       /*The new input frame becomes both the previous and gold
 | 
					
						
							|  |  |  |          original-reference frames.*/ | 
					
						
							|  |  |  |       _enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]= | 
					
						
							|  |  |  |        _enc->state.ref_frame_idx[OC_FRAME_IO]; | 
					
						
							|  |  |  |       _enc->state.ref_frame_data[OC_FRAME_GOLD_ORIG]= | 
					
						
							|  |  |  |        _enc->state.ref_frame_data[OC_FRAME_IO]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   /*Select a free buffer to use for the incoming frame*/ | 
					
						
							|  |  |  |   for(refi=3;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]|| | 
					
						
							|  |  |  |    refi==_enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG];refi++); | 
					
						
							|  |  |  |   _enc->state.ref_frame_idx[OC_FRAME_IO]=refi; | 
					
						
							|  |  |  |   _enc->state.ref_frame_data[OC_FRAME_IO]= | 
					
						
							|  |  |  |    _enc->state.ref_frame_bufs[refi][0].data; | 
					
						
							|  |  |  |   /*Step 3: Copy the input to our internal buffer.
 | 
					
						
							|  |  |  |     This lets us add padding, so we don't have to worry about dereferencing | 
					
						
							|  |  |  |      possibly invalid addresses, and allows us to use the same strides and | 
					
						
							|  |  |  |      fragment offsets for both the input frame and the reference frames.*/ | 
					
						
							|  |  |  |   oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+0,img+0, | 
					
						
							|  |  |  |    pic_x,pic_y,pic_width,pic_height); | 
					
						
							|  |  |  |   oc_state_borders_fill_rows(&_enc->state,refi,0,0,frame_height); | 
					
						
							|  |  |  |   oc_state_borders_fill_caps(&_enc->state,refi,0); | 
					
						
							|  |  |  |   for(pli=1;pli<3;pli++){ | 
					
						
							|  |  |  |     oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+pli,img+pli, | 
					
						
							|  |  |  |      cpic_x,cpic_y,cpic_width,cpic_height); | 
					
						
							|  |  |  |     oc_state_borders_fill_rows(&_enc->state,refi,pli,0,cframe_height); | 
					
						
							|  |  |  |     oc_state_borders_fill_caps(&_enc->state,refi,pli); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   /*Select a free buffer to use for the reconstructed version of this frame.*/ | 
					
						
							|  |  |  |   for(refi=0;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD]|| | 
					
						
							|  |  |  |    refi==_enc->state.ref_frame_idx[OC_FRAME_PREV];refi++); | 
					
						
							|  |  |  |   _enc->state.ref_frame_idx[OC_FRAME_SELF]=refi; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   _enc->state.ref_frame_data[OC_FRAME_SELF]= | 
					
						
							|  |  |  |    _enc->state.ref_frame_bufs[refi][0].data; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   _enc->state.curframe_num+=_enc->prev_dup_count+1; | 
					
						
							|  |  |  |   /*Step 4: Compress the frame.*/ | 
					
						
							|  |  |  |   /*Start with a keyframe, and don't allow the generation of invalid files that
 | 
					
						
							|  |  |  |      overflow the keyframe_granule_shift.*/ | 
					
						
							|  |  |  |   if(_enc->rc.twopass_force_kf||_enc->state.curframe_num==0|| | 
					
						
							|  |  |  |    _enc->state.curframe_num-_enc->state.keyframe_num+_enc->dup_count>= | 
					
						
							|  |  |  |    _enc->keyframe_frequency_force){ | 
					
						
							|  |  |  |     oc_enc_compress_keyframe(_enc,0); | 
					
						
							|  |  |  |     drop=0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else{ | 
					
						
							|  |  |  |     oc_enc_compress_frame(_enc,0); | 
					
						
							|  |  |  |     drop=1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   oc_restore_fpu(&_enc->state); | 
					
						
							|  |  |  |   /*drop currently indicates if the frame is droppable.*/ | 
					
						
							|  |  |  |   if(_enc->state.info.target_bitrate>0){ | 
					
						
							|  |  |  |     drop=oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3, | 
					
						
							|  |  |  |      _enc->state.frame_type,_enc->state.qis[0],0,drop); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else drop=0; | 
					
						
							|  |  |  |   /*drop now indicates if the frame was dropped.*/ | 
					
						
							|  |  |  |   if(drop)oc_enc_drop_frame(_enc); | 
					
						
							|  |  |  |   else _enc->prevframe_dropped=0; | 
					
						
							|  |  |  |   _enc->packet_state=OC_PACKET_READY; | 
					
						
							|  |  |  |   _enc->prev_dup_count=_enc->nqueued_dups=_enc->dup_count; | 
					
						
							|  |  |  |   _enc->dup_count=0; | 
					
						
							|  |  |  | #if defined(OC_DUMP_IMAGES)
 | 
					
						
							|  |  |  |   oc_enc_set_granpos(_enc); | 
					
						
							|  |  |  |   oc_state_dump_frame(&_enc->state,OC_FRAME_IO,"src"); | 
					
						
							|  |  |  |   oc_state_dump_frame(&_enc->state,OC_FRAME_SELF,"rec"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){ | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |   unsigned char *packet; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |   if(_enc==NULL||_op==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |   if(_enc->packet_state==OC_PACKET_READY){ | 
					
						
							|  |  |  |     _enc->packet_state=OC_PACKET_EMPTY; | 
					
						
							|  |  |  |     if(_enc->rc.twopass!=1){ | 
					
						
							|  |  |  |       packet=oggpackB_get_buffer(&_enc->opb); | 
					
						
							|  |  |  |       /*If there's no packet, malloc failed while writing; it's lost forever.*/ | 
					
						
							|  |  |  |       if(packet==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |       _op->packet=packet; | 
					
						
							|  |  |  |       _op->bytes=oggpackB_bytes(&_enc->opb); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*For the first pass in 2-pass mode, don't emit any packet data.*/ | 
					
						
							|  |  |  |     else{ | 
					
						
							|  |  |  |       _op->packet=NULL; | 
					
						
							|  |  |  |       _op->bytes=0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if(_enc->packet_state==OC_PACKET_EMPTY){ | 
					
						
							|  |  |  |     if(_enc->nqueued_dups>0){ | 
					
						
							|  |  |  |       _enc->nqueued_dups--; | 
					
						
							| 
									
										
										
										
											2022-09-27 21:18:11 -03:00
										 |  |  |       /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/ | 
					
						
							|  |  |  |       if(_enc->vp3_compatible){ | 
					
						
							|  |  |  |         oggpackB_reset(&_enc->opb); | 
					
						
							|  |  |  |         oc_enc_drop_frame_pack(_enc); | 
					
						
							|  |  |  |         packet=oggpackB_get_buffer(&_enc->opb); | 
					
						
							|  |  |  |         /*If there's no packet, malloc failed while writing; it's lost
 | 
					
						
							|  |  |  |            forever.*/ | 
					
						
							|  |  |  |         if(packet==NULL)return TH_EFAULT; | 
					
						
							|  |  |  |         _op->packet=packet; | 
					
						
							|  |  |  |         _op->bytes=oggpackB_bytes(&_enc->opb); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /*Otherwise emit a 0-byte packet.*/ | 
					
						
							|  |  |  |       else{ | 
					
						
							|  |  |  |         _op->packet=NULL; | 
					
						
							|  |  |  |         _op->bytes=0; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  |     } | 
					
						
							|  |  |  |     else{ | 
					
						
							|  |  |  |       if(_last_p)_enc->packet_state=OC_PACKET_DONE; | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else return 0; | 
					
						
							|  |  |  |   _last_p=_last_p&&_enc->nqueued_dups<=0; | 
					
						
							|  |  |  |   _op->b_o_s=0; | 
					
						
							|  |  |  |   _op->e_o_s=_last_p; | 
					
						
							|  |  |  |   oc_enc_set_granpos(_enc); | 
					
						
							|  |  |  |   _op->packetno=th_granule_frame(_enc,_enc->state.granpos)+3; | 
					
						
							|  |  |  |   _op->granulepos=_enc->state.granpos; | 
					
						
							|  |  |  |   if(_last_p)_enc->packet_state=OC_PACKET_DONE; | 
					
						
							|  |  |  |   return 1+_enc->nqueued_dups; | 
					
						
							|  |  |  | } |