blob: 90c2c294c0d917af16f155a83eb97edfcd954254 [file] [log] [blame]
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -08001/*
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// Inspect Decoder
13// ================
14//
15// This is a simple decoder loop that writes JSON stats to stdout. This tool
16// can also be compiled with Emscripten and used as a library.
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "./args.h"
23#ifdef __EMSCRIPTEN__
24#include <emscripten.h>
25#else
26#define EMSCRIPTEN_KEEPALIVE
27#endif
28
29#include "aom/aom_decoder.h"
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080030#include "./aom_config.h"
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080031#if CONFIG_ACCOUNTING
Luc Trudeau83fbd572017-04-21 11:24:34 -040032#include "../av1/decoder/accounting.h"
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080033#endif
34#include "../av1/decoder/inspection.h"
Nathan E. Egge1e412752017-05-04 21:09:39 -040035#include "aom/aomdx.h"
36
37#include "../tools_common.h"
38#include "../video_reader.h"
39// #include "av1/av1_dx_iface.c"
40#include "../av1/common/onyxc_int.h"
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080041
42#include "../video_common.h"
43
44// Max JSON buffer size.
45const int MAX_BUFFER = 1024 * 1024 * 32;
46
47typedef enum {
48 ACCOUNTING_LAYER = 1,
49 BLOCK_SIZE_LAYER = 1 << 1,
50 TRANSFORM_SIZE_LAYER = 1 << 2,
51 TRANSFORM_TYPE_LAYER = 1 << 3,
52 MODE_LAYER = 1 << 4,
53 SKIP_LAYER = 1 << 5,
54 FILTER_LAYER = 1 << 6,
55 CDEF_LAYER = 1 << 7,
56 REFERENCE_FRAME_LAYER = 1 << 8,
57 MOTION_VECTORS_LAYER = 1 << 9,
Luc Trudeau0be435a2017-04-07 23:38:52 -040058 UV_MODE_LAYER = 1 << 10,
Luc Trudeauf89056a2017-04-28 16:07:22 -040059 CFL_LAYER = 1 << 11,
60 ALL_LAYERS = (1 << 12) - 1
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080061} LayerType;
62
63static LayerType layers = 0;
64
65static int stop_after = 0;
Michael Bebenitaf1207b62017-04-14 22:30:56 -070066static int compress = 0;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080067
68static const arg_def_t limit_arg =
69 ARG_DEF(NULL, "limit", 1, "Stop decoding after n frames");
70static const arg_def_t dump_all_arg = ARG_DEF("A", "all", 0, "Dump All");
Michael Bebenitaf1207b62017-04-14 22:30:56 -070071static const arg_def_t compress_arg =
72 ARG_DEF("x", "compress", 0, "Compress JSON using RLE");
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080073static const arg_def_t dump_accounting_arg =
74 ARG_DEF("a", "accounting", 0, "Dump Accounting");
75static const arg_def_t dump_block_size_arg =
76 ARG_DEF("bs", "blockSize", 0, "Dump Block Size");
77static const arg_def_t dump_motion_vectors_arg =
78 ARG_DEF("mv", "motionVectors", 0, "Dump Motion Vectors");
79static const arg_def_t dump_transform_size_arg =
80 ARG_DEF("ts", "transformSize", 0, "Dump Transform Size");
81static const arg_def_t dump_transform_type_arg =
82 ARG_DEF("tt", "transformType", 0, "Dump Transform Type");
83static const arg_def_t dump_mode_arg = ARG_DEF("m", "mode", 0, "Dump Mode");
Luc Trudeau0be435a2017-04-07 23:38:52 -040084static const arg_def_t dump_uv_mode_arg =
85 ARG_DEF("uvm", "uv_mode", 0, "Dump UV Intra Prediction Modes");
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080086static const arg_def_t dump_skip_arg = ARG_DEF("s", "skip", 0, "Dump Skip");
87static const arg_def_t dump_filter_arg =
88 ARG_DEF("f", "filter", 0, "Dump Filter");
89static const arg_def_t dump_cdef_arg = ARG_DEF("c", "cdef", 0, "Dump CDEF");
Luc Trudeauf89056a2017-04-28 16:07:22 -040090#if CONFIG_CFL
91static const arg_def_t dump_cfl_arg =
92 ARG_DEF("cfl", "chroma_from_luma", 0, "Dump Chroma from Luma Alphas");
93#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080094static const arg_def_t dump_reference_frame_arg =
95 ARG_DEF("r", "referenceFrame", 0, "Dump Reference Frame");
96static const arg_def_t usage_arg = ARG_DEF("h", "help", 0, "Help");
97
98static const arg_def_t *main_args[] = { &limit_arg,
99 &dump_all_arg,
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700100 &compress_arg,
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800101#if CONFIG_ACCOUNTING
102 &dump_accounting_arg,
103#endif
104 &dump_block_size_arg,
105 &dump_transform_size_arg,
106 &dump_transform_type_arg,
107 &dump_mode_arg,
Luc Trudeau0be435a2017-04-07 23:38:52 -0400108 &dump_uv_mode_arg,
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800109 &dump_skip_arg,
110 &dump_filter_arg,
Alex Converse0ec34d22017-04-03 14:54:07 -0700111#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800112 &dump_cdef_arg,
Alex Converse0ec34d22017-04-03 14:54:07 -0700113#endif
Luc Trudeauf89056a2017-04-28 16:07:22 -0400114#if CONFIG_CFL
115 &dump_cfl_arg,
116#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800117 &dump_reference_frame_arg,
118 &dump_motion_vectors_arg,
119 &usage_arg,
120 NULL };
121#define ENUM(name) \
122 { #name, name }
123#define LAST_ENUM \
124 { NULL, 0 }
125typedef struct map_entry {
126 const char *name;
127 int value;
128} map_entry;
129
130const map_entry refs_map[] = { ENUM(INTRA_FRAME), ENUM(LAST_FRAME),
131#if CONFIG_EXT_REFS
132 ENUM(LAST2_FRAME), ENUM(LAST3_FRAME),
133 ENUM(GOLDEN_FRAME), ENUM(BWDREF_FRAME),
134 ENUM(ALTREF_FRAME),
135#else
136 ENUM(GOLDEN_FRAME), ENUM(ALTREF_FRAME),
137#endif
138 LAST_ENUM };
139
140const map_entry block_size_map[] = {
141#if CONFIG_CB4X4
142 ENUM(BLOCK_2X2), ENUM(BLOCK_2X4), ENUM(BLOCK_4X2),
143#endif
144 ENUM(BLOCK_4X4), ENUM(BLOCK_4X8), ENUM(BLOCK_8X4),
145 ENUM(BLOCK_8X8), ENUM(BLOCK_8X16), ENUM(BLOCK_16X8),
146 ENUM(BLOCK_16X16), ENUM(BLOCK_16X32), ENUM(BLOCK_32X16),
147 ENUM(BLOCK_32X32), ENUM(BLOCK_32X64), ENUM(BLOCK_64X32),
148 ENUM(BLOCK_64X64),
149#if CONFIG_EXT_PARTITION
150 ENUM(BLOCK_64X128), ENUM(BLOCK_128X64), ENUM(BLOCK_128X128),
151#endif
152 LAST_ENUM
153};
154
155const map_entry tx_size_map[] = {
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -0700156#if CONFIG_CHROMA_2X2
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800157 ENUM(TX_2X2),
158#endif
159 ENUM(TX_4X4), ENUM(TX_8X8), ENUM(TX_16X16), ENUM(TX_32X32),
160#if CONFIG_TX64X64
161 ENUM(TX_64X64),
162#endif
163 ENUM(TX_4X8), ENUM(TX_8X4), ENUM(TX_8X16), ENUM(TX_16X8),
164 ENUM(TX_16X32), ENUM(TX_32X16), ENUM(TX_4X16), ENUM(TX_16X4),
165 ENUM(TX_8X32), ENUM(TX_32X8), LAST_ENUM
166};
167
168const map_entry tx_type_map[] = { ENUM(DCT_DCT),
169 ENUM(ADST_DCT),
170 ENUM(DCT_ADST),
171 ENUM(ADST_ADST),
172#if CONFIG_EXT_TX
173 ENUM(FLIPADST_DCT),
174 ENUM(DCT_FLIPADST),
175 ENUM(FLIPADST_FLIPADST),
176 ENUM(ADST_FLIPADST),
177 ENUM(FLIPADST_ADST),
178 ENUM(IDTX),
179 ENUM(V_DCT),
180 ENUM(H_DCT),
181 ENUM(V_ADST),
182 ENUM(H_ADST),
183 ENUM(V_FLIPADST),
184 ENUM(H_FLIPADST),
185#endif
186 LAST_ENUM };
187
Sarah Parkerb9f68d22017-05-25 15:30:26 -0700188const map_entry prediction_mode_map[] = { ENUM(DC_PRED),
189 ENUM(V_PRED),
190 ENUM(H_PRED),
191 ENUM(D45_PRED),
192 ENUM(D135_PRED),
193 ENUM(D117_PRED),
194 ENUM(D153_PRED),
195 ENUM(D207_PRED),
196 ENUM(D63_PRED),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800197#if CONFIG_ALT_INTRA
Sarah Parkerb9f68d22017-05-25 15:30:26 -0700198 ENUM(SMOOTH_PRED),
Urvang Joshifea5f402017-05-22 14:46:10 -0700199#if CONFIG_SMOOTH_HV
Sarah Parkerb9f68d22017-05-25 15:30:26 -0700200 ENUM(SMOOTH_V_PRED),
201 ENUM(SMOOTH_H_PRED),
Urvang Joshifea5f402017-05-22 14:46:10 -0700202#endif // CONFIG_SMOOTH_HV
203#endif // CONFIG_ALT_INTRA
Sarah Parkerb9f68d22017-05-25 15:30:26 -0700204 ENUM(TM_PRED),
205 ENUM(NEARESTMV),
206 ENUM(NEARMV),
207 ENUM(ZEROMV),
208 ENUM(NEWMV),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800209#if CONFIG_EXT_INTER
Sarah Parkerb9f68d22017-05-25 15:30:26 -0700210 ENUM(NEAREST_NEARESTMV),
211 ENUM(NEAR_NEARMV),
212 ENUM(NEAREST_NEWMV),
213 ENUM(NEW_NEARESTMV),
214 ENUM(NEAR_NEWMV),
215 ENUM(NEW_NEARMV),
216 ENUM(ZERO_ZEROMV),
217 ENUM(NEW_NEWMV),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800218#endif
Sarah Parkerb9f68d22017-05-25 15:30:26 -0700219 ENUM(INTRA_INVALID),
220 LAST_ENUM };
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800221
222#define NO_SKIP 0
223#define SKIP 1
224
225const map_entry skip_map[] = { ENUM(SKIP), ENUM(NO_SKIP), LAST_ENUM };
226
227const map_entry config_map[] = { ENUM(MI_SIZE), LAST_ENUM };
228
229static const char *exec_name;
230
231insp_frame_data frame_data;
232int frame_count = 0;
233int decoded_frame_count = 0;
234aom_codec_ctx_t codec;
235AvxVideoReader *reader = NULL;
236const AvxVideoInfo *info = NULL;
237aom_image_t *img = NULL;
238
239void on_frame_decoded_dump(char *json) {
240#ifdef __EMSCRIPTEN__
241 EM_ASM_({ Module.on_frame_decoded_json($0); }, json);
242#else
243 printf("%s", json);
244#endif
245}
246
247// Writing out the JSON buffer using snprintf is very slow, especially when
248// compiled with emscripten, these functions speed things up quite a bit.
249int put_str(char *buffer, const char *str) {
250 int i;
251 for (i = 0; str[i] != '\0'; i++) {
252 buffer[i] = str[i];
253 }
254 return i;
255}
256
257int put_num(char *buffer, char prefix, int num, char suffix) {
258 int i = 0;
259 char *buf = buffer;
260 int is_neg = 0;
261 if (prefix) {
262 buf[i++] = prefix;
263 }
264 if (num == 0) {
265 buf[i++] = '0';
266 } else {
267 if (num < 0) {
268 num = -num;
269 is_neg = 1;
270 }
271 int s = i;
272 while (num != 0) {
273 buf[i++] = '0' + (num % 10);
274 num = num / 10;
275 }
276 if (is_neg) {
277 buf[i++] = '-';
278 }
279 int e = i - 1;
280 while (s < e) {
281 int t = buf[s];
282 buf[s] = buf[e];
283 buf[e] = t;
284 s++;
285 e--;
286 }
287 }
288 if (suffix) {
289 buf[i++] = suffix;
290 }
291 return i;
292}
293
294int put_map(char *buffer, const map_entry *map) {
295 char *buf = buffer;
296 const map_entry *entry = map;
297 while (entry->name != NULL) {
298 *(buf++) = '"';
299 buf += put_str(buf, entry->name);
300 *(buf++) = '"';
301 buf += put_num(buf, ':', entry->value, 0);
302 entry++;
303 if (entry->name != NULL) {
304 *(buf++) = ',';
305 }
306 }
307 return buf - buffer;
308}
309
310int put_reference_frame(char *buffer) {
311 const int mi_rows = frame_data.mi_rows;
312 const int mi_cols = frame_data.mi_cols;
313 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700314 int r, c, t;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800315 buf += put_str(buf, " \"referenceFrameMap\": {");
316 buf += put_map(buf, refs_map);
317 buf += put_str(buf, "},\n");
318 buf += put_str(buf, " \"referenceFrame\": [");
319 for (r = 0; r < mi_rows; ++r) {
320 *(buf++) = '[';
321 for (c = 0; c < mi_cols; ++c) {
322 insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800323 buf += put_num(buf, '[', mi->ref_frame[0], 0);
324 buf += put_num(buf, ',', mi->ref_frame[1], ']');
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700325 if (compress) { // RLE
326 for (t = c + 1; t < mi_cols; ++t) {
327 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
328 if (mi->ref_frame[0] != next_mi->ref_frame[0] ||
329 mi->ref_frame[1] != next_mi->ref_frame[1]) {
330 break;
331 }
332 }
333 if (t - c > 1) {
334 *(buf++) = ',';
335 buf += put_num(buf, '[', t - c - 1, ']');
336 c = t - 1;
337 }
338 }
339 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800340 }
341 *(buf++) = ']';
342 if (r < mi_rows - 1) *(buf++) = ',';
343 }
344 buf += put_str(buf, "],\n");
345 return buf - buffer;
346}
347
348int put_motion_vectors(char *buffer) {
349 const int mi_rows = frame_data.mi_rows;
350 const int mi_cols = frame_data.mi_cols;
351 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700352 int r, c, t;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800353 buf += put_str(buf, " \"motionVectors\": [");
354 for (r = 0; r < mi_rows; ++r) {
355 *(buf++) = '[';
356 for (c = 0; c < mi_cols; ++c) {
357 insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800358 buf += put_num(buf, '[', mi->mv[0].col, 0);
359 buf += put_num(buf, ',', mi->mv[0].row, 0);
360 buf += put_num(buf, ',', mi->mv[1].col, 0);
361 buf += put_num(buf, ',', mi->mv[1].row, ']');
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700362 if (compress) { // RLE
363 for (t = c + 1; t < mi_cols; ++t) {
364 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
365 if (mi->mv[0].col != next_mi->mv[0].col ||
366 mi->mv[0].row != next_mi->mv[0].row ||
367 mi->mv[1].col != next_mi->mv[1].col ||
368 mi->mv[1].row != next_mi->mv[1].row) {
369 break;
370 }
371 }
372 if (t - c > 1) {
373 *(buf++) = ',';
374 buf += put_num(buf, '[', t - c - 1, ']');
375 c = t - 1;
376 }
377 }
378 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800379 }
380 *(buf++) = ']';
381 if (r < mi_rows - 1) *(buf++) = ',';
382 }
383 buf += put_str(buf, "],\n");
384 return buf - buffer;
385}
386
387int put_block_info(char *buffer, const map_entry *map, const char *name,
388 size_t offset) {
389 const int mi_rows = frame_data.mi_rows;
390 const int mi_cols = frame_data.mi_cols;
391 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700392 int r, c, t, v;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800393 if (map) {
394 buf += snprintf(buf, MAX_BUFFER, " \"%sMap\": {", name);
395 buf += put_map(buf, map);
396 buf += put_str(buf, "},\n");
397 }
398 buf += snprintf(buf, MAX_BUFFER, " \"%s\": [", name);
399 for (r = 0; r < mi_rows; ++r) {
400 *(buf++) = '[';
401 for (c = 0; c < mi_cols; ++c) {
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700402 insp_mi_data *curr_mi = &frame_data.mi_grid[r * mi_cols + c];
403 v = *(((int8_t *)curr_mi) + offset);
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800404 buf += put_num(buf, 0, v, 0);
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700405 if (compress) { // RLE
406 for (t = c + 1; t < mi_cols; ++t) {
407 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
408 if (v != *(((int8_t *)next_mi) + offset)) {
409 break;
410 }
411 }
412 if (t - c > 1) {
413 *(buf++) = ',';
414 buf += put_num(buf, '[', t - c - 1, ']');
415 c = t - 1;
416 }
417 }
418 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800419 }
420 *(buf++) = ']';
421 if (r < mi_rows - 1) *(buf++) = ',';
422 }
423 buf += put_str(buf, "],\n");
424 return buf - buffer;
425}
426
427#if CONFIG_ACCOUNTING
428int put_accounting(char *buffer) {
429 char *buf = buffer;
430 int i;
431 const Accounting *accounting = frame_data.accounting;
432 if (accounting == NULL) {
433 printf("XXX\n");
434 return 0;
435 }
436 const int num_syms = accounting->syms.num_syms;
437 const int num_strs = accounting->syms.dictionary.num_strs;
438 buf += put_str(buf, " \"symbolsMap\": [");
439 for (i = 0; i < num_strs; i++) {
440 buf += snprintf(buf, MAX_BUFFER, "\"%s\"",
441 accounting->syms.dictionary.strs[i]);
442 if (i < num_strs - 1) *(buf++) = ',';
443 }
444 buf += put_str(buf, "],\n");
445 buf += put_str(buf, " \"symbols\": [\n ");
446 AccountingSymbolContext context;
447 context.x = -2;
448 context.y = -2;
449 AccountingSymbol *sym;
450 for (i = 0; i < num_syms; i++) {
451 sym = &accounting->syms.syms[i];
452 if (memcmp(&context, &sym->context, sizeof(AccountingSymbolContext)) != 0) {
453 buf += put_num(buf, '[', sym->context.x, 0);
454 buf += put_num(buf, ',', sym->context.y, ']');
455 } else {
456 buf += put_num(buf, '[', sym->id, 0);
457 buf += put_num(buf, ',', sym->bits, 0);
458 buf += put_num(buf, ',', sym->samples, ']');
459 }
460 context = sym->context;
461 if (i < num_syms - 1) *(buf++) = ',';
462 }
463 buf += put_str(buf, "],\n");
464 return buf - buffer;
465}
466#endif
467
468void inspect(void *pbi, void *data) {
469 /* Fetch frame data. */
470 ifd_inspect(&frame_data, pbi);
471 (void)data;
472 // We allocate enough space and hope we don't write out of bounds. Totally
473 // unsafe but this speeds things up, especially when compiled to Javascript.
474 char *buffer = aom_malloc(MAX_BUFFER);
475 char *buf = buffer;
476 buf += put_str(buf, "{\n");
477 if (layers & BLOCK_SIZE_LAYER) {
478 buf += put_block_info(buf, block_size_map, "blockSize",
479 offsetof(insp_mi_data, sb_type));
480 }
481 if (layers & TRANSFORM_SIZE_LAYER) {
482 buf += put_block_info(buf, tx_size_map, "transformSize",
483 offsetof(insp_mi_data, tx_size));
484 }
485 if (layers & TRANSFORM_TYPE_LAYER) {
486 buf += put_block_info(buf, tx_type_map, "transformType",
487 offsetof(insp_mi_data, tx_type));
488 }
489 if (layers & MODE_LAYER) {
490 buf += put_block_info(buf, prediction_mode_map, "mode",
491 offsetof(insp_mi_data, mode));
492 }
Luc Trudeau0be435a2017-04-07 23:38:52 -0400493 if (layers & UV_MODE_LAYER) {
494 buf += put_block_info(buf, prediction_mode_map, "uv_mode",
495 offsetof(insp_mi_data, uv_mode));
496 }
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800497 if (layers & SKIP_LAYER) {
498 buf += put_block_info(buf, skip_map, "skip", offsetof(insp_mi_data, skip));
499 }
500 if (layers & FILTER_LAYER) {
501 buf += put_block_info(buf, NULL, "filter", offsetof(insp_mi_data, filter));
502 }
Alex Converse0ec34d22017-04-03 14:54:07 -0700503#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800504 if (layers & CDEF_LAYER) {
Michael Bebenita09558812017-04-01 20:10:53 -0700505 buf += put_block_info(buf, NULL, "cdef_level",
506 offsetof(insp_mi_data, cdef_level));
507 buf += put_block_info(buf, NULL, "cdef_strength",
508 offsetof(insp_mi_data, cdef_strength));
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800509 }
Alex Converse0ec34d22017-04-03 14:54:07 -0700510#endif
Luc Trudeauf89056a2017-04-28 16:07:22 -0400511#if CONFIG_CFL
512 if (layers & CFL_LAYER) {
Luc Trudeaua9bd85f2017-05-11 14:37:56 -0400513 buf += put_block_info(buf, NULL, "cfl_alpha_idx",
514 offsetof(insp_mi_data, cfl_alpha_idx));
Luc Trudeau9bab28b2017-05-11 15:23:02 -0400515 buf += put_block_info(buf, NULL, "cfl_alpha_sign",
516 offsetof(insp_mi_data, cfl_alpha_sign));
Luc Trudeauf89056a2017-04-28 16:07:22 -0400517 }
518#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800519 if (layers & MOTION_VECTORS_LAYER) {
520 buf += put_motion_vectors(buf);
521 }
522 if (layers & REFERENCE_FRAME_LAYER) {
523 buf += put_reference_frame(buf);
524 }
525#if CONFIG_ACCOUNTING
526 if (layers & ACCOUNTING_LAYER) {
527 buf += put_accounting(buf);
528 }
529#endif
530 buf += snprintf(buf, MAX_BUFFER, " \"frame\": %d,\n", decoded_frame_count);
531 buf += snprintf(buf, MAX_BUFFER, " \"showFrame\": %d,\n",
532 frame_data.show_frame);
533 buf += snprintf(buf, MAX_BUFFER, " \"frameType\": %d,\n",
534 frame_data.frame_type);
535 buf += snprintf(buf, MAX_BUFFER, " \"baseQIndex\": %d,\n",
536 frame_data.base_qindex);
Michael Bebenita2c2e5612017-04-06 22:19:04 -0400537 buf += snprintf(buf, MAX_BUFFER, " \"tileCols\": %d,\n",
538 frame_data.tile_mi_cols);
539 buf += snprintf(buf, MAX_BUFFER, " \"tileRows\": %d,\n",
540 frame_data.tile_mi_rows);
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800541 buf += put_str(buf, " \"config\": {");
542 buf += put_map(buf, config_map);
543 buf += put_str(buf, "},\n");
544 buf += snprintf(buf, MAX_BUFFER, " \"configString\": \"%s\"\n",
545 aom_codec_build_config());
546 decoded_frame_count++;
547 buf += put_str(buf, "},\n");
548 *(buf++) = 0;
549 on_frame_decoded_dump(buffer);
550 aom_free(buffer);
551}
552
553void ifd_init_cb() {
554 aom_inspect_init ii;
555 ii.inspect_cb = inspect;
556 ii.inspect_ctx = NULL;
557 aom_codec_control(&codec, AV1_SET_INSPECTION_CALLBACK, &ii);
558}
559
560EMSCRIPTEN_KEEPALIVE
561int open_file(char *file) {
562 if (file == NULL) {
563 // The JS analyzer puts the .ivf file at this location.
564 file = "/tmp/input.ivf";
565 }
566 reader = aom_video_reader_open(file);
567 if (!reader) die("Failed to open %s for reading.", file);
568 info = aom_video_reader_get_info(reader);
569 const AvxInterface *decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
570 if (!decoder) die("Unknown input codec.");
571 fprintf(stderr, "Using %s\n",
572 aom_codec_iface_name(decoder->codec_interface()));
573 if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
574 die_codec(&codec, "Failed to initialize decoder.");
575 ifd_init(&frame_data, info->frame_width, info->frame_height);
576 ifd_init_cb();
577 return EXIT_SUCCESS;
578}
579
580EMSCRIPTEN_KEEPALIVE
581int read_frame() {
582 if (!aom_video_reader_read_frame(reader)) return EXIT_FAILURE;
583 img = NULL;
584 aom_codec_iter_t iter = NULL;
585 size_t frame_size = 0;
586 const unsigned char *frame = aom_video_reader_get_frame(reader, &frame_size);
587 if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0) !=
588 AOM_CODEC_OK) {
589 die_codec(&codec, "Failed to decode frame.");
590 }
591 img = aom_codec_get_frame(&codec, &iter);
592 if (img == NULL) {
593 return EXIT_FAILURE;
594 }
595 ++frame_count;
596 return EXIT_SUCCESS;
597}
598
599EMSCRIPTEN_KEEPALIVE
600const char *get_aom_codec_build_config() { return aom_codec_build_config(); }
601
602EMSCRIPTEN_KEEPALIVE
603int get_bit_depth() { return img->bit_depth; }
604
605EMSCRIPTEN_KEEPALIVE
Michael Bebenitabf1f9ee2017-06-16 15:54:08 -0700606int get_bits_per_sample() { return img->bps; }
607
608EMSCRIPTEN_KEEPALIVE
609int get_image_format() { return img->fmt; }
610
611EMSCRIPTEN_KEEPALIVE
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800612unsigned char *get_plane(int plane) { return img->planes[plane]; }
613
614EMSCRIPTEN_KEEPALIVE
615int get_plane_stride(int plane) { return img->stride[plane]; }
616
617EMSCRIPTEN_KEEPALIVE
618int get_plane_width(int plane) { return aom_img_plane_width(img, plane); }
619
620EMSCRIPTEN_KEEPALIVE
621int get_plane_height(int plane) { return aom_img_plane_height(img, plane); }
622
623EMSCRIPTEN_KEEPALIVE
624int get_frame_width() { return info->frame_width; }
625
626EMSCRIPTEN_KEEPALIVE
627int get_frame_height() { return info->frame_height; }
628
629static void parse_args(char **argv) {
630 char **argi, **argj;
631 struct arg arg;
632 (void)dump_accounting_arg;
Alex Converse0ec34d22017-04-03 14:54:07 -0700633 (void)dump_cdef_arg;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800634 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
635 arg.argv_step = 1;
636 if (arg_match(&arg, &dump_block_size_arg, argi)) layers |= BLOCK_SIZE_LAYER;
637#if CONFIG_ACCOUNTING
638 else if (arg_match(&arg, &dump_accounting_arg, argi))
639 layers |= ACCOUNTING_LAYER;
640#endif
641 else if (arg_match(&arg, &dump_transform_size_arg, argi))
642 layers |= TRANSFORM_SIZE_LAYER;
643 else if (arg_match(&arg, &dump_transform_type_arg, argi))
644 layers |= TRANSFORM_TYPE_LAYER;
645 else if (arg_match(&arg, &dump_mode_arg, argi))
646 layers |= MODE_LAYER;
Luc Trudeau0be435a2017-04-07 23:38:52 -0400647 else if (arg_match(&arg, &dump_uv_mode_arg, argi))
648 layers |= UV_MODE_LAYER;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800649 else if (arg_match(&arg, &dump_skip_arg, argi))
650 layers |= SKIP_LAYER;
651 else if (arg_match(&arg, &dump_filter_arg, argi))
652 layers |= FILTER_LAYER;
Alex Converse0ec34d22017-04-03 14:54:07 -0700653#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800654 else if (arg_match(&arg, &dump_cdef_arg, argi))
655 layers |= CDEF_LAYER;
Alex Converse0ec34d22017-04-03 14:54:07 -0700656#endif
Luc Trudeauf89056a2017-04-28 16:07:22 -0400657#if CONFIG_CFL
658 else if (arg_match(&arg, &dump_cfl_arg, argi))
659 layers |= CFL_LAYER;
660#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800661 else if (arg_match(&arg, &dump_reference_frame_arg, argi))
662 layers |= REFERENCE_FRAME_LAYER;
663 else if (arg_match(&arg, &dump_motion_vectors_arg, argi))
664 layers |= MOTION_VECTORS_LAYER;
665 else if (arg_match(&arg, &dump_all_arg, argi))
666 layers |= ALL_LAYERS;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700667 else if (arg_match(&arg, &compress_arg, argi))
668 compress = 1;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800669 else if (arg_match(&arg, &usage_arg, argi))
670 usage_exit();
671 else if (arg_match(&arg, &limit_arg, argi))
672 stop_after = arg_parse_uint(&arg);
673 else
674 argj++;
675 }
676}
677
678static const char *exec_name;
679
680void usage_exit(void) {
681 fprintf(stderr, "Usage: %s src_filename <options>\n", exec_name);
682 fprintf(stderr, "\nOptions:\n");
683 arg_show_usage(stderr, main_args);
684 exit(EXIT_FAILURE);
685}
686
687EMSCRIPTEN_KEEPALIVE
688int main(int argc, char **argv) {
689 exec_name = argv[0];
690 parse_args(argv);
691 if (argc >= 2) {
692 open_file(argv[1]);
693 printf("[\n");
694 while (1) {
695 if (stop_after && (decoded_frame_count >= stop_after)) break;
696 if (read_frame()) break;
697 }
698 printf("null\n");
699 printf("]");
700 } else {
701 usage_exit();
702 }
703}
704
705EMSCRIPTEN_KEEPALIVE
706void quit() {
707 if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
708 aom_video_reader_close(reader);
709}
710
711EMSCRIPTEN_KEEPALIVE
712void set_layers(LayerType v) { layers = v; }
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700713
714EMSCRIPTEN_KEEPALIVE
715void set_compress(int v) { compress = v; }