1 /*
2 * Copyright (c) 2019, 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_ports/system_state.h"
13
14 #include "av1/encoder/encoder.h"
15 #include "av1/encoder/level.h"
16
17 #define UNDEFINED_LEVEL \
18 { \
19 .level = SEQ_LEVEL_MAX, .max_picture_size = 0, .max_h_size = 0, \
20 .max_v_size = 0, .max_display_rate = 0, .max_decode_rate = 0, \
21 .max_header_rate = 0, .main_mbps = 0, .high_mbps = 0, .main_cr = 0, \
22 .high_cr = 0, .max_tiles = 0, .max_tile_cols = 0 \
23 }
24
25 static const AV1LevelSpec av1_level_defs[SEQ_LEVELS] = {
26 { .level = SEQ_LEVEL_2_0,
27 .max_picture_size = 147456,
28 .max_h_size = 2048,
29 .max_v_size = 1152,
30 .max_display_rate = 4423680L,
31 .max_decode_rate = 5529600L,
32 .max_header_rate = 150,
33 .main_mbps = 1.5,
34 .high_mbps = 0,
35 .main_cr = 2.0,
36 .high_cr = 0,
37 .max_tiles = 8,
38 .max_tile_cols = 4 },
39 { .level = SEQ_LEVEL_2_1,
40 .max_picture_size = 278784,
41 .max_h_size = 2816,
42 .max_v_size = 1584,
43 .max_display_rate = 8363520L,
44 .max_decode_rate = 10454400L,
45 .max_header_rate = 150,
46 .main_mbps = 3.0,
47 .high_mbps = 0,
48 .main_cr = 2.0,
49 .high_cr = 0,
50 .max_tiles = 8,
51 .max_tile_cols = 4 },
52 UNDEFINED_LEVEL,
53 UNDEFINED_LEVEL,
54 { .level = SEQ_LEVEL_3_0,
55 .max_picture_size = 665856,
56 .max_h_size = 4352,
57 .max_v_size = 2448,
58 .max_display_rate = 19975680L,
59 .max_decode_rate = 24969600L,
60 .max_header_rate = 150,
61 .main_mbps = 6.0,
62 .high_mbps = 0,
63 .main_cr = 2.0,
64 .high_cr = 0,
65 .max_tiles = 16,
66 .max_tile_cols = 6 },
67 { .level = SEQ_LEVEL_3_1,
68 .max_picture_size = 1065024,
69 .max_h_size = 5504,
70 .max_v_size = 3096,
71 .max_display_rate = 31950720L,
72 .max_decode_rate = 39938400L,
73 .max_header_rate = 150,
74 .main_mbps = 10.0,
75 .high_mbps = 0,
76 .main_cr = 2.0,
77 .high_cr = 0,
78 .max_tiles = 16,
79 .max_tile_cols = 6 },
80 UNDEFINED_LEVEL,
81 UNDEFINED_LEVEL,
82 { .level = SEQ_LEVEL_4_0,
83 .max_picture_size = 2359296,
84 .max_h_size = 6144,
85 .max_v_size = 3456,
86 .max_display_rate = 70778880L,
87 .max_decode_rate = 77856768L,
88 .max_header_rate = 300,
89 .main_mbps = 12.0,
90 .high_mbps = 30.0,
91 .main_cr = 4.0,
92 .high_cr = 4.0,
93 .max_tiles = 32,
94 .max_tile_cols = 8 },
95 { .level = SEQ_LEVEL_4_1,
96 .max_picture_size = 2359296,
97 .max_h_size = 6144,
98 .max_v_size = 3456,
99 .max_display_rate = 141557760L,
100 .max_decode_rate = 155713536L,
101 .max_header_rate = 300,
102 .main_mbps = 20.0,
103 .high_mbps = 50.0,
104 .main_cr = 4.0,
105 .high_cr = 4.0,
106 .max_tiles = 32,
107 .max_tile_cols = 8 },
108 UNDEFINED_LEVEL,
109 UNDEFINED_LEVEL,
110 { .level = SEQ_LEVEL_5_0,
111 .max_picture_size = 8912896,
112 .max_h_size = 8192,
113 .max_v_size = 4352,
114 .max_display_rate = 267386880L,
115 .max_decode_rate = 273715200L,
116 .max_header_rate = 300,
117 .main_mbps = 30.0,
118 .high_mbps = 100.0,
119 .main_cr = 6.0,
120 .high_cr = 4.0,
121 .max_tiles = 64,
122 .max_tile_cols = 8 },
123 { .level = SEQ_LEVEL_5_1,
124 .max_picture_size = 8912896,
125 .max_h_size = 8192,
126 .max_v_size = 4352,
127 .max_display_rate = 534773760L,
128 .max_decode_rate = 547430400L,
129 .max_header_rate = 300,
130 .main_mbps = 40.0,
131 .high_mbps = 160.0,
132 .main_cr = 8.0,
133 .high_cr = 4.0,
134 .max_tiles = 64,
135 .max_tile_cols = 8 },
136 { .level = SEQ_LEVEL_5_2,
137 .max_picture_size = 8912896,
138 .max_h_size = 8192,
139 .max_v_size = 4352,
140 .max_display_rate = 1069547520L,
141 .max_decode_rate = 1094860800L,
142 .max_header_rate = 300,
143 .main_mbps = 60.0,
144 .high_mbps = 240.0,
145 .main_cr = 8.0,
146 .high_cr = 4.0,
147 .max_tiles = 64,
148 .max_tile_cols = 8 },
149 { .level = SEQ_LEVEL_5_3,
150 .max_picture_size = 8912896,
151 .max_h_size = 8192,
152 .max_v_size = 4352,
153 .max_display_rate = 1069547520L,
154 .max_decode_rate = 1176502272L,
155 .max_header_rate = 300,
156 .main_mbps = 60.0,
157 .high_mbps = 240.0,
158 .main_cr = 8.0,
159 .high_cr = 4.0,
160 .max_tiles = 64,
161 .max_tile_cols = 8 },
162 { .level = SEQ_LEVEL_6_0,
163 .max_picture_size = 35651584,
164 .max_h_size = 16384,
165 .max_v_size = 8704,
166 .max_display_rate = 1069547520L,
167 .max_decode_rate = 1176502272L,
168 .max_header_rate = 300,
169 .main_mbps = 60.0,
170 .high_mbps = 240.0,
171 .main_cr = 8.0,
172 .high_cr = 4.0,
173 .max_tiles = 128,
174 .max_tile_cols = 16 },
175 { .level = SEQ_LEVEL_6_1,
176 .max_picture_size = 35651584,
177 .max_h_size = 16384,
178 .max_v_size = 8704,
179 .max_display_rate = 2139095040L,
180 .max_decode_rate = 2189721600L,
181 .max_header_rate = 300,
182 .main_mbps = 100.0,
183 .high_mbps = 480.0,
184 .main_cr = 8.0,
185 .high_cr = 4.0,
186 .max_tiles = 128,
187 .max_tile_cols = 16 },
188 { .level = SEQ_LEVEL_6_2,
189 .max_picture_size = 35651584,
190 .max_h_size = 16384,
191 .max_v_size = 8704,
192 .max_display_rate = 4278190080L,
193 .max_decode_rate = 4379443200L,
194 .max_header_rate = 300,
195 .main_mbps = 160.0,
196 .high_mbps = 800.0,
197 .main_cr = 8.0,
198 .high_cr = 4.0,
199 .max_tiles = 128,
200 .max_tile_cols = 16 },
201 { .level = SEQ_LEVEL_6_3,
202 .max_picture_size = 35651584,
203 .max_h_size = 16384,
204 .max_v_size = 8704,
205 .max_display_rate = 4278190080L,
206 .max_decode_rate = 4706009088L,
207 .max_header_rate = 300,
208 .main_mbps = 160.0,
209 .high_mbps = 800.0,
210 .main_cr = 8.0,
211 .high_cr = 4.0,
212 .max_tiles = 128,
213 .max_tile_cols = 16 },
214 UNDEFINED_LEVEL,
215 UNDEFINED_LEVEL,
216 UNDEFINED_LEVEL,
217 UNDEFINED_LEVEL,
218 };
219
220 typedef enum {
221 LUMA_PIC_SIZE_TOO_LARGE,
222 LUMA_PIC_H_SIZE_TOO_LARGE,
223 LUMA_PIC_V_SIZE_TOO_LARGE,
224 LUMA_PIC_H_SIZE_TOO_SMALL,
225 LUMA_PIC_V_SIZE_TOO_SMALL,
226 TOO_MANY_TILE_COLUMNS,
227 TOO_MANY_TILES,
228 TILE_RATE_TOO_HIGH,
229 TILE_TOO_LARGE,
230 SUPERRES_TILE_WIDTH_TOO_LARGE,
231 CROPPED_TILE_WIDTH_TOO_SMALL,
232 CROPPED_TILE_HEIGHT_TOO_SMALL,
233 TILE_WIDTH_INVALID,
234 FRAME_HEADER_RATE_TOO_HIGH,
235 DISPLAY_RATE_TOO_HIGH,
236 DECODE_RATE_TOO_HIGH,
237 CR_TOO_SMALL,
238
239 TARGET_LEVEL_FAIL_IDS,
240 TARGET_LEVEL_OK,
241 } TARGET_LEVEL_FAIL_ID;
242
243 static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] = {
244 "The picture size is too large.",
245 "The picture width is too large.",
246 "The picture height is too large.",
247 "The picture width is too small.",
248 "The picture height is too small.",
249 "Too many tile columns are used.",
250 "Too many tiles are used.",
251 "The tile rate is too high.",
252 "The tile size is too large.",
253 "The superres tile width is too large.",
254 "The cropped tile width is less than 8.",
255 "The cropped tile height is less than 8.",
256 "The tile width is invalid.",
257 "The frame header rate is too high.",
258 "The display luma sample rate is too high.",
259 "The decoded luma sample rate is too high.",
260 "The compression ratio is too small.",
261 };
262
get_min_cr(const AV1LevelSpec * const level_spec,int tier,int is_still_picture,int64_t decoded_sample_rate)263 static double get_min_cr(const AV1LevelSpec *const level_spec, int tier,
264 int is_still_picture, int64_t decoded_sample_rate) {
265 if (is_still_picture) return 0.8;
266 const double min_cr_basis = tier ? level_spec->high_cr : level_spec->main_cr;
267 const double speed_adj =
268 (double)decoded_sample_rate / level_spec->max_display_rate;
269 return AOMMAX(min_cr_basis * speed_adj, 0.8);
270 }
271
check_level_constraints(const AV1LevelSpec * const target_level_spec,const AV1LevelSpec * const level_spec,const AV1LevelStats * const level_stats,int tier,int is_still_picture)272 static TARGET_LEVEL_FAIL_ID check_level_constraints(
273 const AV1LevelSpec *const target_level_spec,
274 const AV1LevelSpec *const level_spec,
275 const AV1LevelStats *const level_stats, int tier, int is_still_picture) {
276 const double min_cr = get_min_cr(target_level_spec, tier, is_still_picture,
277 level_spec->max_decode_rate);
278 TARGET_LEVEL_FAIL_ID fail_id = TARGET_LEVEL_OK;
279
280 do {
281 if (level_spec->max_picture_size > target_level_spec->max_picture_size) {
282 fail_id = LUMA_PIC_SIZE_TOO_LARGE;
283 break;
284 }
285
286 if (level_spec->max_h_size > target_level_spec->max_h_size) {
287 fail_id = LUMA_PIC_H_SIZE_TOO_LARGE;
288 break;
289 }
290
291 if (level_spec->max_v_size > target_level_spec->max_v_size) {
292 fail_id = LUMA_PIC_V_SIZE_TOO_LARGE;
293 break;
294 }
295
296 if (level_spec->max_tile_cols > target_level_spec->max_tile_cols) {
297 fail_id = TOO_MANY_TILE_COLUMNS;
298 break;
299 }
300
301 if (level_spec->max_tiles > target_level_spec->max_tiles) {
302 fail_id = TOO_MANY_TILES;
303 break;
304 }
305
306 if (level_spec->max_header_rate > target_level_spec->max_header_rate) {
307 fail_id = FRAME_HEADER_RATE_TOO_HIGH;
308 break;
309 }
310
311 if (level_spec->max_display_rate > target_level_spec->max_display_rate) {
312 fail_id = DISPLAY_RATE_TOO_HIGH;
313 break;
314 }
315
316 if (level_spec->max_decode_rate > target_level_spec->max_decode_rate) {
317 fail_id = DECODE_RATE_TOO_HIGH;
318 break;
319 }
320
321 if (level_spec->max_tile_rate > target_level_spec->max_tiles * 120) {
322 fail_id = TILE_RATE_TOO_HIGH;
323 break;
324 }
325
326 if (level_stats->max_tile_size > 4096 * 2304) {
327 fail_id = TILE_TOO_LARGE;
328 break;
329 }
330
331 if (level_stats->max_superres_tile_width > MAX_TILE_WIDTH) {
332 fail_id = SUPERRES_TILE_WIDTH_TOO_LARGE;
333 break;
334 }
335
336 if (level_stats->min_cropped_tile_width < 8) {
337 fail_id = CROPPED_TILE_WIDTH_TOO_SMALL;
338 break;
339 }
340
341 if (level_stats->min_cropped_tile_height < 8) {
342 fail_id = CROPPED_TILE_HEIGHT_TOO_SMALL;
343 break;
344 }
345
346 if (level_stats->min_frame_width < 16) {
347 fail_id = LUMA_PIC_H_SIZE_TOO_SMALL;
348 break;
349 }
350
351 if (level_stats->min_frame_height < 16) {
352 fail_id = LUMA_PIC_V_SIZE_TOO_SMALL;
353 break;
354 }
355
356 if (!level_stats->tile_width_is_valid) {
357 fail_id = TILE_WIDTH_INVALID;
358 break;
359 }
360
361 if (level_stats->min_cr < min_cr) {
362 fail_id = CR_TOO_SMALL;
363 break;
364 }
365 } while (0);
366
367 return fail_id;
368 }
369
is_in_operating_point(int operating_point,int temporal_layer_id,int spatial_layer_id)370 static INLINE int is_in_operating_point(int operating_point,
371 int temporal_layer_id,
372 int spatial_layer_id) {
373 if (!operating_point) return 1;
374
375 return ((operating_point >> temporal_layer_id) & 1) &&
376 ((operating_point >> (spatial_layer_id + 8)) & 1);
377 }
378
get_tile_stats(const AV1_COMP * const cpi,int * max_tile_size,int * max_superres_tile_width,int * min_cropped_tile_width,int * min_cropped_tile_height,int * tile_width_valid)379 static void get_tile_stats(const AV1_COMP *const cpi, int *max_tile_size,
380 int *max_superres_tile_width,
381 int *min_cropped_tile_width,
382 int *min_cropped_tile_height,
383 int *tile_width_valid) {
384 const AV1_COMMON *const cm = &cpi->common;
385 const int tile_cols = cm->tile_cols;
386 const int tile_rows = cm->tile_rows;
387 const int superres_scale_denominator = cm->superres_scale_denominator;
388
389 *max_tile_size = 0;
390 *max_superres_tile_width = 0;
391 *min_cropped_tile_width = INT_MAX;
392 *min_cropped_tile_height = INT_MAX;
393 *tile_width_valid = 1;
394
395 for (int tile_row = 0; tile_row < tile_rows; ++tile_row) {
396 for (int tile_col = 0; tile_col < tile_cols; ++tile_col) {
397 const TileInfo *const tile_info =
398 &cpi->tile_data[tile_row * cm->tile_cols + tile_col].tile_info;
399 const int tile_width =
400 (tile_info->mi_col_end - tile_info->mi_col_start) * MI_SIZE;
401 const int tile_height =
402 (tile_info->mi_row_end - tile_info->mi_row_start) * MI_SIZE;
403 const int tile_size = tile_width * tile_height;
404 *max_tile_size = AOMMAX(*max_tile_size, tile_size);
405
406 const int supperres_tile_width =
407 tile_width * superres_scale_denominator / SCALE_NUMERATOR;
408 *max_superres_tile_width =
409 AOMMAX(*max_superres_tile_width, supperres_tile_width);
410
411 const int cropped_tile_width =
412 cm->width - tile_info->mi_col_start * MI_SIZE;
413 const int cropped_tile_height =
414 cm->height - tile_info->mi_row_start * MI_SIZE;
415 *min_cropped_tile_width =
416 AOMMIN(*min_cropped_tile_width, cropped_tile_width);
417 *min_cropped_tile_height =
418 AOMMIN(*min_cropped_tile_height, cropped_tile_height);
419
420 const int is_right_most_tile = tile_info->mi_col_end == cm->mi_cols;
421 if (!is_right_most_tile) {
422 if (av1_superres_scaled(cm))
423 *tile_width_valid &= tile_width >= 128;
424 else
425 *tile_width_valid &= tile_width >= 64;
426 }
427 }
428 }
429 }
430
store_frame_record(int64_t ts_start,int64_t ts_end,int pic_size,int frame_header_count,int tiles,int show_frame,int show_existing_frame,FrameWindowBuffer * const buffer)431 static int store_frame_record(int64_t ts_start, int64_t ts_end, int pic_size,
432 int frame_header_count, int tiles, int show_frame,
433 int show_existing_frame,
434 FrameWindowBuffer *const buffer) {
435 if (buffer->num < FRAME_WINDOW_SIZE) {
436 ++buffer->num;
437 } else {
438 buffer->start = (buffer->start + 1) % FRAME_WINDOW_SIZE;
439 }
440 const int new_idx = (buffer->start + buffer->num - 1) % FRAME_WINDOW_SIZE;
441 FrameRecord *const record = &buffer->buf[new_idx];
442 record->ts_start = ts_start;
443 record->ts_end = ts_end;
444 record->pic_size = pic_size;
445 record->frame_header_count = frame_header_count;
446 record->tiles = tiles;
447 record->show_frame = show_frame;
448 record->show_existing_frame = show_existing_frame;
449
450 return new_idx;
451 }
452
453 // Count the number of frames encoded in the last "duration" ticks, in display
454 // time.
count_frames(const FrameWindowBuffer * const buffer,int64_t duration)455 static int count_frames(const FrameWindowBuffer *const buffer,
456 int64_t duration) {
457 const int current_idx = (buffer->start + buffer->num - 1) % FRAME_WINDOW_SIZE;
458 // Assume current frame is shown frame.
459 assert(buffer->buf[current_idx].show_frame);
460
461 const int64_t current_time = buffer->buf[current_idx].ts_end;
462 const int64_t time_limit = AOMMAX(current_time - duration, 0);
463 int num_frames = 1;
464 int index = current_idx - 1;
465 for (int i = buffer->num - 2; i >= 0; --i, --index, ++num_frames) {
466 if (index < 0) index = FRAME_WINDOW_SIZE - 1;
467 const FrameRecord *const record = &buffer->buf[index];
468 if (!record->show_frame) continue;
469 const int64_t ts_start = record->ts_start;
470 if (ts_start < time_limit) break;
471 }
472
473 return num_frames;
474 }
475
476 // Scan previously encoded frames and update level metrics accordingly.
scan_past_frames(const FrameWindowBuffer * const buffer,int num_frames_to_scan,AV1LevelSpec * const level_spec)477 static void scan_past_frames(const FrameWindowBuffer *const buffer,
478 int num_frames_to_scan,
479 AV1LevelSpec *const level_spec) {
480 const int num_frames_in_buffer = buffer->num;
481 int index = (buffer->start + num_frames_in_buffer - 1) % FRAME_WINDOW_SIZE;
482 int frame_headers = 0;
483 int tiles = 0;
484 int64_t display_samples = 0;
485 int64_t decoded_samples = 0;
486 for (int i = 0; i < AOMMIN(num_frames_in_buffer, num_frames_to_scan); ++i) {
487 const FrameRecord *const record = &buffer->buf[index];
488 if (!record->show_existing_frame) {
489 frame_headers += record->frame_header_count;
490 decoded_samples += record->pic_size;
491 }
492 if (record->show_frame) {
493 display_samples += record->pic_size;
494 }
495 tiles += record->tiles;
496 --index;
497 if (index < 0) index = FRAME_WINDOW_SIZE - 1;
498 }
499 level_spec->max_header_rate =
500 AOMMAX(level_spec->max_header_rate, frame_headers);
501 level_spec->max_display_rate =
502 AOMMAX(level_spec->max_display_rate, display_samples);
503 level_spec->max_decode_rate =
504 AOMMAX(level_spec->max_decode_rate, decoded_samples);
505 level_spec->max_tile_rate = AOMMAX(level_spec->max_tile_rate, tiles);
506 }
507
av1_update_level_info(AV1_COMP * cpi,size_t size,int64_t ts_start,int64_t ts_end)508 void av1_update_level_info(AV1_COMP *cpi, size_t size, int64_t ts_start,
509 int64_t ts_end) {
510 AV1_COMMON *const cm = &cpi->common;
511 const int upscaled_width = cm->superres_upscaled_width;
512 const int width = cm->width;
513 const int height = cm->height;
514 const int tile_cols = cm->tile_cols;
515 const int tile_rows = cm->tile_rows;
516 const int tiles = tile_cols * tile_rows;
517 const int luma_pic_size = upscaled_width * height;
518 const int frame_header_count = cpi->frame_header_count;
519 const int show_frame = cm->show_frame;
520 const int show_existing_frame = cm->show_existing_frame;
521
522 // Store info. of current frame into FrameWindowBuffer.
523 FrameWindowBuffer *const buffer = &cpi->frame_window_buffer;
524 store_frame_record(ts_start, ts_end, luma_pic_size, frame_header_count, tiles,
525 show_frame, show_existing_frame, buffer);
526 // Count the number of frames encoded in the past 1 second.
527 const int encoded_frames_in_last_second =
528 show_frame ? count_frames(buffer, TICKS_PER_SEC) : 0;
529
530 int max_tile_size;
531 int min_cropped_tile_width;
532 int min_cropped_tile_height;
533 int max_superres_tile_width;
534 int tile_width_is_valid;
535 get_tile_stats(cpi, &max_tile_size, &max_superres_tile_width,
536 &min_cropped_tile_width, &min_cropped_tile_height,
537 &tile_width_is_valid);
538
539 const SequenceHeader *const seq_params = &cm->seq_params;
540 const BITSTREAM_PROFILE profile = seq_params->profile;
541 const int pic_size_profile_factor =
542 profile == PROFILE_0 ? 15 : (profile == PROFILE_1 ? 30 : 36);
543 const size_t frame_compressed_size = (size > 129 ? size - 128 : 1);
544 const size_t frame_uncompressed_size =
545 (luma_pic_size * pic_size_profile_factor) >> 3;
546
547 aom_clear_system_state();
548 const double compression_ratio =
549 frame_uncompressed_size / (double)frame_compressed_size;
550 const double total_time_encoded =
551 (cpi->last_end_time_stamp_seen - cpi->first_time_stamp_ever) /
552 (double)TICKS_PER_SEC;
553
554 const int temporal_layer_id = cm->temporal_layer_id;
555 const int spatial_layer_id = cm->spatial_layer_id;
556 const int is_still_picture = seq_params->still_picture;
557 // update level_stats
558 // TODO(kyslov@) fix the implementation according to buffer model
559 for (int i = 0; i < seq_params->operating_points_cnt_minus_1 + 1; ++i) {
560 if (!is_in_operating_point(seq_params->operating_point_idc[i],
561 temporal_layer_id, spatial_layer_id)) {
562 continue;
563 }
564
565 AV1LevelInfo *const level_info = &cpi->level_info[i];
566 AV1LevelStats *const level_stats = &level_info->level_stats;
567
568 level_stats->max_tile_size =
569 AOMMAX(level_stats->max_tile_size, max_tile_size);
570 level_stats->max_superres_tile_width =
571 AOMMAX(level_stats->max_superres_tile_width, max_superres_tile_width);
572 level_stats->min_cropped_tile_width =
573 AOMMIN(level_stats->min_cropped_tile_width, min_cropped_tile_width);
574 level_stats->min_cropped_tile_height =
575 AOMMIN(level_stats->min_cropped_tile_height, min_cropped_tile_height);
576 level_stats->tile_width_is_valid &= tile_width_is_valid;
577 level_stats->min_frame_width = AOMMIN(level_stats->min_frame_width, width);
578 level_stats->min_frame_height =
579 AOMMIN(level_stats->min_frame_height, height);
580 level_stats->total_compressed_size += frame_compressed_size;
581 if (show_frame) level_stats->total_time_encoded = total_time_encoded;
582 level_stats->min_cr = AOMMIN(level_stats->min_cr, compression_ratio);
583
584 // update level_spec
585 // TODO(kyslov@) update all spec fields
586 AV1LevelSpec *const level_spec = &level_info->level_spec;
587 level_spec->max_picture_size =
588 AOMMAX(level_spec->max_picture_size, luma_pic_size);
589 level_spec->max_h_size =
590 AOMMAX(level_spec->max_h_size, cm->superres_upscaled_width);
591 level_spec->max_v_size = AOMMAX(level_spec->max_v_size, height);
592 level_spec->max_tile_cols = AOMMAX(level_spec->max_tile_cols, tile_cols);
593 level_spec->max_tiles = AOMMAX(level_spec->max_tiles, tiles);
594
595 if (show_frame) {
596 scan_past_frames(buffer, encoded_frames_in_last_second, level_spec);
597 }
598
599 // Check whether target level is met.
600 const AV1_LEVEL target_seq_level_idx = cpi->target_seq_level_idx[i];
601 if (target_seq_level_idx < SEQ_LEVELS) {
602 const AV1LevelSpec *const target_level_spec =
603 av1_level_defs + target_seq_level_idx;
604 const int tier = seq_params->tier[i];
605 const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
606 target_level_spec, level_spec, level_stats, tier, is_still_picture);
607 if (fail_id != TARGET_LEVEL_OK) {
608 const int target_level_major = 2 + (target_seq_level_idx >> 2);
609 const int target_level_minor = target_seq_level_idx & 3;
610 aom_internal_error(&cm->error, AOM_CODEC_ERROR,
611 "Failed to encode to the target level %d_%d. %s",
612 target_level_major, target_level_minor,
613 level_fail_messages[fail_id]);
614 }
615 }
616 }
617 }
618
av1_get_seq_level_idx(const AV1_COMP * cpi,int * seq_level_idx)619 aom_codec_err_t av1_get_seq_level_idx(const AV1_COMP *cpi, int *seq_level_idx) {
620 const SequenceHeader *const seq_params = &cpi->common.seq_params;
621 if (!cpi->keep_level_stats) {
622 for (int op = 0; op < seq_params->operating_points_cnt_minus_1 + 1; ++op) {
623 seq_level_idx[op] = (int)SEQ_LEVEL_MAX;
624 }
625 return AOM_CODEC_OK;
626 }
627
628 const int is_still_picture = seq_params->still_picture;
629 for (int op = 0; op < seq_params->operating_points_cnt_minus_1 + 1; ++op) {
630 seq_level_idx[op] = (int)SEQ_LEVEL_MAX;
631 const int tier = seq_params->tier[op];
632 const AV1LevelInfo *const level_info = &cpi->level_info[op];
633 const AV1LevelStats *const level_stats = &level_info->level_stats;
634 const AV1LevelSpec *const level_spec = &level_info->level_spec;
635 for (int level = 0; level < SEQ_LEVELS; ++level) {
636 const AV1LevelSpec *const target_level_spec = av1_level_defs + level;
637 const TARGET_LEVEL_FAIL_ID fail_id = check_level_constraints(
638 target_level_spec, level_spec, level_stats, tier, is_still_picture);
639 if (fail_id == TARGET_LEVEL_OK) {
640 seq_level_idx[op] = level;
641 break;
642 }
643 }
644 }
645
646 return AOM_CODEC_OK;
647 }
648