• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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