accounting.c (4918B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <assert.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #include "aom/aom_integer.h" 18 #include "av1/decoder/accounting.h" 19 20 static int accounting_hash(const char *str) { 21 uint32_t val; 22 const unsigned char *ustr; 23 val = 0; 24 ustr = (const unsigned char *)str; 25 /* This is about the worst hash one can design, but it should be good enough 26 here. */ 27 while (*ustr) val += *ustr++; 28 return val % AOM_ACCOUNTING_HASH_SIZE; 29 } 30 31 /* Dictionary lookup based on an open-addressing hash table. */ 32 int aom_accounting_dictionary_lookup(Accounting *accounting, const char *str) { 33 int hash; 34 size_t len; 35 AccountingDictionary *dictionary; 36 dictionary = &accounting->syms.dictionary; 37 hash = accounting_hash(str); 38 while (accounting->hash_dictionary[hash] != -1) { 39 if (strcmp(dictionary->strs[accounting->hash_dictionary[hash]], str) == 0) { 40 return accounting->hash_dictionary[hash]; 41 } 42 hash++; 43 if (hash == AOM_ACCOUNTING_HASH_SIZE) hash = 0; 44 } 45 /* No match found. */ 46 assert(dictionary->num_strs + 1 < MAX_SYMBOL_TYPES); 47 accounting->hash_dictionary[hash] = dictionary->num_strs; 48 len = strlen(str); 49 dictionary->strs[dictionary->num_strs] = malloc(len + 1); 50 if (!dictionary->strs[dictionary->num_strs]) abort(); 51 snprintf(dictionary->strs[dictionary->num_strs], len + 1, "%s", str); 52 dictionary->num_strs++; 53 return dictionary->num_strs - 1; 54 } 55 56 void aom_accounting_init(Accounting *accounting) { 57 int i; 58 accounting->num_syms_allocated = 1000; 59 accounting->syms.syms = 60 malloc(sizeof(AccountingSymbol) * accounting->num_syms_allocated); 61 if (!accounting->syms.syms) abort(); 62 accounting->syms.dictionary.num_strs = 0; 63 assert(AOM_ACCOUNTING_HASH_SIZE > 2 * MAX_SYMBOL_TYPES); 64 for (i = 0; i < AOM_ACCOUNTING_HASH_SIZE; i++) 65 accounting->hash_dictionary[i] = -1; 66 aom_accounting_reset(accounting); 67 } 68 69 void aom_accounting_reset(Accounting *accounting) { 70 accounting->syms.num_syms = 0; 71 accounting->syms.num_binary_syms = 0; 72 accounting->syms.num_multi_syms = 0; 73 accounting->context.x = -1; 74 accounting->context.y = -1; 75 accounting->last_tell_frac = 0; 76 } 77 78 void aom_accounting_clear(Accounting *accounting) { 79 int i; 80 AccountingDictionary *dictionary; 81 free(accounting->syms.syms); 82 dictionary = &accounting->syms.dictionary; 83 for (i = 0; i < dictionary->num_strs; i++) { 84 free(dictionary->strs[i]); 85 } 86 } 87 88 void aom_accounting_set_context(Accounting *accounting, int16_t x, int16_t y) { 89 accounting->context.x = x; 90 accounting->context.y = y; 91 } 92 93 void aom_accounting_record(Accounting *accounting, const char *str, 94 uint32_t bits) { 95 AccountingSymbol sym; 96 // Reuse previous symbol if it has the same context and symbol id. 97 if (accounting->syms.num_syms) { 98 AccountingSymbol *last_sym; 99 last_sym = &accounting->syms.syms[accounting->syms.num_syms - 1]; 100 if (memcmp(&last_sym->context, &accounting->context, 101 sizeof(AccountingSymbolContext)) == 0) { 102 uint32_t id; 103 id = aom_accounting_dictionary_lookup(accounting, str); 104 if (id == last_sym->id) { 105 last_sym->bits += bits; 106 last_sym->samples++; 107 return; 108 } 109 } 110 } 111 sym.context = accounting->context; 112 sym.samples = 1; 113 sym.bits = bits; 114 sym.id = aom_accounting_dictionary_lookup(accounting, str); 115 assert(sym.id <= 255); 116 if (accounting->syms.num_syms == accounting->num_syms_allocated) { 117 accounting->num_syms_allocated *= 2; 118 accounting->syms.syms = 119 realloc(accounting->syms.syms, 120 sizeof(AccountingSymbol) * accounting->num_syms_allocated); 121 if (!accounting->syms.syms) abort(); 122 } 123 accounting->syms.syms[accounting->syms.num_syms++] = sym; 124 } 125 126 void aom_accounting_dump(Accounting *accounting) { 127 int i; 128 AccountingSymbol *sym; 129 printf("\n----- Number of recorded syntax elements = %d -----\n", 130 accounting->syms.num_syms); 131 printf("----- Total number of symbol calls = %d (%d binary) -----\n", 132 accounting->syms.num_multi_syms + accounting->syms.num_binary_syms, 133 accounting->syms.num_binary_syms); 134 for (i = 0; i < accounting->syms.num_syms; i++) { 135 sym = &accounting->syms.syms[i]; 136 printf("%s x: %d, y: %d bits: %f samples: %d\n", 137 accounting->syms.dictionary.strs[sym->id], sym->context.x, 138 sym->context.y, (float)sym->bits / 8.0, sym->samples); 139 } 140 }