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 "stats/aomstats.h"
13
14 #include <assert.h>
15 #include <math.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include "aom_dsp/aom_dsp_common.h"
20 #include "common/tools_common.h"
21
stats_open_file(stats_io_t * stats,const char * fpf,int pass)22 int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
23 int res;
24 stats->pass = pass;
25
26 if (pass == 0) {
27 stats->file = fopen(fpf, "wb");
28 stats->buf.sz = 0;
29 stats->buf.buf = NULL;
30 res = (stats->file != NULL);
31 } else {
32 size_t nbytes;
33
34 stats->file = fopen(fpf, "rb");
35
36 if (stats->file == NULL) fatal("First-pass stats file does not exist!");
37
38 if (fseek(stats->file, 0, SEEK_END))
39 fatal("First-pass stats file must be seekable!");
40
41 stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
42 rewind(stats->file);
43
44 stats->buf.buf = malloc(stats->buf_alloc_sz);
45
46 if (!stats->buf.buf)
47 fatal("Failed to allocate first-pass stats buffer (%u bytes)",
48 (unsigned int)stats->buf_alloc_sz);
49
50 nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
51 res = (nbytes == stats->buf.sz);
52 }
53
54 return res;
55 }
56
stats_open_mem(stats_io_t * stats,int pass)57 int stats_open_mem(stats_io_t *stats, int pass) {
58 int res;
59 stats->pass = pass;
60
61 if (!pass) {
62 stats->buf.sz = 0;
63 stats->buf_alloc_sz = 64 * 1024;
64 stats->buf.buf = malloc(stats->buf_alloc_sz);
65 }
66
67 stats->buf_ptr = stats->buf.buf;
68 res = (stats->buf.buf != NULL);
69 return res;
70 }
71
stats_close(stats_io_t * stats,int last_pass)72 void stats_close(stats_io_t *stats, int last_pass) {
73 if (stats->file) {
74 if (stats->pass == last_pass) {
75 free(stats->buf.buf);
76 }
77
78 fclose(stats->file);
79 stats->file = NULL;
80 } else {
81 if (stats->pass == last_pass) free(stats->buf.buf);
82 }
83 }
84
stats_write(stats_io_t * stats,const void * pkt,size_t len)85 void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
86 if (stats->file) {
87 (void)fwrite(pkt, 1, len, stats->file);
88 return;
89 }
90 assert(stats->buf.sz <= stats->buf_alloc_sz);
91 assert(0 < stats->buf_alloc_sz);
92 if (stats->buf.sz + len > stats->buf_alloc_sz) {
93 // Grow by a factor of 1.5 each time, for amortized constant time.
94 // Also make sure there is enough room for the data.
95 size_t new_sz = AOMMAX((3 * stats->buf_alloc_sz) / 2, stats->buf.sz + len);
96 char *new_ptr = realloc(stats->buf.buf, new_sz);
97
98 if (new_ptr) {
99 stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
100 stats->buf.buf = new_ptr;
101 stats->buf_alloc_sz = new_sz;
102 } else {
103 fatal("Failed to realloc firstpass stats buffer.");
104 }
105 }
106
107 memcpy(stats->buf_ptr, pkt, len);
108 stats->buf.sz += len;
109 stats->buf_ptr += len;
110 }
111
stats_get(stats_io_t * stats)112 aom_fixed_buf_t stats_get(stats_io_t *stats) { return stats->buf; }
113