2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
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.
23 #include <emscripten.h>
25 #define EMSCRIPTEN_KEEPALIVE
28 #include "config/aom_config.h"
30 #include "aom/aom_decoder.h"
31 #include "aom/aomdx.h"
32 #include "av1/common/onyxc_int.h"
35 #include "av1/decoder/accounting.h"
38 #include "av1/decoder/inspection.h"
39 #include "common/args.h"
40 #include "common/tools_common.h"
41 #include "common/video_common.h"
42 #include "common/video_reader.h"
44 // Max JSON buffer size.
45 const int MAX_BUFFER
= 1024 * 1024 * 32;
49 BLOCK_SIZE_LAYER
= 1 << 1,
50 TRANSFORM_SIZE_LAYER
= 1 << 2,
51 TRANSFORM_TYPE_LAYER
= 1 << 3,
54 FILTER_LAYER
= 1 << 6,
56 REFERENCE_FRAME_LAYER
= 1 << 8,
57 MOTION_VECTORS_LAYER
= 1 << 9,
58 UV_MODE_LAYER
= 1 << 10,
60 DUAL_FILTER_LAYER
= 1 << 12,
61 Q_INDEX_LAYER
= 1 << 13,
62 SEGMENT_ID_LAYER
= 1 << 14,
63 ALL_LAYERS
= (1 << 15) - 1
66 static LayerType layers
= 0;
68 static int stop_after
= 0;
69 static int compress
= 0;
71 static const arg_def_t limit_arg
=
72 ARG_DEF(NULL
, "limit", 1, "Stop decoding after n frames");
73 static const arg_def_t dump_all_arg
= ARG_DEF("A", "all", 0, "Dump All");
74 static const arg_def_t compress_arg
=
75 ARG_DEF("x", "compress", 0, "Compress JSON using RLE");
76 static const arg_def_t dump_accounting_arg
=
77 ARG_DEF("a", "accounting", 0, "Dump Accounting");
78 static const arg_def_t dump_block_size_arg
=
79 ARG_DEF("bs", "blockSize", 0, "Dump Block Size");
80 static const arg_def_t dump_motion_vectors_arg
=
81 ARG_DEF("mv", "motionVectors", 0, "Dump Motion Vectors");
82 static const arg_def_t dump_transform_size_arg
=
83 ARG_DEF("ts", "transformSize", 0, "Dump Transform Size");
84 static const arg_def_t dump_transform_type_arg
=
85 ARG_DEF("tt", "transformType", 0, "Dump Transform Type");
86 static const arg_def_t dump_mode_arg
= ARG_DEF("m", "mode", 0, "Dump Mode");
87 static const arg_def_t dump_uv_mode_arg
=
88 ARG_DEF("uvm", "uv_mode", 0, "Dump UV Intra Prediction Modes");
89 static const arg_def_t dump_skip_arg
= ARG_DEF("s", "skip", 0, "Dump Skip");
90 static const arg_def_t dump_filter_arg
=
91 ARG_DEF("f", "filter", 0, "Dump Filter");
92 static const arg_def_t dump_cdef_arg
= ARG_DEF("c", "cdef", 0, "Dump CDEF");
93 static const arg_def_t dump_cfl_arg
=
94 ARG_DEF("cfl", "chroma_from_luma", 0, "Dump Chroma from Luma Alphas");
95 static const arg_def_t dump_dual_filter_type_arg
=
96 ARG_DEF("df", "dualFilterType", 0, "Dump Dual Filter Type");
97 static const arg_def_t dump_reference_frame_arg
=
98 ARG_DEF("r", "referenceFrame", 0, "Dump Reference Frame");
99 static const arg_def_t dump_delta_q_arg
=
100 ARG_DEF("dq", "delta_q", 0, "Dump QIndex");
101 static const arg_def_t dump_seg_id_arg
=
102 ARG_DEF("si", "seg_id", 0, "Dump Segment ID");
103 static const arg_def_t usage_arg
= ARG_DEF("h", "help", 0, "Help");
105 static const arg_def_t
*main_args
[] = { &limit_arg
,
108 #if CONFIG_ACCOUNTING
109 &dump_accounting_arg
,
111 &dump_block_size_arg
,
112 &dump_transform_size_arg
,
113 &dump_transform_type_arg
,
119 &dump_dual_filter_type_arg
,
121 &dump_reference_frame_arg
,
122 &dump_motion_vectors_arg
,
131 typedef struct map_entry
{
136 const map_entry refs_map
[] = {
137 ENUM(INTRA_FRAME
), ENUM(LAST_FRAME
), ENUM(LAST2_FRAME
),
138 ENUM(LAST3_FRAME
), ENUM(GOLDEN_FRAME
), ENUM(BWDREF_FRAME
),
139 ENUM(ALTREF2_FRAME
), ENUM(ALTREF_FRAME
), LAST_ENUM
142 const map_entry block_size_map
[] = {
143 ENUM(BLOCK_4X4
), ENUM(BLOCK_4X8
), ENUM(BLOCK_8X4
),
144 ENUM(BLOCK_8X8
), ENUM(BLOCK_8X16
), ENUM(BLOCK_16X8
),
145 ENUM(BLOCK_16X16
), ENUM(BLOCK_16X32
), ENUM(BLOCK_32X16
),
146 ENUM(BLOCK_32X32
), ENUM(BLOCK_32X64
), ENUM(BLOCK_64X32
),
147 ENUM(BLOCK_64X64
), ENUM(BLOCK_64X128
), ENUM(BLOCK_128X64
),
148 ENUM(BLOCK_128X128
), ENUM(BLOCK_4X16
), ENUM(BLOCK_16X4
),
149 ENUM(BLOCK_8X32
), ENUM(BLOCK_32X8
), ENUM(BLOCK_16X64
),
150 ENUM(BLOCK_64X16
), LAST_ENUM
153 const map_entry tx_size_map
[] = {
154 ENUM(TX_4X4
), ENUM(TX_8X8
), ENUM(TX_16X16
), ENUM(TX_32X32
),
155 ENUM(TX_64X64
), ENUM(TX_4X8
), ENUM(TX_8X4
), ENUM(TX_8X16
),
156 ENUM(TX_16X8
), ENUM(TX_16X32
), ENUM(TX_32X16
), ENUM(TX_32X64
),
157 ENUM(TX_64X32
), ENUM(TX_4X16
), ENUM(TX_16X4
), ENUM(TX_8X32
),
158 ENUM(TX_32X8
), LAST_ENUM
161 const map_entry tx_type_map
[] = { ENUM(DCT_DCT
),
167 ENUM(FLIPADST_FLIPADST
),
178 const map_entry dual_filter_map
[] = { ENUM(REG_REG
), ENUM(REG_SMOOTH
),
179 ENUM(REG_SHARP
), ENUM(SMOOTH_REG
),
180 ENUM(SMOOTH_SMOOTH
), ENUM(SMOOTH_SHARP
),
181 ENUM(SHARP_REG
), ENUM(SHARP_SMOOTH
),
182 ENUM(SHARP_SHARP
), LAST_ENUM
};
184 const map_entry prediction_mode_map
[] = {
185 ENUM(DC_PRED
), ENUM(V_PRED
), ENUM(H_PRED
),
186 ENUM(D45_PRED
), ENUM(D135_PRED
), ENUM(D113_PRED
),
187 ENUM(D157_PRED
), ENUM(D203_PRED
), ENUM(D67_PRED
),
188 ENUM(SMOOTH_PRED
), ENUM(SMOOTH_V_PRED
), ENUM(SMOOTH_H_PRED
),
189 ENUM(PAETH_PRED
), ENUM(NEARESTMV
), ENUM(NEARMV
),
190 ENUM(GLOBALMV
), ENUM(NEWMV
), ENUM(NEAREST_NEARESTMV
),
191 ENUM(NEAR_NEARMV
), ENUM(NEAREST_NEWMV
), ENUM(NEW_NEARESTMV
),
192 ENUM(NEAR_NEWMV
), ENUM(NEW_NEARMV
), ENUM(GLOBAL_GLOBALMV
),
193 ENUM(NEW_NEWMV
), ENUM(INTRA_INVALID
), LAST_ENUM
196 const map_entry uv_prediction_mode_map
[] = {
197 ENUM(UV_DC_PRED
), ENUM(UV_V_PRED
),
198 ENUM(UV_H_PRED
), ENUM(UV_D45_PRED
),
199 ENUM(UV_D135_PRED
), ENUM(UV_D113_PRED
),
200 ENUM(UV_D157_PRED
), ENUM(UV_D203_PRED
),
201 ENUM(UV_D67_PRED
), ENUM(UV_SMOOTH_PRED
),
202 ENUM(UV_SMOOTH_V_PRED
), ENUM(UV_SMOOTH_H_PRED
),
203 ENUM(UV_PAETH_PRED
), ENUM(UV_CFL_PRED
),
204 ENUM(UV_MODE_INVALID
), LAST_ENUM
209 const map_entry skip_map
[] = { ENUM(SKIP
), ENUM(NO_SKIP
), LAST_ENUM
};
211 const map_entry config_map
[] = { ENUM(MI_SIZE
), LAST_ENUM
};
213 static const char *exec_name
;
215 insp_frame_data frame_data
;
217 int decoded_frame_count
= 0;
218 aom_codec_ctx_t codec
;
219 AvxVideoReader
*reader
= NULL
;
220 const AvxVideoInfo
*info
= NULL
;
221 aom_image_t
*img
= NULL
;
223 void on_frame_decoded_dump(char *json
) {
224 #ifdef __EMSCRIPTEN__
225 EM_ASM_({ Module
.on_frame_decoded_json($
0); }, json
);
231 // Writing out the JSON buffer using snprintf is very slow, especially when
232 // compiled with emscripten, these functions speed things up quite a bit.
233 int put_str(char *buffer
, const char *str
) {
235 for (i
= 0; str
[i
] != '\0'; i
++) {
241 int put_str_with_escape(char *buffer
, const char *str
) {
244 for (i
= 0; str
[i
] != '\0'; i
++) {
247 } else if (str
[i
] == '"' || str
[i
] == '\\') {
250 buffer
[j
++] = str
[i
];
255 int put_num(char *buffer
, char prefix
, int num
, char suffix
) {
271 buf
[i
++] = '0' + (num
% 10);
292 int put_map(char *buffer
, const map_entry
*map
) {
294 const map_entry
*entry
= map
;
295 while (entry
->name
!= NULL
) {
297 buf
+= put_str(buf
, entry
->name
);
299 buf
+= put_num(buf
, ':', entry
->value
, 0);
301 if (entry
->name
!= NULL
) {
305 return (int)(buf
- buffer
);
308 int put_reference_frame(char *buffer
) {
309 const int mi_rows
= frame_data
.mi_rows
;
310 const int mi_cols
= frame_data
.mi_cols
;
313 buf
+= put_str(buf
, " \"referenceFrameMap\": {");
314 buf
+= put_map(buf
, refs_map
);
315 buf
+= put_str(buf
, "},\n");
316 buf
+= put_str(buf
, " \"referenceFrame\": [");
317 for (r
= 0; r
< mi_rows
; ++r
) {
319 for (c
= 0; c
< mi_cols
; ++c
) {
320 insp_mi_data
*mi
= &frame_data
.mi_grid
[r
* mi_cols
+ c
];
321 buf
+= put_num(buf
, '[', mi
->ref_frame
[0], 0);
322 buf
+= put_num(buf
, ',', mi
->ref_frame
[1], ']');
323 if (compress
) { // RLE
324 for (t
= c
+ 1; t
< mi_cols
; ++t
) {
325 insp_mi_data
*next_mi
= &frame_data
.mi_grid
[r
* mi_cols
+ t
];
326 if (mi
->ref_frame
[0] != next_mi
->ref_frame
[0] ||
327 mi
->ref_frame
[1] != next_mi
->ref_frame
[1]) {
333 buf
+= put_num(buf
, '[', t
- c
- 1, ']');
337 if (c
< mi_cols
- 1) *(buf
++) = ',';
340 if (r
< mi_rows
- 1) *(buf
++) = ',';
342 buf
+= put_str(buf
, "],\n");
343 return (int)(buf
- buffer
);
346 int put_motion_vectors(char *buffer
) {
347 const int mi_rows
= frame_data
.mi_rows
;
348 const int mi_cols
= frame_data
.mi_cols
;
351 buf
+= put_str(buf
, " \"motionVectors\": [");
352 for (r
= 0; r
< mi_rows
; ++r
) {
354 for (c
= 0; c
< mi_cols
; ++c
) {
355 insp_mi_data
*mi
= &frame_data
.mi_grid
[r
* mi_cols
+ c
];
356 buf
+= put_num(buf
, '[', mi
->mv
[0].col
, 0);
357 buf
+= put_num(buf
, ',', mi
->mv
[0].row
, 0);
358 buf
+= put_num(buf
, ',', mi
->mv
[1].col
, 0);
359 buf
+= put_num(buf
, ',', mi
->mv
[1].row
, ']');
360 if (compress
) { // RLE
361 for (t
= c
+ 1; t
< mi_cols
; ++t
) {
362 insp_mi_data
*next_mi
= &frame_data
.mi_grid
[r
* mi_cols
+ t
];
363 if (mi
->mv
[0].col
!= next_mi
->mv
[0].col
||
364 mi
->mv
[0].row
!= next_mi
->mv
[0].row
||
365 mi
->mv
[1].col
!= next_mi
->mv
[1].col
||
366 mi
->mv
[1].row
!= next_mi
->mv
[1].row
) {
372 buf
+= put_num(buf
, '[', t
- c
- 1, ']');
376 if (c
< mi_cols
- 1) *(buf
++) = ',';
379 if (r
< mi_rows
- 1) *(buf
++) = ',';
381 buf
+= put_str(buf
, "],\n");
382 return (int)(buf
- buffer
);
385 int put_block_info(char *buffer
, const map_entry
*map
, const char *name
,
386 size_t offset
, int len
) {
387 const int mi_rows
= frame_data
.mi_rows
;
388 const int mi_cols
= frame_data
.mi_cols
;
391 if (compress
&& len
== 1) {
392 die("Can't encode scalars as arrays when RLE compression is enabled.");
396 buf
+= snprintf(buf
, MAX_BUFFER
, " \"%sMap\": {", name
);
397 buf
+= put_map(buf
, map
);
398 buf
+= put_str(buf
, "},\n");
400 buf
+= snprintf(buf
, MAX_BUFFER
, " \"%s\": [", name
);
401 for (r
= 0; r
< mi_rows
; ++r
) {
403 for (c
= 0; c
< mi_cols
; ++c
) {
404 insp_mi_data
*mi
= &frame_data
.mi_grid
[r
* mi_cols
+ c
];
405 int16_t *v
= (int16_t *)(((int8_t *)mi
) + offset
);
407 buf
+= put_num(buf
, 0, v
[0], 0);
409 buf
+= put_str(buf
, "[");
410 for (i
= 0; i
< len
; i
++) {
411 buf
+= put_num(buf
, 0, v
[i
], 0);
413 buf
+= put_str(buf
, ",");
416 buf
+= put_str(buf
, "]");
418 if (compress
) { // RLE
419 for (t
= c
+ 1; t
< mi_cols
; ++t
) {
420 insp_mi_data
*next_mi
= &frame_data
.mi_grid
[r
* mi_cols
+ t
];
421 int16_t *nv
= (int16_t *)(((int8_t *)next_mi
) + offset
);
424 same
= v
[0] == nv
[0];
426 for (i
= 0; i
< len
; i
++) {
427 same
= v
[i
] == nv
[i
];
439 buf
+= put_num(buf
, '[', t
- c
- 1, ']');
443 if (c
< mi_cols
- 1) *(buf
++) = ',';
446 if (r
< mi_rows
- 1) *(buf
++) = ',';
448 buf
+= put_str(buf
, "],\n");
449 return (int)(buf
- buffer
);
452 #if CONFIG_ACCOUNTING
453 int put_accounting(char *buffer
) {
456 const Accounting
*accounting
= frame_data
.accounting
;
457 if (accounting
== NULL
) {
461 const int num_syms
= accounting
->syms
.num_syms
;
462 const int num_strs
= accounting
->syms
.dictionary
.num_strs
;
463 buf
+= put_str(buf
, " \"symbolsMap\": [");
464 for (i
= 0; i
< num_strs
; i
++) {
465 buf
+= snprintf(buf
, MAX_BUFFER
, "\"%s\"",
466 accounting
->syms
.dictionary
.strs
[i
]);
467 if (i
< num_strs
- 1) *(buf
++) = ',';
469 buf
+= put_str(buf
, "],\n");
470 buf
+= put_str(buf
, " \"symbols\": [\n ");
471 AccountingSymbolContext context
;
474 AccountingSymbol
*sym
;
475 for (i
= 0; i
< num_syms
; i
++) {
476 sym
= &accounting
->syms
.syms
[i
];
477 if (memcmp(&context
, &sym
->context
, sizeof(AccountingSymbolContext
)) != 0) {
478 buf
+= put_num(buf
, '[', sym
->context
.x
, 0);
479 buf
+= put_num(buf
, ',', sym
->context
.y
, ']');
481 buf
+= put_num(buf
, '[', sym
->id
, 0);
482 buf
+= put_num(buf
, ',', sym
->bits
, 0);
483 buf
+= put_num(buf
, ',', sym
->samples
, ']');
485 context
= sym
->context
;
486 if (i
< num_syms
- 1) *(buf
++) = ',';
488 buf
+= put_str(buf
, "],\n");
489 return (int)(buf
- buffer
);
493 void inspect(void *pbi
, void *data
) {
494 /* Fetch frame data. */
495 ifd_inspect(&frame_data
, pbi
);
497 // We allocate enough space and hope we don't write out of bounds. Totally
498 // unsafe but this speeds things up, especially when compiled to Javascript.
499 char *buffer
= aom_malloc(MAX_BUFFER
);
501 buf
+= put_str(buf
, "{\n");
502 if (layers
& BLOCK_SIZE_LAYER
) {
503 buf
+= put_block_info(buf
, block_size_map
, "blockSize",
504 offsetof(insp_mi_data
, sb_type
), 0);
506 if (layers
& TRANSFORM_SIZE_LAYER
) {
507 buf
+= put_block_info(buf
, tx_size_map
, "transformSize",
508 offsetof(insp_mi_data
, tx_size
), 0);
510 if (layers
& TRANSFORM_TYPE_LAYER
) {
511 buf
+= put_block_info(buf
, tx_type_map
, "transformType",
512 offsetof(insp_mi_data
, tx_type
), 0);
514 if (layers
& DUAL_FILTER_LAYER
) {
515 buf
+= put_block_info(buf
, dual_filter_map
, "dualFilterType",
516 offsetof(insp_mi_data
, dual_filter_type
), 0);
518 if (layers
& MODE_LAYER
) {
519 buf
+= put_block_info(buf
, prediction_mode_map
, "mode",
520 offsetof(insp_mi_data
, mode
), 0);
522 if (layers
& UV_MODE_LAYER
) {
523 buf
+= put_block_info(buf
, uv_prediction_mode_map
, "uv_mode",
524 offsetof(insp_mi_data
, uv_mode
), 0);
526 if (layers
& SKIP_LAYER
) {
528 put_block_info(buf
, skip_map
, "skip", offsetof(insp_mi_data
, skip
), 0);
530 if (layers
& FILTER_LAYER
) {
532 put_block_info(buf
, NULL
, "filter", offsetof(insp_mi_data
, filter
), 2);
534 if (layers
& CDEF_LAYER
) {
535 buf
+= put_block_info(buf
, NULL
, "cdef_level",
536 offsetof(insp_mi_data
, cdef_level
), 0);
537 buf
+= put_block_info(buf
, NULL
, "cdef_strength",
538 offsetof(insp_mi_data
, cdef_strength
), 0);
540 if (layers
& CFL_LAYER
) {
541 buf
+= put_block_info(buf
, NULL
, "cfl_alpha_idx",
542 offsetof(insp_mi_data
, cfl_alpha_idx
), 0);
543 buf
+= put_block_info(buf
, NULL
, "cfl_alpha_sign",
544 offsetof(insp_mi_data
, cfl_alpha_sign
), 0);
546 if (layers
& Q_INDEX_LAYER
) {
547 buf
+= put_block_info(buf
, NULL
, "delta_q",
548 offsetof(insp_mi_data
, current_qindex
), 0);
550 if (layers
& SEGMENT_ID_LAYER
) {
551 buf
+= put_block_info(buf
, NULL
, "seg_id",
552 offsetof(insp_mi_data
, segment_id
), 0);
554 if (layers
& MOTION_VECTORS_LAYER
) {
555 buf
+= put_motion_vectors(buf
);
557 if (layers
& REFERENCE_FRAME_LAYER
) {
558 buf
+= put_block_info(buf
, refs_map
, "referenceFrame",
559 offsetof(insp_mi_data
, ref_frame
), 2);
561 #if CONFIG_ACCOUNTING
562 if (layers
& ACCOUNTING_LAYER
) {
563 buf
+= put_accounting(buf
);
566 buf
+= snprintf(buf
, MAX_BUFFER
, " \"frame\": %d,\n", decoded_frame_count
);
567 buf
+= snprintf(buf
, MAX_BUFFER
, " \"showFrame\": %d,\n",
568 frame_data
.show_frame
);
569 buf
+= snprintf(buf
, MAX_BUFFER
, " \"frameType\": %d,\n",
570 frame_data
.frame_type
);
571 buf
+= snprintf(buf
, MAX_BUFFER
, " \"baseQIndex\": %d,\n",
572 frame_data
.base_qindex
);
573 buf
+= snprintf(buf
, MAX_BUFFER
, " \"tileCols\": %d,\n",
574 frame_data
.tile_mi_cols
);
575 buf
+= snprintf(buf
, MAX_BUFFER
, " \"tileRows\": %d,\n",
576 frame_data
.tile_mi_rows
);
577 buf
+= snprintf(buf
, MAX_BUFFER
, " \"deltaQPresentFlag\": %d,\n",
578 frame_data
.delta_q_present_flag
);
579 buf
+= snprintf(buf
, MAX_BUFFER
, " \"deltaQRes\": %d,\n",
580 frame_data
.delta_q_res
);
581 buf
+= put_str(buf
, " \"config\": {");
582 buf
+= put_map(buf
, config_map
);
583 buf
+= put_str(buf
, "},\n");
584 buf
+= put_str(buf
, " \"configString\": \"");
585 buf
+= put_str_with_escape(buf
, aom_codec_build_config());
586 buf
+= put_str(buf
, "\"\n");
587 decoded_frame_count
++;
588 buf
+= put_str(buf
, "},\n");
590 on_frame_decoded_dump(buffer
);
596 ii
.inspect_cb
= inspect
;
597 ii
.inspect_ctx
= NULL
;
598 aom_codec_control(&codec
, AV1_SET_INSPECTION_CALLBACK
, &ii
);
602 int open_file(char *file
) {
604 // The JS analyzer puts the .ivf file at this location.
605 file
= "/tmp/input.ivf";
607 reader
= aom_video_reader_open(file
);
608 if (!reader
) die("Failed to open %s for reading.", file
);
609 info
= aom_video_reader_get_info(reader
);
610 const AvxInterface
*decoder
= get_aom_decoder_by_fourcc(info
->codec_fourcc
);
611 if (!decoder
) die("Unknown input codec.");
612 fprintf(stderr
, "Using %s\n",
613 aom_codec_iface_name(decoder
->codec_interface()));
614 if (aom_codec_dec_init(&codec
, decoder
->codec_interface(), NULL
, 0))
615 die_codec(&codec
, "Failed to initialize decoder.");
616 ifd_init(&frame_data
, info
->frame_width
, info
->frame_height
);
623 if (!aom_video_reader_read_frame(reader
)) return EXIT_FAILURE
;
625 aom_codec_iter_t iter
= NULL
;
626 size_t frame_size
= 0;
627 const unsigned char *frame
= aom_video_reader_get_frame(reader
, &frame_size
);
628 if (aom_codec_decode(&codec
, frame
, (unsigned int)frame_size
, NULL
) !=
630 die_codec(&codec
, "Failed to decode frame.");
632 int got_any_frames
= 0;
633 aom_image_t
*frame_img
;
634 while ((frame_img
= aom_codec_get_frame(&codec
, &iter
))) {
639 if (!got_any_frames
) {
646 const char *get_aom_codec_build_config() { return aom_codec_build_config(); }
649 int get_bit_depth() { return img
->bit_depth
; }
652 int get_bits_per_sample() { return img
->bps
; }
655 int get_image_format() { return img
->fmt
; }
658 unsigned char *get_plane(int plane
) { return img
->planes
[plane
]; }
661 int get_plane_stride(int plane
) { return img
->stride
[plane
]; }
664 int get_plane_width(int plane
) { return aom_img_plane_width(img
, plane
); }
667 int get_plane_height(int plane
) { return aom_img_plane_height(img
, plane
); }
670 int get_frame_width() { return info
->frame_width
; }
673 int get_frame_height() { return info
->frame_height
; }
675 static void parse_args(char **argv
) {
678 (void)dump_accounting_arg
;
680 for (argi
= argj
= argv
; (*argj
= *argi
); argi
+= arg
.argv_step
) {
682 if (arg_match(&arg
, &dump_block_size_arg
, argi
)) layers
|= BLOCK_SIZE_LAYER
;
683 #if CONFIG_ACCOUNTING
684 else if (arg_match(&arg
, &dump_accounting_arg
, argi
))
685 layers
|= ACCOUNTING_LAYER
;
687 else if (arg_match(&arg
, &dump_transform_size_arg
, argi
))
688 layers
|= TRANSFORM_SIZE_LAYER
;
689 else if (arg_match(&arg
, &dump_transform_type_arg
, argi
))
690 layers
|= TRANSFORM_TYPE_LAYER
;
691 else if (arg_match(&arg
, &dump_mode_arg
, argi
))
692 layers
|= MODE_LAYER
;
693 else if (arg_match(&arg
, &dump_uv_mode_arg
, argi
))
694 layers
|= UV_MODE_LAYER
;
695 else if (arg_match(&arg
, &dump_skip_arg
, argi
))
696 layers
|= SKIP_LAYER
;
697 else if (arg_match(&arg
, &dump_filter_arg
, argi
))
698 layers
|= FILTER_LAYER
;
699 else if (arg_match(&arg
, &dump_cdef_arg
, argi
))
700 layers
|= CDEF_LAYER
;
701 else if (arg_match(&arg
, &dump_cfl_arg
, argi
))
703 else if (arg_match(&arg
, &dump_reference_frame_arg
, argi
))
704 layers
|= REFERENCE_FRAME_LAYER
;
705 else if (arg_match(&arg
, &dump_motion_vectors_arg
, argi
))
706 layers
|= MOTION_VECTORS_LAYER
;
707 else if (arg_match(&arg
, &dump_dual_filter_type_arg
, argi
))
708 layers
|= DUAL_FILTER_LAYER
;
709 else if (arg_match(&arg
, &dump_delta_q_arg
, argi
))
710 layers
|= Q_INDEX_LAYER
;
711 else if (arg_match(&arg
, &dump_seg_id_arg
, argi
))
712 layers
|= SEGMENT_ID_LAYER
;
713 else if (arg_match(&arg
, &dump_all_arg
, argi
))
714 layers
|= ALL_LAYERS
;
715 else if (arg_match(&arg
, &compress_arg
, argi
))
717 else if (arg_match(&arg
, &usage_arg
, argi
))
719 else if (arg_match(&arg
, &limit_arg
, argi
))
720 stop_after
= arg_parse_uint(&arg
);
726 static const char *exec_name
;
728 void usage_exit(void) {
729 fprintf(stderr
, "Usage: %s src_filename <options>\n", exec_name
);
730 fprintf(stderr
, "\nOptions:\n");
731 arg_show_usage(stderr
, main_args
);
736 int main(int argc
, char **argv
) {
743 if (stop_after
&& (decoded_frame_count
>= stop_after
)) break;
744 if (read_frame()) break;
755 if (aom_codec_destroy(&codec
)) die_codec(&codec
, "Failed to destroy codec");
756 aom_video_reader_close(reader
);
760 void set_layers(LayerType v
) { layers
= v
; }
763 void set_compress(int v
) { compress
= v
; }