blob: 595cb0242a9ef67b22e0574d501bbb06b1299bdf [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[] = {
Timothy B. Terriberry81ec2612017-04-26 16:53:47 -0700141#if CONFIG_CHROMA_2X2 || CONFIG_CHROMA_SUB8X8
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800142 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
Rupert Swarbricka5263752017-09-11 11:59:12 +0100152 ENUM(BLOCK_4X16), ENUM(BLOCK_16X4), ENUM(BLOCK_8X32),
153 ENUM(BLOCK_32X8), ENUM(BLOCK_16X64), ENUM(BLOCK_64X16),
Rupert Swarbrick2fa6e1c2017-09-11 12:38:10 +0100154#if CONFIG_EXT_PARTITION
155 ENUM(BLOCK_32X128), ENUM(BLOCK_128X32),
156#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800157 LAST_ENUM
158};
159
160const map_entry tx_size_map[] = {
Timothy B. Terriberryfe67ed62017-04-26 16:53:47 -0700161#if CONFIG_CHROMA_2X2
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800162 ENUM(TX_2X2),
163#endif
164 ENUM(TX_4X4), ENUM(TX_8X8), ENUM(TX_16X16), ENUM(TX_32X32),
165#if CONFIG_TX64X64
166 ENUM(TX_64X64),
167#endif
168 ENUM(TX_4X8), ENUM(TX_8X4), ENUM(TX_8X16), ENUM(TX_16X8),
Urvang Joshib2752172017-10-04 17:51:17 -0700169 ENUM(TX_16X32), ENUM(TX_32X16),
170#if CONFIG_TX64X64
171 ENUM(TX_32X64), ENUM(TX_64X32),
172#endif // CONFIG_TX64X64
173 ENUM(TX_4X16), ENUM(TX_16X4), ENUM(TX_8X32), ENUM(TX_32X8),
174 LAST_ENUM
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800175};
176
177const map_entry tx_type_map[] = { ENUM(DCT_DCT),
178 ENUM(ADST_DCT),
179 ENUM(DCT_ADST),
180 ENUM(ADST_ADST),
181#if CONFIG_EXT_TX
182 ENUM(FLIPADST_DCT),
183 ENUM(DCT_FLIPADST),
184 ENUM(FLIPADST_FLIPADST),
185 ENUM(ADST_FLIPADST),
186 ENUM(FLIPADST_ADST),
187 ENUM(IDTX),
188 ENUM(V_DCT),
189 ENUM(H_DCT),
190 ENUM(V_ADST),
191 ENUM(H_ADST),
192 ENUM(V_FLIPADST),
193 ENUM(H_FLIPADST),
194#endif
195 LAST_ENUM };
196
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +0200197const map_entry prediction_mode_map[] = {
198 ENUM(DC_PRED), ENUM(V_PRED), ENUM(H_PRED),
199 ENUM(D45_PRED), ENUM(D135_PRED), ENUM(D117_PRED),
200 ENUM(D153_PRED), ENUM(D207_PRED), ENUM(D63_PRED),
201 ENUM(SMOOTH_PRED),
Urvang Joshifea5f402017-05-22 14:46:10 -0700202#if CONFIG_SMOOTH_HV
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +0200203 ENUM(SMOOTH_V_PRED), ENUM(SMOOTH_H_PRED),
Urvang Joshifea5f402017-05-22 14:46:10 -0700204#endif // CONFIG_SMOOTH_HV
Urvang Joshi96d1c0a2017-10-10 13:15:32 -0700205 ENUM(PAETH_PRED), ENUM(NEARESTMV), ENUM(NEARMV),
Sebastien Alaiwan0bdea0d2017-10-02 15:15:05 +0200206 ENUM(ZEROMV), ENUM(NEWMV), ENUM(NEAREST_NEARESTMV),
207 ENUM(NEAR_NEARMV), ENUM(NEAREST_NEWMV), ENUM(NEW_NEARESTMV),
208 ENUM(NEAR_NEWMV), ENUM(NEW_NEARMV), ENUM(ZERO_ZEROMV),
209 ENUM(NEW_NEWMV), ENUM(INTRA_INVALID), LAST_ENUM
210};
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800211
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400212#if CONFIG_CFL
213const map_entry uv_prediction_mode_map[] = {
Luc Trudeau6e1cd782017-06-21 13:52:36 -0400214 ENUM(UV_DC_PRED), ENUM(UV_V_PRED),
215 ENUM(UV_H_PRED), ENUM(UV_D45_PRED),
216 ENUM(UV_D135_PRED), ENUM(UV_D117_PRED),
217 ENUM(UV_D153_PRED), ENUM(UV_D207_PRED),
Urvang Joshi93b543a2017-06-01 17:32:41 -0700218 ENUM(UV_D63_PRED), ENUM(UV_SMOOTH_PRED),
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400219#if CONFIG_SMOOTH_HV
220 ENUM(UV_SMOOTH_V_PRED), ENUM(UV_SMOOTH_H_PRED),
221#endif // CONFIG_SMOOTH_HV
Urvang Joshi96d1c0a2017-10-10 13:15:32 -0700222 ENUM(UV_PAETH_PRED),
Luc Trudeau6e1cd782017-06-21 13:52:36 -0400223#if CONFIG_CFL
224 ENUM(UV_CFL_PRED),
225#endif
226 ENUM(UV_MODE_INVALID), LAST_ENUM
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400227};
228#else
229#define uv_prediction_mode_map prediction_mode_map
230#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800231#define NO_SKIP 0
232#define SKIP 1
233
234const map_entry skip_map[] = { ENUM(SKIP), ENUM(NO_SKIP), LAST_ENUM };
235
236const map_entry config_map[] = { ENUM(MI_SIZE), LAST_ENUM };
237
238static const char *exec_name;
239
240insp_frame_data frame_data;
241int frame_count = 0;
242int decoded_frame_count = 0;
243aom_codec_ctx_t codec;
244AvxVideoReader *reader = NULL;
245const AvxVideoInfo *info = NULL;
246aom_image_t *img = NULL;
247
248void on_frame_decoded_dump(char *json) {
249#ifdef __EMSCRIPTEN__
250 EM_ASM_({ Module.on_frame_decoded_json($0); }, json);
251#else
252 printf("%s", json);
253#endif
254}
255
256// Writing out the JSON buffer using snprintf is very slow, especially when
257// compiled with emscripten, these functions speed things up quite a bit.
258int put_str(char *buffer, const char *str) {
259 int i;
260 for (i = 0; str[i] != '\0'; i++) {
261 buffer[i] = str[i];
262 }
263 return i;
264}
265
Michael Bebenita4aee17d2017-07-05 14:03:36 -0700266int put_str_with_escape(char *buffer, const char *str) {
267 int i;
268 int j = 0;
269 for (i = 0; str[i] != '\0'; i++) {
Thomas Daede3a1bd782017-07-21 12:17:10 -0700270 if (str[i] < ' ') {
271 continue;
272 } else if (str[i] == '"' || str[i] == '\\') {
Michael Bebenita4aee17d2017-07-05 14:03:36 -0700273 buffer[j++] = '\\';
274 }
275 buffer[j++] = str[i];
276 }
277 return j;
278}
279
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800280int put_num(char *buffer, char prefix, int num, char suffix) {
281 int i = 0;
282 char *buf = buffer;
283 int is_neg = 0;
284 if (prefix) {
285 buf[i++] = prefix;
286 }
287 if (num == 0) {
288 buf[i++] = '0';
289 } else {
290 if (num < 0) {
291 num = -num;
292 is_neg = 1;
293 }
294 int s = i;
295 while (num != 0) {
296 buf[i++] = '0' + (num % 10);
297 num = num / 10;
298 }
299 if (is_neg) {
300 buf[i++] = '-';
301 }
302 int e = i - 1;
303 while (s < e) {
304 int t = buf[s];
305 buf[s] = buf[e];
306 buf[e] = t;
307 s++;
308 e--;
309 }
310 }
311 if (suffix) {
312 buf[i++] = suffix;
313 }
314 return i;
315}
316
317int put_map(char *buffer, const map_entry *map) {
318 char *buf = buffer;
319 const map_entry *entry = map;
320 while (entry->name != NULL) {
321 *(buf++) = '"';
322 buf += put_str(buf, entry->name);
323 *(buf++) = '"';
324 buf += put_num(buf, ':', entry->value, 0);
325 entry++;
326 if (entry->name != NULL) {
327 *(buf++) = ',';
328 }
329 }
330 return buf - buffer;
331}
332
333int put_reference_frame(char *buffer) {
334 const int mi_rows = frame_data.mi_rows;
335 const int mi_cols = frame_data.mi_cols;
336 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700337 int r, c, t;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800338 buf += put_str(buf, " \"referenceFrameMap\": {");
339 buf += put_map(buf, refs_map);
340 buf += put_str(buf, "},\n");
341 buf += put_str(buf, " \"referenceFrame\": [");
342 for (r = 0; r < mi_rows; ++r) {
343 *(buf++) = '[';
344 for (c = 0; c < mi_cols; ++c) {
345 insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800346 buf += put_num(buf, '[', mi->ref_frame[0], 0);
347 buf += put_num(buf, ',', mi->ref_frame[1], ']');
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700348 if (compress) { // RLE
349 for (t = c + 1; t < mi_cols; ++t) {
350 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
351 if (mi->ref_frame[0] != next_mi->ref_frame[0] ||
352 mi->ref_frame[1] != next_mi->ref_frame[1]) {
353 break;
354 }
355 }
356 if (t - c > 1) {
357 *(buf++) = ',';
358 buf += put_num(buf, '[', t - c - 1, ']');
359 c = t - 1;
360 }
361 }
362 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800363 }
364 *(buf++) = ']';
365 if (r < mi_rows - 1) *(buf++) = ',';
366 }
367 buf += put_str(buf, "],\n");
368 return buf - buffer;
369}
370
371int put_motion_vectors(char *buffer) {
372 const int mi_rows = frame_data.mi_rows;
373 const int mi_cols = frame_data.mi_cols;
374 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700375 int r, c, t;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800376 buf += put_str(buf, " \"motionVectors\": [");
377 for (r = 0; r < mi_rows; ++r) {
378 *(buf++) = '[';
379 for (c = 0; c < mi_cols; ++c) {
380 insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800381 buf += put_num(buf, '[', mi->mv[0].col, 0);
382 buf += put_num(buf, ',', mi->mv[0].row, 0);
383 buf += put_num(buf, ',', mi->mv[1].col, 0);
384 buf += put_num(buf, ',', mi->mv[1].row, ']');
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700385 if (compress) { // RLE
386 for (t = c + 1; t < mi_cols; ++t) {
387 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
388 if (mi->mv[0].col != next_mi->mv[0].col ||
389 mi->mv[0].row != next_mi->mv[0].row ||
390 mi->mv[1].col != next_mi->mv[1].col ||
391 mi->mv[1].row != next_mi->mv[1].row) {
392 break;
393 }
394 }
395 if (t - c > 1) {
396 *(buf++) = ',';
397 buf += put_num(buf, '[', t - c - 1, ']');
398 c = t - 1;
399 }
400 }
401 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800402 }
403 *(buf++) = ']';
404 if (r < mi_rows - 1) *(buf++) = ',';
405 }
406 buf += put_str(buf, "],\n");
407 return buf - buffer;
408}
409
410int put_block_info(char *buffer, const map_entry *map, const char *name,
411 size_t offset) {
412 const int mi_rows = frame_data.mi_rows;
413 const int mi_cols = frame_data.mi_cols;
414 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700415 int r, c, t, v;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800416 if (map) {
417 buf += snprintf(buf, MAX_BUFFER, " \"%sMap\": {", name);
418 buf += put_map(buf, map);
419 buf += put_str(buf, "},\n");
420 }
421 buf += snprintf(buf, MAX_BUFFER, " \"%s\": [", name);
422 for (r = 0; r < mi_rows; ++r) {
423 *(buf++) = '[';
424 for (c = 0; c < mi_cols; ++c) {
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700425 insp_mi_data *curr_mi = &frame_data.mi_grid[r * mi_cols + c];
426 v = *(((int8_t *)curr_mi) + offset);
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800427 buf += put_num(buf, 0, v, 0);
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700428 if (compress) { // RLE
429 for (t = c + 1; t < mi_cols; ++t) {
430 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
431 if (v != *(((int8_t *)next_mi) + offset)) {
432 break;
433 }
434 }
435 if (t - c > 1) {
436 *(buf++) = ',';
437 buf += put_num(buf, '[', t - c - 1, ']');
438 c = t - 1;
439 }
440 }
441 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800442 }
443 *(buf++) = ']';
444 if (r < mi_rows - 1) *(buf++) = ',';
445 }
446 buf += put_str(buf, "],\n");
447 return buf - buffer;
448}
449
450#if CONFIG_ACCOUNTING
451int put_accounting(char *buffer) {
452 char *buf = buffer;
453 int i;
454 const Accounting *accounting = frame_data.accounting;
455 if (accounting == NULL) {
456 printf("XXX\n");
457 return 0;
458 }
459 const int num_syms = accounting->syms.num_syms;
460 const int num_strs = accounting->syms.dictionary.num_strs;
461 buf += put_str(buf, " \"symbolsMap\": [");
462 for (i = 0; i < num_strs; i++) {
463 buf += snprintf(buf, MAX_BUFFER, "\"%s\"",
464 accounting->syms.dictionary.strs[i]);
465 if (i < num_strs - 1) *(buf++) = ',';
466 }
467 buf += put_str(buf, "],\n");
468 buf += put_str(buf, " \"symbols\": [\n ");
469 AccountingSymbolContext context;
470 context.x = -2;
471 context.y = -2;
472 AccountingSymbol *sym;
473 for (i = 0; i < num_syms; i++) {
474 sym = &accounting->syms.syms[i];
475 if (memcmp(&context, &sym->context, sizeof(AccountingSymbolContext)) != 0) {
476 buf += put_num(buf, '[', sym->context.x, 0);
477 buf += put_num(buf, ',', sym->context.y, ']');
478 } else {
479 buf += put_num(buf, '[', sym->id, 0);
480 buf += put_num(buf, ',', sym->bits, 0);
481 buf += put_num(buf, ',', sym->samples, ']');
482 }
483 context = sym->context;
484 if (i < num_syms - 1) *(buf++) = ',';
485 }
486 buf += put_str(buf, "],\n");
487 return buf - buffer;
488}
489#endif
490
491void inspect(void *pbi, void *data) {
492 /* Fetch frame data. */
493 ifd_inspect(&frame_data, pbi);
494 (void)data;
495 // We allocate enough space and hope we don't write out of bounds. Totally
496 // unsafe but this speeds things up, especially when compiled to Javascript.
497 char *buffer = aom_malloc(MAX_BUFFER);
498 char *buf = buffer;
499 buf += put_str(buf, "{\n");
500 if (layers & BLOCK_SIZE_LAYER) {
501 buf += put_block_info(buf, block_size_map, "blockSize",
502 offsetof(insp_mi_data, sb_type));
503 }
504 if (layers & TRANSFORM_SIZE_LAYER) {
505 buf += put_block_info(buf, tx_size_map, "transformSize",
506 offsetof(insp_mi_data, tx_size));
507 }
508 if (layers & TRANSFORM_TYPE_LAYER) {
509 buf += put_block_info(buf, tx_type_map, "transformType",
510 offsetof(insp_mi_data, tx_type));
511 }
512 if (layers & MODE_LAYER) {
513 buf += put_block_info(buf, prediction_mode_map, "mode",
514 offsetof(insp_mi_data, mode));
515 }
Luc Trudeau0be435a2017-04-07 23:38:52 -0400516 if (layers & UV_MODE_LAYER) {
Luc Trudeaud6d9eee2017-07-12 12:36:50 -0400517 buf += put_block_info(buf, uv_prediction_mode_map, "uv_mode",
Luc Trudeau0be435a2017-04-07 23:38:52 -0400518 offsetof(insp_mi_data, uv_mode));
519 }
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800520 if (layers & SKIP_LAYER) {
521 buf += put_block_info(buf, skip_map, "skip", offsetof(insp_mi_data, skip));
522 }
523 if (layers & FILTER_LAYER) {
524 buf += put_block_info(buf, NULL, "filter", offsetof(insp_mi_data, filter));
525 }
Alex Converse0ec34d22017-04-03 14:54:07 -0700526#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800527 if (layers & CDEF_LAYER) {
Michael Bebenita09558812017-04-01 20:10:53 -0700528 buf += put_block_info(buf, NULL, "cdef_level",
529 offsetof(insp_mi_data, cdef_level));
530 buf += put_block_info(buf, NULL, "cdef_strength",
531 offsetof(insp_mi_data, cdef_strength));
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800532 }
Alex Converse0ec34d22017-04-03 14:54:07 -0700533#endif
Luc Trudeauf89056a2017-04-28 16:07:22 -0400534#if CONFIG_CFL
535 if (layers & CFL_LAYER) {
Luc Trudeaua9bd85f2017-05-11 14:37:56 -0400536 buf += put_block_info(buf, NULL, "cfl_alpha_idx",
537 offsetof(insp_mi_data, cfl_alpha_idx));
Luc Trudeau9bab28b2017-05-11 15:23:02 -0400538 buf += put_block_info(buf, NULL, "cfl_alpha_sign",
539 offsetof(insp_mi_data, cfl_alpha_sign));
Luc Trudeauf89056a2017-04-28 16:07:22 -0400540 }
541#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800542 if (layers & MOTION_VECTORS_LAYER) {
543 buf += put_motion_vectors(buf);
544 }
545 if (layers & REFERENCE_FRAME_LAYER) {
546 buf += put_reference_frame(buf);
547 }
548#if CONFIG_ACCOUNTING
549 if (layers & ACCOUNTING_LAYER) {
550 buf += put_accounting(buf);
551 }
552#endif
553 buf += snprintf(buf, MAX_BUFFER, " \"frame\": %d,\n", decoded_frame_count);
554 buf += snprintf(buf, MAX_BUFFER, " \"showFrame\": %d,\n",
555 frame_data.show_frame);
556 buf += snprintf(buf, MAX_BUFFER, " \"frameType\": %d,\n",
557 frame_data.frame_type);
558 buf += snprintf(buf, MAX_BUFFER, " \"baseQIndex\": %d,\n",
559 frame_data.base_qindex);
Michael Bebenita2c2e5612017-04-06 22:19:04 -0400560 buf += snprintf(buf, MAX_BUFFER, " \"tileCols\": %d,\n",
561 frame_data.tile_mi_cols);
562 buf += snprintf(buf, MAX_BUFFER, " \"tileRows\": %d,\n",
563 frame_data.tile_mi_rows);
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800564 buf += put_str(buf, " \"config\": {");
565 buf += put_map(buf, config_map);
566 buf += put_str(buf, "},\n");
Michael Bebenita4aee17d2017-07-05 14:03:36 -0700567 buf += put_str(buf, " \"configString\": \"");
568 buf += put_str_with_escape(buf, aom_codec_build_config());
569 buf += put_str(buf, "\"\n");
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800570 decoded_frame_count++;
571 buf += put_str(buf, "},\n");
572 *(buf++) = 0;
573 on_frame_decoded_dump(buffer);
574 aom_free(buffer);
575}
576
577void ifd_init_cb() {
578 aom_inspect_init ii;
579 ii.inspect_cb = inspect;
580 ii.inspect_ctx = NULL;
581 aom_codec_control(&codec, AV1_SET_INSPECTION_CALLBACK, &ii);
582}
583
584EMSCRIPTEN_KEEPALIVE
585int open_file(char *file) {
586 if (file == NULL) {
587 // The JS analyzer puts the .ivf file at this location.
588 file = "/tmp/input.ivf";
589 }
590 reader = aom_video_reader_open(file);
591 if (!reader) die("Failed to open %s for reading.", file);
592 info = aom_video_reader_get_info(reader);
593 const AvxInterface *decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
594 if (!decoder) die("Unknown input codec.");
595 fprintf(stderr, "Using %s\n",
596 aom_codec_iface_name(decoder->codec_interface()));
597 if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
598 die_codec(&codec, "Failed to initialize decoder.");
599 ifd_init(&frame_data, info->frame_width, info->frame_height);
600 ifd_init_cb();
601 return EXIT_SUCCESS;
602}
603
604EMSCRIPTEN_KEEPALIVE
605int read_frame() {
606 if (!aom_video_reader_read_frame(reader)) return EXIT_FAILURE;
607 img = NULL;
608 aom_codec_iter_t iter = NULL;
609 size_t frame_size = 0;
610 const unsigned char *frame = aom_video_reader_get_frame(reader, &frame_size);
611 if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0) !=
612 AOM_CODEC_OK) {
613 die_codec(&codec, "Failed to decode frame.");
614 }
615 img = aom_codec_get_frame(&codec, &iter);
616 if (img == NULL) {
617 return EXIT_FAILURE;
618 }
619 ++frame_count;
620 return EXIT_SUCCESS;
621}
622
623EMSCRIPTEN_KEEPALIVE
624const char *get_aom_codec_build_config() { return aom_codec_build_config(); }
625
626EMSCRIPTEN_KEEPALIVE
627int get_bit_depth() { return img->bit_depth; }
628
629EMSCRIPTEN_KEEPALIVE
Michael Bebenitabf1f9ee2017-06-16 15:54:08 -0700630int get_bits_per_sample() { return img->bps; }
631
632EMSCRIPTEN_KEEPALIVE
633int get_image_format() { return img->fmt; }
634
635EMSCRIPTEN_KEEPALIVE
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800636unsigned char *get_plane(int plane) { return img->planes[plane]; }
637
638EMSCRIPTEN_KEEPALIVE
639int get_plane_stride(int plane) { return img->stride[plane]; }
640
641EMSCRIPTEN_KEEPALIVE
642int get_plane_width(int plane) { return aom_img_plane_width(img, plane); }
643
644EMSCRIPTEN_KEEPALIVE
645int get_plane_height(int plane) { return aom_img_plane_height(img, plane); }
646
647EMSCRIPTEN_KEEPALIVE
648int get_frame_width() { return info->frame_width; }
649
650EMSCRIPTEN_KEEPALIVE
651int get_frame_height() { return info->frame_height; }
652
653static void parse_args(char **argv) {
654 char **argi, **argj;
655 struct arg arg;
656 (void)dump_accounting_arg;
Alex Converse0ec34d22017-04-03 14:54:07 -0700657 (void)dump_cdef_arg;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800658 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
659 arg.argv_step = 1;
660 if (arg_match(&arg, &dump_block_size_arg, argi)) layers |= BLOCK_SIZE_LAYER;
661#if CONFIG_ACCOUNTING
662 else if (arg_match(&arg, &dump_accounting_arg, argi))
663 layers |= ACCOUNTING_LAYER;
664#endif
665 else if (arg_match(&arg, &dump_transform_size_arg, argi))
666 layers |= TRANSFORM_SIZE_LAYER;
667 else if (arg_match(&arg, &dump_transform_type_arg, argi))
668 layers |= TRANSFORM_TYPE_LAYER;
669 else if (arg_match(&arg, &dump_mode_arg, argi))
670 layers |= MODE_LAYER;
Luc Trudeau0be435a2017-04-07 23:38:52 -0400671 else if (arg_match(&arg, &dump_uv_mode_arg, argi))
672 layers |= UV_MODE_LAYER;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800673 else if (arg_match(&arg, &dump_skip_arg, argi))
674 layers |= SKIP_LAYER;
675 else if (arg_match(&arg, &dump_filter_arg, argi))
676 layers |= FILTER_LAYER;
Alex Converse0ec34d22017-04-03 14:54:07 -0700677#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800678 else if (arg_match(&arg, &dump_cdef_arg, argi))
679 layers |= CDEF_LAYER;
Alex Converse0ec34d22017-04-03 14:54:07 -0700680#endif
Luc Trudeauf89056a2017-04-28 16:07:22 -0400681#if CONFIG_CFL
682 else if (arg_match(&arg, &dump_cfl_arg, argi))
683 layers |= CFL_LAYER;
684#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800685 else if (arg_match(&arg, &dump_reference_frame_arg, argi))
686 layers |= REFERENCE_FRAME_LAYER;
687 else if (arg_match(&arg, &dump_motion_vectors_arg, argi))
688 layers |= MOTION_VECTORS_LAYER;
689 else if (arg_match(&arg, &dump_all_arg, argi))
690 layers |= ALL_LAYERS;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700691 else if (arg_match(&arg, &compress_arg, argi))
692 compress = 1;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800693 else if (arg_match(&arg, &usage_arg, argi))
694 usage_exit();
695 else if (arg_match(&arg, &limit_arg, argi))
696 stop_after = arg_parse_uint(&arg);
697 else
698 argj++;
699 }
700}
701
702static const char *exec_name;
703
704void usage_exit(void) {
705 fprintf(stderr, "Usage: %s src_filename <options>\n", exec_name);
706 fprintf(stderr, "\nOptions:\n");
707 arg_show_usage(stderr, main_args);
708 exit(EXIT_FAILURE);
709}
710
711EMSCRIPTEN_KEEPALIVE
712int main(int argc, char **argv) {
713 exec_name = argv[0];
714 parse_args(argv);
715 if (argc >= 2) {
716 open_file(argv[1]);
717 printf("[\n");
718 while (1) {
719 if (stop_after && (decoded_frame_count >= stop_after)) break;
720 if (read_frame()) break;
721 }
722 printf("null\n");
723 printf("]");
724 } else {
725 usage_exit();
726 }
727}
728
729EMSCRIPTEN_KEEPALIVE
730void quit() {
731 if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
732 aom_video_reader_close(reader);
733}
734
735EMSCRIPTEN_KEEPALIVE
736void set_layers(LayerType v) { layers = v; }
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700737
738EMSCRIPTEN_KEEPALIVE
739void set_compress(int v) { compress = v; }