blob: 345c0884d17aa758ce480485611d744b55110649 [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"
30#include "aom/aomdx.h"
31
32#include "../tools_common.h"
33#include "../video_reader.h"
34#include "./aom_config.h"
35// #include "av1/av1_dx_iface.c"
36#include "../av1/common/onyxc_int.h"
37#if CONFIG_ACCOUNTING
Luc Trudeau83fbd572017-04-21 11:24:34 -040038#include "../av1/decoder/accounting.h"
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080039#endif
40#include "../av1/decoder/inspection.h"
41
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,
59 ALL_LAYERS = (1 << 11) - 1
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080060} LayerType;
61
62static LayerType layers = 0;
63
64static int stop_after = 0;
Michael Bebenitaf1207b62017-04-14 22:30:56 -070065static int compress = 0;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080066
67static const arg_def_t limit_arg =
68 ARG_DEF(NULL, "limit", 1, "Stop decoding after n frames");
69static const arg_def_t dump_all_arg = ARG_DEF("A", "all", 0, "Dump All");
Michael Bebenitaf1207b62017-04-14 22:30:56 -070070static const arg_def_t compress_arg =
71 ARG_DEF("x", "compress", 0, "Compress JSON using RLE");
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080072static const arg_def_t dump_accounting_arg =
73 ARG_DEF("a", "accounting", 0, "Dump Accounting");
74static const arg_def_t dump_block_size_arg =
75 ARG_DEF("bs", "blockSize", 0, "Dump Block Size");
76static const arg_def_t dump_motion_vectors_arg =
77 ARG_DEF("mv", "motionVectors", 0, "Dump Motion Vectors");
78static const arg_def_t dump_transform_size_arg =
79 ARG_DEF("ts", "transformSize", 0, "Dump Transform Size");
80static const arg_def_t dump_transform_type_arg =
81 ARG_DEF("tt", "transformType", 0, "Dump Transform Type");
82static const arg_def_t dump_mode_arg = ARG_DEF("m", "mode", 0, "Dump Mode");
Luc Trudeau0be435a2017-04-07 23:38:52 -040083static const arg_def_t dump_uv_mode_arg =
84 ARG_DEF("uvm", "uv_mode", 0, "Dump UV Intra Prediction Modes");
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080085static const arg_def_t dump_skip_arg = ARG_DEF("s", "skip", 0, "Dump Skip");
86static const arg_def_t dump_filter_arg =
87 ARG_DEF("f", "filter", 0, "Dump Filter");
88static const arg_def_t dump_cdef_arg = ARG_DEF("c", "cdef", 0, "Dump CDEF");
89static const arg_def_t dump_reference_frame_arg =
90 ARG_DEF("r", "referenceFrame", 0, "Dump Reference Frame");
91static const arg_def_t usage_arg = ARG_DEF("h", "help", 0, "Help");
92
93static const arg_def_t *main_args[] = { &limit_arg,
94 &dump_all_arg,
Michael Bebenitaf1207b62017-04-14 22:30:56 -070095 &compress_arg,
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -080096#if CONFIG_ACCOUNTING
97 &dump_accounting_arg,
98#endif
99 &dump_block_size_arg,
100 &dump_transform_size_arg,
101 &dump_transform_type_arg,
102 &dump_mode_arg,
Luc Trudeau0be435a2017-04-07 23:38:52 -0400103 &dump_uv_mode_arg,
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800104 &dump_skip_arg,
105 &dump_filter_arg,
Alex Converse0ec34d22017-04-03 14:54:07 -0700106#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800107 &dump_cdef_arg,
Alex Converse0ec34d22017-04-03 14:54:07 -0700108#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800109 &dump_reference_frame_arg,
110 &dump_motion_vectors_arg,
111 &usage_arg,
112 NULL };
113#define ENUM(name) \
114 { #name, name }
115#define LAST_ENUM \
116 { NULL, 0 }
117typedef struct map_entry {
118 const char *name;
119 int value;
120} map_entry;
121
122const map_entry refs_map[] = { ENUM(INTRA_FRAME), ENUM(LAST_FRAME),
123#if CONFIG_EXT_REFS
124 ENUM(LAST2_FRAME), ENUM(LAST3_FRAME),
125 ENUM(GOLDEN_FRAME), ENUM(BWDREF_FRAME),
126 ENUM(ALTREF_FRAME),
127#else
128 ENUM(GOLDEN_FRAME), ENUM(ALTREF_FRAME),
129#endif
130 LAST_ENUM };
131
132const map_entry block_size_map[] = {
133#if CONFIG_CB4X4
134 ENUM(BLOCK_2X2), ENUM(BLOCK_2X4), ENUM(BLOCK_4X2),
135#endif
136 ENUM(BLOCK_4X4), ENUM(BLOCK_4X8), ENUM(BLOCK_8X4),
137 ENUM(BLOCK_8X8), ENUM(BLOCK_8X16), ENUM(BLOCK_16X8),
138 ENUM(BLOCK_16X16), ENUM(BLOCK_16X32), ENUM(BLOCK_32X16),
139 ENUM(BLOCK_32X32), ENUM(BLOCK_32X64), ENUM(BLOCK_64X32),
140 ENUM(BLOCK_64X64),
141#if CONFIG_EXT_PARTITION
142 ENUM(BLOCK_64X128), ENUM(BLOCK_128X64), ENUM(BLOCK_128X128),
143#endif
144 LAST_ENUM
145};
146
147const map_entry tx_size_map[] = {
148#if CONFIG_CB4X4
149 ENUM(TX_2X2),
150#endif
151 ENUM(TX_4X4), ENUM(TX_8X8), ENUM(TX_16X16), ENUM(TX_32X32),
152#if CONFIG_TX64X64
153 ENUM(TX_64X64),
154#endif
155 ENUM(TX_4X8), ENUM(TX_8X4), ENUM(TX_8X16), ENUM(TX_16X8),
156 ENUM(TX_16X32), ENUM(TX_32X16), ENUM(TX_4X16), ENUM(TX_16X4),
157 ENUM(TX_8X32), ENUM(TX_32X8), LAST_ENUM
158};
159
160const map_entry tx_type_map[] = { ENUM(DCT_DCT),
161 ENUM(ADST_DCT),
162 ENUM(DCT_ADST),
163 ENUM(ADST_ADST),
164#if CONFIG_EXT_TX
165 ENUM(FLIPADST_DCT),
166 ENUM(DCT_FLIPADST),
167 ENUM(FLIPADST_FLIPADST),
168 ENUM(ADST_FLIPADST),
169 ENUM(FLIPADST_ADST),
170 ENUM(IDTX),
171 ENUM(V_DCT),
172 ENUM(H_DCT),
173 ENUM(V_ADST),
174 ENUM(H_ADST),
175 ENUM(V_FLIPADST),
176 ENUM(H_FLIPADST),
177#endif
178 LAST_ENUM };
179
Luc Trudeaua5e499f2017-04-14 21:33:27 -0400180const map_entry prediction_mode_map[] = {
181 ENUM(DC_PRED), ENUM(V_PRED),
182 ENUM(H_PRED), ENUM(D45_PRED),
183 ENUM(D135_PRED), ENUM(D117_PRED),
184 ENUM(D153_PRED), ENUM(D207_PRED),
185 ENUM(D63_PRED),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800186#if CONFIG_ALT_INTRA
Luc Trudeaua5e499f2017-04-14 21:33:27 -0400187 ENUM(SMOOTH_PRED),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800188#endif
Luc Trudeaua5e499f2017-04-14 21:33:27 -0400189 ENUM(TM_PRED), ENUM(NEARESTMV),
190 ENUM(NEARMV), ENUM(ZEROMV),
191 ENUM(NEWMV),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800192#if CONFIG_EXT_INTER
Luc Trudeaua5e499f2017-04-14 21:33:27 -0400193 ENUM(NEWFROMNEARMV), ENUM(NEAREST_NEARESTMV),
194 ENUM(NEAREST_NEARMV), ENUM(NEAR_NEARESTMV),
195 ENUM(NEAR_NEARMV), ENUM(NEAREST_NEWMV),
196 ENUM(NEW_NEARESTMV), ENUM(NEAR_NEWMV),
197 ENUM(NEW_NEARMV), ENUM(ZERO_ZEROMV),
198 ENUM(NEW_NEWMV),
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800199#endif
Luc Trudeaua5e499f2017-04-14 21:33:27 -0400200 ENUM(INTRA_INVALID), LAST_ENUM
201};
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800202
203#define NO_SKIP 0
204#define SKIP 1
205
206const map_entry skip_map[] = { ENUM(SKIP), ENUM(NO_SKIP), LAST_ENUM };
207
208const map_entry config_map[] = { ENUM(MI_SIZE), LAST_ENUM };
209
210static const char *exec_name;
211
212insp_frame_data frame_data;
213int frame_count = 0;
214int decoded_frame_count = 0;
215aom_codec_ctx_t codec;
216AvxVideoReader *reader = NULL;
217const AvxVideoInfo *info = NULL;
218aom_image_t *img = NULL;
219
220void on_frame_decoded_dump(char *json) {
221#ifdef __EMSCRIPTEN__
222 EM_ASM_({ Module.on_frame_decoded_json($0); }, json);
223#else
224 printf("%s", json);
225#endif
226}
227
228// Writing out the JSON buffer using snprintf is very slow, especially when
229// compiled with emscripten, these functions speed things up quite a bit.
230int put_str(char *buffer, const char *str) {
231 int i;
232 for (i = 0; str[i] != '\0'; i++) {
233 buffer[i] = str[i];
234 }
235 return i;
236}
237
238int put_num(char *buffer, char prefix, int num, char suffix) {
239 int i = 0;
240 char *buf = buffer;
241 int is_neg = 0;
242 if (prefix) {
243 buf[i++] = prefix;
244 }
245 if (num == 0) {
246 buf[i++] = '0';
247 } else {
248 if (num < 0) {
249 num = -num;
250 is_neg = 1;
251 }
252 int s = i;
253 while (num != 0) {
254 buf[i++] = '0' + (num % 10);
255 num = num / 10;
256 }
257 if (is_neg) {
258 buf[i++] = '-';
259 }
260 int e = i - 1;
261 while (s < e) {
262 int t = buf[s];
263 buf[s] = buf[e];
264 buf[e] = t;
265 s++;
266 e--;
267 }
268 }
269 if (suffix) {
270 buf[i++] = suffix;
271 }
272 return i;
273}
274
275int put_map(char *buffer, const map_entry *map) {
276 char *buf = buffer;
277 const map_entry *entry = map;
278 while (entry->name != NULL) {
279 *(buf++) = '"';
280 buf += put_str(buf, entry->name);
281 *(buf++) = '"';
282 buf += put_num(buf, ':', entry->value, 0);
283 entry++;
284 if (entry->name != NULL) {
285 *(buf++) = ',';
286 }
287 }
288 return buf - buffer;
289}
290
291int put_reference_frame(char *buffer) {
292 const int mi_rows = frame_data.mi_rows;
293 const int mi_cols = frame_data.mi_cols;
294 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700295 int r, c, t;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800296 buf += put_str(buf, " \"referenceFrameMap\": {");
297 buf += put_map(buf, refs_map);
298 buf += put_str(buf, "},\n");
299 buf += put_str(buf, " \"referenceFrame\": [");
300 for (r = 0; r < mi_rows; ++r) {
301 *(buf++) = '[';
302 for (c = 0; c < mi_cols; ++c) {
303 insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800304 buf += put_num(buf, '[', mi->ref_frame[0], 0);
305 buf += put_num(buf, ',', mi->ref_frame[1], ']');
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700306 if (compress) { // RLE
307 for (t = c + 1; t < mi_cols; ++t) {
308 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
309 if (mi->ref_frame[0] != next_mi->ref_frame[0] ||
310 mi->ref_frame[1] != next_mi->ref_frame[1]) {
311 break;
312 }
313 }
314 if (t - c > 1) {
315 *(buf++) = ',';
316 buf += put_num(buf, '[', t - c - 1, ']');
317 c = t - 1;
318 }
319 }
320 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800321 }
322 *(buf++) = ']';
323 if (r < mi_rows - 1) *(buf++) = ',';
324 }
325 buf += put_str(buf, "],\n");
326 return buf - buffer;
327}
328
329int put_motion_vectors(char *buffer) {
330 const int mi_rows = frame_data.mi_rows;
331 const int mi_cols = frame_data.mi_cols;
332 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700333 int r, c, t;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800334 buf += put_str(buf, " \"motionVectors\": [");
335 for (r = 0; r < mi_rows; ++r) {
336 *(buf++) = '[';
337 for (c = 0; c < mi_cols; ++c) {
338 insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800339 buf += put_num(buf, '[', mi->mv[0].col, 0);
340 buf += put_num(buf, ',', mi->mv[0].row, 0);
341 buf += put_num(buf, ',', mi->mv[1].col, 0);
342 buf += put_num(buf, ',', mi->mv[1].row, ']');
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700343 if (compress) { // RLE
344 for (t = c + 1; t < mi_cols; ++t) {
345 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
346 if (mi->mv[0].col != next_mi->mv[0].col ||
347 mi->mv[0].row != next_mi->mv[0].row ||
348 mi->mv[1].col != next_mi->mv[1].col ||
349 mi->mv[1].row != next_mi->mv[1].row) {
350 break;
351 }
352 }
353 if (t - c > 1) {
354 *(buf++) = ',';
355 buf += put_num(buf, '[', t - c - 1, ']');
356 c = t - 1;
357 }
358 }
359 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800360 }
361 *(buf++) = ']';
362 if (r < mi_rows - 1) *(buf++) = ',';
363 }
364 buf += put_str(buf, "],\n");
365 return buf - buffer;
366}
367
368int put_block_info(char *buffer, const map_entry *map, const char *name,
369 size_t offset) {
370 const int mi_rows = frame_data.mi_rows;
371 const int mi_cols = frame_data.mi_cols;
372 char *buf = buffer;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700373 int r, c, t, v;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800374 if (map) {
375 buf += snprintf(buf, MAX_BUFFER, " \"%sMap\": {", name);
376 buf += put_map(buf, map);
377 buf += put_str(buf, "},\n");
378 }
379 buf += snprintf(buf, MAX_BUFFER, " \"%s\": [", name);
380 for (r = 0; r < mi_rows; ++r) {
381 *(buf++) = '[';
382 for (c = 0; c < mi_cols; ++c) {
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700383 insp_mi_data *curr_mi = &frame_data.mi_grid[r * mi_cols + c];
384 v = *(((int8_t *)curr_mi) + offset);
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800385 buf += put_num(buf, 0, v, 0);
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700386 if (compress) { // RLE
387 for (t = c + 1; t < mi_cols; ++t) {
388 insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
389 if (v != *(((int8_t *)next_mi) + offset)) {
390 break;
391 }
392 }
393 if (t - c > 1) {
394 *(buf++) = ',';
395 buf += put_num(buf, '[', t - c - 1, ']');
396 c = t - 1;
397 }
398 }
399 if (c < mi_cols - 1) *(buf++) = ',';
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800400 }
401 *(buf++) = ']';
402 if (r < mi_rows - 1) *(buf++) = ',';
403 }
404 buf += put_str(buf, "],\n");
405 return buf - buffer;
406}
407
408#if CONFIG_ACCOUNTING
409int put_accounting(char *buffer) {
410 char *buf = buffer;
411 int i;
412 const Accounting *accounting = frame_data.accounting;
413 if (accounting == NULL) {
414 printf("XXX\n");
415 return 0;
416 }
417 const int num_syms = accounting->syms.num_syms;
418 const int num_strs = accounting->syms.dictionary.num_strs;
419 buf += put_str(buf, " \"symbolsMap\": [");
420 for (i = 0; i < num_strs; i++) {
421 buf += snprintf(buf, MAX_BUFFER, "\"%s\"",
422 accounting->syms.dictionary.strs[i]);
423 if (i < num_strs - 1) *(buf++) = ',';
424 }
425 buf += put_str(buf, "],\n");
426 buf += put_str(buf, " \"symbols\": [\n ");
427 AccountingSymbolContext context;
428 context.x = -2;
429 context.y = -2;
430 AccountingSymbol *sym;
431 for (i = 0; i < num_syms; i++) {
432 sym = &accounting->syms.syms[i];
433 if (memcmp(&context, &sym->context, sizeof(AccountingSymbolContext)) != 0) {
434 buf += put_num(buf, '[', sym->context.x, 0);
435 buf += put_num(buf, ',', sym->context.y, ']');
436 } else {
437 buf += put_num(buf, '[', sym->id, 0);
438 buf += put_num(buf, ',', sym->bits, 0);
439 buf += put_num(buf, ',', sym->samples, ']');
440 }
441 context = sym->context;
442 if (i < num_syms - 1) *(buf++) = ',';
443 }
444 buf += put_str(buf, "],\n");
445 return buf - buffer;
446}
447#endif
448
449void inspect(void *pbi, void *data) {
450 /* Fetch frame data. */
451 ifd_inspect(&frame_data, pbi);
452 (void)data;
453 // We allocate enough space and hope we don't write out of bounds. Totally
454 // unsafe but this speeds things up, especially when compiled to Javascript.
455 char *buffer = aom_malloc(MAX_BUFFER);
456 char *buf = buffer;
457 buf += put_str(buf, "{\n");
458 if (layers & BLOCK_SIZE_LAYER) {
459 buf += put_block_info(buf, block_size_map, "blockSize",
460 offsetof(insp_mi_data, sb_type));
461 }
462 if (layers & TRANSFORM_SIZE_LAYER) {
463 buf += put_block_info(buf, tx_size_map, "transformSize",
464 offsetof(insp_mi_data, tx_size));
465 }
466 if (layers & TRANSFORM_TYPE_LAYER) {
467 buf += put_block_info(buf, tx_type_map, "transformType",
468 offsetof(insp_mi_data, tx_type));
469 }
470 if (layers & MODE_LAYER) {
471 buf += put_block_info(buf, prediction_mode_map, "mode",
472 offsetof(insp_mi_data, mode));
473 }
Luc Trudeau0be435a2017-04-07 23:38:52 -0400474 if (layers & UV_MODE_LAYER) {
475 buf += put_block_info(buf, prediction_mode_map, "uv_mode",
476 offsetof(insp_mi_data, uv_mode));
477 }
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800478 if (layers & SKIP_LAYER) {
479 buf += put_block_info(buf, skip_map, "skip", offsetof(insp_mi_data, skip));
480 }
481 if (layers & FILTER_LAYER) {
482 buf += put_block_info(buf, NULL, "filter", offsetof(insp_mi_data, filter));
483 }
Alex Converse0ec34d22017-04-03 14:54:07 -0700484#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800485 if (layers & CDEF_LAYER) {
Michael Bebenita09558812017-04-01 20:10:53 -0700486 buf += put_block_info(buf, NULL, "cdef_level",
487 offsetof(insp_mi_data, cdef_level));
488 buf += put_block_info(buf, NULL, "cdef_strength",
489 offsetof(insp_mi_data, cdef_strength));
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800490 }
Alex Converse0ec34d22017-04-03 14:54:07 -0700491#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800492 if (layers & MOTION_VECTORS_LAYER) {
493 buf += put_motion_vectors(buf);
494 }
495 if (layers & REFERENCE_FRAME_LAYER) {
496 buf += put_reference_frame(buf);
497 }
498#if CONFIG_ACCOUNTING
499 if (layers & ACCOUNTING_LAYER) {
500 buf += put_accounting(buf);
501 }
502#endif
503 buf += snprintf(buf, MAX_BUFFER, " \"frame\": %d,\n", decoded_frame_count);
504 buf += snprintf(buf, MAX_BUFFER, " \"showFrame\": %d,\n",
505 frame_data.show_frame);
506 buf += snprintf(buf, MAX_BUFFER, " \"frameType\": %d,\n",
507 frame_data.frame_type);
508 buf += snprintf(buf, MAX_BUFFER, " \"baseQIndex\": %d,\n",
509 frame_data.base_qindex);
Michael Bebenita2c2e5612017-04-06 22:19:04 -0400510 buf += snprintf(buf, MAX_BUFFER, " \"tileCols\": %d,\n",
511 frame_data.tile_mi_cols);
512 buf += snprintf(buf, MAX_BUFFER, " \"tileRows\": %d,\n",
513 frame_data.tile_mi_rows);
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800514 buf += put_str(buf, " \"config\": {");
515 buf += put_map(buf, config_map);
516 buf += put_str(buf, "},\n");
517 buf += snprintf(buf, MAX_BUFFER, " \"configString\": \"%s\"\n",
518 aom_codec_build_config());
519 decoded_frame_count++;
520 buf += put_str(buf, "},\n");
521 *(buf++) = 0;
522 on_frame_decoded_dump(buffer);
523 aom_free(buffer);
524}
525
526void ifd_init_cb() {
527 aom_inspect_init ii;
528 ii.inspect_cb = inspect;
529 ii.inspect_ctx = NULL;
530 aom_codec_control(&codec, AV1_SET_INSPECTION_CALLBACK, &ii);
531}
532
533EMSCRIPTEN_KEEPALIVE
534int open_file(char *file) {
535 if (file == NULL) {
536 // The JS analyzer puts the .ivf file at this location.
537 file = "/tmp/input.ivf";
538 }
539 reader = aom_video_reader_open(file);
540 if (!reader) die("Failed to open %s for reading.", file);
541 info = aom_video_reader_get_info(reader);
542 const AvxInterface *decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
543 if (!decoder) die("Unknown input codec.");
544 fprintf(stderr, "Using %s\n",
545 aom_codec_iface_name(decoder->codec_interface()));
546 if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
547 die_codec(&codec, "Failed to initialize decoder.");
548 ifd_init(&frame_data, info->frame_width, info->frame_height);
549 ifd_init_cb();
550 return EXIT_SUCCESS;
551}
552
553EMSCRIPTEN_KEEPALIVE
554int read_frame() {
555 if (!aom_video_reader_read_frame(reader)) return EXIT_FAILURE;
556 img = NULL;
557 aom_codec_iter_t iter = NULL;
558 size_t frame_size = 0;
559 const unsigned char *frame = aom_video_reader_get_frame(reader, &frame_size);
560 if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0) !=
561 AOM_CODEC_OK) {
562 die_codec(&codec, "Failed to decode frame.");
563 }
564 img = aom_codec_get_frame(&codec, &iter);
565 if (img == NULL) {
566 return EXIT_FAILURE;
567 }
568 ++frame_count;
569 return EXIT_SUCCESS;
570}
571
572EMSCRIPTEN_KEEPALIVE
573const char *get_aom_codec_build_config() { return aom_codec_build_config(); }
574
575EMSCRIPTEN_KEEPALIVE
576int get_bit_depth() { return img->bit_depth; }
577
578EMSCRIPTEN_KEEPALIVE
579unsigned char *get_plane(int plane) { return img->planes[plane]; }
580
581EMSCRIPTEN_KEEPALIVE
582int get_plane_stride(int plane) { return img->stride[plane]; }
583
584EMSCRIPTEN_KEEPALIVE
585int get_plane_width(int plane) { return aom_img_plane_width(img, plane); }
586
587EMSCRIPTEN_KEEPALIVE
588int get_plane_height(int plane) { return aom_img_plane_height(img, plane); }
589
590EMSCRIPTEN_KEEPALIVE
591int get_frame_width() { return info->frame_width; }
592
593EMSCRIPTEN_KEEPALIVE
594int get_frame_height() { return info->frame_height; }
595
596static void parse_args(char **argv) {
597 char **argi, **argj;
598 struct arg arg;
599 (void)dump_accounting_arg;
Alex Converse0ec34d22017-04-03 14:54:07 -0700600 (void)dump_cdef_arg;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800601 for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
602 arg.argv_step = 1;
603 if (arg_match(&arg, &dump_block_size_arg, argi)) layers |= BLOCK_SIZE_LAYER;
604#if CONFIG_ACCOUNTING
605 else if (arg_match(&arg, &dump_accounting_arg, argi))
606 layers |= ACCOUNTING_LAYER;
607#endif
608 else if (arg_match(&arg, &dump_transform_size_arg, argi))
609 layers |= TRANSFORM_SIZE_LAYER;
610 else if (arg_match(&arg, &dump_transform_type_arg, argi))
611 layers |= TRANSFORM_TYPE_LAYER;
612 else if (arg_match(&arg, &dump_mode_arg, argi))
613 layers |= MODE_LAYER;
Luc Trudeau0be435a2017-04-07 23:38:52 -0400614 else if (arg_match(&arg, &dump_uv_mode_arg, argi))
615 layers |= UV_MODE_LAYER;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800616 else if (arg_match(&arg, &dump_skip_arg, argi))
617 layers |= SKIP_LAYER;
618 else if (arg_match(&arg, &dump_filter_arg, argi))
619 layers |= FILTER_LAYER;
Alex Converse0ec34d22017-04-03 14:54:07 -0700620#if CONFIG_CDEF
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800621 else if (arg_match(&arg, &dump_cdef_arg, argi))
622 layers |= CDEF_LAYER;
Alex Converse0ec34d22017-04-03 14:54:07 -0700623#endif
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800624 else if (arg_match(&arg, &dump_reference_frame_arg, argi))
625 layers |= REFERENCE_FRAME_LAYER;
626 else if (arg_match(&arg, &dump_motion_vectors_arg, argi))
627 layers |= MOTION_VECTORS_LAYER;
628 else if (arg_match(&arg, &dump_all_arg, argi))
629 layers |= ALL_LAYERS;
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700630 else if (arg_match(&arg, &compress_arg, argi))
631 compress = 1;
Michael Bebenitaf4f27fe2017-03-02 17:40:44 -0800632 else if (arg_match(&arg, &usage_arg, argi))
633 usage_exit();
634 else if (arg_match(&arg, &limit_arg, argi))
635 stop_after = arg_parse_uint(&arg);
636 else
637 argj++;
638 }
639}
640
641static const char *exec_name;
642
643void usage_exit(void) {
644 fprintf(stderr, "Usage: %s src_filename <options>\n", exec_name);
645 fprintf(stderr, "\nOptions:\n");
646 arg_show_usage(stderr, main_args);
647 exit(EXIT_FAILURE);
648}
649
650EMSCRIPTEN_KEEPALIVE
651int main(int argc, char **argv) {
652 exec_name = argv[0];
653 parse_args(argv);
654 if (argc >= 2) {
655 open_file(argv[1]);
656 printf("[\n");
657 while (1) {
658 if (stop_after && (decoded_frame_count >= stop_after)) break;
659 if (read_frame()) break;
660 }
661 printf("null\n");
662 printf("]");
663 } else {
664 usage_exit();
665 }
666}
667
668EMSCRIPTEN_KEEPALIVE
669void quit() {
670 if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
671 aom_video_reader_close(reader);
672}
673
674EMSCRIPTEN_KEEPALIVE
675void set_layers(LayerType v) { layers = v; }
Michael Bebenitaf1207b62017-04-14 22:30:56 -0700676
677EMSCRIPTEN_KEEPALIVE
678void set_compress(int v) { compress = v; }