133 строки
4.4 KiB
C
133 строки
4.4 KiB
C
/*
|
|
* 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 <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "aom/aom_integer.h"
|
|
#include "./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;
|
|
int 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->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("----- %d -----\n", accounting->syms.num_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);
|
|
}
|
|
}
|