/* * Copyright (c) 2016, Alliance for Open Media. All rights reserved * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent. */ #include #include #include #include #include "aom/aom_integer.h" #include "av1/decoder/accounting.h" static int aom_accounting_hash(const char *str) { uint32_t val; const unsigned char *ustr; val = 0; ustr = (const unsigned char *)str; /* This is about the worst hash one can design, but it should be good enough here. */ while (*ustr) val += *ustr++; return val % AOM_ACCOUNTING_HASH_SIZE; } /* Dictionary lookup based on an open-addressing hash table. */ int aom_accounting_dictionary_lookup(Accounting *accounting, const char *str) { int hash; size_t len; AccountingDictionary *dictionary; dictionary = &accounting->syms.dictionary; hash = aom_accounting_hash(str); while (accounting->hash_dictionary[hash] != -1) { if (strcmp(dictionary->strs[accounting->hash_dictionary[hash]], str) == 0) { return accounting->hash_dictionary[hash]; } hash++; if (hash == AOM_ACCOUNTING_HASH_SIZE) hash = 0; } /* No match found. */ assert(dictionary->num_strs + 1 < MAX_SYMBOL_TYPES); accounting->hash_dictionary[hash] = dictionary->num_strs; len = strlen(str); dictionary->strs[dictionary->num_strs] = malloc(len + 1); snprintf(dictionary->strs[dictionary->num_strs], len + 1, "%s", str); dictionary->num_strs++; return dictionary->num_strs - 1; } void aom_accounting_init(Accounting *accounting) { int i; accounting->num_syms_allocated = 1000; accounting->syms.syms = malloc(sizeof(AccountingSymbol) * accounting->num_syms_allocated); accounting->syms.dictionary.num_strs = 0; assert(AOM_ACCOUNTING_HASH_SIZE > 2 * MAX_SYMBOL_TYPES); for (i = 0; i < AOM_ACCOUNTING_HASH_SIZE; i++) accounting->hash_dictionary[i] = -1; aom_accounting_reset(accounting); } void aom_accounting_reset(Accounting *accounting) { accounting->syms.num_syms = 0; accounting->syms.num_binary_syms = 0; accounting->syms.num_multi_syms = 0; accounting->context.x = -1; accounting->context.y = -1; accounting->last_tell_frac = 0; } void aom_accounting_clear(Accounting *accounting) { int i; AccountingDictionary *dictionary; free(accounting->syms.syms); dictionary = &accounting->syms.dictionary; for (i = 0; i < dictionary->num_strs; i++) { free(dictionary->strs[i]); } } void aom_accounting_set_context(Accounting *accounting, int16_t x, int16_t y) { accounting->context.x = x; accounting->context.y = y; } void aom_accounting_record(Accounting *accounting, const char *str, uint32_t bits) { AccountingSymbol sym; // Reuse previous symbol if it has the same context and symbol id. if (accounting->syms.num_syms) { AccountingSymbol *last_sym; last_sym = &accounting->syms.syms[accounting->syms.num_syms - 1]; if (memcmp(&last_sym->context, &accounting->context, sizeof(AccountingSymbolContext)) == 0) { uint32_t id; id = aom_accounting_dictionary_lookup(accounting, str); if (id == last_sym->id) { last_sym->bits += bits; last_sym->samples++; return; } } } sym.context = accounting->context; sym.samples = 1; sym.bits = bits; sym.id = aom_accounting_dictionary_lookup(accounting, str); assert(sym.id <= 255); if (accounting->syms.num_syms == accounting->num_syms_allocated) { accounting->num_syms_allocated *= 2; accounting->syms.syms = realloc(accounting->syms.syms, sizeof(AccountingSymbol) * accounting->num_syms_allocated); assert(accounting->syms.syms != NULL); } accounting->syms.syms[accounting->syms.num_syms++] = sym; } void aom_accounting_dump(Accounting *accounting) { int i; AccountingSymbol *sym; printf("\n----- Number of recorded syntax elements = %d -----\n", accounting->syms.num_syms); printf("----- Total number of symbol calls = %d (%d binary) -----\n", accounting->syms.num_multi_syms + accounting->syms.num_binary_syms, accounting->syms.num_binary_syms); for (i = 0; i < accounting->syms.num_syms; i++) { sym = &accounting->syms.syms[i]; printf("%s x: %d, y: %d bits: %f samples: %d\n", accounting->syms.dictionary.strs[sym->id], sym->context.x, sym->context.y, (float)sym->bits / 8.0, sym->samples); } }