tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }