1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker *
4*77c1e3ccSAndroid Build Coastguard Worker * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker */
11*77c1e3ccSAndroid Build Coastguard Worker
12*77c1e3ccSAndroid Build Coastguard Worker /*!\file
13*77c1e3ccSAndroid Build Coastguard Worker * \brief This file has the implementation details of the grain table.
14*77c1e3ccSAndroid Build Coastguard Worker *
15*77c1e3ccSAndroid Build Coastguard Worker * The file format is an ascii representation for readability and
16*77c1e3ccSAndroid Build Coastguard Worker * editability. Array parameters are separated from the non-array
17*77c1e3ccSAndroid Build Coastguard Worker * parameters and prefixed with a few characters to make for easy
18*77c1e3ccSAndroid Build Coastguard Worker * localization with a parameter set. Each entry is prefixed with "E"
19*77c1e3ccSAndroid Build Coastguard Worker * and the other parameters are only specified if "update-parms" is
20*77c1e3ccSAndroid Build Coastguard Worker * non-zero.
21*77c1e3ccSAndroid Build Coastguard Worker *
22*77c1e3ccSAndroid Build Coastguard Worker * filmgrn1
23*77c1e3ccSAndroid Build Coastguard Worker * E <start-time> <end-time> <apply-grain> <random-seed> <update-parms>
24*77c1e3ccSAndroid Build Coastguard Worker * p <ar_coeff_lag> <ar_coeff_shift> <grain_scale_shift> ...
25*77c1e3ccSAndroid Build Coastguard Worker * sY <num_y_points> <point_0_x> <point_0_y> ...
26*77c1e3ccSAndroid Build Coastguard Worker * sCb <num_cb_points> <point_0_x> <point_0_y> ...
27*77c1e3ccSAndroid Build Coastguard Worker * sCr <num_cr_points> <point_0_x> <point_0_y> ...
28*77c1e3ccSAndroid Build Coastguard Worker * cY <ar_coeff_y_0> ....
29*77c1e3ccSAndroid Build Coastguard Worker * cCb <ar_coeff_cb_0> ....
30*77c1e3ccSAndroid Build Coastguard Worker * cCr <ar_coeff_cr_0> ....
31*77c1e3ccSAndroid Build Coastguard Worker * E <start-time> ...
32*77c1e3ccSAndroid Build Coastguard Worker */
33*77c1e3ccSAndroid Build Coastguard Worker #include <string.h>
34*77c1e3ccSAndroid Build Coastguard Worker #include <stdio.h>
35*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
36*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/grain_table.h"
37*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h"
38*77c1e3ccSAndroid Build Coastguard Worker
39*77c1e3ccSAndroid Build Coastguard Worker static const char kFileMagic[8] = "filmgrn1";
40*77c1e3ccSAndroid Build Coastguard Worker
grain_table_entry_read(FILE * file,struct aom_internal_error_info * error_info,aom_film_grain_table_entry_t * entry)41*77c1e3ccSAndroid Build Coastguard Worker static void grain_table_entry_read(FILE *file,
42*77c1e3ccSAndroid Build Coastguard Worker struct aom_internal_error_info *error_info,
43*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *entry) {
44*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_t *pars = &entry->params;
45*77c1e3ccSAndroid Build Coastguard Worker int num_read =
46*77c1e3ccSAndroid Build Coastguard Worker fscanf(file, "E %" PRId64 " %" PRId64 " %d %hd %d\n", &entry->start_time,
47*77c1e3ccSAndroid Build Coastguard Worker &entry->end_time, &pars->apply_grain, &pars->random_seed,
48*77c1e3ccSAndroid Build Coastguard Worker &pars->update_parameters);
49*77c1e3ccSAndroid Build Coastguard Worker if (num_read == 0 && feof(file)) return;
50*77c1e3ccSAndroid Build Coastguard Worker if (num_read != 5) {
51*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
52*77c1e3ccSAndroid Build Coastguard Worker "Unable to read entry header. Read %d != 5", num_read);
53*77c1e3ccSAndroid Build Coastguard Worker return;
54*77c1e3ccSAndroid Build Coastguard Worker }
55*77c1e3ccSAndroid Build Coastguard Worker if (pars->update_parameters) {
56*77c1e3ccSAndroid Build Coastguard Worker num_read = fscanf(file, "p %d %d %d %d %d %d %d %d %d %d %d %d\n",
57*77c1e3ccSAndroid Build Coastguard Worker &pars->ar_coeff_lag, &pars->ar_coeff_shift,
58*77c1e3ccSAndroid Build Coastguard Worker &pars->grain_scale_shift, &pars->scaling_shift,
59*77c1e3ccSAndroid Build Coastguard Worker &pars->chroma_scaling_from_luma, &pars->overlap_flag,
60*77c1e3ccSAndroid Build Coastguard Worker &pars->cb_mult, &pars->cb_luma_mult, &pars->cb_offset,
61*77c1e3ccSAndroid Build Coastguard Worker &pars->cr_mult, &pars->cr_luma_mult, &pars->cr_offset);
62*77c1e3ccSAndroid Build Coastguard Worker if (num_read != 12) {
63*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
64*77c1e3ccSAndroid Build Coastguard Worker "Unable to read entry params. Read %d != 12",
65*77c1e3ccSAndroid Build Coastguard Worker num_read);
66*77c1e3ccSAndroid Build Coastguard Worker return;
67*77c1e3ccSAndroid Build Coastguard Worker }
68*77c1e3ccSAndroid Build Coastguard Worker if (!fscanf(file, "\tsY %d ", &pars->num_y_points)) {
69*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
70*77c1e3ccSAndroid Build Coastguard Worker "Unable to read num y points");
71*77c1e3ccSAndroid Build Coastguard Worker return;
72*77c1e3ccSAndroid Build Coastguard Worker }
73*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < pars->num_y_points; ++i) {
74*77c1e3ccSAndroid Build Coastguard Worker if (2 != fscanf(file, "%d %d", &pars->scaling_points_y[i][0],
75*77c1e3ccSAndroid Build Coastguard Worker &pars->scaling_points_y[i][1])) {
76*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
77*77c1e3ccSAndroid Build Coastguard Worker "Unable to read y scaling points");
78*77c1e3ccSAndroid Build Coastguard Worker return;
79*77c1e3ccSAndroid Build Coastguard Worker }
80*77c1e3ccSAndroid Build Coastguard Worker }
81*77c1e3ccSAndroid Build Coastguard Worker if (!fscanf(file, "\n\tsCb %d", &pars->num_cb_points)) {
82*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
83*77c1e3ccSAndroid Build Coastguard Worker "Unable to read num cb points");
84*77c1e3ccSAndroid Build Coastguard Worker return;
85*77c1e3ccSAndroid Build Coastguard Worker }
86*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < pars->num_cb_points; ++i) {
87*77c1e3ccSAndroid Build Coastguard Worker if (2 != fscanf(file, "%d %d", &pars->scaling_points_cb[i][0],
88*77c1e3ccSAndroid Build Coastguard Worker &pars->scaling_points_cb[i][1])) {
89*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
90*77c1e3ccSAndroid Build Coastguard Worker "Unable to read cb scaling points");
91*77c1e3ccSAndroid Build Coastguard Worker return;
92*77c1e3ccSAndroid Build Coastguard Worker }
93*77c1e3ccSAndroid Build Coastguard Worker }
94*77c1e3ccSAndroid Build Coastguard Worker if (!fscanf(file, "\n\tsCr %d", &pars->num_cr_points)) {
95*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
96*77c1e3ccSAndroid Build Coastguard Worker "Unable to read num cr points");
97*77c1e3ccSAndroid Build Coastguard Worker return;
98*77c1e3ccSAndroid Build Coastguard Worker }
99*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < pars->num_cr_points; ++i) {
100*77c1e3ccSAndroid Build Coastguard Worker if (2 != fscanf(file, "%d %d", &pars->scaling_points_cr[i][0],
101*77c1e3ccSAndroid Build Coastguard Worker &pars->scaling_points_cr[i][1])) {
102*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
103*77c1e3ccSAndroid Build Coastguard Worker "Unable to read cr scaling points");
104*77c1e3ccSAndroid Build Coastguard Worker return;
105*77c1e3ccSAndroid Build Coastguard Worker }
106*77c1e3ccSAndroid Build Coastguard Worker }
107*77c1e3ccSAndroid Build Coastguard Worker
108*77c1e3ccSAndroid Build Coastguard Worker if (fscanf(file, "\n\tcY")) {
109*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
110*77c1e3ccSAndroid Build Coastguard Worker "Unable to read Y coeffs header (cY)");
111*77c1e3ccSAndroid Build Coastguard Worker return;
112*77c1e3ccSAndroid Build Coastguard Worker }
113*77c1e3ccSAndroid Build Coastguard Worker const int n = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
114*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < n; ++i) {
115*77c1e3ccSAndroid Build Coastguard Worker if (1 != fscanf(file, "%d", &pars->ar_coeffs_y[i])) {
116*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
117*77c1e3ccSAndroid Build Coastguard Worker "Unable to read Y coeffs");
118*77c1e3ccSAndroid Build Coastguard Worker return;
119*77c1e3ccSAndroid Build Coastguard Worker }
120*77c1e3ccSAndroid Build Coastguard Worker }
121*77c1e3ccSAndroid Build Coastguard Worker if (fscanf(file, "\n\tcCb")) {
122*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
123*77c1e3ccSAndroid Build Coastguard Worker "Unable to read Cb coeffs header (cCb)");
124*77c1e3ccSAndroid Build Coastguard Worker return;
125*77c1e3ccSAndroid Build Coastguard Worker }
126*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i <= n; ++i) {
127*77c1e3ccSAndroid Build Coastguard Worker if (1 != fscanf(file, "%d", &pars->ar_coeffs_cb[i])) {
128*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
129*77c1e3ccSAndroid Build Coastguard Worker "Unable to read Cb coeffs");
130*77c1e3ccSAndroid Build Coastguard Worker return;
131*77c1e3ccSAndroid Build Coastguard Worker }
132*77c1e3ccSAndroid Build Coastguard Worker }
133*77c1e3ccSAndroid Build Coastguard Worker if (fscanf(file, "\n\tcCr")) {
134*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
135*77c1e3ccSAndroid Build Coastguard Worker "Unable read to Cr coeffs header (cCr)");
136*77c1e3ccSAndroid Build Coastguard Worker return;
137*77c1e3ccSAndroid Build Coastguard Worker }
138*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i <= n; ++i) {
139*77c1e3ccSAndroid Build Coastguard Worker if (1 != fscanf(file, "%d", &pars->ar_coeffs_cr[i])) {
140*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
141*77c1e3ccSAndroid Build Coastguard Worker "Unable to read Cr coeffs");
142*77c1e3ccSAndroid Build Coastguard Worker return;
143*77c1e3ccSAndroid Build Coastguard Worker }
144*77c1e3ccSAndroid Build Coastguard Worker }
145*77c1e3ccSAndroid Build Coastguard Worker (void)fscanf(file, "\n");
146*77c1e3ccSAndroid Build Coastguard Worker }
147*77c1e3ccSAndroid Build Coastguard Worker }
148*77c1e3ccSAndroid Build Coastguard Worker
grain_table_entry_write(FILE * file,aom_film_grain_table_entry_t * entry)149*77c1e3ccSAndroid Build Coastguard Worker static void grain_table_entry_write(FILE *file,
150*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *entry) {
151*77c1e3ccSAndroid Build Coastguard Worker const aom_film_grain_t *pars = &entry->params;
152*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "E %" PRId64 " %" PRId64 " %d %d %d\n", entry->start_time,
153*77c1e3ccSAndroid Build Coastguard Worker entry->end_time, pars->apply_grain, pars->random_seed,
154*77c1e3ccSAndroid Build Coastguard Worker pars->update_parameters);
155*77c1e3ccSAndroid Build Coastguard Worker if (pars->update_parameters) {
156*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\tp %d %d %d %d %d %d %d %d %d %d %d %d\n",
157*77c1e3ccSAndroid Build Coastguard Worker pars->ar_coeff_lag, pars->ar_coeff_shift, pars->grain_scale_shift,
158*77c1e3ccSAndroid Build Coastguard Worker pars->scaling_shift, pars->chroma_scaling_from_luma,
159*77c1e3ccSAndroid Build Coastguard Worker pars->overlap_flag, pars->cb_mult, pars->cb_luma_mult,
160*77c1e3ccSAndroid Build Coastguard Worker pars->cb_offset, pars->cr_mult, pars->cr_luma_mult,
161*77c1e3ccSAndroid Build Coastguard Worker pars->cr_offset);
162*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\tsY %d ", pars->num_y_points);
163*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < pars->num_y_points; ++i) {
164*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, " %d %d", pars->scaling_points_y[i][0],
165*77c1e3ccSAndroid Build Coastguard Worker pars->scaling_points_y[i][1]);
166*77c1e3ccSAndroid Build Coastguard Worker }
167*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n\tsCb %d", pars->num_cb_points);
168*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < pars->num_cb_points; ++i) {
169*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, " %d %d", pars->scaling_points_cb[i][0],
170*77c1e3ccSAndroid Build Coastguard Worker pars->scaling_points_cb[i][1]);
171*77c1e3ccSAndroid Build Coastguard Worker }
172*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n\tsCr %d", pars->num_cr_points);
173*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < pars->num_cr_points; ++i) {
174*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, " %d %d", pars->scaling_points_cr[i][0],
175*77c1e3ccSAndroid Build Coastguard Worker pars->scaling_points_cr[i][1]);
176*77c1e3ccSAndroid Build Coastguard Worker }
177*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n\tcY");
178*77c1e3ccSAndroid Build Coastguard Worker const int n = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
179*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i < n; ++i) {
180*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, " %d", pars->ar_coeffs_y[i]);
181*77c1e3ccSAndroid Build Coastguard Worker }
182*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n\tcCb");
183*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i <= n; ++i) {
184*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, " %d", pars->ar_coeffs_cb[i]);
185*77c1e3ccSAndroid Build Coastguard Worker }
186*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n\tcCr");
187*77c1e3ccSAndroid Build Coastguard Worker for (int i = 0; i <= n; ++i) {
188*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, " %d", pars->ar_coeffs_cr[i]);
189*77c1e3ccSAndroid Build Coastguard Worker }
190*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n");
191*77c1e3ccSAndroid Build Coastguard Worker }
192*77c1e3ccSAndroid Build Coastguard Worker }
193*77c1e3ccSAndroid Build Coastguard Worker
194*77c1e3ccSAndroid Build Coastguard Worker // TODO(https://crbug.com/aomedia/3228): Update this function to return an
195*77c1e3ccSAndroid Build Coastguard Worker // integer status.
aom_film_grain_table_append(aom_film_grain_table_t * t,int64_t time_stamp,int64_t end_time,const aom_film_grain_t * grain)196*77c1e3ccSAndroid Build Coastguard Worker void aom_film_grain_table_append(aom_film_grain_table_t *t, int64_t time_stamp,
197*77c1e3ccSAndroid Build Coastguard Worker int64_t end_time,
198*77c1e3ccSAndroid Build Coastguard Worker const aom_film_grain_t *grain) {
199*77c1e3ccSAndroid Build Coastguard Worker if (!t->tail || memcmp(grain, &t->tail->params, sizeof(*grain))) {
200*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *new_tail = aom_malloc(sizeof(*new_tail));
201*77c1e3ccSAndroid Build Coastguard Worker if (!new_tail) return;
202*77c1e3ccSAndroid Build Coastguard Worker memset(new_tail, 0, sizeof(*new_tail));
203*77c1e3ccSAndroid Build Coastguard Worker if (t->tail) t->tail->next = new_tail;
204*77c1e3ccSAndroid Build Coastguard Worker if (!t->head) t->head = new_tail;
205*77c1e3ccSAndroid Build Coastguard Worker t->tail = new_tail;
206*77c1e3ccSAndroid Build Coastguard Worker
207*77c1e3ccSAndroid Build Coastguard Worker new_tail->start_time = time_stamp;
208*77c1e3ccSAndroid Build Coastguard Worker new_tail->end_time = end_time;
209*77c1e3ccSAndroid Build Coastguard Worker new_tail->params = *grain;
210*77c1e3ccSAndroid Build Coastguard Worker } else {
211*77c1e3ccSAndroid Build Coastguard Worker t->tail->end_time = AOMMAX(t->tail->end_time, end_time);
212*77c1e3ccSAndroid Build Coastguard Worker t->tail->start_time = AOMMIN(t->tail->start_time, time_stamp);
213*77c1e3ccSAndroid Build Coastguard Worker }
214*77c1e3ccSAndroid Build Coastguard Worker }
215*77c1e3ccSAndroid Build Coastguard Worker
aom_film_grain_table_lookup(aom_film_grain_table_t * t,int64_t time_stamp,int64_t end_time,int erase,aom_film_grain_t * grain)216*77c1e3ccSAndroid Build Coastguard Worker int aom_film_grain_table_lookup(aom_film_grain_table_t *t, int64_t time_stamp,
217*77c1e3ccSAndroid Build Coastguard Worker int64_t end_time, int erase,
218*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_t *grain) {
219*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *entry = t->head;
220*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *prev_entry = NULL;
221*77c1e3ccSAndroid Build Coastguard Worker uint16_t random_seed = grain ? grain->random_seed : 0;
222*77c1e3ccSAndroid Build Coastguard Worker if (grain) memset(grain, 0, sizeof(*grain));
223*77c1e3ccSAndroid Build Coastguard Worker
224*77c1e3ccSAndroid Build Coastguard Worker while (entry) {
225*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *next = entry->next;
226*77c1e3ccSAndroid Build Coastguard Worker if (time_stamp >= entry->start_time && time_stamp < entry->end_time) {
227*77c1e3ccSAndroid Build Coastguard Worker if (grain) {
228*77c1e3ccSAndroid Build Coastguard Worker *grain = entry->params;
229*77c1e3ccSAndroid Build Coastguard Worker if (time_stamp != 0) grain->random_seed = random_seed;
230*77c1e3ccSAndroid Build Coastguard Worker }
231*77c1e3ccSAndroid Build Coastguard Worker if (!erase) return 1;
232*77c1e3ccSAndroid Build Coastguard Worker
233*77c1e3ccSAndroid Build Coastguard Worker const int64_t entry_end_time = entry->end_time;
234*77c1e3ccSAndroid Build Coastguard Worker if (time_stamp <= entry->start_time && end_time >= entry->end_time) {
235*77c1e3ccSAndroid Build Coastguard Worker if (t->tail == entry) t->tail = prev_entry;
236*77c1e3ccSAndroid Build Coastguard Worker if (prev_entry) {
237*77c1e3ccSAndroid Build Coastguard Worker prev_entry->next = entry->next;
238*77c1e3ccSAndroid Build Coastguard Worker } else {
239*77c1e3ccSAndroid Build Coastguard Worker t->head = entry->next;
240*77c1e3ccSAndroid Build Coastguard Worker }
241*77c1e3ccSAndroid Build Coastguard Worker aom_free(entry);
242*77c1e3ccSAndroid Build Coastguard Worker } else if (time_stamp <= entry->start_time &&
243*77c1e3ccSAndroid Build Coastguard Worker end_time < entry->end_time) {
244*77c1e3ccSAndroid Build Coastguard Worker entry->start_time = end_time;
245*77c1e3ccSAndroid Build Coastguard Worker } else if (time_stamp > entry->start_time &&
246*77c1e3ccSAndroid Build Coastguard Worker end_time >= entry->end_time) {
247*77c1e3ccSAndroid Build Coastguard Worker entry->end_time = time_stamp;
248*77c1e3ccSAndroid Build Coastguard Worker } else {
249*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *new_entry =
250*77c1e3ccSAndroid Build Coastguard Worker aom_malloc(sizeof(*new_entry));
251*77c1e3ccSAndroid Build Coastguard Worker if (!new_entry) return 0;
252*77c1e3ccSAndroid Build Coastguard Worker new_entry->next = entry->next;
253*77c1e3ccSAndroid Build Coastguard Worker new_entry->start_time = end_time;
254*77c1e3ccSAndroid Build Coastguard Worker new_entry->end_time = entry->end_time;
255*77c1e3ccSAndroid Build Coastguard Worker new_entry->params = entry->params;
256*77c1e3ccSAndroid Build Coastguard Worker entry->next = new_entry;
257*77c1e3ccSAndroid Build Coastguard Worker entry->end_time = time_stamp;
258*77c1e3ccSAndroid Build Coastguard Worker if (t->tail == entry) t->tail = new_entry;
259*77c1e3ccSAndroid Build Coastguard Worker }
260*77c1e3ccSAndroid Build Coastguard Worker // If segments aren't aligned, delete from the beginning of subsequent
261*77c1e3ccSAndroid Build Coastguard Worker // segments
262*77c1e3ccSAndroid Build Coastguard Worker if (end_time > entry_end_time) {
263*77c1e3ccSAndroid Build Coastguard Worker // Ignoring the return value here is safe since we're erasing from the
264*77c1e3ccSAndroid Build Coastguard Worker // beginning of subsequent entries.
265*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_lookup(t, entry_end_time, end_time, /*erase=*/1,
266*77c1e3ccSAndroid Build Coastguard Worker NULL);
267*77c1e3ccSAndroid Build Coastguard Worker }
268*77c1e3ccSAndroid Build Coastguard Worker return 1;
269*77c1e3ccSAndroid Build Coastguard Worker }
270*77c1e3ccSAndroid Build Coastguard Worker prev_entry = entry;
271*77c1e3ccSAndroid Build Coastguard Worker entry = next;
272*77c1e3ccSAndroid Build Coastguard Worker }
273*77c1e3ccSAndroid Build Coastguard Worker return 0;
274*77c1e3ccSAndroid Build Coastguard Worker }
275*77c1e3ccSAndroid Build Coastguard Worker
aom_film_grain_table_read(aom_film_grain_table_t * t,const char * filename,struct aom_internal_error_info * error_info)276*77c1e3ccSAndroid Build Coastguard Worker aom_codec_err_t aom_film_grain_table_read(
277*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_t *t, const char *filename,
278*77c1e3ccSAndroid Build Coastguard Worker struct aom_internal_error_info *error_info) {
279*77c1e3ccSAndroid Build Coastguard Worker FILE *file = fopen(filename, "rb");
280*77c1e3ccSAndroid Build Coastguard Worker if (!file) {
281*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR, "Unable to open %s",
282*77c1e3ccSAndroid Build Coastguard Worker filename);
283*77c1e3ccSAndroid Build Coastguard Worker return error_info->error_code;
284*77c1e3ccSAndroid Build Coastguard Worker }
285*77c1e3ccSAndroid Build Coastguard Worker error_info->error_code = AOM_CODEC_OK;
286*77c1e3ccSAndroid Build Coastguard Worker
287*77c1e3ccSAndroid Build Coastguard Worker // Read in one extra character as there should be white space after
288*77c1e3ccSAndroid Build Coastguard Worker // the header.
289*77c1e3ccSAndroid Build Coastguard Worker char magic[9];
290*77c1e3ccSAndroid Build Coastguard Worker if (!fread(magic, 9, 1, file) || memcmp(magic, kFileMagic, 8)) {
291*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
292*77c1e3ccSAndroid Build Coastguard Worker "Unable to read (or invalid) file magic");
293*77c1e3ccSAndroid Build Coastguard Worker fclose(file);
294*77c1e3ccSAndroid Build Coastguard Worker return error_info->error_code;
295*77c1e3ccSAndroid Build Coastguard Worker }
296*77c1e3ccSAndroid Build Coastguard Worker
297*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *prev_entry = NULL;
298*77c1e3ccSAndroid Build Coastguard Worker while (!feof(file)) {
299*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *entry = aom_malloc(sizeof(*entry));
300*77c1e3ccSAndroid Build Coastguard Worker if (!entry) {
301*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_MEM_ERROR,
302*77c1e3ccSAndroid Build Coastguard Worker "Unable to allocate grain table entry");
303*77c1e3ccSAndroid Build Coastguard Worker break;
304*77c1e3ccSAndroid Build Coastguard Worker }
305*77c1e3ccSAndroid Build Coastguard Worker memset(entry, 0, sizeof(*entry));
306*77c1e3ccSAndroid Build Coastguard Worker grain_table_entry_read(file, error_info, entry);
307*77c1e3ccSAndroid Build Coastguard Worker entry->next = NULL;
308*77c1e3ccSAndroid Build Coastguard Worker
309*77c1e3ccSAndroid Build Coastguard Worker if (prev_entry) prev_entry->next = entry;
310*77c1e3ccSAndroid Build Coastguard Worker if (!t->head) t->head = entry;
311*77c1e3ccSAndroid Build Coastguard Worker t->tail = entry;
312*77c1e3ccSAndroid Build Coastguard Worker prev_entry = entry;
313*77c1e3ccSAndroid Build Coastguard Worker
314*77c1e3ccSAndroid Build Coastguard Worker if (error_info->error_code != AOM_CODEC_OK) break;
315*77c1e3ccSAndroid Build Coastguard Worker }
316*77c1e3ccSAndroid Build Coastguard Worker
317*77c1e3ccSAndroid Build Coastguard Worker fclose(file);
318*77c1e3ccSAndroid Build Coastguard Worker return error_info->error_code;
319*77c1e3ccSAndroid Build Coastguard Worker }
320*77c1e3ccSAndroid Build Coastguard Worker
aom_film_grain_table_write(const aom_film_grain_table_t * t,const char * filename,struct aom_internal_error_info * error_info)321*77c1e3ccSAndroid Build Coastguard Worker aom_codec_err_t aom_film_grain_table_write(
322*77c1e3ccSAndroid Build Coastguard Worker const aom_film_grain_table_t *t, const char *filename,
323*77c1e3ccSAndroid Build Coastguard Worker struct aom_internal_error_info *error_info) {
324*77c1e3ccSAndroid Build Coastguard Worker error_info->error_code = AOM_CODEC_OK;
325*77c1e3ccSAndroid Build Coastguard Worker
326*77c1e3ccSAndroid Build Coastguard Worker FILE *file = fopen(filename, "wb");
327*77c1e3ccSAndroid Build Coastguard Worker if (!file) {
328*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR, "Unable to open file %s",
329*77c1e3ccSAndroid Build Coastguard Worker filename);
330*77c1e3ccSAndroid Build Coastguard Worker return error_info->error_code;
331*77c1e3ccSAndroid Build Coastguard Worker }
332*77c1e3ccSAndroid Build Coastguard Worker
333*77c1e3ccSAndroid Build Coastguard Worker if (!fwrite(kFileMagic, 8, 1, file)) {
334*77c1e3ccSAndroid Build Coastguard Worker aom_internal_error(error_info, AOM_CODEC_ERROR,
335*77c1e3ccSAndroid Build Coastguard Worker "Unable to write file magic");
336*77c1e3ccSAndroid Build Coastguard Worker fclose(file);
337*77c1e3ccSAndroid Build Coastguard Worker return error_info->error_code;
338*77c1e3ccSAndroid Build Coastguard Worker }
339*77c1e3ccSAndroid Build Coastguard Worker
340*77c1e3ccSAndroid Build Coastguard Worker fprintf(file, "\n");
341*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *entry = t->head;
342*77c1e3ccSAndroid Build Coastguard Worker while (entry) {
343*77c1e3ccSAndroid Build Coastguard Worker grain_table_entry_write(file, entry);
344*77c1e3ccSAndroid Build Coastguard Worker entry = entry->next;
345*77c1e3ccSAndroid Build Coastguard Worker }
346*77c1e3ccSAndroid Build Coastguard Worker fclose(file);
347*77c1e3ccSAndroid Build Coastguard Worker return error_info->error_code;
348*77c1e3ccSAndroid Build Coastguard Worker }
349*77c1e3ccSAndroid Build Coastguard Worker
aom_film_grain_table_free(aom_film_grain_table_t * t)350*77c1e3ccSAndroid Build Coastguard Worker void aom_film_grain_table_free(aom_film_grain_table_t *t) {
351*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *entry = t->head;
352*77c1e3ccSAndroid Build Coastguard Worker while (entry) {
353*77c1e3ccSAndroid Build Coastguard Worker aom_film_grain_table_entry_t *next = entry->next;
354*77c1e3ccSAndroid Build Coastguard Worker aom_free(entry);
355*77c1e3ccSAndroid Build Coastguard Worker entry = next;
356*77c1e3ccSAndroid Build Coastguard Worker }
357*77c1e3ccSAndroid Build Coastguard Worker memset(t, 0, sizeof(*t));
358*77c1e3ccSAndroid Build Coastguard Worker }
359