• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
accounting_hash(const char * str)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. */
aom_accounting_dictionary_lookup(Accounting * accounting,const char * str)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 
aom_accounting_init(Accounting * accounting)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 
aom_accounting_reset(Accounting * accounting)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 
aom_accounting_clear(Accounting * accounting)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 
aom_accounting_set_context(Accounting * accounting,int16_t x,int16_t y)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 
aom_accounting_record(Accounting * accounting,const char * str,uint32_t bits)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 
aom_accounting_dump(Accounting * accounting)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 }
141