1/*
2 *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "./vpxstats.h"
12
13#include <math.h>
14#include <stdlib.h>
15#include <string.h>
16
17#include "./tools_common.h"
18
19int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
20  int res;
21  stats->pass = pass;
22
23  if (pass == 0) {
24    stats->file = fopen(fpf, "wb");
25    stats->buf.sz = 0;
26    stats->buf.buf = NULL;
27    res = (stats->file != NULL);
28  } else {
29#if USE_POSIX_MMAP
30    struct stat stat_buf;
31    int fd;
32
33    fd = open(fpf, O_RDONLY);
34    stats->file = fdopen(fd, "rb");
35    fstat(fd, &stat_buf);
36    stats->buf.sz = stat_buf.st_size;
37    stats->buf.buf = mmap(NULL, stats->buf.sz, PROT_READ, MAP_PRIVATE, fd, 0);
38    res = (stats->buf.buf != NULL);
39#else
40    size_t nbytes;
41
42    stats->file = fopen(fpf, "rb");
43
44    if (fseek(stats->file, 0, SEEK_END))
45      fatal("First-pass stats file must be seekable!");
46
47    stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
48    rewind(stats->file);
49
50    stats->buf.buf = malloc(stats->buf_alloc_sz);
51
52    if (!stats->buf.buf)
53      fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
54            (unsigned int)stats->buf_alloc_sz);
55
56    nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
57    res = (nbytes == stats->buf.sz);
58#endif  /* USE_POSIX_MMAP */
59  }
60
61  return res;
62}
63
64int stats_open_mem(stats_io_t *stats, int pass) {
65  int res;
66  stats->pass = pass;
67
68  if (!pass) {
69    stats->buf.sz = 0;
70    stats->buf_alloc_sz = 64 * 1024;
71    stats->buf.buf = malloc(stats->buf_alloc_sz);
72  }
73
74  stats->buf_ptr = stats->buf.buf;
75  res = (stats->buf.buf != NULL);
76  return res;
77}
78
79void stats_close(stats_io_t *stats, int last_pass) {
80  if (stats->file) {
81    if (stats->pass == last_pass) {
82#if USE_POSIX_MMAP
83      munmap(stats->buf.buf, stats->buf.sz);
84#else
85      free(stats->buf.buf);
86#endif  /* USE_POSIX_MMAP */
87    }
88
89    fclose(stats->file);
90    stats->file = NULL;
91  } else {
92    if (stats->pass == last_pass)
93      free(stats->buf.buf);
94  }
95}
96
97void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
98  if (stats->file) {
99    (void) fwrite(pkt, 1, len, stats->file);
100  } else {
101    if (stats->buf.sz + len > stats->buf_alloc_sz) {
102      size_t  new_sz = stats->buf_alloc_sz + 64 * 1024;
103      char   *new_ptr = realloc(stats->buf.buf, new_sz);
104
105      if (new_ptr) {
106        stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
107        stats->buf.buf = new_ptr;
108        stats->buf_alloc_sz = new_sz;
109      } else {
110        fatal("Failed to realloc firstpass stats buffer.");
111      }
112    }
113
114    memcpy(stats->buf_ptr, pkt, len);
115    stats->buf.sz += len;
116    stats->buf_ptr += len;
117  }
118}
119
120vpx_fixed_buf_t stats_get(stats_io_t *stats) {
121  return stats->buf;
122}
123