blob: 6beb4fb0607a21fcc3892559aa5bac8c9aa236db [file] [log] [blame]
Yunqing Wang9aaa3c92016-03-25 11:57:20 -07001/*
Yaowu Xu9c01aa12016-09-01 14:32:49 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yunqing Wang9aaa3c92016-03-25 11:57:20 -07003 *
Yaowu Xu9c01aa12016-09-01 14:32:49 -07004 * 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.
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070010 */
11
Yaowu Xuf883b422016-08-30 14:01:10 -070012// AV1 Set Reference Frame
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070013// ============================
14//
Yaowu Xuf883b422016-08-30 14:01:10 -070015// This is an example demonstrating how to overwrite the AV1 encoder's
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070016// internal reference frame. In the sample we set the last frame to the
17// current frame. This technique could be used to bounce between two cameras.
18//
19// The decoder would also have to set the reference frame to the same value
20// on the same frame, or the video will become corrupt. The 'test_decode'
21// variable is set to 1 in this example that tests if the encoder and decoder
22// results are matching.
23//
24// Usage
25// -----
26// This example encodes a raw video. And the last argument passed in specifies
27// the frame number to update the reference frame on. For example, run
Yaowu Xuf883b422016-08-30 14:01:10 -070028// examples/aom_cx_set_ref av1 352 288 in.yuv out.ivf 4 30
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070029// The parameter is parsed as follows:
30//
31//
32// Extra Variables
33// ---------------
34// This example maintains the frame number passed on the command line
35// in the `update_frame_num` variable.
36//
37//
38// Configuration
39// -------------
40//
41// The reference frame is updated on the frame specified on the command
42// line.
43//
44// Observing The Effects
45// ---------------------
46// The encoder and decoder results should be matching when the same reference
47// frame setting operation is done in both encoder and decoder. Otherwise,
48// the encoder/decoder mismatch would be seen.
49
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53
Yaowu Xuf883b422016-08-30 14:01:10 -070054#include "aom/aomcx.h"
55#include "aom/aom_decoder.h"
56#include "aom/aom_encoder.h"
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070057
58#include "./tools_common.h"
59#include "./video_writer.h"
60
61static const char *exec_name;
62
63void usage_exit() {
clang-format397d9642016-08-08 18:51:16 -070064 fprintf(stderr,
65 "Usage: %s <codec> <width> <height> <infile> <outfile> "
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070066 "<frame> <limit(optional)>\n",
67 exec_name);
68 exit(EXIT_FAILURE);
69}
70
Yaowu Xuf883b422016-08-30 14:01:10 -070071static int compare_img(const aom_image_t *const img1,
72 const aom_image_t *const img2) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070073 uint32_t l_w = img1->d_w;
clang-format397d9642016-08-08 18:51:16 -070074 uint32_t c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070075 const uint32_t c_h =
76 (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
77 uint32_t i;
78 int match = 1;
79
80 match &= (img1->fmt == img2->fmt);
81 match &= (img1->d_w == img2->d_w);
82 match &= (img1->d_h == img2->d_h);
83
84 for (i = 0; i < img1->d_h; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070085 match &= (memcmp(img1->planes[AOM_PLANE_Y] + i * img1->stride[AOM_PLANE_Y],
86 img2->planes[AOM_PLANE_Y] + i * img2->stride[AOM_PLANE_Y],
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070087 l_w) == 0);
88
89 for (i = 0; i < c_h; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070090 match &= (memcmp(img1->planes[AOM_PLANE_U] + i * img1->stride[AOM_PLANE_U],
91 img2->planes[AOM_PLANE_U] + i * img2->stride[AOM_PLANE_U],
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070092 c_w) == 0);
93
94 for (i = 0; i < c_h; ++i)
Yaowu Xuf883b422016-08-30 14:01:10 -070095 match &= (memcmp(img1->planes[AOM_PLANE_V] + i * img1->stride[AOM_PLANE_V],
96 img2->planes[AOM_PLANE_V] + i * img2->stride[AOM_PLANE_V],
Yunqing Wang9aaa3c92016-03-25 11:57:20 -070097 c_w) == 0);
98
99 return match;
100}
101
clang-format397d9642016-08-08 18:51:16 -0700102#define mmin(a, b) ((a) < (b) ? (a) : (b))
Yaowu Xuf883b422016-08-30 14:01:10 -0700103static void find_mismatch(const aom_image_t *const img1,
104 const aom_image_t *const img2, int yloc[4],
clang-format397d9642016-08-08 18:51:16 -0700105 int uloc[4], int vloc[4]) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700106 const uint32_t bsize = 64;
107 const uint32_t bsizey = bsize >> img1->y_chroma_shift;
108 const uint32_t bsizex = bsize >> img1->x_chroma_shift;
109 const uint32_t c_w =
110 (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
111 const uint32_t c_h =
112 (img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
113 int match = 1;
114 uint32_t i, j;
115 yloc[0] = yloc[1] = yloc[2] = yloc[3] = -1;
116 for (i = 0, match = 1; match && i < img1->d_h; i += bsize) {
117 for (j = 0; match && j < img1->d_w; j += bsize) {
118 int k, l;
119 const int si = mmin(i + bsize, img1->d_h) - i;
120 const int sj = mmin(j + bsize, img1->d_w) - j;
121 for (k = 0; match && k < si; ++k) {
122 for (l = 0; match && l < sj; ++l) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700123 if (*(img1->planes[AOM_PLANE_Y] +
124 (i + k) * img1->stride[AOM_PLANE_Y] + j + l) !=
125 *(img2->planes[AOM_PLANE_Y] +
126 (i + k) * img2->stride[AOM_PLANE_Y] + j + l)) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700127 yloc[0] = i + k;
128 yloc[1] = j + l;
Yaowu Xuf883b422016-08-30 14:01:10 -0700129 yloc[2] = *(img1->planes[AOM_PLANE_Y] +
130 (i + k) * img1->stride[AOM_PLANE_Y] + j + l);
131 yloc[3] = *(img2->planes[AOM_PLANE_Y] +
132 (i + k) * img2->stride[AOM_PLANE_Y] + j + l);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700133 match = 0;
134 break;
135 }
136 }
137 }
138 }
139 }
140
141 uloc[0] = uloc[1] = uloc[2] = uloc[3] = -1;
142 for (i = 0, match = 1; match && i < c_h; i += bsizey) {
143 for (j = 0; match && j < c_w; j += bsizex) {
144 int k, l;
145 const int si = mmin(i + bsizey, c_h - i);
146 const int sj = mmin(j + bsizex, c_w - j);
147 for (k = 0; match && k < si; ++k) {
148 for (l = 0; match && l < sj; ++l) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700149 if (*(img1->planes[AOM_PLANE_U] +
150 (i + k) * img1->stride[AOM_PLANE_U] + j + l) !=
151 *(img2->planes[AOM_PLANE_U] +
152 (i + k) * img2->stride[AOM_PLANE_U] + j + l)) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700153 uloc[0] = i + k;
154 uloc[1] = j + l;
Yaowu Xuf883b422016-08-30 14:01:10 -0700155 uloc[2] = *(img1->planes[AOM_PLANE_U] +
156 (i + k) * img1->stride[AOM_PLANE_U] + j + l);
157 uloc[3] = *(img2->planes[AOM_PLANE_U] +
158 (i + k) * img2->stride[AOM_PLANE_U] + j + l);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700159 match = 0;
160 break;
161 }
162 }
163 }
164 }
165 }
166 vloc[0] = vloc[1] = vloc[2] = vloc[3] = -1;
167 for (i = 0, match = 1; match && i < c_h; i += bsizey) {
168 for (j = 0; match && j < c_w; j += bsizex) {
169 int k, l;
170 const int si = mmin(i + bsizey, c_h - i);
171 const int sj = mmin(j + bsizex, c_w - j);
172 for (k = 0; match && k < si; ++k) {
173 for (l = 0; match && l < sj; ++l) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700174 if (*(img1->planes[AOM_PLANE_V] +
175 (i + k) * img1->stride[AOM_PLANE_V] + j + l) !=
176 *(img2->planes[AOM_PLANE_V] +
177 (i + k) * img2->stride[AOM_PLANE_V] + j + l)) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700178 vloc[0] = i + k;
179 vloc[1] = j + l;
Yaowu Xuf883b422016-08-30 14:01:10 -0700180 vloc[2] = *(img1->planes[AOM_PLANE_V] +
181 (i + k) * img1->stride[AOM_PLANE_V] + j + l);
182 vloc[3] = *(img2->planes[AOM_PLANE_V] +
183 (i + k) * img2->stride[AOM_PLANE_V] + j + l);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700184 match = 0;
185 break;
186 }
187 }
188 }
189 }
190 }
191}
192
Yaowu Xuf883b422016-08-30 14:01:10 -0700193static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
Urvang Joshid71a2312016-07-14 12:33:48 -0700194 unsigned int frame_out, int *mismatch_seen) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700195 aom_image_t enc_img, dec_img;
196 struct av1_ref_frame ref_enc, ref_dec;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700197
clang-format397d9642016-08-08 18:51:16 -0700198 if (*mismatch_seen) return;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700199
200 ref_enc.idx = 0;
201 ref_dec.idx = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700202 if (aom_codec_control(encoder, AV1_GET_REFERENCE, &ref_enc))
clang-format397d9642016-08-08 18:51:16 -0700203 die_codec(encoder, "Failed to get encoder reference frame");
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700204 enc_img = ref_enc.img;
Yaowu Xuf883b422016-08-30 14:01:10 -0700205 if (aom_codec_control(decoder, AV1_GET_REFERENCE, &ref_dec))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700206 die_codec(decoder, "Failed to get decoder reference frame");
207 dec_img = ref_dec.img;
208
209 if (!compare_img(&enc_img, &dec_img)) {
210 int y[4], u[4], v[4];
211
212 *mismatch_seen = 1;
213
214 find_mismatch(&enc_img, &dec_img, y, u, v);
clang-format397d9642016-08-08 18:51:16 -0700215 printf(
216 "Encode/decode mismatch on frame %d at"
217 " Y[%d, %d] {%d/%d},"
218 " U[%d, %d] {%d/%d},"
219 " V[%d, %d] {%d/%d}",
220 frame_out, y[0], y[1], y[2], y[3], u[0], u[1], u[2], u[3], v[0], v[1],
221 v[2], v[3]);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700222 }
223
Yaowu Xuf883b422016-08-30 14:01:10 -0700224 aom_img_free(&enc_img);
225 aom_img_free(&dec_img);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700226}
227
Urvang Joshid71a2312016-07-14 12:33:48 -0700228static int encode_frame(aom_codec_ctx_t *ecodec, aom_image_t *img,
229 unsigned int frame_in, AvxVideoWriter *writer,
230 int test_decode, aom_codec_ctx_t *dcodec,
231 unsigned int *frame_out, int *mismatch_seen) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700232 int got_pkts = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700233 aom_codec_iter_t iter = NULL;
234 const aom_codec_cx_pkt_t *pkt = NULL;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700235 int got_data;
Yaowu Xuf883b422016-08-30 14:01:10 -0700236 const aom_codec_err_t res =
237 aom_codec_encode(ecodec, img, frame_in, 1, 0, AOM_DL_GOOD_QUALITY);
238 if (res != AOM_CODEC_OK) die_codec(ecodec, "Failed to encode frame");
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700239
240 got_data = 0;
241
Yaowu Xuf883b422016-08-30 14:01:10 -0700242 while ((pkt = aom_codec_get_cx_data(ecodec, &iter)) != NULL) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700243 got_pkts = 1;
244
Yaowu Xuf883b422016-08-30 14:01:10 -0700245 if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
246 const int keyframe = (pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700247
Yaowu Xuf883b422016-08-30 14:01:10 -0700248 if (!(pkt->data.frame.flags & AOM_FRAME_IS_FRAGMENT)) {
clang-format397d9642016-08-08 18:51:16 -0700249 *frame_out += 1;
250 }
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700251
Yaowu Xuf883b422016-08-30 14:01:10 -0700252 if (!aom_video_writer_write_frame(writer, pkt->data.frame.buf,
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700253 pkt->data.frame.sz,
254 pkt->data.frame.pts)) {
255 die_codec(ecodec, "Failed to write compressed frame");
256 }
257 printf(keyframe ? "K" : ".");
258 fflush(stdout);
259 got_data = 1;
260
261 // Decode 1 frame.
262 if (test_decode) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700263 if (aom_codec_decode(dcodec, pkt->data.frame.buf,
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700264 (unsigned int)pkt->data.frame.sz, NULL, 0))
265 die_codec(dcodec, "Failed to decode frame.");
266 }
267 }
268 }
269
270 // Mismatch checking
271 if (got_data && test_decode) {
Urvang Joshid71a2312016-07-14 12:33:48 -0700272 testing_decode(ecodec, dcodec, *frame_out, mismatch_seen);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700273 }
274
275 return got_pkts;
276}
277
278int main(int argc, char **argv) {
279 FILE *infile = NULL;
280 // Encoder
Urvang Joshid71a2312016-07-14 12:33:48 -0700281 aom_codec_ctx_t ecodec;
282 aom_codec_enc_cfg_t cfg;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700283 unsigned int frame_in = 0;
Yaowu Xuf883b422016-08-30 14:01:10 -0700284 aom_image_t raw;
285 aom_codec_err_t res;
Urvang Joshid71a2312016-07-14 12:33:48 -0700286 AvxVideoInfo info;
Yaowu Xuf883b422016-08-30 14:01:10 -0700287 AvxVideoWriter *writer = NULL;
288 const AvxInterface *encoder = NULL;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700289
290 // Test encoder/decoder mismatch.
291 int test_decode = 1;
292 // Decoder
Yaowu Xuf883b422016-08-30 14:01:10 -0700293 aom_codec_ctx_t dcodec;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700294 unsigned int frame_out = 0;
295
296 // The frame number to set reference frame on
Yunqing Wang2a5a3f62016-07-22 17:14:22 -0700297 unsigned int update_frame_num = 0;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700298 int mismatch_seen = 0;
299
300 const int fps = 30;
301 const int bitrate = 500;
302
303 const char *codec_arg = NULL;
304 const char *width_arg = NULL;
305 const char *height_arg = NULL;
306 const char *infile_arg = NULL;
307 const char *outfile_arg = NULL;
Urvang Joshid3a75762016-07-08 16:09:36 -0700308 const char *update_frame_num_arg = NULL;
Yunqing Wang2a5a3f62016-07-22 17:14:22 -0700309 unsigned int limit = 0;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700310 exec_name = argv[0];
311
Urvang Joshid71a2312016-07-14 12:33:48 -0700312 // Clear explicitly, as simply assigning "{ 0 }" generates
313 // "missing-field-initializers" warning in some compilers.
314 memset(&ecodec, 0, sizeof(ecodec));
315 memset(&cfg, 0, sizeof(cfg));
316 memset(&info, 0, sizeof(info));
317
clang-format397d9642016-08-08 18:51:16 -0700318 if (argc < 7) die("Invalid number of arguments");
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700319
320 codec_arg = argv[1];
321 width_arg = argv[2];
322 height_arg = argv[3];
323 infile_arg = argv[4];
324 outfile_arg = argv[5];
Urvang Joshid3a75762016-07-08 16:09:36 -0700325 update_frame_num_arg = argv[6];
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700326
Yaowu Xuf883b422016-08-30 14:01:10 -0700327 encoder = get_aom_encoder_by_name(codec_arg);
clang-format397d9642016-08-08 18:51:16 -0700328 if (!encoder) die("Unsupported codec.");
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700329
Urvang Joshid3a75762016-07-08 16:09:36 -0700330 update_frame_num = (unsigned int)strtoul(update_frame_num_arg, NULL, 0);
Yaowu Xuf883b422016-08-30 14:01:10 -0700331 // In AV1, the reference buffers (cm->buffer_pool->frame_bufs[i].buf) are
332 // allocated while calling aom_codec_encode(), thus, setting reference for
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700333 // 1st frame isn't supported.
Urvang Joshid3a75762016-07-08 16:09:36 -0700334 if (update_frame_num <= 1) {
335 die("Couldn't parse frame number '%s'\n", update_frame_num_arg);
336 }
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700337
338 if (argc > 7) {
Urvang Joshid3a75762016-07-08 16:09:36 -0700339 limit = (unsigned int)strtoul(argv[7], NULL, 0);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700340 if (update_frame_num > limit)
341 die("Update frame number couldn't larger than limit\n");
342 }
343
344 info.codec_fourcc = encoder->fourcc;
345 info.frame_width = strtol(width_arg, NULL, 0);
346 info.frame_height = strtol(height_arg, NULL, 0);
347 info.time_base.numerator = 1;
348 info.time_base.denominator = fps;
349
clang-format397d9642016-08-08 18:51:16 -0700350 if (info.frame_width <= 0 || info.frame_height <= 0 ||
351 (info.frame_width % 2) != 0 || (info.frame_height % 2) != 0) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700352 die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
353 }
354
Yaowu Xuf883b422016-08-30 14:01:10 -0700355 if (!aom_img_alloc(&raw, AOM_IMG_FMT_I420, info.frame_width,
clang-format397d9642016-08-08 18:51:16 -0700356 info.frame_height, 1)) {
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700357 die("Failed to allocate image.");
358 }
359
Yaowu Xuf883b422016-08-30 14:01:10 -0700360 printf("Using %s\n", aom_codec_iface_name(encoder->codec_interface()));
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700361
Yaowu Xuf883b422016-08-30 14:01:10 -0700362 res = aom_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
clang-format397d9642016-08-08 18:51:16 -0700363 if (res) die_codec(&ecodec, "Failed to get default codec config.");
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700364
365 cfg.g_w = info.frame_width;
366 cfg.g_h = info.frame_height;
367 cfg.g_timebase.num = info.time_base.numerator;
368 cfg.g_timebase.den = info.time_base.denominator;
369 cfg.rc_target_bitrate = bitrate;
370 cfg.g_lag_in_frames = 3;
371
Yaowu Xuf883b422016-08-30 14:01:10 -0700372 writer = aom_video_writer_open(outfile_arg, kContainerIVF, &info);
clang-format397d9642016-08-08 18:51:16 -0700373 if (!writer) die("Failed to open %s for writing.", outfile_arg);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700374
375 if (!(infile = fopen(infile_arg, "rb")))
376 die("Failed to open %s for reading.", infile_arg);
377
Yaowu Xuf883b422016-08-30 14:01:10 -0700378 if (aom_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, 0))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700379 die_codec(&ecodec, "Failed to initialize encoder");
380
381 // Disable alt_ref.
Yaowu Xuf883b422016-08-30 14:01:10 -0700382 if (aom_codec_control(&ecodec, AOME_SET_ENABLEAUTOALTREF, 0))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700383 die_codec(&ecodec, "Failed to set enable auto alt ref");
384
385 if (test_decode) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700386 const AvxInterface *decoder = get_aom_decoder_by_name(codec_arg);
387 if (aom_codec_dec_init(&dcodec, decoder->codec_interface(), NULL, 0))
clang-format397d9642016-08-08 18:51:16 -0700388 die_codec(&dcodec, "Failed to initialize decoder.");
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700389 }
390
391 // Encode frames.
Yaowu Xuf883b422016-08-30 14:01:10 -0700392 while (aom_img_read(&raw, infile)) {
clang-format397d9642016-08-08 18:51:16 -0700393 if (limit && frame_in >= limit) break;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700394 if (update_frame_num > 1 && frame_out + 1 == update_frame_num) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700395 aom_ref_frame_t ref;
396 ref.frame_type = AOM_LAST_FRAME;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700397 ref.img = raw;
398 // Set reference frame in encoder.
Yaowu Xuf883b422016-08-30 14:01:10 -0700399 if (aom_codec_control(&ecodec, AOM_SET_REFERENCE, &ref))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700400 die_codec(&ecodec, "Failed to set reference frame");
401 printf(" <SET_REF>");
402
403 // If set_reference in decoder is commented out, the enc/dec mismatch
404 // would be seen.
405 if (test_decode) {
Yaowu Xuf883b422016-08-30 14:01:10 -0700406 if (aom_codec_control(&dcodec, AOM_SET_REFERENCE, &ref))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700407 die_codec(&dcodec, "Failed to set reference frame");
408 }
409 }
410
Urvang Joshid71a2312016-07-14 12:33:48 -0700411 encode_frame(&ecodec, &raw, frame_in, writer, test_decode, &dcodec,
clang-format397d9642016-08-08 18:51:16 -0700412 &frame_out, &mismatch_seen);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700413 frame_in++;
clang-format397d9642016-08-08 18:51:16 -0700414 if (mismatch_seen) break;
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700415 }
416
417 // Flush encoder.
418 if (!mismatch_seen)
Urvang Joshid71a2312016-07-14 12:33:48 -0700419 while (encode_frame(&ecodec, NULL, frame_in, writer, test_decode, &dcodec,
420 &frame_out, &mismatch_seen)) {
clang-format397d9642016-08-08 18:51:16 -0700421 }
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700422
423 printf("\n");
424 fclose(infile);
425 printf("Processed %d frames.\n", frame_out);
426
427 if (test_decode) {
428 if (!mismatch_seen)
429 printf("Encoder/decoder results are matching.\n");
430 else
431 printf("Encoder/decoder results are NOT matching.\n");
432 }
433
434 if (test_decode)
Yaowu Xuf883b422016-08-30 14:01:10 -0700435 if (aom_codec_destroy(&dcodec))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700436 die_codec(&dcodec, "Failed to destroy decoder");
437
Yaowu Xuf883b422016-08-30 14:01:10 -0700438 aom_img_free(&raw);
439 if (aom_codec_destroy(&ecodec))
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700440 die_codec(&ecodec, "Failed to destroy encoder.");
441
Yaowu Xuf883b422016-08-30 14:01:10 -0700442 aom_video_writer_close(writer);
Yunqing Wang9aaa3c92016-03-25 11:57:20 -0700443
444 return EXIT_SUCCESS;
445}