Coverage Report

Created: 2026-09-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/avm/av2/decoder/obu_ops.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2025, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 3-Clause Clear License
5
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6
 * License was not distributed with this source code in the LICENSE file, you
7
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
8
 * Alliance for Open Media Patent License 1.0 was not distributed with this
9
 * source code in the PATENTS file, you can obtain it at
10
 * aomedia.org/license/patent-license/.
11
 */
12
13
#include <assert.h>
14
15
#include "config/avm_config.h"
16
#include "avm_dsp/bitreader_buffer.h"
17
#include "av2/common/common.h"
18
#include "av2/common/obu_util.h"
19
#include "av2/decoder/decoder.h"
20
#include "av2/decoder/decodeframe.h"
21
#include "av2/decoder/obu.h"
22
23
static void read_ops_mlayer_info(int xLId,
24
                                 struct OpsMLayerInfo *ops_mlayer_info,
25
48
                                 struct avm_read_bit_buffer *rb) {
26
  // mlayer map
27
48
  ops_mlayer_info->ops_mlayer_map[xLId] =
28
48
      avm_rb_read_literal(rb, MAX_NUM_MLAYERS);
29
48
  int mCount = 0;
30
417
  for (int j = 0; j < MAX_NUM_MLAYERS; j++) {
31
369
    if ((ops_mlayer_info->ops_mlayer_map[xLId] & (1 << j))) {
32
      // tlayer map
33
160
      ops_mlayer_info->ops_tlayer_map[xLId][j] =
34
160
          avm_rb_read_literal(rb, MAX_NUM_TLAYERS);
35
160
      int tCount = 0;
36
788
      for (int k = 0; k < MAX_NUM_TLAYERS; k++) {
37
628
        if ((ops_mlayer_info->ops_tlayer_map[xLId][j] & (1 << k))) {
38
299
          tCount++;
39
299
        }
40
628
      }
41
160
      ops_mlayer_info->OPTLayerCount[xLId][j] = tCount;
42
160
      mCount++;
43
160
    }
44
369
  }
45
48
  ops_mlayer_info->OPMLayerCount[xLId] = mCount;
46
48
}
47
48
static void read_ops_color_info(struct OpsColorInfo *opsColInfo,
49
29
                                struct avm_read_bit_buffer *rb) {
50
29
  av2_read_color_info(&opsColInfo->ops_color_description_idc,
51
29
                      &opsColInfo->ops_color_primaries,
52
29
                      &opsColInfo->ops_transfer_characteristics,
53
29
                      &opsColInfo->ops_matrix_coefficients,
54
29
                      &opsColInfo->ops_full_range_flag, rb);
55
29
}
56
57
static void read_ops_decoder_model_info(
58
    struct OpsDecoderModelInfo *ops_decoder_model_info,
59
27
    struct avm_read_bit_buffer *rb) {
60
27
  ops_decoder_model_info->ops_decoder_buffer_delay =
61
27
      avm_rb_read_uvlc(rb);  // decoder delay
62
27
  ops_decoder_model_info->ops_encoder_buffer_delay =
63
27
      avm_rb_read_uvlc(rb);  // encoder delay
64
27
  ops_decoder_model_info->ops_low_delay_mode_flag =
65
27
      avm_rb_read_bit(rb);  // low-delay mode flag
66
27
}
67
68
uint32_t av2_read_operating_point_set_obu(struct AV2Decoder *pbi,
69
                                          int obu_xlayer_id,
70
71
                                          struct avm_read_bit_buffer *rb) {
71
71
  const uint32_t saved_bit_offset = rb->bit_offset;
72
73
71
  int ops_reset_flag = avm_rb_read_bit(rb);
74
71
  const int ops_id = avm_rb_read_literal(rb, OPS_ID_BITS);
75
71
  const int ops_cnt = avm_rb_read_literal(rb, OPS_COUNT_BITS);
76
77
  // Apply reset semantics before writing to any slot (spec
78
  // #ops_general_semantics):
79
  //   Case 1: reset_flag=1, cnt=0   -> reset all OPS for this layer
80
  //   Case 2: reset_flag=1, cnt=N>0 -> reset all OPS for this layer, then
81
  //                                     define OPS x
82
  //   Case 3: reset_flag=0, cnt=0   -> reset only OPS x
83
  //   Case 4: reset_flag=0, cnt=N>0 -> update OPS x only (no reset)
84
71
  if (ops_reset_flag) {
85
11
    if (obu_xlayer_id == GLOBAL_XLAYER_ID) {
86
      // Cases 1 & 2 (global): clear all slots across all extended layers
87
0
      for (int x = 0; x < MAX_NUM_XLAYERS; x++)
88
0
        for (int k = 0; k < MAX_NUM_OPS_ID; k++)
89
0
          memset(&pbi->ops_list[x][k], 0, sizeof(pbi->ops_list[x][k]));
90
11
    } else {
91
      // Cases 1 & 2 (local): clear all slots for this extended layer only
92
187
      for (int k = 0; k < MAX_NUM_OPS_ID; k++)
93
176
        memset(&pbi->ops_list[obu_xlayer_id][k], 0,
94
176
               sizeof(pbi->ops_list[obu_xlayer_id][k]));
95
11
    }
96
60
  } else if (ops_cnt == 0) {
97
    // Case 3: clear only the targeted OPS slot
98
8
    memset(&pbi->ops_list[obu_xlayer_id][ops_id], 0,
99
8
           sizeof(pbi->ops_list[obu_xlayer_id][ops_id]));
100
8
  }
101
102
71
  OperatingPointSet *ops = &pbi->ops_list[obu_xlayer_id][ops_id];
103
71
  ops->obu_xlayer_id = obu_xlayer_id;
104
71
  ops->ops_reset_flag = ops_reset_flag;
105
71
  ops->ops_id = ops_id;
106
71
  ops->ops_cnt = ops_cnt;
107
108
71
  if (ops->ops_cnt > 0) {
109
61
    ops->ops_priority = avm_rb_read_literal(rb, 4);
110
61
    ops->ops_intent = avm_rb_read_literal(rb, 7);
111
61
    ops->ops_intent_present_flag = avm_rb_read_bit(rb);
112
61
    ops->ops_ptl_present_flag = avm_rb_read_bit(rb);
113
61
    ops->ops_color_info_present_flag = avm_rb_read_bit(rb);
114
115
61
    if (obu_xlayer_id == GLOBAL_XLAYER_ID) {
116
0
      ops->ops_mlayer_info_idc = avm_rb_read_literal(rb, 2);
117
0
      if (ops->ops_mlayer_info_idc >= 3) {
118
0
        avm_internal_error(
119
0
            &pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
120
0
            "value of ops_mlayer_info_idc should be smaller than 3.");
121
0
      }
122
61
    } else {
123
61
      ops->ops_mlayer_info_idc = 1;
124
61
      (void)avm_rb_read_literal(rb, 2);  // ops_reserved_2bits
125
61
    }
126
127
126
    for (int i = 0; i < ops->ops_cnt; i++) {
128
65
      OperatingPoint *op = &ops->op[i];
129
      // Read ops_data_size (ULEB128 encoded)
130
65
      op->ops_data_size = avm_rb_read_uleb(rb);
131
65
      const uint32_t max_reasonable_size = 1024 * 1024;  // Set a max size
132
65
      if (op->ops_data_size > max_reasonable_size) {
133
11
        avm_internal_error(&pbi->common.error, AVM_CODEC_CORRUPT_FRAME,
134
11
                           "ops_data_size value %u exceeds reasonable limit in "
135
11
                           "av2_read_operating_point_set_obu()",
136
11
                           op->ops_data_size);
137
11
      }
138
139
65
      const uint32_t op_start_bit_offset = rb->bit_offset;
140
141
65
      if (ops->ops_intent_present_flag)
142
34
        op->ops_intent_op = avm_rb_read_literal(rb, 7);
143
144
65
      if (ops->ops_ptl_present_flag) {
145
34
        if (obu_xlayer_id == GLOBAL_XLAYER_ID) {
146
0
          op->ops_config_idc = avm_rb_read_literal(rb, MULTI_SEQ_CONFIG_BITS);
147
0
          op->ops_aggregate_level_idx = avm_rb_read_literal(rb, LEVEL_BITS);
148
0
          op->ops_max_tier_flag = avm_rb_read_bit(rb);
149
0
          op->ops_max_interop = avm_rb_read_literal(rb, INTEROP_BITS);
150
34
        } else {
151
34
          op->ops_seq_profile_idc[obu_xlayer_id] =
152
34
              avm_rb_read_literal(rb, PROFILE_BITS);
153
34
          op->ops_level_idx[obu_xlayer_id] =
154
34
              avm_rb_read_literal(rb, LEVEL_BITS);
155
34
          op->ops_tier_flag[obu_xlayer_id] = avm_rb_read_bit(rb);
156
34
          op->ops_mlayer_count[obu_xlayer_id] = avm_rb_read_literal(rb, 3);
157
34
          (void)avm_rb_read_literal(rb, 2);  // ops_ptl_reserved_2bits
158
34
        }
159
34
      }
160
65
      if (ops->ops_color_info_present_flag) {
161
29
        read_ops_color_info(&op->color_info, rb);
162
36
      } else {
163
36
        op->color_info.ops_color_description_idc = AVM_COLOR_DESC_IDC_EXPLICIT;
164
36
        op->color_info.ops_color_primaries = AVM_CICP_CP_UNSPECIFIED;
165
36
        op->color_info.ops_transfer_characteristics = AVM_CICP_TC_UNSPECIFIED;
166
36
        op->color_info.ops_matrix_coefficients = AVM_CICP_MC_UNSPECIFIED;
167
36
        op->color_info.ops_full_range_flag = 0;
168
36
      }
169
65
      op->ops_decoder_model_info_for_this_op_present_flag = avm_rb_read_bit(rb);
170
65
      if (op->ops_decoder_model_info_for_this_op_present_flag) {
171
27
        read_ops_decoder_model_info(&op->decoder_model_info, rb);
172
27
      }
173
65
      int ops_initial_display_delay_present_flag = avm_rb_read_bit(rb);
174
65
      if (ops_initial_display_delay_present_flag) {
175
22
        int ops_initial_display_delay_minus_1 = avm_rb_read_literal(rb, 4);
176
22
        op->ops_initial_display_delay = ops_initial_display_delay_minus_1 + 1;
177
43
      } else {
178
43
        op->ops_initial_display_delay = BUFFER_POOL_MAX_SIZE;
179
43
      }
180
181
65
      if (obu_xlayer_id == GLOBAL_XLAYER_ID) {
182
0
        op->ops_xlayer_map = avm_rb_read_literal(rb, MAX_NUM_XLAYERS - 1);
183
0
        int k = 0;
184
0
        for (int j = 0; j < MAX_NUM_XLAYERS - 1; j++) {
185
0
          if ((op->ops_xlayer_map & (1 << j))) {
186
0
            op->OpsxLayerID[k] = j;
187
0
            k++;
188
189
0
            if (ops->ops_ptl_present_flag) {
190
0
              op->ops_seq_profile_idc[j] =
191
0
                  avm_rb_read_literal(rb, PROFILE_BITS);
192
0
              op->ops_level_idx[j] = avm_rb_read_literal(rb, LEVEL_BITS);
193
0
              op->ops_tier_flag[j] = avm_rb_read_bit(rb);
194
0
              op->ops_mlayer_count[j] = avm_rb_read_literal(rb, 3);
195
0
              (void)avm_rb_read_literal(rb, 2);  // ops_ptl_reserved_2bits
196
0
            }
197
            // The ops_mlayer_indo_idc = 0, specifies that mlayer information
198
            // syntax structure is not present in the current OPS.
199
0
            if (ops->ops_mlayer_info_idc == 1) {
200
0
              read_ops_mlayer_info(j, &op->mlayer_info, rb);
201
0
            } else if (ops->ops_mlayer_info_idc == 2) {
202
0
              op->ops_mlayer_explicit_info_flag[j] = avm_rb_read_bit(rb);
203
0
              if (op->ops_mlayer_explicit_info_flag[j]) {
204
0
                read_ops_mlayer_info(j, &op->mlayer_info, rb);
205
0
              } else {
206
0
                op->ops_embedded_ops_id[j] = avm_rb_read_literal(rb, 4);
207
0
                op->ops_embedded_op_index[j] = avm_rb_read_literal(rb, 3);
208
0
                if (op->ops_embedded_op_index[j] > 6) {
209
0
                  avm_internal_error(
210
0
                      &pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
211
0
                      "value of ops_embedded_op_index shall not be "
212
0
                      "larger than 6.");
213
0
                }
214
                // Inherit mlayer_info from the referenced operating point.
215
0
                const int ref_ops_id = op->ops_embedded_ops_id[j];
216
0
                const int ref_op_index = op->ops_embedded_op_index[j];
217
0
                const OperatingPointSet *ref_ops =
218
0
                    &pbi->ops_list[obu_xlayer_id][ref_ops_id];
219
0
                if (ref_op_index >= ref_ops->ops_cnt) {
220
0
                  avm_internal_error(
221
0
                      &pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
222
0
                      "ops_embedded_op_index[%d] value %d exceeds ops_cnt %d "
223
0
                      "of referenced OPS %d.",
224
0
                      j, ref_op_index, ref_ops->ops_cnt, ref_ops_id);
225
0
                }
226
0
                if (ref_ops_id == ops_id && ref_op_index >= i) {
227
0
                  avm_internal_error(
228
0
                      &pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
229
0
                      "ops_embedded_ops_id[%d] references current OPS %d "
230
0
                      "with op_index %d >= current op_index %d.",
231
0
                      j, ops_id, ref_op_index, i);
232
0
                }
233
0
                const OperatingPoint *ref_op = &ref_ops->op[ref_op_index];
234
0
                op->mlayer_info.ops_mlayer_map[j] =
235
0
                    ref_op->mlayer_info.ops_mlayer_map[j];
236
0
                op->mlayer_info.OPMLayerCount[j] =
237
0
                    ref_op->mlayer_info.OPMLayerCount[j];
238
0
                for (int m = 0; m < MAX_NUM_MLAYERS; m++) {
239
0
                  op->mlayer_info.ops_tlayer_map[j][m] =
240
0
                      ref_op->mlayer_info.ops_tlayer_map[j][m];
241
0
                  op->mlayer_info.OPTLayerCount[j][m] =
242
0
                      ref_op->mlayer_info.OPTLayerCount[j][m];
243
0
                }
244
0
              }
245
0
            }
246
0
          }
247
0
        }
248
0
        op->XCount = k;
249
65
      } else {
250
65
        op->XCount = 1;
251
65
        op->OpsxLayerID[0] = obu_xlayer_id;
252
65
        assert(ops->ops_mlayer_info_idc == 1);
253
65
        read_ops_mlayer_info(obu_xlayer_id, &op->mlayer_info, rb);
254
65
      }
255
256
      // Byte alignment at end of each operating point iteration
257
65
      if (av2_check_byte_alignment(&pbi->common, rb) != 0) {
258
19
        avm_internal_error(&pbi->common.error, AVM_CODEC_CORRUPT_FRAME,
259
19
                           "Byte alignment error at end of operating point in "
260
19
                           "av2_read_operating_point_set_obu()");
261
19
      }
262
263
65
      const uint32_t op_end_bit_offset = rb->bit_offset;
264
65
      const uint32_t actual_bits_read = op_end_bit_offset - op_start_bit_offset;
265
65
      assert(actual_bits_read % 8 == 0);
266
65
      const uint32_t actual_bytes_read = actual_bits_read / 8;
267
268
65
      if (op->ops_data_size != actual_bytes_read) {
269
21
        avm_internal_error(
270
21
            &pbi->common.error, AVM_CODEC_CORRUPT_FRAME,
271
21
            "ops_data_size mismatch in av2_read_operating_point_set_obu()");
272
21
      }
273
65
    }
274
61
  }
275
71
  size_t bits_before_ext = rb->bit_offset - saved_bit_offset;
276
71
  ops->ops_extension_present_flag = avm_rb_read_bit(rb);
277
71
  if (ops->ops_extension_present_flag) {
278
    // Extension data bits = total - bits_read_before_extension -1 (ext flag) -
279
    // trailing bits
280
6
    int extension_bits = read_obu_extension_bits(
281
6
        rb->bit_buffer, rb->bit_buffer_end - rb->bit_buffer, bits_before_ext,
282
6
        &pbi->common.error);
283
6
    if (extension_bits > 0) {
284
6
      rb->bit_offset += extension_bits;  // skip over the extension bits
285
6
    } else {
286
      // No extension data present
287
0
    }
288
6
  }
289
290
71
  if (av2_check_trailing_bits(pbi, rb) != 0) {
291
4
    return 0;
292
4
  }
293
67
  ops->valid = 1;
294
67
  return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
295
71
}