• 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 <stdint.h>
13 
14 #include "config/aom_config.h"
15 #include "config/aom_scale_rtcd.h"
16 
17 #include "aom/aom_codec.h"
18 #include "aom/aom_encoder.h"
19 
20 #include "aom_ports/system_state.h"
21 
22 #include "av1/common/onyxc_int.h"
23 
24 #include "av1/encoder/encoder.h"
25 #include "av1/encoder/firstpass.h"
26 #include "av1/encoder/gop_structure.h"
27 
28 // Set parameters for frames between 'start' and 'end' (excluding both).
set_multi_layer_params(GF_GROUP * const gf_group,int start,int end,int * frame_ind,int arf_ind,int level)29 static void set_multi_layer_params(GF_GROUP *const gf_group, int start, int end,
30                                    int *frame_ind, int arf_ind, int level) {
31   assert(level >= MIN_PYRAMID_LVL);
32   const int num_frames_to_process = end - start - 1;
33   assert(num_frames_to_process >= 0);
34   if (num_frames_to_process == 0) return;
35 
36   // Either we are at the last level of the pyramid, or we don't have enough
37   // frames between 'l' and 'r' to create one more level.
38   if (level == MIN_PYRAMID_LVL || num_frames_to_process < 3) {
39     // Leaf nodes.
40     while (++start < end) {
41       gf_group->update_type[*frame_ind] = LF_UPDATE;
42       gf_group->arf_src_offset[*frame_ind] = 0;
43       gf_group->arf_pos_in_gf[*frame_ind] = 0;
44       gf_group->arf_update_idx[*frame_ind] = arf_ind;
45       gf_group->pyramid_level[*frame_ind] = MIN_PYRAMID_LVL;
46       ++gf_group->pyramid_lvl_nodes[MIN_PYRAMID_LVL];
47       ++(*frame_ind);
48     }
49   } else {
50     const int m = (start + end) / 2;
51     const int arf_pos_in_gf = *frame_ind;
52 
53     // Internal ARF.
54     gf_group->update_type[*frame_ind] = INTNL_ARF_UPDATE;
55     gf_group->arf_src_offset[*frame_ind] = m - start - 1;
56     gf_group->arf_pos_in_gf[*frame_ind] = 0;
57     gf_group->arf_update_idx[*frame_ind] = 1;  // mark all internal ARF 1
58     gf_group->pyramid_level[*frame_ind] = level;
59     ++gf_group->pyramid_lvl_nodes[level];
60     ++(*frame_ind);
61 
62     // Frames displayed before this internal ARF.
63     set_multi_layer_params(gf_group, start, m, frame_ind, 1, level - 1);
64 
65     // Overlay for internal ARF.
66     gf_group->update_type[*frame_ind] = INTNL_OVERLAY_UPDATE;
67     gf_group->arf_src_offset[*frame_ind] = 0;
68     gf_group->arf_pos_in_gf[*frame_ind] = arf_pos_in_gf;  // For bit allocation.
69     gf_group->arf_update_idx[*frame_ind] = 1;
70     gf_group->pyramid_level[*frame_ind] = MIN_PYRAMID_LVL;
71     ++(*frame_ind);
72 
73     // Frames displayed after this internal ARF.
74     set_multi_layer_params(gf_group, m, end, frame_ind, arf_ind, level - 1);
75   }
76 }
77 
construct_multi_layer_gf_structure(GF_GROUP * const gf_group,int gf_interval,int pyr_height,FRAME_UPDATE_TYPE first_frame_update_type)78 static int construct_multi_layer_gf_structure(
79     GF_GROUP *const gf_group, int gf_interval, int pyr_height,
80     FRAME_UPDATE_TYPE first_frame_update_type) {
81   gf_group->pyramid_height = pyr_height;
82   av1_zero_array(gf_group->pyramid_lvl_nodes, MAX_PYRAMID_LVL);
83   int frame_index = 0;
84 
85   // Keyframe / Overlay frame / Golden frame.
86   assert(gf_interval >= 1);
87   assert(first_frame_update_type == KF_UPDATE ||
88          first_frame_update_type == OVERLAY_UPDATE ||
89          first_frame_update_type == GF_UPDATE);
90   gf_group->update_type[frame_index] = first_frame_update_type;
91   gf_group->arf_src_offset[frame_index] = 0;
92   gf_group->arf_pos_in_gf[frame_index] = 0;
93   gf_group->arf_update_idx[frame_index] = 0;
94   gf_group->pyramid_level[frame_index] = MIN_PYRAMID_LVL;
95   ++frame_index;
96 
97   // ALTREF.
98   const int use_altref = (gf_group->pyramid_height > 0);
99   if (use_altref) {
100     gf_group->update_type[frame_index] = ARF_UPDATE;
101     gf_group->arf_src_offset[frame_index] = gf_interval - 1;
102     gf_group->arf_pos_in_gf[frame_index] = 0;
103     gf_group->arf_update_idx[frame_index] = 0;
104     gf_group->pyramid_level[frame_index] = gf_group->pyramid_height;
105     ++frame_index;
106   }
107 
108   // Rest of the frames.
109   const int next_height =
110       use_altref ? gf_group->pyramid_height - 1 : gf_group->pyramid_height;
111   assert(next_height >= MIN_PYRAMID_LVL);
112   set_multi_layer_params(gf_group, 0, gf_interval, &frame_index, 0,
113                          next_height);
114   return frame_index;
115 }
116 
117 #define CHECK_GF_PARAMETER 0
118 #if CHECK_GF_PARAMETER
check_frame_params(GF_GROUP * const gf_group,int gf_interval)119 void check_frame_params(GF_GROUP *const gf_group, int gf_interval) {
120   static const char *update_type_strings[FRAME_UPDATE_TYPES] = {
121     "KF_UPDATE",       "LF_UPDATE",      "GF_UPDATE",
122     "ARF_UPDATE",      "OVERLAY_UPDATE", "INTNL_OVERLAY_UPDATE",
123     "INTNL_ARF_UPDATE"
124   };
125   FILE *fid = fopen("GF_PARAMS.txt", "a");
126 
127   fprintf(fid, "\ngf_interval = {%d}\n", gf_interval);
128   for (int i = 0; i <= gf_group->size; ++i) {
129     fprintf(fid, "#%2d : %s %d %d %d %d\n", i,
130             update_type_strings[gf_group->update_type[i]],
131             gf_group->arf_src_offset[i], gf_group->arf_pos_in_gf[i],
132             gf_group->arf_update_idx[i], gf_group->pyramid_level[i]);
133   }
134 
135   fprintf(fid, "number of nodes in each level: \n");
136   for (int i = 0; i < gf_group->pyramid_height; ++i) {
137     fprintf(fid, "lvl %d: %d ", i, gf_group->pyramid_lvl_nodes[i]);
138   }
139   fprintf(fid, "\n");
140   fclose(fid);
141 }
142 #endif  // CHECK_GF_PARAMETER
143 
max_pyramid_height_from_width(int pyramid_width)144 static INLINE int max_pyramid_height_from_width(int pyramid_width) {
145   if (pyramid_width > 12) return 4;
146   if (pyramid_width > 6) return 3;
147   if (pyramid_width > 3) return 2;
148   if (pyramid_width > 1) return 1;
149   return 0;
150 }
151 
get_pyramid_height(const AV1_COMP * const cpi)152 static int get_pyramid_height(const AV1_COMP *const cpi) {
153   const RATE_CONTROL *const rc = &cpi->rc;
154   assert(IMPLIES(cpi->oxcf.gf_max_pyr_height == MIN_PYRAMID_LVL,
155                  !rc->source_alt_ref_pending));  // define_gf_group() enforced.
156   if (!rc->source_alt_ref_pending) {
157     return MIN_PYRAMID_LVL;
158   }
159   assert(cpi->oxcf.gf_max_pyr_height > MIN_PYRAMID_LVL);
160   if (!cpi->internal_altref_allowed) {
161     assert(MIN_PYRAMID_LVL + 1 <= cpi->oxcf.gf_max_pyr_height);
162     return MIN_PYRAMID_LVL + 1;
163   }
164   return AOMMIN(max_pyramid_height_from_width(rc->baseline_gf_interval),
165                 cpi->oxcf.gf_max_pyr_height);
166 }
167 
av1_gop_setup_structure(AV1_COMP * cpi,const EncodeFrameParams * const frame_params)168 void av1_gop_setup_structure(AV1_COMP *cpi,
169                              const EncodeFrameParams *const frame_params) {
170   RATE_CONTROL *const rc = &cpi->rc;
171   TWO_PASS *const twopass = &cpi->twopass;
172   GF_GROUP *const gf_group = &twopass->gf_group;
173   const int key_frame = (frame_params->frame_type == KEY_FRAME);
174   const FRAME_UPDATE_TYPE first_frame_update_type =
175       key_frame ? KF_UPDATE
176                 : rc->source_alt_ref_active ? OVERLAY_UPDATE : GF_UPDATE;
177   gf_group->size = construct_multi_layer_gf_structure(
178       gf_group, rc->baseline_gf_interval, get_pyramid_height(cpi),
179       first_frame_update_type);
180 
181   // We need to configure the frame at the end of the sequence + 1 that
182   // will be the start frame for the next group. Otherwise prior to the
183   // call to av1_get_second_pass_params(), the data will be undefined.
184   gf_group->update_type[gf_group->size] =
185       (rc->source_alt_ref_pending) ? OVERLAY_UPDATE : GF_UPDATE;
186   gf_group->arf_update_idx[gf_group->size] = 0;
187   gf_group->arf_pos_in_gf[gf_group->size] = 0;
188 
189 #if CHECK_GF_PARAMETER
190   check_frame_params(gf_group, rc->baseline_gf_interval);
191 #endif
192 }
193