Commit dddb38c6a2 for aom

commit dddb38c6a2c1d8db418ef5135ab941982172991d
Author: Cheng Chen <chengchen@google.com>
Date:   Wed Jan 14 16:25:48 2026 -0800

    Allow inspect to get number of decoded bits per superblock

    For CONFIG_INSPECTION = 1, we add a new option "-b" or "--bits",
    which dumps the decoded bits of each superblock to each MI unit
    (all MI units inside the same superblock have the same value,
    so the dumped data has repeated values)

    BUG: 475908343
    Change-Id: Ifd1b1886aef4b881bda8110eee47d9c00bf0af74

diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index d76b1b91bd..69e1e13e38 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -2786,9 +2786,25 @@ static inline void decode_tile(AV1Decoder *pbi, ThreadData *const td,
          mi_col += cm->seq_params->mib_size) {
       set_cb_buffer(pbi, dcb, &td->cb_buffer_base, num_planes, 0, 0);

+#if CONFIG_INSPECTION
+      const int start_bits = aom_reader_tell(td->bit_reader);
+#endif
       // Bit-stream parsing and decoding of the superblock
       decode_partition(pbi, td, mi_row, mi_col, td->bit_reader,
                        cm->seq_params->sb_size, 0x3);
+#if CONFIG_INSPECTION
+      const int end_bits = aom_reader_tell(td->bit_reader);
+#endif
+
+#if CONFIG_INSPECTION
+      if (pbi->sb_bits) {
+        const int mib_size = cm->seq_params->mib_size;
+        const int sb_cols = (cm->mi_params.mi_cols + mib_size - 1) / mib_size;
+        const int sb_row = mi_row / mib_size;
+        const int sb_col = mi_col / mib_size;
+        pbi->sb_bits[sb_row * sb_cols + sb_col] = end_bits - start_bits;
+      }
+#endif

       if (aom_reader_has_overflowed(td->bit_reader)) {
         aom_merge_corrupted_flag(&dcb->corrupted, 1);
@@ -2809,6 +2825,18 @@ static const uint8_t *decode_tiles(AV1Decoder *pbi, const uint8_t *data,
                                    const uint8_t *data_end, int start_tile,
                                    int end_tile) {
   AV1_COMMON *const cm = &pbi->common;
+#if CONFIG_INSPECTION
+  const int mib_size = cm->seq_params->mib_size;
+  const int sb_cols = (cm->mi_params.mi_cols + mib_size - 1) / mib_size;
+  const int sb_rows = (cm->mi_params.mi_rows + mib_size - 1) / mib_size;
+  const int required_size = sb_cols * sb_rows;
+  if (pbi->sb_bits_alloc_size < required_size) {
+    aom_free(pbi->sb_bits);
+    CHECK_MEM_ERROR(cm, pbi->sb_bits,
+                    (int *)aom_malloc(sizeof(*pbi->sb_bits) * required_size));
+    pbi->sb_bits_alloc_size = required_size;
+  }
+#endif
   ThreadData *const td = &pbi->td;
   CommonTileParams *const tiles = &cm->tiles;
   const int tile_cols = tiles->cols;
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index fac6007161..81a88b403e 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -148,6 +148,11 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) {
   aom_get_worker_interface()->init(&pbi->lf_worker);
   pbi->lf_worker.thread_name = "aom lf worker";

+#if CONFIG_INSPECTION
+  pbi->sb_bits = NULL;
+  pbi->sb_bits_alloc_size = 0;
+#endif
+
   return pbi;
 }

@@ -225,6 +230,9 @@ void av1_decoder_remove(AV1Decoder *pbi) {
   av1_dec_free_cb_buf(pbi);
 #if CONFIG_ACCOUNTING
   aom_accounting_clear(&pbi->accounting);
+#endif
+#if CONFIG_INSPECTION
+  aom_free(pbi->sb_bits);
 #endif
   av1_free_mc_tmp_buf(&pbi->td);
   aom_img_metadata_array_free(pbi->metadata);
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index 67049d8dac..006c1c4d39 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -334,6 +334,8 @@ typedef struct AV1Decoder {
 #if CONFIG_INSPECTION
   aom_inspect_cb inspect_cb;
   void *inspect_ctx;
+  int *sb_bits;
+  int sb_bits_alloc_size;
 #endif
   int operating_point;
   int current_operating_point;
diff --git a/av1/decoder/inspection.c b/av1/decoder/inspection.c
index f84ed17d20..0eb6f38eb8 100644
--- a/av1/decoder/inspection.c
+++ b/av1/decoder/inspection.c
@@ -156,6 +156,16 @@ int ifd_inspect(insp_frame_data *fd, void *decoder, int skip_not_transform) {
       }
       // delta_q
       mi->current_qindex = mbmi->current_qindex;
+
+      if (pbi->sb_bits) {
+        const int mib_size = cm->seq_params->mib_size;
+        const int sb_cols = (cm->mi_params.mi_cols + mib_size - 1) / mib_size;
+        const int sb_row = j / mib_size;
+        const int sb_col = i / mib_size;
+        mi->sb_bits = (int16_t)pbi->sb_bits[sb_row * sb_cols + sb_col];
+      } else {
+        mi->sb_bits = 0;
+      }
     }
   }
   return 1;
diff --git a/av1/decoder/inspection.h b/av1/decoder/inspection.h
index 7d1c14db2a..132147b913 100644
--- a/av1/decoder/inspection.h
+++ b/av1/decoder/inspection.h
@@ -55,6 +55,7 @@ struct insp_mi_data {
   int16_t intrabc;
   int16_t palette;
   int16_t uv_palette;
+  int16_t sb_bits;
 };

 typedef struct insp_frame_data insp_frame_data;
diff --git a/examples/inspect.c b/examples/inspect.c
index 9042eb825a..43fb04907d 100644
--- a/examples/inspect.c
+++ b/examples/inspect.c
@@ -65,7 +65,8 @@ typedef enum {
   INTRABC_LAYER = 1 << 17,
   PALETTE_LAYER = 1 << 18,
   UV_PALETTE_LAYER = 1 << 19,
-  ALL_LAYERS = (1 << 20) - 1
+  BITS_LAYER = 1 << 20,
+  ALL_LAYERS = (1 << 21) - 1
 } LayerType;

 static LayerType layers = 0;
@@ -115,6 +116,8 @@ static const arg_def_t dump_palette_arg =
     ARG_DEF("plt", "palette", 0, "Dump Palette Size");
 static const arg_def_t dump_uv_palette_arg =
     ARG_DEF("uvp", "uv_palette", 0, "Dump UV Palette Size");
+static const arg_def_t dump_bits_arg =
+    ARG_DEF("sb", "sb_bits", 0, "Dump Bits of each superblock");
 static const arg_def_t usage_arg = ARG_DEF("h", "help", 0, "Help");
 static const arg_def_t skip_non_transform_arg = ARG_DEF(
     "snt", "skip_non_transform", 1, "Skip is counted as a non transform.");
@@ -149,6 +152,7 @@ static const arg_def_t *main_args[] = { &limit_arg,
                                         &dump_intrabc_arg,
                                         &dump_palette_arg,
                                         &dump_uv_palette_arg,
+                                        &dump_bits_arg,
                                         &usage_arg,
                                         &skip_non_transform_arg,
                                         &combined_arg,
@@ -275,6 +279,7 @@ struct parm_offset parm_offsets[] = {
   { "compound_type", offsetof(insp_mi_data, compound_type) },
   { "referenceFrame", offsetof(insp_mi_data, ref_frame) },
   { "skip", offsetof(insp_mi_data, skip) },
+  { "sb_bits", offsetof(insp_mi_data, sb_bits) },
 };
 int parm_count = sizeof(parm_offsets) / sizeof(parm_offsets[0]);

@@ -704,6 +709,10 @@ static void inspect(void *pbi, void *data) {
     buf += put_block_info(buf, palette_map, "uv_palette",
                           offsetof(insp_mi_data, uv_palette), 0);
   }
+  if (layers & BITS_LAYER) {
+    buf += put_block_info(buf, NULL, "sb_bits", offsetof(insp_mi_data, sb_bits),
+                          0);
+  }
   if (combined_parm_count > 0) buf += put_combined(buf);
   if (layers & REFERENCE_FRAME_LAYER) {
     buf += put_block_info(buf, refs_map, "referenceFrame",
@@ -928,6 +937,8 @@ static void parse_args(char **argv) {
       layers |= PALETTE_LAYER;
     else if (arg_match(&arg, &dump_uv_palette_arg, argi))
       layers |= UV_PALETTE_LAYER;
+    else if (arg_match(&arg, &dump_bits_arg, argi))
+      layers |= BITS_LAYER;
     else if (arg_match(&arg, &dump_all_arg, argi))
       layers |= ALL_LAYERS;
     else if (arg_match(&arg, &compress_arg, argi))