encoder_huffman.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 *
  9. * by the Xiph.Org Foundation http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function:
  13. last mod: $Id: encoder_huffman.c 13884 2007-09-22 08:38:10Z giles $
  14. ********************************************************************/
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include "codec_internal.h"
  18. #include "hufftables.h"
  19. static void CreateHuffmanList(HUFF_ENTRY ** HuffRoot,
  20. ogg_uint32_t HIndex,
  21. const ogg_uint32_t *FreqList ) {
  22. int i;
  23. HUFF_ENTRY *entry_ptr;
  24. HUFF_ENTRY *search_ptr;
  25. /* Create a HUFF entry for token zero. */
  26. HuffRoot[HIndex] = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*HuffRoot[HIndex]));
  27. HuffRoot[HIndex]->Previous = NULL;
  28. HuffRoot[HIndex]->Next = NULL;
  29. HuffRoot[HIndex]->ZeroChild = NULL;
  30. HuffRoot[HIndex]->OneChild = NULL;
  31. HuffRoot[HIndex]->Value = 0;
  32. HuffRoot[HIndex]->Frequency = FreqList[0];
  33. if ( HuffRoot[HIndex]->Frequency == 0 )
  34. HuffRoot[HIndex]->Frequency = 1;
  35. /* Now add entries for all the other possible tokens. */
  36. for ( i = 1; i < MAX_ENTROPY_TOKENS; i++ ) {
  37. entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr));
  38. entry_ptr->Value = i;
  39. entry_ptr->Frequency = FreqList[i];
  40. entry_ptr->ZeroChild = NULL;
  41. entry_ptr->OneChild = NULL;
  42. /* Force min value of 1. This prevents the tree getting too deep. */
  43. if ( entry_ptr->Frequency == 0 )
  44. entry_ptr->Frequency = 1;
  45. if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){
  46. entry_ptr->Next = HuffRoot[HIndex];
  47. HuffRoot[HIndex]->Previous = entry_ptr;
  48. entry_ptr->Previous = NULL;
  49. HuffRoot[HIndex] = entry_ptr;
  50. }else{
  51. search_ptr = HuffRoot[HIndex];
  52. while ( (search_ptr->Next != NULL) &&
  53. (search_ptr->Frequency < entry_ptr->Frequency) ){
  54. search_ptr = (HUFF_ENTRY *)search_ptr->Next;
  55. }
  56. if ( search_ptr->Frequency < entry_ptr->Frequency ){
  57. entry_ptr->Next = NULL;
  58. entry_ptr->Previous = search_ptr;
  59. search_ptr->Next = entry_ptr;
  60. }else{
  61. entry_ptr->Next = search_ptr;
  62. entry_ptr->Previous = search_ptr->Previous;
  63. search_ptr->Previous->Next = entry_ptr;
  64. search_ptr->Previous = entry_ptr;
  65. }
  66. }
  67. }
  68. }
  69. static void CreateCodeArray( HUFF_ENTRY * HuffRoot,
  70. ogg_uint32_t *HuffCodeArray,
  71. unsigned char *HuffCodeLengthArray,
  72. ogg_uint32_t CodeValue,
  73. unsigned char CodeLength ) {
  74. /* If we are at a leaf then fill in a code array entry. */
  75. if ( ( HuffRoot->ZeroChild == NULL ) && ( HuffRoot->OneChild == NULL ) ){
  76. HuffCodeArray[HuffRoot->Value] = CodeValue;
  77. HuffCodeLengthArray[HuffRoot->Value] = CodeLength;
  78. }else{
  79. /* Recursive calls to scan down the tree. */
  80. CodeLength++;
  81. CreateCodeArray(HuffRoot->ZeroChild, HuffCodeArray, HuffCodeLengthArray,
  82. ((CodeValue << 1) + 0), CodeLength);
  83. CreateCodeArray(HuffRoot->OneChild, HuffCodeArray, HuffCodeLengthArray,
  84. ((CodeValue << 1) + 1), CodeLength);
  85. }
  86. }
  87. static void BuildHuffmanTree( HUFF_ENTRY **HuffRoot,
  88. ogg_uint32_t *HuffCodeArray,
  89. unsigned char *HuffCodeLengthArray,
  90. ogg_uint32_t HIndex,
  91. const ogg_uint32_t *FreqList ){
  92. HUFF_ENTRY *entry_ptr;
  93. HUFF_ENTRY *search_ptr;
  94. /* First create a sorted linked list representing the frequencies of
  95. each token. */
  96. CreateHuffmanList( HuffRoot, HIndex, FreqList );
  97. /* Now build the tree from the list. */
  98. /* While there are at least two items left in the list. */
  99. while ( HuffRoot[HIndex]->Next != NULL ){
  100. /* Create the new node as the parent of the first two in the list. */
  101. entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr));
  102. entry_ptr->Value = -1;
  103. entry_ptr->Frequency = HuffRoot[HIndex]->Frequency +
  104. HuffRoot[HIndex]->Next->Frequency ;
  105. entry_ptr->ZeroChild = HuffRoot[HIndex];
  106. entry_ptr->OneChild = HuffRoot[HIndex]->Next;
  107. /* If there are still more items in the list then insert the new
  108. node into the list. */
  109. if (entry_ptr->OneChild->Next != NULL ){
  110. /* Set up the provisional 'new root' */
  111. HuffRoot[HIndex] = entry_ptr->OneChild->Next;
  112. HuffRoot[HIndex]->Previous = NULL;
  113. /* Now scan through the remaining list to insert the new entry
  114. at the appropriate point. */
  115. if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){
  116. entry_ptr->Next = HuffRoot[HIndex];
  117. HuffRoot[HIndex]->Previous = entry_ptr;
  118. entry_ptr->Previous = NULL;
  119. HuffRoot[HIndex] = entry_ptr;
  120. }else{
  121. search_ptr = HuffRoot[HIndex];
  122. while ( (search_ptr->Next != NULL) &&
  123. (search_ptr->Frequency < entry_ptr->Frequency) ){
  124. search_ptr = search_ptr->Next;
  125. }
  126. if ( search_ptr->Frequency < entry_ptr->Frequency ){
  127. entry_ptr->Next = NULL;
  128. entry_ptr->Previous = search_ptr;
  129. search_ptr->Next = entry_ptr;
  130. }else{
  131. entry_ptr->Next = search_ptr;
  132. entry_ptr->Previous = search_ptr->Previous;
  133. search_ptr->Previous->Next = entry_ptr;
  134. search_ptr->Previous = entry_ptr;
  135. }
  136. }
  137. }else{
  138. /* Build has finished. */
  139. entry_ptr->Next = NULL;
  140. entry_ptr->Previous = NULL;
  141. HuffRoot[HIndex] = entry_ptr;
  142. }
  143. /* Delete the Next/Previous properties of the children (PROB NOT NEC). */
  144. entry_ptr->ZeroChild->Next = NULL;
  145. entry_ptr->ZeroChild->Previous = NULL;
  146. entry_ptr->OneChild->Next = NULL;
  147. entry_ptr->OneChild->Previous = NULL;
  148. }
  149. /* Now build a code array from the tree. */
  150. CreateCodeArray( HuffRoot[HIndex], HuffCodeArray,
  151. HuffCodeLengthArray, 0, 0);
  152. }
  153. static void DestroyHuffTree(HUFF_ENTRY *root_ptr){
  154. if (root_ptr){
  155. if ( root_ptr->ZeroChild )
  156. DestroyHuffTree(root_ptr->ZeroChild);
  157. if ( root_ptr->OneChild )
  158. DestroyHuffTree(root_ptr->OneChild);
  159. _ogg_free(root_ptr);
  160. }
  161. }
  162. void ClearHuffmanSet( PB_INSTANCE *pbi ){
  163. int i;
  164. ClearHuffmanTrees(pbi->HuffRoot_VP3x);
  165. for ( i = 0; i < NUM_HUFF_TABLES; i++ )
  166. if (pbi->HuffCodeArray_VP3x[i])
  167. _ogg_free (pbi->HuffCodeArray_VP3x[i]);
  168. for ( i = 0; i < NUM_HUFF_TABLES; i++ )
  169. if (pbi->HuffCodeLengthArray_VP3x[i])
  170. _ogg_free (pbi->HuffCodeLengthArray_VP3x[i]);
  171. }
  172. void InitHuffmanSet( PB_INSTANCE *pbi ){
  173. int i;
  174. ClearHuffmanSet(pbi);
  175. pbi->ExtraBitLengths_VP3x = ExtraBitLengths_VP31;
  176. for ( i = 0; i < NUM_HUFF_TABLES; i++ ){
  177. pbi->HuffCodeArray_VP3x[i] =
  178. _ogg_calloc(MAX_ENTROPY_TOKENS,
  179. sizeof(*pbi->HuffCodeArray_VP3x[i]));
  180. pbi->HuffCodeLengthArray_VP3x[i] =
  181. _ogg_calloc(MAX_ENTROPY_TOKENS,
  182. sizeof(*pbi->HuffCodeLengthArray_VP3x[i]));
  183. BuildHuffmanTree( pbi->HuffRoot_VP3x,
  184. pbi->HuffCodeArray_VP3x[i],
  185. pbi->HuffCodeLengthArray_VP3x[i],
  186. i, FrequencyCounts_VP3[i]);
  187. }
  188. }
  189. static int ReadHuffTree(HUFF_ENTRY * HuffRoot, int depth,
  190. oggpack_buffer *opb) {
  191. long bit;
  192. long ret;
  193. theora_read(opb,1,&bit);
  194. if(bit < 0) return OC_BADHEADER;
  195. else if(!bit) {
  196. int ret;
  197. if (++depth > 32) return OC_BADHEADER;
  198. HuffRoot->ZeroChild = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
  199. ret = ReadHuffTree(HuffRoot->ZeroChild, depth, opb);
  200. if (ret < 0) return ret;
  201. HuffRoot->OneChild = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
  202. ret = ReadHuffTree(HuffRoot->OneChild, depth, opb);
  203. if (ret < 0) return ret;
  204. HuffRoot->Value = -1;
  205. } else {
  206. HuffRoot->ZeroChild = NULL;
  207. HuffRoot->OneChild = NULL;
  208. theora_read(opb,5,&ret);
  209. HuffRoot->Value=ret;;
  210. if (HuffRoot->Value < 0) return OC_BADHEADER;
  211. }
  212. return 0;
  213. }
  214. int ReadHuffmanTrees(codec_setup_info *ci, oggpack_buffer *opb) {
  215. int i;
  216. for (i=0; i<NUM_HUFF_TABLES; i++) {
  217. int ret;
  218. ci->HuffRoot[i] = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
  219. ret = ReadHuffTree(ci->HuffRoot[i], 0, opb);
  220. if (ret) return ret;
  221. }
  222. return 0;
  223. }
  224. static void WriteHuffTree(HUFF_ENTRY *HuffRoot, oggpack_buffer *opb) {
  225. if (HuffRoot->Value >= 0) {
  226. oggpackB_write(opb, 1, 1);
  227. oggpackB_write(opb, HuffRoot->Value, 5);
  228. } else {
  229. oggpackB_write(opb, 0, 1);
  230. WriteHuffTree(HuffRoot->ZeroChild, opb);
  231. WriteHuffTree(HuffRoot->OneChild, opb);
  232. }
  233. }
  234. void WriteHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES],
  235. oggpack_buffer *opb) {
  236. int i;
  237. for(i=0; i<NUM_HUFF_TABLES; i++) {
  238. WriteHuffTree(HuffRoot[i], opb);
  239. }
  240. }
  241. static HUFF_ENTRY *CopyHuffTree(const HUFF_ENTRY *HuffSrc) {
  242. if(HuffSrc){
  243. HUFF_ENTRY *HuffDst;
  244. HuffDst = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
  245. HuffDst->Value = HuffSrc->Value;
  246. if (HuffSrc->Value < 0) {
  247. HuffDst->ZeroChild = CopyHuffTree(HuffSrc->ZeroChild);
  248. HuffDst->OneChild = CopyHuffTree(HuffSrc->OneChild);
  249. }
  250. return HuffDst;
  251. }
  252. return NULL;
  253. }
  254. void InitHuffmanTrees(PB_INSTANCE *pbi, const codec_setup_info *ci) {
  255. int i;
  256. pbi->ExtraBitLengths_VP3x = ExtraBitLengths_VP31;
  257. for(i=0; i<NUM_HUFF_TABLES; i++){
  258. pbi->HuffRoot_VP3x[i] = CopyHuffTree(ci->HuffRoot[i]);
  259. }
  260. }
  261. void ClearHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES]){
  262. int i;
  263. for(i=0; i<NUM_HUFF_TABLES; i++) {
  264. DestroyHuffTree(HuffRoot[i]);
  265. HuffRoot[i] = NULL;
  266. }
  267. }