Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/aom/av1/encoder/av1_ext_ratectrl.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 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
#include "aom/aom_ext_ratectrl.h"
13
#include "av1/encoder/av1_ext_ratectrl.h"
14
15
0
aom_codec_err_t av1_extrc_init(AOM_EXT_RATECTRL *ext_ratectrl) {
16
0
  if (ext_ratectrl == NULL) {
17
0
    return AOM_CODEC_INVALID_PARAM;
18
0
  }
19
0
  av1_zero(*ext_ratectrl);
20
0
  return AOM_CODEC_OK;
21
0
}
22
23
aom_codec_err_t av1_extrc_create(aom_rc_funcs_t funcs,
24
                                 aom_rc_config_t ratectrl_config,
25
0
                                 AOM_EXT_RATECTRL *ext_ratectrl) {
26
0
  aom_rc_status_t rc_status;
27
0
  aom_rc_firstpass_stats_t *rc_firstpass_stats;
28
0
  if (ext_ratectrl == NULL) {
29
0
    return AOM_CODEC_INVALID_PARAM;
30
0
  }
31
0
  av1_extrc_delete(ext_ratectrl);
32
0
  ext_ratectrl->funcs = funcs;
33
0
  ext_ratectrl->ratectrl_config = ratectrl_config;
34
0
  rc_status = ext_ratectrl->funcs.create_model(ext_ratectrl->funcs.priv,
35
0
                                               &ext_ratectrl->ratectrl_config,
36
0
                                               &ext_ratectrl->model);
37
0
  if (rc_status == AOM_RC_ERROR) {
38
0
    return AOM_CODEC_ERROR;
39
0
  }
40
0
  rc_firstpass_stats = &ext_ratectrl->rc_firstpass_stats;
41
0
  rc_firstpass_stats->num_frames = ratectrl_config.show_frame_count;
42
0
  rc_firstpass_stats->frame_stats =
43
0
      aom_malloc(sizeof(*rc_firstpass_stats->frame_stats) *
44
0
                 rc_firstpass_stats->num_frames);
45
0
  if (rc_firstpass_stats->frame_stats == NULL) {
46
0
    return AOM_CODEC_MEM_ERROR;
47
0
  }
48
49
0
  ext_ratectrl->ready = 1;
50
0
  return AOM_CODEC_OK;
51
0
}
52
53
static void gen_rc_firstpass_stats(const FIRSTPASS_STATS *stats,
54
0
                                   aom_rc_frame_stats_t *rc_frame_stats) {
55
0
  rc_frame_stats->frame = stats->frame;
56
0
  rc_frame_stats->weight = stats->weight;
57
0
  rc_frame_stats->intra_error = stats->intra_error;
58
0
  rc_frame_stats->coded_error = stats->coded_error;
59
0
  rc_frame_stats->sr_coded_error = stats->sr_coded_error;
60
0
  rc_frame_stats->frame_avg_wavelet_energy = stats->frame_avg_wavelet_energy;
61
0
  rc_frame_stats->pcnt_inter = stats->pcnt_inter;
62
0
  rc_frame_stats->pcnt_motion = stats->pcnt_motion;
63
0
  rc_frame_stats->pcnt_second_ref = stats->pcnt_second_ref;
64
0
  rc_frame_stats->pcnt_neutral = stats->pcnt_neutral;
65
0
  rc_frame_stats->intra_skip_pct = stats->intra_skip_pct;
66
0
  rc_frame_stats->inactive_zone_rows = stats->inactive_zone_rows;
67
0
  rc_frame_stats->inactive_zone_cols = stats->inactive_zone_cols;
68
0
  rc_frame_stats->MVr = stats->MVr;
69
0
  rc_frame_stats->mvr_abs = stats->mvr_abs;
70
0
  rc_frame_stats->MVc = stats->MVc;
71
0
  rc_frame_stats->mvc_abs = stats->mvc_abs;
72
0
  rc_frame_stats->MVrv = stats->MVrv;
73
0
  rc_frame_stats->MVcv = stats->MVcv;
74
0
  rc_frame_stats->mv_in_out_count = stats->mv_in_out_count;
75
0
  rc_frame_stats->duration = stats->duration;
76
0
  rc_frame_stats->count = stats->count;
77
0
  rc_frame_stats->new_mv_count = stats->new_mv_count;
78
0
  rc_frame_stats->raw_error_stdev = stats->raw_error_stdev;
79
0
  rc_frame_stats->is_flash = stats->is_flash;
80
0
  rc_frame_stats->noise_var = stats->noise_var;
81
0
  rc_frame_stats->cor_coeff = stats->cor_coeff;
82
0
  rc_frame_stats->log_intra_error = stats->log_intra_error;
83
0
  rc_frame_stats->log_coded_error = stats->log_coded_error;
84
0
}
85
86
aom_codec_err_t av1_extrc_send_firstpass_stats(
87
0
    AOM_EXT_RATECTRL *ext_ratectrl, const FIRSTPASS_INFO *first_pass_info) {
88
0
  assert(first_pass_info != NULL);
89
0
  assert(ext_ratectrl != NULL);
90
0
  if (ext_ratectrl->ready) {
91
0
    aom_rc_status_t rc_status;
92
0
    aom_rc_firstpass_stats_t *rc_firstpass_stats =
93
0
        &ext_ratectrl->rc_firstpass_stats;
94
0
    assert(rc_firstpass_stats->num_frames == first_pass_info->stats_buf_size);
95
0
    for (int i = 0; i < rc_firstpass_stats->num_frames; ++i) {
96
0
      gen_rc_firstpass_stats(&first_pass_info->stats_buf[i],
97
0
                             &rc_firstpass_stats->frame_stats[i]);
98
0
    }
99
0
    rc_status = ext_ratectrl->funcs.send_firstpass_stats(ext_ratectrl->model,
100
0
                                                         rc_firstpass_stats);
101
0
    if (rc_status == AOM_RC_ERROR) {
102
0
      return AOM_CODEC_ERROR;
103
0
    }
104
0
  }
105
0
  return AOM_CODEC_OK;
106
0
}
107
108
aom_codec_err_t av1_extrc_send_tpl_stats(
109
0
    AOM_EXT_RATECTRL *ext_ratectrl, const AomTplGopStats *extrc_tpl_gop_stats) {
110
0
  assert(ext_ratectrl != NULL);
111
0
  assert(extrc_tpl_gop_stats != NULL);
112
0
  if (ext_ratectrl->ready && ext_ratectrl->funcs.send_tpl_gop_stats != NULL) {
113
0
    aom_rc_status_t rc_status = ext_ratectrl->funcs.send_tpl_gop_stats(
114
0
        ext_ratectrl->model, extrc_tpl_gop_stats);
115
0
    if (rc_status == AOM_RC_ERROR) {
116
0
      return AOM_CODEC_ERROR;
117
0
    }
118
0
  }
119
0
  return AOM_CODEC_OK;
120
0
}
121
122
aom_codec_err_t av1_extrc_get_gop_decision(
123
0
    AOM_EXT_RATECTRL *ext_ratectrl, aom_rc_gop_decision_t *gop_decision) {
124
0
  aom_rc_status_t rc_status;
125
0
  assert(ext_ratectrl != NULL);
126
0
  assert(gop_decision != NULL);
127
0
  if ((ext_ratectrl->funcs.rc_type & AOM_RC_GOP) == 0) {
128
0
    return AOM_CODEC_INVALID_PARAM;
129
0
  }
130
0
  rc_status =
131
0
      ext_ratectrl->funcs.get_gop_decision(ext_ratectrl->model, gop_decision);
132
0
  if (rc_status == AOM_RC_ERROR) {
133
0
    return AOM_CODEC_ERROR;
134
0
  }
135
0
  return AOM_CODEC_OK;
136
0
}
137
138
aom_codec_err_t av1_extrc_get_encodeframe_decision(
139
    AOM_EXT_RATECTRL *ext_ratectrl, int gop_index,
140
0
    aom_rc_encodeframe_decision_t *encode_frame_decision) {
141
0
  assert(ext_ratectrl != NULL);
142
0
  assert(ext_ratectrl->ready && (ext_ratectrl->funcs.rc_type & AOM_RC_QP) != 0);
143
0
  assert(encode_frame_decision != NULL);
144
0
  aom_rc_status_t rc_status = ext_ratectrl->funcs.get_encodeframe_decision(
145
0
      ext_ratectrl->model, gop_index, encode_frame_decision);
146
0
  if (rc_status == AOM_RC_ERROR) {
147
0
    return AOM_CODEC_ERROR;
148
0
  }
149
0
  return AOM_CODEC_OK;
150
0
}
151
152
aom_codec_err_t av1_extrc_update_encodeframe_result(
153
    AOM_EXT_RATECTRL *ext_ratectrl, int64_t bit_count,
154
0
    int actual_encoding_qindex) {
155
0
  assert(ext_ratectrl != NULL);
156
0
  if (ext_ratectrl->ready) {
157
0
    aom_rc_status_t rc_status;
158
0
    aom_rc_encodeframe_result_t encode_frame_result;
159
0
    encode_frame_result.bit_count = bit_count;
160
0
    encode_frame_result.actual_encoding_qindex = actual_encoding_qindex;
161
0
    rc_status = ext_ratectrl->funcs.update_encodeframe_result(
162
0
        ext_ratectrl->model, &encode_frame_result);
163
0
    if (rc_status == AOM_RC_ERROR) {
164
0
      return AOM_CODEC_ERROR;
165
0
    }
166
0
  }
167
0
  return AOM_CODEC_OK;
168
0
}
169
170
aom_codec_err_t av1_extrc_get_key_frame_decision(
171
    AOM_EXT_RATECTRL *ext_ratectrl,
172
0
    aom_rc_key_frame_decision_t *key_frame_decision) {
173
0
  assert(ext_ratectrl != NULL);
174
0
  if (!ext_ratectrl->ready || (ext_ratectrl->funcs.rc_type & AOM_RC_GOP) == 0) {
175
0
    return AOM_CODEC_INVALID_PARAM;
176
0
  }
177
0
  aom_rc_status_t rc_status = ext_ratectrl->funcs.get_key_frame_decision(
178
0
      ext_ratectrl->model, key_frame_decision);
179
0
  return rc_status == AOM_RC_OK ? AOM_CODEC_OK : AOM_CODEC_ERROR;
180
0
}
181
182
0
aom_codec_err_t av1_extrc_delete(AOM_EXT_RATECTRL *ext_ratectrl) {
183
0
  if (ext_ratectrl == NULL) {
184
0
    return AOM_CODEC_INVALID_PARAM;
185
0
  }
186
0
  if (ext_ratectrl->ready) {
187
0
    aom_rc_status_t rc_status =
188
0
        ext_ratectrl->funcs.delete_model(ext_ratectrl->model);
189
0
    if (rc_status == AOM_RC_ERROR) {
190
0
      return AOM_CODEC_ERROR;
191
0
    }
192
0
    aom_free(ext_ratectrl->rc_firstpass_stats.frame_stats);
193
0
    aom_free(ext_ratectrl->sb_params_list);
194
0
  }
195
0
  return av1_extrc_init(ext_ratectrl);
196
0
}