Line data Source code
1 : /*
2 : * Copyright(c) 2019 Intel Corporation
3 : * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 : */
5 :
6 : #include <stdlib.h>
7 :
8 : #include "EbDefinitions.h"
9 : #include "EbSystemResourceManager.h"
10 : #include "EbPictureControlSet.h"
11 : #include "EbSequenceControlSet.h"
12 :
13 : #include "EbMotionEstimationResults.h"
14 : #include "EbInitialRateControlProcess.h"
15 : #include "EbInitialRateControlResults.h"
16 : #include "EbMotionEstimationContext.h"
17 : #include "EbUtility.h"
18 : #include "EbReferenceObject.h"
19 :
20 : /**************************************
21 : * Macros
22 : **************************************/
23 : #define PAN_LCU_PERCENTAGE 75
24 : #define LOW_AMPLITUDE_TH 16
25 :
26 3740 : void GetMv(
27 : PictureParentControlSet *picture_control_set_ptr,
28 : uint32_t sb_index,
29 : int32_t *xCurrentMv,
30 : int32_t *yCurrentMv)
31 : {
32 : uint32_t meCandidateIndex;
33 :
34 3740 : const MeLcuResults *me_results = picture_control_set_ptr->me_results[sb_index];
35 3740 : uint8_t total_me_cnt = me_results->total_me_candidate_index[0];
36 3740 : const MeCandidate *me_block_results = me_results->me_candidate[0];
37 20287 : for (meCandidateIndex = 0; meCandidateIndex < total_me_cnt; meCandidateIndex++) {
38 18176 : if (me_block_results->direction == UNI_PRED_LIST_0) {
39 1629 : *xCurrentMv = me_results->me_mv_array[0][0].x_mv;
40 1629 : *yCurrentMv = me_results->me_mv_array[0][0].y_mv;
41 1629 : break;
42 : }
43 : }
44 3740 : }
45 :
46 2420 : void GetMeDist(
47 : PictureParentControlSet *picture_control_set_ptr,
48 : uint32_t sb_index,
49 : uint32_t *distortion)
50 : {
51 2420 : *distortion = (uint32_t)picture_control_set_ptr->me_results[sb_index]->me_candidate[0][0].distortion;
52 2420 : }
53 :
54 0 : EbBool CheckMvForPanHighAmp(
55 : uint32_t hierarchical_levels,
56 : uint32_t temporal_layer_index,
57 : int32_t *xCurrentMv,
58 : int32_t *xCandidateMv)
59 : {
60 0 : if (*xCurrentMv * *xCandidateMv > 0 // both negative or both positives and both different than 0 i.e. same direction and non Stationary)
61 0 : && ABS(*xCurrentMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
62 0 : && ABS(*xCandidateMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
63 0 : && ABS(*xCurrentMv - *xCandidateMv) < LOW_AMPLITUDE_TH) { // close amplitude
64 :
65 0 : return(EB_TRUE);
66 : }
67 :
68 : else
69 0 : return(EB_FALSE);
70 : }
71 :
72 0 : EbBool CheckMvForTiltHighAmp(
73 : uint32_t hierarchical_levels,
74 : uint32_t temporal_layer_index,
75 : int32_t *yCurrentMv,
76 : int32_t *yCandidateMv)
77 : {
78 0 : if (*yCurrentMv * *yCandidateMv > 0 // both negative or both positives and both different than 0 i.e. same direction and non Stationary)
79 0 : && ABS(*yCurrentMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
80 0 : && ABS(*yCandidateMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
81 0 : && ABS(*yCurrentMv - *yCandidateMv) < LOW_AMPLITUDE_TH) { // close amplitude
82 :
83 0 : return(EB_TRUE);
84 : }
85 :
86 : else
87 0 : return(EB_FALSE);
88 : }
89 :
90 0 : EbBool CheckMvForPan(
91 : uint32_t hierarchical_levels,
92 : uint32_t temporal_layer_index,
93 : int32_t *xCurrentMv,
94 : int32_t *yCurrentMv,
95 : int32_t *xCandidateMv,
96 : int32_t *yCandidateMv)
97 : {
98 0 : if (*yCurrentMv < LOW_AMPLITUDE_TH
99 0 : && *yCandidateMv < LOW_AMPLITUDE_TH
100 0 : && *xCurrentMv * *xCandidateMv > 0 // both negative or both positives and both different than 0 i.e. same direction and non Stationary)
101 0 : && ABS(*xCurrentMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
102 0 : && ABS(*xCandidateMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
103 0 : && ABS(*xCurrentMv - *xCandidateMv) < LOW_AMPLITUDE_TH) { // close amplitude
104 :
105 0 : return(EB_TRUE);
106 : }
107 :
108 : else
109 0 : return(EB_FALSE);
110 : }
111 :
112 0 : EbBool CheckMvForTilt(
113 : uint32_t hierarchical_levels,
114 : uint32_t temporal_layer_index,
115 : int32_t *xCurrentMv,
116 : int32_t *yCurrentMv,
117 : int32_t *xCandidateMv,
118 : int32_t *yCandidateMv)
119 : {
120 0 : if (*xCurrentMv < LOW_AMPLITUDE_TH
121 0 : && *xCandidateMv < LOW_AMPLITUDE_TH
122 0 : && *yCurrentMv * *yCandidateMv > 0 // both negative or both positives and both different than 0 i.e. same direction and non Stationary)
123 0 : && ABS(*yCurrentMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
124 0 : && ABS(*yCandidateMv) >= global_motion_threshold[hierarchical_levels][temporal_layer_index] // high amplitude
125 0 : && ABS(*yCurrentMv - *yCandidateMv) < LOW_AMPLITUDE_TH) { // close amplitude
126 :
127 0 : return(EB_TRUE);
128 : }
129 :
130 : else
131 0 : return(EB_FALSE);
132 : }
133 :
134 1200 : EbBool CheckMvForNonUniformMotion(
135 : int32_t *xCurrentMv,
136 : int32_t *yCurrentMv,
137 : int32_t *xCandidateMv,
138 : int32_t *yCandidateMv)
139 : {
140 1200 : int32_t mvThreshold = 40;//LOW_AMPLITUDE_TH + 18;
141 : // Either the x or the y direction is greater than threshold
142 1200 : if ((ABS(*xCurrentMv - *xCandidateMv) > mvThreshold) || (ABS(*yCurrentMv - *yCandidateMv) > mvThreshold))
143 512 : return(EB_TRUE);
144 : else
145 688 : return(EB_FALSE);
146 : }
147 :
148 6 : void CheckForNonUniformMotionVectorField(
149 : PictureParentControlSet *picture_control_set_ptr)
150 : {
151 : uint32_t sb_count;
152 6 : uint32_t picture_width_in_sb = (picture_control_set_ptr->enhanced_picture_ptr->width + BLOCK_SIZE_64 - 1) / BLOCK_SIZE_64;
153 : uint32_t sb_origin_x;
154 : uint32_t sb_origin_y;
155 :
156 6 : int32_t xCurrentMv = 0;
157 6 : int32_t yCurrentMv = 0;
158 6 : int32_t xLeftMv = 0;
159 6 : int32_t yLeftMv = 0;
160 6 : int32_t xTopMv = 0;
161 6 : int32_t yTopMv = 0;
162 6 : int32_t xRightMv = 0;
163 6 : int32_t yRightMv = 0;
164 6 : int32_t xBottomMv = 0;
165 6 : int32_t yBottomMv = 0;
166 6 : uint32_t countOfNonUniformNeighbors = 0;
167 :
168 366 : for (sb_count = 0; sb_count < picture_control_set_ptr->sb_total_count; ++sb_count) {
169 360 : countOfNonUniformNeighbors = 0;
170 :
171 360 : sb_origin_x = (sb_count % picture_width_in_sb) * BLOCK_SIZE_64;
172 360 : sb_origin_y = (sb_count / picture_width_in_sb) * BLOCK_SIZE_64;
173 :
174 360 : if (((sb_origin_x + BLOCK_SIZE_64) <= picture_control_set_ptr->enhanced_picture_ptr->width) &&
175 360 : ((sb_origin_y + BLOCK_SIZE_64) <= picture_control_set_ptr->enhanced_picture_ptr->height)) {
176 : // Current MV
177 300 : GetMv(picture_control_set_ptr, sb_count, &xCurrentMv, &yCurrentMv);
178 :
179 : // Left MV
180 300 : if (sb_origin_x == 0) {
181 30 : xLeftMv = 0;
182 30 : yLeftMv = 0;
183 : }
184 : else
185 270 : GetMv(picture_control_set_ptr, sb_count - 1, &xLeftMv, &yLeftMv);
186 300 : countOfNonUniformNeighbors += CheckMvForNonUniformMotion(&xCurrentMv, &yCurrentMv, &xLeftMv, &yLeftMv);
187 :
188 : // Top MV
189 300 : if (sb_origin_y == 0) {
190 60 : xTopMv = 0;
191 60 : yTopMv = 0;
192 : }
193 : else
194 240 : GetMv(picture_control_set_ptr, sb_count - picture_width_in_sb, &xTopMv, &yTopMv);
195 300 : countOfNonUniformNeighbors += CheckMvForNonUniformMotion(&xCurrentMv, &yCurrentMv, &xTopMv, &yTopMv);
196 :
197 : // Right MV
198 300 : if ((sb_origin_x + (BLOCK_SIZE_64 << 1)) > picture_control_set_ptr->enhanced_picture_ptr->width) {
199 30 : xRightMv = 0;
200 30 : yRightMv = 0;
201 : }
202 : else
203 270 : GetMv(picture_control_set_ptr, sb_count + 1, &xRightMv, &yRightMv);
204 300 : countOfNonUniformNeighbors += CheckMvForNonUniformMotion(&xCurrentMv, &yCurrentMv, &xRightMv, &yRightMv);
205 :
206 : // Bottom MV
207 300 : if ((sb_origin_y + (BLOCK_SIZE_64 << 1)) > picture_control_set_ptr->enhanced_picture_ptr->height) {
208 60 : xBottomMv = 0;
209 60 : yBottomMv = 0;
210 : }
211 : else
212 240 : GetMv(picture_control_set_ptr, sb_count + picture_width_in_sb, &xBottomMv, &yBottomMv);
213 300 : countOfNonUniformNeighbors += CheckMvForNonUniformMotion(&xCurrentMv, &yCurrentMv, &xBottomMv, &yBottomMv);
214 : }
215 : }
216 6 : }
217 :
218 :
219 118 : void DetectGlobalMotion(
220 : PictureParentControlSet *picture_control_set_ptr)
221 : {
222 : #if GLOBAL_WARPED_MOTION
223 118 : uint32_t numOfListToSearch = (picture_control_set_ptr->slice_type == P_SLICE)
224 118 : ? (uint32_t)REF_LIST_0 : (uint32_t)REF_LIST_1;
225 :
226 346 : for (uint32_t listIndex = REF_LIST_0; listIndex <= numOfListToSearch; ++listIndex) {
227 :
228 : uint32_t num_of_ref_pic_to_search;
229 228 : if (picture_control_set_ptr->is_alt_ref == EB_TRUE)
230 0 : num_of_ref_pic_to_search = 1;
231 : else
232 228 : num_of_ref_pic_to_search = picture_control_set_ptr->slice_type == P_SLICE
233 8 : ? picture_control_set_ptr->ref_list0_count
234 448 : : listIndex == REF_LIST_0
235 110 : ? picture_control_set_ptr->ref_list0_count
236 110 : : picture_control_set_ptr->ref_list1_count;
237 :
238 : // Ref Picture Loop
239 628 : for (uint32_t ref_pic_index = 0; ref_pic_index < num_of_ref_pic_to_search;
240 400 : ++ref_pic_index)
241 : {
242 400 : picture_control_set_ptr->is_global_motion[listIndex][ref_pic_index] = EB_FALSE;
243 400 : if (picture_control_set_ptr->global_motion_estimation[listIndex][ref_pic_index].wmtype > TRANSLATION)
244 114 : picture_control_set_ptr->is_global_motion[listIndex][ref_pic_index] = EB_TRUE;
245 : }
246 : }
247 : #else
248 : uint32_t sb_count;
249 : uint32_t picture_width_in_sb = (picture_control_set_ptr->enhanced_picture_ptr->width + BLOCK_SIZE_64 - 1) / BLOCK_SIZE_64;
250 : uint32_t sb_origin_x;
251 : uint32_t sb_origin_y;
252 :
253 : uint32_t totalCheckedLcus = 0;
254 : uint32_t totalPanLcus = 0;
255 :
256 : int32_t xCurrentMv = 0;
257 : int32_t yCurrentMv = 0;
258 : int32_t xLeftMv = 0;
259 : int32_t yLeftMv = 0;
260 : int32_t xTopMv = 0;
261 : int32_t yTopMv = 0;
262 : int32_t xRightMv = 0;
263 : int32_t yRightMv = 0;
264 : int32_t xBottomMv = 0;
265 : int32_t yBottomMv = 0;
266 : int64_t xTiltMvSum = 0;
267 : int64_t yTiltMvSum = 0;
268 : int64_t xPanMvSum = 0;
269 : int64_t yPanMvSum = 0;
270 : uint32_t totalTiltLcus = 0;
271 :
272 : uint32_t totalTiltHighAmpLcus = 0;
273 : uint32_t totalPanHighAmpLcus = 0;
274 :
275 : for (sb_count = 0; sb_count < picture_control_set_ptr->sb_total_count; ++sb_count) {
276 : sb_origin_x = (sb_count % picture_width_in_sb) * BLOCK_SIZE_64;
277 : sb_origin_y = (sb_count / picture_width_in_sb) * BLOCK_SIZE_64;
278 : if (((sb_origin_x + BLOCK_SIZE_64) <= picture_control_set_ptr->enhanced_picture_ptr->width) &&
279 : ((sb_origin_y + BLOCK_SIZE_64) <= picture_control_set_ptr->enhanced_picture_ptr->height)) {
280 : // Current MV
281 : GetMv(picture_control_set_ptr, sb_count, &xCurrentMv, &yCurrentMv);
282 :
283 : // Left MV
284 : if (sb_origin_x == 0) {
285 : xLeftMv = 0;
286 : yLeftMv = 0;
287 : }
288 : else
289 : GetMv(picture_control_set_ptr, sb_count - 1, &xLeftMv, &yLeftMv);
290 : // Top MV
291 : if (sb_origin_y == 0) {
292 : xTopMv = 0;
293 : yTopMv = 0;
294 : }
295 : else
296 : GetMv(picture_control_set_ptr, sb_count - picture_width_in_sb, &xTopMv, &yTopMv);
297 : // Right MV
298 : if ((sb_origin_x + (BLOCK_SIZE_64 << 1)) > picture_control_set_ptr->enhanced_picture_ptr->width) {
299 : xRightMv = 0;
300 : yRightMv = 0;
301 : }
302 : else
303 : GetMv(picture_control_set_ptr, sb_count + 1, &xRightMv, &yRightMv);
304 : // Bottom MV
305 : if ((sb_origin_y + (BLOCK_SIZE_64 << 1)) > picture_control_set_ptr->enhanced_picture_ptr->height) {
306 : xBottomMv = 0;
307 : yBottomMv = 0;
308 : }
309 : else
310 : GetMv(picture_control_set_ptr, sb_count + picture_width_in_sb, &xBottomMv, &yBottomMv);
311 : totalCheckedLcus++;
312 :
313 : if ((EbBool)(CheckMvForPan(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xLeftMv, &yLeftMv) ||
314 : CheckMvForPan(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xTopMv, &yTopMv) ||
315 : CheckMvForPan(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xRightMv, &yRightMv) ||
316 : CheckMvForPan(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xBottomMv, &yBottomMv))) {
317 : totalPanLcus++;
318 :
319 : xPanMvSum += xCurrentMv;
320 : yPanMvSum += yCurrentMv;
321 : }
322 :
323 : if ((EbBool)(CheckMvForTilt(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xLeftMv, &yLeftMv) ||
324 : CheckMvForTilt(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xTopMv, &yTopMv) ||
325 : CheckMvForTilt(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xRightMv, &yRightMv) ||
326 : CheckMvForTilt(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &yCurrentMv, &xBottomMv, &yBottomMv))) {
327 : totalTiltLcus++;
328 :
329 : xTiltMvSum += xCurrentMv;
330 : yTiltMvSum += yCurrentMv;
331 : }
332 :
333 : if ((EbBool)(CheckMvForPanHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &xLeftMv) ||
334 : CheckMvForPanHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &xTopMv) ||
335 : CheckMvForPanHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &xRightMv) ||
336 : CheckMvForPanHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &xCurrentMv, &xBottomMv))) {
337 : totalPanHighAmpLcus++;
338 : }
339 :
340 : if ((EbBool)(CheckMvForTiltHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &yCurrentMv, &yLeftMv) ||
341 : CheckMvForTiltHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &yCurrentMv, &yTopMv) ||
342 : CheckMvForTiltHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &yCurrentMv, &yRightMv) ||
343 : CheckMvForTiltHighAmp(picture_control_set_ptr->hierarchical_levels, picture_control_set_ptr->temporal_layer_index, &yCurrentMv, &yBottomMv))) {
344 : totalTiltHighAmpLcus++;
345 : }
346 : }
347 : }
348 : picture_control_set_ptr->is_pan = EB_FALSE;
349 : picture_control_set_ptr->is_tilt = EB_FALSE;
350 :
351 : picture_control_set_ptr->panMvx = 0;
352 : picture_control_set_ptr->panMvy = 0;
353 : picture_control_set_ptr->tiltMvx = 0;
354 : picture_control_set_ptr->tiltMvy = 0;
355 :
356 : // If more than PAN_LCU_PERCENTAGE % of LCUs are PAN
357 : if ((totalCheckedLcus > 0) && ((totalPanLcus * 100 / totalCheckedLcus) > PAN_LCU_PERCENTAGE)) {
358 : picture_control_set_ptr->is_pan = EB_TRUE;
359 : if (totalPanLcus > 0) {
360 : picture_control_set_ptr->panMvx = (int16_t)(xPanMvSum / totalPanLcus);
361 : picture_control_set_ptr->panMvy = (int16_t)(yPanMvSum / totalPanLcus);
362 : }
363 : }
364 :
365 : if ((totalCheckedLcus > 0) && ((totalTiltLcus * 100 / totalCheckedLcus) > PAN_LCU_PERCENTAGE)) {
366 : picture_control_set_ptr->is_tilt = EB_TRUE;
367 : if (totalTiltLcus > 0) {
368 : picture_control_set_ptr->tiltMvx = (int16_t)(xTiltMvSum / totalTiltLcus);
369 : picture_control_set_ptr->tiltMvy = (int16_t)(yTiltMvSum / totalTiltLcus);
370 : }
371 : }
372 : #endif
373 118 : }
374 :
375 : /************************************************
376 : * Initial Rate Control Context Constructor
377 : ************************************************/
378 2 : EbErrorType initial_rate_control_context_ctor(
379 : InitialRateControlContext *context_ptr,
380 : EbFifo *motion_estimation_results_input_fifo_ptr,
381 : EbFifo *initialrate_control_results_output_fifo_ptr)
382 : {
383 2 : context_ptr->motion_estimation_results_input_fifo_ptr = motion_estimation_results_input_fifo_ptr;
384 2 : context_ptr->initialrate_control_results_output_fifo_ptr = initialrate_control_results_output_fifo_ptr;
385 :
386 2 : return EB_ErrorNone;
387 : }
388 :
389 : /************************************************
390 : * Release Pa Reference Objects
391 : ** Check if reference pictures are needed
392 : ** release them when appropriate
393 : ************************************************/
394 120 : void ReleasePaReferenceObjects(
395 : SequenceControlSet *sequence_control_set_ptr,
396 : PictureParentControlSet *picture_control_set_ptr)
397 : {
398 : // PA Reference Pictures
399 : uint32_t numOfListToSearch;
400 : uint32_t listIndex;
401 : uint32_t ref_pic_index;
402 120 : if (picture_control_set_ptr->slice_type != I_SLICE) {
403 116 : numOfListToSearch = (picture_control_set_ptr->slice_type == P_SLICE) ? REF_LIST_0 : REF_LIST_1;
404 :
405 : // List Loop
406 342 : for (listIndex = REF_LIST_0; listIndex <= numOfListToSearch; ++listIndex) {
407 : // Release PA Reference Pictures
408 446 : uint8_t num_of_ref_pic_to_search = (picture_control_set_ptr->slice_type == P_SLICE) ?
409 6 : MIN(picture_control_set_ptr->ref_list0_count, sequence_control_set_ptr->reference_count) :
410 : (listIndex == REF_LIST_0) ?
411 110 : MIN(picture_control_set_ptr->ref_list0_count, sequence_control_set_ptr->reference_count) :
412 110 : MIN(picture_control_set_ptr->ref_list1_count, sequence_control_set_ptr->reference_count);
413 :
414 621 : for (ref_pic_index = 0; ref_pic_index < num_of_ref_pic_to_search; ++ref_pic_index) {
415 395 : if (picture_control_set_ptr->ref_pa_pic_ptr_array[listIndex][ref_pic_index] != EB_NULL) {
416 395 : eb_release_object(picture_control_set_ptr->ref_pa_pic_ptr_array[listIndex][ref_pic_index]);
417 : }
418 : }
419 : }
420 : }
421 :
422 120 : if (picture_control_set_ptr->pa_reference_picture_wrapper_ptr != EB_NULL) {
423 120 : eb_release_object(picture_control_set_ptr->pa_reference_picture_wrapper_ptr);
424 : }
425 :
426 120 : return;
427 : }
428 :
429 : /************************************************
430 : * Global Motion Detection Based on ME information
431 : ** Mark pictures for pan
432 : ** Mark pictures for tilt
433 : ** No lookahead information used in this function
434 : ************************************************/
435 120 : void MeBasedGlobalMotionDetection(
436 : PictureParentControlSet *picture_control_set_ptr)
437 : {
438 : // PAN Generation
439 120 : picture_control_set_ptr->is_pan = EB_FALSE;
440 120 : picture_control_set_ptr->is_tilt = EB_FALSE;
441 :
442 120 : if (picture_control_set_ptr->slice_type != I_SLICE)
443 116 : DetectGlobalMotion(picture_control_set_ptr);
444 : // Check if the motion vector field for temporal layer 0 pictures
445 120 : if (picture_control_set_ptr->slice_type != I_SLICE && picture_control_set_ptr->temporal_layer_index == 0)
446 6 : CheckForNonUniformMotionVectorField(picture_control_set_ptr);
447 120 : return;
448 : }
449 :
450 688 : void StationaryEdgeCountLcu(
451 : SequenceControlSet *sequence_control_set_ptr,
452 : PictureParentControlSet *picture_control_set_ptr,
453 : PictureParentControlSet *temporalPictureControlSetPtr,
454 : uint32_t totalLcuCount)
455 : {
456 : uint32_t sb_index;
457 41968 : for (sb_index = 0; sb_index < totalLcuCount; sb_index++) {
458 41280 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
459 41280 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
460 41280 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb && sb_stat_ptr->check1_for_logo_stationary_edge_over_time_flag && sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag) {
461 8597 : SbStat *tempLcuStatPtr = &temporalPictureControlSetPtr->sb_stat_array[sb_index];
462 : uint32_t rasterScanCuIndex;
463 :
464 8597 : if (tempLcuStatPtr->check1_for_logo_stationary_edge_over_time_flag)
465 : {
466 77299 : for (rasterScanCuIndex = RASTER_SCAN_CU_INDEX_16x16_0; rasterScanCuIndex <= RASTER_SCAN_CU_INDEX_16x16_15; rasterScanCuIndex++)
467 72752 : sb_stat_ptr->cu_stat_array[rasterScanCuIndex].similar_edge_count += tempLcuStatPtr->cu_stat_array[rasterScanCuIndex].edge_cu;
468 : }
469 : }
470 :
471 41280 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb && sb_stat_ptr->pm_check1_for_logo_stationary_edge_over_time_flag && sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag) {
472 11882 : SbStat *tempLcuStatPtr = &temporalPictureControlSetPtr->sb_stat_array[sb_index];
473 : uint32_t rasterScanCuIndex;
474 :
475 11882 : if (tempLcuStatPtr->pm_check1_for_logo_stationary_edge_over_time_flag)
476 : {
477 190536 : for (rasterScanCuIndex = RASTER_SCAN_CU_INDEX_16x16_0; rasterScanCuIndex <= RASTER_SCAN_CU_INDEX_16x16_15; rasterScanCuIndex++)
478 179328 : sb_stat_ptr->cu_stat_array[rasterScanCuIndex].pm_similar_edge_count += tempLcuStatPtr->cu_stat_array[rasterScanCuIndex].edge_cu;
479 : }
480 : }
481 : }
482 688 : }
483 :
484 120 : void StationaryEdgeOverUpdateOverTimeLcuPart1(
485 : SequenceControlSet *sequence_control_set_ptr,
486 : PictureParentControlSet *picture_control_set_ptr)
487 : {
488 : uint32_t sb_index;
489 120 : int32_t xCurrentMv = 0;
490 120 : int32_t yCurrentMv = 0;
491 :
492 7320 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; sb_index++) {
493 7200 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
494 7200 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
495 :
496 9840 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb) {
497 : // Current MV
498 2640 : if (picture_control_set_ptr->temporal_layer_index > 0)
499 2420 : GetMv(picture_control_set_ptr, sb_index, &xCurrentMv, &yCurrentMv);
500 :
501 2640 : EbBool lowMotion = picture_control_set_ptr->temporal_layer_index == 0 ? EB_TRUE : (ABS(xCurrentMv) < 16) && (ABS(yCurrentMv) < 16) ? EB_TRUE : EB_FALSE;
502 2640 : uint16_t *yVariancePtr = picture_control_set_ptr->variance[sb_index];
503 2640 : uint64_t var0 = yVariancePtr[ME_TIER_ZERO_PU_32x32_0];
504 2640 : uint64_t var1 = yVariancePtr[ME_TIER_ZERO_PU_32x32_1];
505 2640 : uint64_t var2 = yVariancePtr[ME_TIER_ZERO_PU_32x32_2];
506 2640 : uint64_t var3 = yVariancePtr[ME_TIER_ZERO_PU_32x32_3];
507 :
508 2640 : uint64_t averageVar = (var0 + var1 + var2 + var3) >> 2;
509 2640 : uint64_t varOfVar = (((int32_t)(var0 - averageVar) * (int32_t)(var0 - averageVar)) +
510 2640 : ((int32_t)(var1 - averageVar) * (int32_t)(var1 - averageVar)) +
511 2640 : ((int32_t)(var2 - averageVar) * (int32_t)(var2 - averageVar)) +
512 2640 : ((int32_t)(var3 - averageVar) * (int32_t)(var3 - averageVar))) >> 2;
513 :
514 2640 : if ((varOfVar <= 50000) || !lowMotion)
515 1214 : sb_stat_ptr->check1_for_logo_stationary_edge_over_time_flag = 0;
516 : else
517 1426 : sb_stat_ptr->check1_for_logo_stationary_edge_over_time_flag = 1;
518 2640 : if ((varOfVar <= 1000))
519 594 : sb_stat_ptr->pm_check1_for_logo_stationary_edge_over_time_flag = 0;
520 : else
521 2046 : sb_stat_ptr->pm_check1_for_logo_stationary_edge_over_time_flag = 1;
522 : }
523 : else {
524 4560 : sb_stat_ptr->check1_for_logo_stationary_edge_over_time_flag = 0;
525 :
526 4560 : sb_stat_ptr->pm_check1_for_logo_stationary_edge_over_time_flag = 0;
527 : }
528 : }
529 120 : }
530 118 : void StationaryEdgeOverUpdateOverTimeLcuPart2(
531 : SequenceControlSet *sequence_control_set_ptr,
532 : PictureParentControlSet *picture_control_set_ptr)
533 : {
534 : uint32_t sb_index;
535 :
536 118 : uint32_t lowSadTh = (sequence_control_set_ptr->input_resolution < INPUT_SIZE_1080p_RANGE) ? 5 : 2;
537 :
538 7198 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; sb_index++) {
539 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
540 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
541 :
542 9676 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb) {
543 2596 : uint32_t meDist = 0;
544 :
545 2596 : EbBool lowSad = EB_FALSE;
546 :
547 2596 : if (picture_control_set_ptr->slice_type == B_SLICE)
548 2420 : GetMeDist(picture_control_set_ptr, sb_index, &meDist);
549 5192 : lowSad = (picture_control_set_ptr->slice_type != B_SLICE) ?
550 :
551 2596 : EB_FALSE : (meDist < 64 * 64 * lowSadTh) ? EB_TRUE : EB_FALSE;
552 :
553 2596 : if (lowSad) {
554 2108 : sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag = 0;
555 2108 : sb_stat_ptr->low_dist_logo = 1;
556 : }
557 : else {
558 488 : sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag = 1;
559 :
560 488 : sb_stat_ptr->low_dist_logo = 0;
561 : }
562 : }
563 : else {
564 4484 : sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag = 0;
565 :
566 4484 : sb_stat_ptr->low_dist_logo = 0;
567 : }
568 7080 : sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag = 1;
569 : }
570 118 : }
571 :
572 118 : void StationaryEdgeOverUpdateOverTimeLcu(
573 : SequenceControlSet *sequence_control_set_ptr,
574 : uint32_t totalCheckedPictures,
575 : PictureParentControlSet *picture_control_set_ptr,
576 : uint32_t totalLcuCount)
577 : {
578 : uint32_t sb_index;
579 118 : const uint32_t slideWindowTh = ((totalCheckedPictures / 4) - 1);
580 :
581 7198 : for (sb_index = 0; sb_index < totalLcuCount; sb_index++) {
582 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
583 :
584 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
585 7080 : sb_stat_ptr->stationary_edge_over_time_flag = EB_FALSE;
586 7080 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb && sb_stat_ptr->check1_for_logo_stationary_edge_over_time_flag && sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag) {
587 : uint32_t rasterScanCuIndex;
588 1400 : uint32_t similarEdgeCountLcu = 0;
589 : // CU Loop
590 23800 : for (rasterScanCuIndex = RASTER_SCAN_CU_INDEX_16x16_0; rasterScanCuIndex <= RASTER_SCAN_CU_INDEX_16x16_15; rasterScanCuIndex++)
591 22400 : similarEdgeCountLcu += (sb_stat_ptr->cu_stat_array[rasterScanCuIndex].similar_edge_count > slideWindowTh) ? 1 : 0;
592 1400 : sb_stat_ptr->stationary_edge_over_time_flag = (similarEdgeCountLcu >= 4) ? EB_TRUE : EB_FALSE;
593 : }
594 :
595 7080 : sb_stat_ptr->pm_stationary_edge_over_time_flag = EB_FALSE;
596 7080 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb && sb_stat_ptr->pm_check1_for_logo_stationary_edge_over_time_flag && sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag) {
597 : uint32_t rasterScanCuIndex;
598 2012 : uint32_t similarEdgeCountLcu = 0;
599 : // CU Loop
600 34204 : for (rasterScanCuIndex = RASTER_SCAN_CU_INDEX_16x16_0; rasterScanCuIndex <= RASTER_SCAN_CU_INDEX_16x16_15; rasterScanCuIndex++)
601 32192 : similarEdgeCountLcu += (sb_stat_ptr->cu_stat_array[rasterScanCuIndex].pm_similar_edge_count > slideWindowTh) ? 1 : 0;
602 2012 : sb_stat_ptr->pm_stationary_edge_over_time_flag = (similarEdgeCountLcu >= 4) ? EB_TRUE : EB_FALSE;
603 : }
604 : }
605 : {
606 : uint32_t sb_index;
607 : uint32_t sb_x, sb_y;
608 118 : uint32_t countOfNeighbors = 0;
609 :
610 118 : uint32_t countOfNeighborsPm = 0;
611 :
612 : int32_t lcuHor, lcuVer, lcuVerOffset;
613 : int32_t lcuHorS, lcuVerS, lcuHorE, lcuVerE;
614 118 : uint32_t picture_width_in_sb = sequence_control_set_ptr->picture_width_in_sb;
615 118 : uint32_t picture_height_in_sb = sequence_control_set_ptr->picture_height_in_sb;
616 :
617 7198 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; ++sb_index) {
618 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
619 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
620 :
621 7080 : sb_x = sb_params.horizontal_index;
622 7080 : sb_y = sb_params.vertical_index;
623 7080 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb && sb_stat_ptr->check1_for_logo_stationary_edge_over_time_flag && sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag) {
624 : {
625 1400 : lcuHorS = (sb_x > 0) ? -1 : 0;
626 1400 : lcuHorE = (sb_x < picture_width_in_sb - 1) ? 1 : 0;
627 1400 : lcuVerS = (sb_y > 0) ? -1 : 0;
628 1400 : lcuVerE = (sb_y < picture_height_in_sb - 1) ? 1 : 0;
629 1400 : countOfNeighbors = 0;
630 5057 : for (lcuVer = lcuVerS; lcuVer <= lcuVerE; lcuVer++) {
631 3657 : lcuVerOffset = lcuVer * (int32_t)picture_width_in_sb;
632 13610 : for (lcuHor = lcuHorS; lcuHor <= lcuHorE; lcuHor++)
633 9953 : countOfNeighbors += (picture_control_set_ptr->sb_stat_array[sb_index + lcuVerOffset + lcuHor].stationary_edge_over_time_flag == 1);
634 : }
635 1400 : if (countOfNeighbors == 1)
636 216 : sb_stat_ptr->stationary_edge_over_time_flag = 0;
637 : }
638 : }
639 :
640 7080 : if (sb_params.potential_logo_sb &&sb_params.is_complete_sb && sb_stat_ptr->pm_check1_for_logo_stationary_edge_over_time_flag && sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag) {
641 : {
642 2012 : lcuHorS = (sb_x > 0) ? -1 : 0;
643 2012 : lcuHorE = (sb_x < picture_width_in_sb - 1) ? 1 : 0;
644 2012 : lcuVerS = (sb_y > 0) ? -1 : 0;
645 2012 : lcuVerE = (sb_y < picture_height_in_sb - 1) ? 1 : 0;
646 2012 : countOfNeighborsPm = 0;
647 7402 : for (lcuVer = lcuVerS; lcuVer <= lcuVerE; lcuVer++) {
648 5390 : lcuVerOffset = lcuVer * (int32_t)picture_width_in_sb;
649 19672 : for (lcuHor = lcuHorS; lcuHor <= lcuHorE; lcuHor++)
650 14282 : countOfNeighborsPm += (picture_control_set_ptr->sb_stat_array[sb_index + lcuVerOffset + lcuHor].pm_stationary_edge_over_time_flag == 1);
651 : }
652 :
653 2012 : if (countOfNeighborsPm == 1)
654 80 : sb_stat_ptr->pm_stationary_edge_over_time_flag = 0;
655 : }
656 : }
657 : }
658 : }
659 :
660 : {
661 : uint32_t sb_index;
662 : uint32_t sb_x, sb_y;
663 118 : uint32_t countOfNeighbors = 0;
664 : int32_t lcuHor, lcuVer, lcuVerOffset;
665 : int32_t lcuHorS, lcuVerS, lcuHorE, lcuVerE;
666 118 : uint32_t picture_width_in_sb = sequence_control_set_ptr->picture_width_in_sb;
667 118 : uint32_t picture_height_in_sb = sequence_control_set_ptr->picture_height_in_sb;
668 :
669 7198 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; ++sb_index) {
670 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
671 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
672 :
673 7080 : sb_x = sb_params.horizontal_index;
674 7080 : sb_y = sb_params.vertical_index;
675 :
676 : {
677 7080 : if (sb_stat_ptr->stationary_edge_over_time_flag == 0 && sb_params.potential_logo_sb && (sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag || !sb_params.is_complete_sb)) {
678 3601 : lcuHorS = (sb_x > 0) ? -1 : 0;
679 3601 : lcuHorE = (sb_x < picture_width_in_sb - 1) ? 1 : 0;
680 3601 : lcuVerS = (sb_y > 0) ? -1 : 0;
681 3601 : lcuVerE = (sb_y < picture_height_in_sb - 1) ? 1 : 0;
682 3601 : countOfNeighbors = 0;
683 12618 : for (lcuVer = lcuVerS; lcuVer <= lcuVerE; lcuVer++) {
684 9017 : lcuVerOffset = lcuVer * (int32_t)picture_width_in_sb;
685 33757 : for (lcuHor = lcuHorS; lcuHor <= lcuHorE; lcuHor++)
686 24740 : countOfNeighbors += (picture_control_set_ptr->sb_stat_array[sb_index + lcuVerOffset + lcuHor].stationary_edge_over_time_flag == 1);
687 : }
688 3601 : if (countOfNeighbors > 0)
689 237 : sb_stat_ptr->stationary_edge_over_time_flag = 2;
690 : }
691 : }
692 : }
693 :
694 7198 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; ++sb_index) {
695 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
696 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
697 :
698 7080 : sb_x = sb_params.horizontal_index;
699 7080 : sb_y = sb_params.vertical_index;
700 :
701 : {
702 7080 : if (sb_stat_ptr->stationary_edge_over_time_flag == 0 && sb_params.potential_logo_sb && (sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag || !sb_params.is_complete_sb)) {
703 3364 : lcuHorS = (sb_x > 0) ? -1 : 0;
704 3364 : lcuHorE = (sb_x < picture_width_in_sb - 1) ? 1 : 0;
705 3364 : lcuVerS = (sb_y > 0) ? -1 : 0;
706 3364 : lcuVerE = (sb_y < picture_height_in_sb - 1) ? 1 : 0;
707 3364 : countOfNeighbors = 0;
708 11774 : for (lcuVer = lcuVerS; lcuVer <= lcuVerE; lcuVer++) {
709 8410 : lcuVerOffset = lcuVer * (int32_t)picture_width_in_sb;
710 31565 : for (lcuHor = lcuHorS; lcuHor <= lcuHorE; lcuHor++)
711 23155 : countOfNeighbors += (picture_control_set_ptr->sb_stat_array[sb_index + lcuVerOffset + lcuHor].stationary_edge_over_time_flag == 2);
712 : }
713 3364 : if (countOfNeighbors > 3)
714 0 : sb_stat_ptr->stationary_edge_over_time_flag = 3;
715 : }
716 : }
717 : }
718 : }
719 :
720 : {
721 : uint32_t sb_index;
722 : uint32_t sb_x, sb_y;
723 118 : uint32_t countOfNeighbors = 0;
724 : int32_t lcuHor, lcuVer, lcuVerOffset;
725 : int32_t lcuHorS, lcuVerS, lcuHorE, lcuVerE;
726 118 : uint32_t picture_width_in_sb = sequence_control_set_ptr->picture_width_in_sb;
727 118 : uint32_t picture_height_in_sb = sequence_control_set_ptr->picture_height_in_sb;
728 :
729 7198 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; ++sb_index) {
730 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
731 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
732 :
733 7080 : sb_x = sb_params.horizontal_index;
734 7080 : sb_y = sb_params.vertical_index;
735 :
736 : {
737 7080 : if (sb_stat_ptr->pm_stationary_edge_over_time_flag == 0 && sb_params.potential_logo_sb && (sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag || !sb_params.is_complete_sb)) {
738 2152 : lcuHorS = (sb_x > 0) ? -1 : 0;
739 2152 : lcuHorE = (sb_x < picture_width_in_sb - 1) ? 1 : 0;
740 2152 : lcuVerS = (sb_y > 0) ? -1 : 0;
741 2152 : lcuVerE = (sb_y < picture_height_in_sb - 1) ? 1 : 0;
742 2152 : countOfNeighbors = 0;
743 7228 : for (lcuVer = lcuVerS; lcuVer <= lcuVerE; lcuVer++) {
744 5076 : lcuVerOffset = lcuVer * (int32_t)picture_width_in_sb;
745 19420 : for (lcuHor = lcuHorS; lcuHor <= lcuHorE; lcuHor++)
746 14344 : countOfNeighbors += (picture_control_set_ptr->sb_stat_array[sb_index + lcuVerOffset + lcuHor].pm_stationary_edge_over_time_flag == 1);
747 : }
748 2152 : if (countOfNeighbors > 0)
749 1132 : sb_stat_ptr->pm_stationary_edge_over_time_flag = 2;
750 : }
751 : }
752 : }
753 :
754 7198 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; ++sb_index) {
755 7080 : SbParams sb_params = sequence_control_set_ptr->sb_params_array[sb_index];
756 7080 : SbStat *sb_stat_ptr = &picture_control_set_ptr->sb_stat_array[sb_index];
757 :
758 7080 : sb_x = sb_params.horizontal_index;
759 7080 : sb_y = sb_params.vertical_index;
760 :
761 : {
762 7080 : if (sb_stat_ptr->pm_stationary_edge_over_time_flag == 0 && sb_params.potential_logo_sb && (sb_stat_ptr->check2_for_logo_stationary_edge_over_time_flag || !sb_params.is_complete_sb)) {
763 1020 : lcuHorS = (sb_x > 0) ? -1 : 0;
764 1020 : lcuHorE = (sb_x < picture_width_in_sb - 1) ? 1 : 0;
765 1020 : lcuVerS = (sb_y > 0) ? -1 : 0;
766 1020 : lcuVerE = (sb_y < picture_height_in_sb - 1) ? 1 : 0;
767 1020 : countOfNeighbors = 0;
768 3570 : for (lcuVer = lcuVerS; lcuVer <= lcuVerE; lcuVer++) {
769 2550 : lcuVerOffset = lcuVer * (int32_t)picture_width_in_sb;
770 9550 : for (lcuHor = lcuHorS; lcuHor <= lcuHorE; lcuHor++)
771 7000 : countOfNeighbors += (picture_control_set_ptr->sb_stat_array[sb_index + lcuVerOffset + lcuHor].pm_stationary_edge_over_time_flag == 2);
772 : }
773 1020 : if (countOfNeighbors > 3)
774 0 : sb_stat_ptr->pm_stationary_edge_over_time_flag = 3;
775 : }
776 : }
777 : }
778 : }
779 118 : }
780 :
781 : /************************************************
782 : * Global Motion Detection Based on Lookahead
783 : ** Mark pictures for pan
784 : ** Mark pictures for tilt
785 : ** LAD Window: min (8 or sliding window size)
786 : ************************************************/
787 118 : void UpdateGlobalMotionDetectionOverTime(
788 : EncodeContext *encode_context_ptr,
789 : SequenceControlSet *sequence_control_set_ptr,
790 : PictureParentControlSet *picture_control_set_ptr)
791 : {
792 : InitialRateControlReorderEntry *temporaryQueueEntryPtr;
793 : PictureParentControlSet *temporaryPictureControlSetPtr;
794 :
795 118 : uint32_t totalPanPictures = 0;
796 118 : uint32_t totalCheckedPictures = 0;
797 118 : uint32_t totalTiltPictures = 0;
798 : uint32_t updateIsPanFramesToCheck;
799 : uint32_t inputQueueIndex;
800 : uint32_t framesToCheckIndex;
801 :
802 : (void)sequence_control_set_ptr;
803 :
804 : // Determine number of frames to check (8 frames)
805 118 : updateIsPanFramesToCheck = MIN(8, picture_control_set_ptr->frames_in_sw);
806 :
807 : // Walk the first N entries in the sliding window
808 118 : inputQueueIndex = encode_context_ptr->initial_rate_control_reorder_queue_head_index;
809 118 : uint32_t updateFramesToCheck = updateIsPanFramesToCheck;
810 1020 : for (framesToCheckIndex = 0; framesToCheckIndex < updateFramesToCheck; framesToCheckIndex++) {
811 902 : temporaryQueueEntryPtr = encode_context_ptr->initial_rate_control_reorder_queue[inputQueueIndex];
812 902 : temporaryPictureControlSetPtr = ((PictureParentControlSet*)(temporaryQueueEntryPtr->parent_pcs_wrapper_ptr)->object_ptr);
813 :
814 902 : if (temporaryPictureControlSetPtr->slice_type != I_SLICE) {
815 884 : totalPanPictures += (temporaryPictureControlSetPtr->is_pan == EB_TRUE);
816 :
817 884 : totalTiltPictures += (temporaryPictureControlSetPtr->is_tilt == EB_TRUE);
818 :
819 : // Keep track of checked pictures
820 884 : totalCheckedPictures++;
821 : }
822 :
823 : // Increment the inputQueueIndex Iterator
824 902 : inputQueueIndex = (inputQueueIndex == INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? 0 : inputQueueIndex + 1;
825 : }
826 :
827 118 : picture_control_set_ptr->is_pan = EB_FALSE;
828 118 : picture_control_set_ptr->is_tilt = EB_FALSE;
829 :
830 118 : if (totalCheckedPictures) {
831 118 : if (picture_control_set_ptr->slice_type != I_SLICE) {
832 114 : if ((totalPanPictures * 100 / totalCheckedPictures) > 75)
833 0 : picture_control_set_ptr->is_pan = EB_TRUE;
834 : }
835 : }
836 118 : return;
837 : }
838 :
839 : /************************************************
840 : * Update BEA Information Based on Lookahead
841 : ** Average zzCost of Collocated SB throughout lookahead frames
842 : ** Set isMostOfPictureNonMoving based on number of non moving LCUs
843 : ** LAD Window: min (2xmgpos+1 or sliding window size)
844 : ************************************************/
845 :
846 118 : void UpdateBeaInfoOverTime(
847 : EncodeContext *encode_context_ptr,
848 : PictureParentControlSet *picture_control_set_ptr)
849 : {
850 : InitialRateControlReorderEntry *temporaryQueueEntryPtr;
851 : PictureParentControlSet *temporaryPictureControlSetPtr;
852 : uint32_t updateNonMovingIndexArrayFramesToCheck;
853 : uint16_t lcuIdx;
854 : uint16_t framesToCheckIndex;
855 118 : uint64_t nonMovingIndexSum = 0;
856 : uint32_t inputQueueIndex;
857 :
858 118 : SequenceControlSet *sequence_control_set_ptr = (SequenceControlSet*)picture_control_set_ptr->sequence_control_set_wrapper_ptr->object_ptr;
859 : // Update motionIndexArray of the current picture by averaging the motionIndexArray of the N future pictures
860 : // Determine number of frames to check N
861 118 : updateNonMovingIndexArrayFramesToCheck = MIN(MIN(((picture_control_set_ptr->pred_struct_ptr->pred_struct_period << 1) + 1), picture_control_set_ptr->frames_in_sw), sequence_control_set_ptr->static_config.look_ahead_distance);
862 118 : uint64_t me_dist = 0;
863 118 : uint8_t me_dist_pic_count = 0;
864 : // SB Loop
865 7198 : for (lcuIdx = 0; lcuIdx < picture_control_set_ptr->sb_total_count; ++lcuIdx) {
866 7080 : uint16_t nonMovingIndexOverSlidingWindow = picture_control_set_ptr->non_moving_index_array[lcuIdx];
867 :
868 : // Walk the first N entries in the sliding window starting picture + 1
869 7080 : inputQueueIndex = (encode_context_ptr->initial_rate_control_reorder_queue_head_index == INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? 0 : encode_context_ptr->initial_rate_control_reorder_queue_head_index + 1;
870 108720 : for (framesToCheckIndex = 0; framesToCheckIndex < updateNonMovingIndexArrayFramesToCheck - 1; framesToCheckIndex++) {
871 108720 : temporaryQueueEntryPtr = encode_context_ptr->initial_rate_control_reorder_queue[inputQueueIndex];
872 108720 : temporaryPictureControlSetPtr = ((PictureParentControlSet*)(temporaryQueueEntryPtr->parent_pcs_wrapper_ptr)->object_ptr);
873 :
874 108720 : if (temporaryPictureControlSetPtr->slice_type == I_SLICE || temporaryPictureControlSetPtr->end_of_sequence_flag)
875 : break;
876 : // Limit the distortion to lower layers 0, 1 and 2 only. Higher layers have close temporal distance and lower distortion that might contaminate the data
877 101640 : if (temporaryPictureControlSetPtr->temporal_layer_index < MAX((int8_t)picture_control_set_ptr->hierarchical_levels - 1, 2) ) {
878 29640 : if (lcuIdx == 0)
879 494 : me_dist_pic_count++;
880 29640 : me_dist += (temporaryPictureControlSetPtr->slice_type == I_SLICE) ? 0 : (uint64_t)temporaryPictureControlSetPtr->rc_me_distortion[lcuIdx];
881 : }
882 : // Store the filtered_sse of next ALT_REF picture in the I slice to be used in QP Scaling
883 101640 : if (picture_control_set_ptr->slice_type == I_SLICE && picture_control_set_ptr->filtered_sse == 0 && lcuIdx == 0 && temporaryPictureControlSetPtr->temporal_layer_index == 0) {
884 2 : picture_control_set_ptr->filtered_sse = temporaryPictureControlSetPtr->filtered_sse;
885 2 : picture_control_set_ptr->filtered_sse_uv = temporaryPictureControlSetPtr->filtered_sse_uv;
886 : }
887 101640 : nonMovingIndexOverSlidingWindow += temporaryPictureControlSetPtr->non_moving_index_array[lcuIdx];
888 :
889 : // Increment the inputQueueIndex Iterator
890 101640 : inputQueueIndex = (inputQueueIndex == INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? 0 : inputQueueIndex + 1;
891 : }
892 7080 : picture_control_set_ptr->non_moving_index_array[lcuIdx] = (uint8_t)(nonMovingIndexOverSlidingWindow / (framesToCheckIndex + 1));
893 :
894 7080 : nonMovingIndexSum += picture_control_set_ptr->non_moving_index_array[lcuIdx];
895 : }
896 :
897 118 : picture_control_set_ptr->non_moving_index_average = (uint16_t)nonMovingIndexSum / picture_control_set_ptr->sb_total_count;
898 118 : me_dist_pic_count = MAX(me_dist_pic_count, 1);
899 118 : picture_control_set_ptr->qp_scaling_average_complexity = (uint16_t)((uint64_t)me_dist / picture_control_set_ptr->sb_total_count / 256 / me_dist_pic_count);
900 118 : return;
901 : }
902 :
903 : /****************************************
904 : * Init ZZ Cost array to default values
905 : ** Used when no Lookahead is available
906 : ****************************************/
907 2 : void InitZzCostInfo(
908 : PictureParentControlSet *picture_control_set_ptr)
909 : {
910 : uint16_t lcuIdx;
911 2 : picture_control_set_ptr->non_moving_index_average = INVALID_ZZ_COST;
912 :
913 : // SB Loop
914 122 : for (lcuIdx = 0; lcuIdx < picture_control_set_ptr->sb_total_count; ++lcuIdx)
915 120 : picture_control_set_ptr->non_moving_index_array[lcuIdx] = INVALID_ZZ_COST;
916 2 : return;
917 : }
918 :
919 : /************************************************
920 : * Update uniform motion field
921 : ** Update Uniformly moving LCUs using
922 : ** collocated LCUs infor in lookahead pictures
923 : ** LAD Window: min (2xmgpos+1 or sliding window size)
924 : ************************************************/
925 118 : void UpdateMotionFieldUniformityOverTime(
926 : EncodeContext *encode_context_ptr,
927 : SequenceControlSet *sequence_control_set_ptr,
928 : PictureParentControlSet *picture_control_set_ptr)
929 : {
930 : InitialRateControlReorderEntry *temporaryQueueEntryPtr;
931 : PictureParentControlSet *temporaryPictureControlSetPtr;
932 : uint32_t inputQueueIndex;
933 : uint32_t NoFramesToCheck;
934 : uint32_t framesToCheckIndex;
935 : //printf("To update POC %d\tframesInSw = %d\n", picture_control_set_ptr->picture_number, picture_control_set_ptr->frames_in_sw);
936 :
937 : //Check conditions for statinary edge over time
938 118 : StationaryEdgeOverUpdateOverTimeLcuPart2(
939 : sequence_control_set_ptr,
940 : picture_control_set_ptr);
941 :
942 : // Determine number of frames to check N
943 118 : NoFramesToCheck = MIN(MIN(((picture_control_set_ptr->pred_struct_ptr->pred_struct_period << 1) + 1), picture_control_set_ptr->frames_in_sw), sequence_control_set_ptr->static_config.look_ahead_distance);
944 :
945 : // Walk the first N entries in the sliding window starting picture + 1
946 118 : inputQueueIndex = (encode_context_ptr->initial_rate_control_reorder_queue_head_index == INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? 0 : encode_context_ptr->initial_rate_control_reorder_queue_head_index;
947 2902 : for (framesToCheckIndex = 0; framesToCheckIndex < NoFramesToCheck - 1; framesToCheckIndex++) {
948 2784 : temporaryQueueEntryPtr = encode_context_ptr->initial_rate_control_reorder_queue[inputQueueIndex];
949 2784 : temporaryPictureControlSetPtr = ((PictureParentControlSet*)(temporaryQueueEntryPtr->parent_pcs_wrapper_ptr)->object_ptr);
950 :
951 2784 : if (temporaryPictureControlSetPtr->end_of_sequence_flag)
952 0 : break;
953 : // The values are calculated for every 4th frame
954 2784 : if ((temporaryPictureControlSetPtr->picture_number & 3) == 0) {
955 688 : StationaryEdgeCountLcu(
956 : sequence_control_set_ptr,
957 : picture_control_set_ptr,
958 : temporaryPictureControlSetPtr,
959 688 : picture_control_set_ptr->sb_total_count);
960 : }
961 : // Increment the inputQueueIndex Iterator
962 2784 : inputQueueIndex = (inputQueueIndex == INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? 0 : inputQueueIndex + 1;
963 : }
964 118 : StationaryEdgeOverUpdateOverTimeLcu(
965 : sequence_control_set_ptr,
966 : NoFramesToCheck,
967 : picture_control_set_ptr,
968 118 : picture_control_set_ptr->sb_total_count);
969 118 : return;
970 : }
971 120 : InitialRateControlReorderEntry * DeterminePictureOffsetInQueue(
972 : EncodeContext *encode_context_ptr,
973 : PictureParentControlSet *picture_control_set_ptr,
974 : MotionEstimationResults *inputResultsPtr)
975 : {
976 : InitialRateControlReorderEntry *queueEntryPtr;
977 : int32_t queueEntryIndex;
978 :
979 120 : queueEntryIndex = (int32_t)(picture_control_set_ptr->picture_number - encode_context_ptr->initial_rate_control_reorder_queue[encode_context_ptr->initial_rate_control_reorder_queue_head_index]->picture_number);
980 120 : queueEntryIndex += encode_context_ptr->initial_rate_control_reorder_queue_head_index;
981 120 : queueEntryIndex = (queueEntryIndex > INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? queueEntryIndex - INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH : queueEntryIndex;
982 120 : queueEntryPtr = encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndex];
983 120 : queueEntryPtr->parent_pcs_wrapper_ptr = inputResultsPtr->picture_control_set_wrapper_ptr;
984 120 : queueEntryPtr->picture_number = picture_control_set_ptr->picture_number;
985 :
986 120 : return queueEntryPtr;
987 : }
988 :
989 0 : void GetHistogramQueueData(
990 : SequenceControlSet *sequence_control_set_ptr,
991 : EncodeContext *encode_context_ptr,
992 : PictureParentControlSet *picture_control_set_ptr)
993 : {
994 : HlRateControlHistogramEntry *histogramQueueEntryPtr;
995 : int32_t histogramQueueEntryIndex;
996 :
997 : // Determine offset from the Head Ptr for HLRC histogram queue
998 0 : eb_block_on_mutex(sequence_control_set_ptr->encode_context_ptr->hl_rate_control_historgram_queue_mutex);
999 0 : histogramQueueEntryIndex = (int32_t)(picture_control_set_ptr->picture_number - encode_context_ptr->hl_rate_control_historgram_queue[encode_context_ptr->hl_rate_control_historgram_queue_head_index]->picture_number);
1000 0 : histogramQueueEntryIndex += encode_context_ptr->hl_rate_control_historgram_queue_head_index;
1001 0 : histogramQueueEntryIndex = (histogramQueueEntryIndex > HIGH_LEVEL_RATE_CONTROL_HISTOGRAM_QUEUE_MAX_DEPTH - 1) ?
1002 0 : histogramQueueEntryIndex - HIGH_LEVEL_RATE_CONTROL_HISTOGRAM_QUEUE_MAX_DEPTH :
1003 : (histogramQueueEntryIndex < 0) ?
1004 0 : histogramQueueEntryIndex + HIGH_LEVEL_RATE_CONTROL_HISTOGRAM_QUEUE_MAX_DEPTH :
1005 : histogramQueueEntryIndex;
1006 0 : histogramQueueEntryPtr = encode_context_ptr->hl_rate_control_historgram_queue[histogramQueueEntryIndex];
1007 :
1008 : //histogramQueueEntryPtr->parent_pcs_wrapper_ptr = inputResultsPtr->picture_control_set_wrapper_ptr;
1009 0 : histogramQueueEntryPtr->picture_number = picture_control_set_ptr->picture_number;
1010 0 : histogramQueueEntryPtr->end_of_sequence_flag = picture_control_set_ptr->end_of_sequence_flag;
1011 0 : histogramQueueEntryPtr->slice_type = picture_control_set_ptr->slice_type;
1012 0 : histogramQueueEntryPtr->temporal_layer_index = picture_control_set_ptr->temporal_layer_index;
1013 0 : histogramQueueEntryPtr->full_sb_count = picture_control_set_ptr->full_sb_count;
1014 0 : histogramQueueEntryPtr->life_count = 0;
1015 0 : histogramQueueEntryPtr->passed_to_hlrc = EB_FALSE;
1016 0 : histogramQueueEntryPtr->is_coded = EB_FALSE;
1017 0 : histogramQueueEntryPtr->total_num_bits_coded = 0;
1018 0 : histogramQueueEntryPtr->frames_in_sw = 0;
1019 0 : EB_MEMCPY(
1020 : histogramQueueEntryPtr->me_distortion_histogram,
1021 : picture_control_set_ptr->me_distortion_histogram,
1022 : sizeof(uint16_t) * NUMBER_OF_SAD_INTERVALS);
1023 :
1024 0 : EB_MEMCPY(
1025 : histogramQueueEntryPtr->ois_distortion_histogram,
1026 : picture_control_set_ptr->ois_distortion_histogram,
1027 : sizeof(uint16_t) * NUMBER_OF_INTRA_SAD_INTERVALS);
1028 :
1029 0 : eb_release_mutex(sequence_control_set_ptr->encode_context_ptr->hl_rate_control_historgram_queue_mutex);
1030 : //printf("Test1 POC: %d\t POC: %d\t LifeCount: %d\n", histogramQueueEntryPtr->picture_number, picture_control_set_ptr->picture_number, histogramQueueEntryPtr->life_count);
1031 :
1032 0 : return;
1033 : }
1034 :
1035 0 : void UpdateHistogramQueueEntry(
1036 : SequenceControlSet *sequence_control_set_ptr,
1037 : EncodeContext *encode_context_ptr,
1038 : PictureParentControlSet *picture_control_set_ptr,
1039 : uint32_t frames_in_sw)
1040 : {
1041 : HlRateControlHistogramEntry *histogramQueueEntryPtr;
1042 : int32_t histogramQueueEntryIndex;
1043 :
1044 0 : eb_block_on_mutex(sequence_control_set_ptr->encode_context_ptr->hl_rate_control_historgram_queue_mutex);
1045 :
1046 0 : histogramQueueEntryIndex = (int32_t)(picture_control_set_ptr->picture_number - encode_context_ptr->hl_rate_control_historgram_queue[encode_context_ptr->hl_rate_control_historgram_queue_head_index]->picture_number);
1047 0 : histogramQueueEntryIndex += encode_context_ptr->hl_rate_control_historgram_queue_head_index;
1048 0 : histogramQueueEntryIndex = (histogramQueueEntryIndex > HIGH_LEVEL_RATE_CONTROL_HISTOGRAM_QUEUE_MAX_DEPTH - 1) ?
1049 0 : histogramQueueEntryIndex - HIGH_LEVEL_RATE_CONTROL_HISTOGRAM_QUEUE_MAX_DEPTH :
1050 : (histogramQueueEntryIndex < 0) ?
1051 0 : histogramQueueEntryIndex + HIGH_LEVEL_RATE_CONTROL_HISTOGRAM_QUEUE_MAX_DEPTH :
1052 : histogramQueueEntryIndex;
1053 0 : histogramQueueEntryPtr = encode_context_ptr->hl_rate_control_historgram_queue[histogramQueueEntryIndex];
1054 0 : histogramQueueEntryPtr->passed_to_hlrc = EB_TRUE;
1055 0 : if (sequence_control_set_ptr->static_config.rate_control_mode == 3)
1056 0 : histogramQueueEntryPtr->life_count += (int16_t)(sequence_control_set_ptr->static_config.intra_period_length + 1) - 3; // FramelevelRC does not decrease the life count for first picture in each temporal layer
1057 : else
1058 0 : histogramQueueEntryPtr->life_count += picture_control_set_ptr->historgram_life_count;
1059 0 : histogramQueueEntryPtr->frames_in_sw = frames_in_sw;
1060 0 : eb_release_mutex(sequence_control_set_ptr->encode_context_ptr->hl_rate_control_historgram_queue_mutex);
1061 :
1062 0 : return;
1063 : }
1064 : EbAuraStatus AuraDetection64x64Gold(
1065 : PictureControlSet *picture_control_set_ptr,
1066 : uint8_t picture_qp,
1067 : uint32_t x_lcu_index,
1068 : uint32_t y_lcu_index
1069 : );
1070 :
1071 : /******************************************************
1072 : Input : variance
1073 : Output : true if current & neighbors are spatially complex
1074 : ******************************************************/
1075 7200 : EbBool IsSpatiallyComplexArea(
1076 : PictureParentControlSet *parentPcs,
1077 : uint32_t pictureWidthInLcus,
1078 : uint32_t lcuAdrr,
1079 : uint32_t sb_origin_x,
1080 : uint32_t sb_origin_y)
1081 : {
1082 7200 : uint32_t availableLcusCount = 0;
1083 7200 : uint32_t highVarianceLcusCount = 0;
1084 :
1085 : // Check the variance of the current LCU
1086 7200 : if ((parentPcs->variance[lcuAdrr][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH) {
1087 4134 : availableLcusCount++;
1088 4134 : highVarianceLcusCount++;
1089 : }
1090 :
1091 : // Check the variance of left SB if available
1092 7200 : if (sb_origin_x != 0) {
1093 6480 : availableLcusCount++;
1094 6480 : if ((parentPcs->variance[lcuAdrr - 1][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1095 3892 : highVarianceLcusCount++;
1096 : }
1097 :
1098 : // Check the variance of right SB if available
1099 7200 : if ((sb_origin_x + BLOCK_SIZE_64) < parentPcs->enhanced_picture_ptr->width) {
1100 6480 : availableLcusCount++;
1101 6480 : if ((parentPcs->variance[lcuAdrr + 1][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1102 3420 : highVarianceLcusCount++;
1103 : }
1104 :
1105 : // Check the variance of top SB if available
1106 7200 : if (sb_origin_y != 0) {
1107 6000 : availableLcusCount++;
1108 6000 : if ((parentPcs->variance[lcuAdrr - pictureWidthInLcus][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1109 3374 : highVarianceLcusCount++;
1110 : }
1111 :
1112 : // Check the variance of bottom LCU
1113 7200 : if ((sb_origin_y + BLOCK_SIZE_64) < parentPcs->enhanced_picture_ptr->height) {
1114 6000 : availableLcusCount++;
1115 6000 : if ((parentPcs->variance[lcuAdrr + pictureWidthInLcus][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1116 3398 : highVarianceLcusCount++;
1117 : }
1118 :
1119 : // Check the variance of top-left LCU
1120 7200 : if ((sb_origin_x >= BLOCK_SIZE_64) && (sb_origin_y >= BLOCK_SIZE_64)) {
1121 5400 : availableLcusCount++;
1122 5400 : if ((parentPcs->variance[lcuAdrr - pictureWidthInLcus - 1][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1123 3132 : highVarianceLcusCount++;
1124 : }
1125 :
1126 : // Check the variance of top-right LCU
1127 7200 : if ((sb_origin_x < parentPcs->enhanced_picture_ptr->width - BLOCK_SIZE_64) && (sb_origin_y >= BLOCK_SIZE_64)) {
1128 5400 : availableLcusCount++;
1129 5400 : if ((parentPcs->variance[lcuAdrr - pictureWidthInLcus + 1][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1130 2776 : highVarianceLcusCount++;
1131 : }
1132 :
1133 : // Check the variance of bottom-left LCU
1134 7200 : if ((sb_origin_x >= BLOCK_SIZE_64) && (sb_origin_y < parentPcs->enhanced_picture_ptr->height - BLOCK_SIZE_64)) {
1135 5400 : availableLcusCount++;
1136 5400 : if ((parentPcs->variance[lcuAdrr + pictureWidthInLcus - 1][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1137 3276 : highVarianceLcusCount++;
1138 : }
1139 :
1140 : // Check the variance of bottom-right LCU
1141 7200 : if ((sb_origin_x < parentPcs->enhanced_picture_ptr->width - BLOCK_SIZE_64) && (sb_origin_y < parentPcs->enhanced_picture_ptr->height - BLOCK_SIZE_64)) {
1142 5400 : availableLcusCount++;
1143 5400 : if ((parentPcs->variance[lcuAdrr + pictureWidthInLcus + 1][ME_TIER_ZERO_PU_64x64]) > IS_COMPLEX_LCU_VARIANCE_TH)
1144 2804 : highVarianceLcusCount++;
1145 : }
1146 :
1147 7200 : if (highVarianceLcusCount == availableLcusCount)
1148 2674 : return EB_TRUE;
1149 4526 : return EB_FALSE;
1150 : }
1151 :
1152 : // Derives blockinessPresentFlag
1153 120 : void DeriveBlockinessPresentFlag(
1154 : SequenceControlSet *sequence_control_set_ptr,
1155 : PictureParentControlSet *picture_control_set_ptr)
1156 : {
1157 : uint32_t sb_index;
1158 :
1159 7320 : for (sb_index = 0; sb_index < picture_control_set_ptr->sb_total_count; ++sb_index) {
1160 7200 : SbParams *lcuParamPtr = &sequence_control_set_ptr->sb_params_array[sb_index];
1161 7200 : picture_control_set_ptr->complex_sb_array[sb_index] = SB_COMPLEXITY_STATUS_INVALID;
1162 :
1163 : // Spatially complex SB within a spatially complex area
1164 7200 : if (IsSpatiallyComplexArea(
1165 : picture_control_set_ptr,
1166 7200 : (picture_control_set_ptr->enhanced_picture_ptr->width + BLOCK_SIZE_64 - 1) / BLOCK_SIZE_64,
1167 : sb_index,
1168 7200 : lcuParamPtr->origin_x,
1169 7200 : lcuParamPtr->origin_y)) {
1170 : // Active SB within an active scene (added a check on 4K & non-BASE to restrict the action - could be generated for all resolutions/layers)
1171 2674 : if (picture_control_set_ptr->non_moving_index_array[sb_index] == SB_COMPLEXITY_NON_MOVING_INDEX_TH_0 && picture_control_set_ptr->non_moving_index_average >= SB_COMPLEXITY_NON_MOVING_INDEX_TH_1 && picture_control_set_ptr->temporal_layer_index > 0 && sequence_control_set_ptr->input_resolution == INPUT_SIZE_4K_RANGE)
1172 0 : picture_control_set_ptr->complex_sb_array[sb_index] = SB_COMPLEXITY_STATUS_2;
1173 : // Active SB within a scene with a moderate acitivity (eg. active foregroud & static background)
1174 2674 : else if (picture_control_set_ptr->non_moving_index_array[sb_index] == SB_COMPLEXITY_NON_MOVING_INDEX_TH_0 && picture_control_set_ptr->non_moving_index_average >= SB_COMPLEXITY_NON_MOVING_INDEX_TH_2 && picture_control_set_ptr->non_moving_index_average < SB_COMPLEXITY_NON_MOVING_INDEX_TH_1)
1175 0 : picture_control_set_ptr->complex_sb_array[sb_index] = SB_COMPLEXITY_STATUS_1;
1176 : else
1177 2674 : picture_control_set_ptr->complex_sb_array[sb_index] = SB_COMPLEXITY_STATUS_0;
1178 : }
1179 : else
1180 4526 : picture_control_set_ptr->complex_sb_array[sb_index] = SB_COMPLEXITY_STATUS_0;
1181 : }
1182 120 : }
1183 :
1184 : /************************************************
1185 : * Initial Rate Control Kernel
1186 : * The Initial Rate Control Process determines the initial bit budget for each
1187 : * picture depending on the data gathered in the Picture Analysis and Motion
1188 : * Analysis processes as well as the settings determined in the Picture Decision process.
1189 : * The Initial Rate Control process also employs a sliding window buffer to analyze multiple
1190 : * pictures if the delay is allowed. Note that through this process, until the subsequent
1191 : * Picture Manager process, no reference picture data has been used.
1192 : * P.S. Temporal noise reduction is now performed in Initial Rate Control Process.
1193 : * In future we might decide to move it to Motion Analysis Process.
1194 : ************************************************/
1195 2 : void* initial_rate_control_kernel(void *input_ptr)
1196 : {
1197 2 : InitialRateControlContext *context_ptr = (InitialRateControlContext*)input_ptr;
1198 : PictureParentControlSet *picture_control_set_ptr;
1199 : PictureParentControlSet *pictureControlSetPtrTemp;
1200 : EncodeContext *encode_context_ptr;
1201 : SequenceControlSet *sequence_control_set_ptr;
1202 :
1203 : EbObjectWrapper *inputResultsWrapperPtr;
1204 : MotionEstimationResults *inputResultsPtr;
1205 :
1206 : EbObjectWrapper *outputResultsWrapperPtr;
1207 : InitialRateControlResults *outputResultsPtr;
1208 :
1209 : // Queue variables
1210 : uint32_t queueEntryIndexTemp;
1211 : uint32_t queueEntryIndexTemp2;
1212 : InitialRateControlReorderEntry *queueEntryPtr;
1213 :
1214 2 : EbBool moveSlideWondowFlag = EB_TRUE;
1215 2 : EbBool end_of_sequence_flag = EB_TRUE;
1216 : uint8_t frames_in_sw;
1217 : uint8_t temporal_layer_index;
1218 : EbObjectWrapper *reference_picture_wrapper_ptr;
1219 :
1220 : // Segments
1221 : uint32_t segment_index;
1222 :
1223 : EbObjectWrapper *output_stream_wrapper_ptr;
1224 :
1225 : for (;;) {
1226 : // Get Input Full Object
1227 7202 : eb_get_full_object(
1228 : context_ptr->motion_estimation_results_input_fifo_ptr,
1229 : &inputResultsWrapperPtr);
1230 :
1231 7200 : inputResultsPtr = (MotionEstimationResults*)inputResultsWrapperPtr->object_ptr;
1232 7200 : picture_control_set_ptr = (PictureParentControlSet*)inputResultsPtr->picture_control_set_wrapper_ptr->object_ptr;
1233 :
1234 7200 : segment_index = inputResultsPtr->segment_index;
1235 :
1236 : // Set the segment mask
1237 7200 : SEGMENT_COMPLETION_MASK_SET(picture_control_set_ptr->me_segments_completion_mask, segment_index);
1238 :
1239 : // If the picture is complete, proceed
1240 7200 : if (SEGMENT_COMPLETION_MASK_TEST(picture_control_set_ptr->me_segments_completion_mask, picture_control_set_ptr->me_segments_total_count)) {
1241 120 : sequence_control_set_ptr = (SequenceControlSet*)picture_control_set_ptr->sequence_control_set_wrapper_ptr->object_ptr;
1242 120 : encode_context_ptr = (EncodeContext*)sequence_control_set_ptr->encode_context_ptr;
1243 : // Mark picture when global motion is detected using ME results
1244 : //reset intraCodedEstimationLcu
1245 120 : MeBasedGlobalMotionDetection(
1246 : picture_control_set_ptr);
1247 : // Release Pa Ref pictures when not needed
1248 120 : ReleasePaReferenceObjects(
1249 : sequence_control_set_ptr,
1250 : picture_control_set_ptr);
1251 :
1252 : //****************************************************
1253 : // Input Motion Analysis Results into Reordering Queue
1254 : //****************************************************
1255 :
1256 120 : if(!picture_control_set_ptr->is_overlay)
1257 : // Determine offset from the Head Ptr
1258 120 : queueEntryPtr = DeterminePictureOffsetInQueue(
1259 : encode_context_ptr,
1260 : picture_control_set_ptr,
1261 : inputResultsPtr);
1262 :
1263 120 : if (sequence_control_set_ptr->static_config.rate_control_mode)
1264 : {
1265 0 : if (sequence_control_set_ptr->static_config.look_ahead_distance != 0) {
1266 : // Getting the Histogram Queue Data
1267 0 : GetHistogramQueueData(
1268 : sequence_control_set_ptr,
1269 : encode_context_ptr,
1270 : picture_control_set_ptr);
1271 : }
1272 : }
1273 :
1274 840 : for (temporal_layer_index = 0; temporal_layer_index < EB_MAX_TEMPORAL_LAYERS; temporal_layer_index++)
1275 720 : picture_control_set_ptr->frames_in_interval[temporal_layer_index] = 0;
1276 120 : picture_control_set_ptr->frames_in_sw = 0;
1277 120 : picture_control_set_ptr->historgram_life_count = 0;
1278 120 : picture_control_set_ptr->scene_change_in_gop = EB_FALSE;
1279 :
1280 : //Check conditions for statinary edge over time
1281 :
1282 120 : StationaryEdgeOverUpdateOverTimeLcuPart1(
1283 : sequence_control_set_ptr,
1284 : picture_control_set_ptr);
1285 :
1286 120 : moveSlideWondowFlag = EB_TRUE;
1287 360 : while (moveSlideWondowFlag) {
1288 : // Check if the sliding window condition is valid
1289 240 : queueEntryIndexTemp = encode_context_ptr->initial_rate_control_reorder_queue_head_index;
1290 240 : if (encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndexTemp]->parent_pcs_wrapper_ptr != EB_NULL)
1291 238 : end_of_sequence_flag = (((PictureParentControlSet*)(encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndexTemp]->parent_pcs_wrapper_ptr)->object_ptr))->end_of_sequence_flag;
1292 : else
1293 2 : end_of_sequence_flag = EB_FALSE;
1294 240 : frames_in_sw = 0;
1295 6152 : while (moveSlideWondowFlag && !end_of_sequence_flag &&
1296 5964 : queueEntryIndexTemp <= encode_context_ptr->initial_rate_control_reorder_queue_head_index + sequence_control_set_ptr->static_config.look_ahead_distance) {
1297 : // frames_in_sw <= sequence_control_set_ptr->static_config.look_ahead_distance){
1298 5912 : frames_in_sw++;
1299 :
1300 5912 : queueEntryIndexTemp2 = (queueEntryIndexTemp > INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? queueEntryIndexTemp - INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH : queueEntryIndexTemp;
1301 :
1302 5912 : moveSlideWondowFlag = (EbBool)(moveSlideWondowFlag && (encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndexTemp2]->parent_pcs_wrapper_ptr != EB_NULL));
1303 5912 : if (encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndexTemp2]->parent_pcs_wrapper_ptr != EB_NULL) {
1304 : // check if it is the last frame. If we have reached the last frame, we would output the buffered frames in the Queue.
1305 5792 : end_of_sequence_flag = ((PictureParentControlSet*)(encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndexTemp2]->parent_pcs_wrapper_ptr)->object_ptr)->end_of_sequence_flag;
1306 : }
1307 : else
1308 120 : end_of_sequence_flag = EB_FALSE;
1309 5912 : queueEntryIndexTemp++;
1310 : }
1311 :
1312 240 : if (moveSlideWondowFlag) {
1313 : //get a new entry spot
1314 120 : queueEntryPtr = encode_context_ptr->initial_rate_control_reorder_queue[encode_context_ptr->initial_rate_control_reorder_queue_head_index];
1315 120 : picture_control_set_ptr = ((PictureParentControlSet*)(queueEntryPtr->parent_pcs_wrapper_ptr)->object_ptr);
1316 120 : sequence_control_set_ptr = (SequenceControlSet*)picture_control_set_ptr->sequence_control_set_wrapper_ptr->object_ptr;
1317 : // overlay picture was not added to the queue. For the alt_ref picture with an overlay picture, it loops on both alt ref and overlay pictures
1318 120 : uint8_t has_overlay = picture_control_set_ptr->is_alt_ref ? 1 : 0;
1319 240 : for (uint8_t loop_index = 0; loop_index <= has_overlay; loop_index++) {
1320 120 : if (loop_index)
1321 0 : picture_control_set_ptr = picture_control_set_ptr->overlay_ppcs_ptr;
1322 120 : picture_control_set_ptr->frames_in_sw = frames_in_sw;
1323 120 : queueEntryIndexTemp = encode_context_ptr->initial_rate_control_reorder_queue_head_index;
1324 120 : end_of_sequence_flag = EB_FALSE;
1325 : // find the frames_in_interval for the peroid I frames
1326 3078 : while (!end_of_sequence_flag &&
1327 3010 : queueEntryIndexTemp <= encode_context_ptr->initial_rate_control_reorder_queue_head_index + sequence_control_set_ptr->static_config.look_ahead_distance) {
1328 2958 : queueEntryIndexTemp2 = (queueEntryIndexTemp > INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? queueEntryIndexTemp - INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH : queueEntryIndexTemp;
1329 2958 : pictureControlSetPtrTemp = ((PictureParentControlSet*)(encode_context_ptr->initial_rate_control_reorder_queue[queueEntryIndexTemp2]->parent_pcs_wrapper_ptr)->object_ptr);
1330 2958 : if (sequence_control_set_ptr->intra_period_length != -1) {
1331 2958 : if (picture_control_set_ptr->picture_number % ((sequence_control_set_ptr->intra_period_length + 1)) == 0) {
1332 124 : picture_control_set_ptr->frames_in_interval[pictureControlSetPtrTemp->temporal_layer_index] ++;
1333 124 : if (pictureControlSetPtrTemp->scene_change_flag)
1334 0 : picture_control_set_ptr->scene_change_in_gop = EB_TRUE;
1335 : }
1336 : }
1337 :
1338 2958 : pictureControlSetPtrTemp->historgram_life_count++;
1339 2958 : end_of_sequence_flag = pictureControlSetPtrTemp->end_of_sequence_flag;
1340 2958 : queueEntryIndexTemp++;
1341 : }
1342 :
1343 120 : if ((sequence_control_set_ptr->static_config.look_ahead_distance != 0) && (frames_in_sw < (sequence_control_set_ptr->static_config.look_ahead_distance + 1)))
1344 66 : picture_control_set_ptr->end_of_sequence_region = EB_TRUE;
1345 : else
1346 54 : picture_control_set_ptr->end_of_sequence_region = EB_FALSE;
1347 :
1348 120 : if (sequence_control_set_ptr->static_config.rate_control_mode)
1349 : {
1350 : // Determine offset from the Head Ptr for HLRC histogram queue and set the life count
1351 0 : if (sequence_control_set_ptr->static_config.look_ahead_distance != 0) {
1352 : // Update Histogram Queue Entry Life count
1353 0 : UpdateHistogramQueueEntry(
1354 : sequence_control_set_ptr,
1355 : encode_context_ptr,
1356 : picture_control_set_ptr,
1357 : frames_in_sw);
1358 : }
1359 : }
1360 :
1361 : // Mark each input picture as PAN or not
1362 : // If a lookahead is present then check PAN for a period of time
1363 120 : if (!picture_control_set_ptr->end_of_sequence_flag && sequence_control_set_ptr->static_config.look_ahead_distance != 0) {
1364 : // Check for Pan,Tilt, Zoom and other global motion detectors over the future pictures in the lookahead
1365 118 : UpdateGlobalMotionDetectionOverTime(
1366 : encode_context_ptr,
1367 : sequence_control_set_ptr,
1368 : picture_control_set_ptr);
1369 : }
1370 : else {
1371 2 : if (picture_control_set_ptr->slice_type != I_SLICE)
1372 2 : DetectGlobalMotion(picture_control_set_ptr);
1373 : }
1374 :
1375 : // BACKGROUND ENHANCEMENT PART II
1376 120 : if (!picture_control_set_ptr->end_of_sequence_flag && sequence_control_set_ptr->static_config.look_ahead_distance != 0) {
1377 : // Update BEA information based on Lookahead information
1378 118 : UpdateBeaInfoOverTime(
1379 : encode_context_ptr,
1380 : picture_control_set_ptr);
1381 : }
1382 : else {
1383 : // Reset zzCost information to default When there's no lookahead available
1384 2 : InitZzCostInfo(
1385 : picture_control_set_ptr);
1386 : }
1387 :
1388 : // Use the temporal layer 0 isLcuMotionFieldNonUniform array for all the other layer pictures in the mini GOP
1389 120 : if (!picture_control_set_ptr->end_of_sequence_flag && sequence_control_set_ptr->static_config.look_ahead_distance != 0) {
1390 : // Updat uniformly moving LCUs based on Collocated LCUs in LookAhead window
1391 118 : UpdateMotionFieldUniformityOverTime(
1392 : encode_context_ptr,
1393 : sequence_control_set_ptr,
1394 : picture_control_set_ptr);
1395 : }
1396 : // Derive blockinessPresentFlag
1397 120 : DeriveBlockinessPresentFlag(
1398 : sequence_control_set_ptr,
1399 : picture_control_set_ptr);
1400 :
1401 : // Get Empty Reference Picture Object
1402 120 : eb_get_empty_object(
1403 120 : sequence_control_set_ptr->encode_context_ptr->reference_picture_pool_fifo_ptr,
1404 : &reference_picture_wrapper_ptr);
1405 120 : if (loop_index) {
1406 0 : picture_control_set_ptr->reference_picture_wrapper_ptr = reference_picture_wrapper_ptr;
1407 : // Give the new Reference a nominal live_count of 1
1408 0 : eb_object_inc_live_count(
1409 : picture_control_set_ptr->reference_picture_wrapper_ptr,
1410 : 1);
1411 : }
1412 : else {
1413 120 : ((PictureParentControlSet*)(queueEntryPtr->parent_pcs_wrapper_ptr->object_ptr))->reference_picture_wrapper_ptr = reference_picture_wrapper_ptr;
1414 : // Give the new Reference a nominal live_count of 1
1415 120 : eb_object_inc_live_count(
1416 120 : ((PictureParentControlSet*)(queueEntryPtr->parent_pcs_wrapper_ptr->object_ptr))->reference_picture_wrapper_ptr,
1417 : 1);
1418 : }
1419 : #if TWO_PASS
1420 120 : picture_control_set_ptr->stat_struct_first_pass_ptr = picture_control_set_ptr->is_used_as_reference_flag ? &((EbReferenceObject*)picture_control_set_ptr->reference_picture_wrapper_ptr->object_ptr)->stat_struct : &picture_control_set_ptr->stat_struct;
1421 120 : if (sequence_control_set_ptr->use_output_stat_file)
1422 0 : memset(picture_control_set_ptr->stat_struct_first_pass_ptr, 0, sizeof(stat_struct_t));
1423 : #endif
1424 : //OPTION 1: get the output stream buffer in ressource coordination
1425 120 : eb_get_empty_object(
1426 120 : sequence_control_set_ptr->encode_context_ptr->stream_output_fifo_ptr,
1427 : &output_stream_wrapper_ptr);
1428 :
1429 120 : picture_control_set_ptr->output_stream_wrapper_ptr = output_stream_wrapper_ptr;
1430 :
1431 : // Get Empty Results Object
1432 120 : eb_get_empty_object(
1433 : context_ptr->initialrate_control_results_output_fifo_ptr,
1434 : &outputResultsWrapperPtr);
1435 :
1436 120 : outputResultsPtr = (InitialRateControlResults*)outputResultsWrapperPtr->object_ptr;
1437 :
1438 120 : if (loop_index)
1439 0 : outputResultsPtr->picture_control_set_wrapper_ptr = picture_control_set_ptr->p_pcs_wrapper_ptr;
1440 : else
1441 120 : outputResultsPtr->picture_control_set_wrapper_ptr = queueEntryPtr->parent_pcs_wrapper_ptr;
1442 : // Post the Full Results Object
1443 120 : eb_post_full_object(outputResultsWrapperPtr);
1444 : }
1445 : // Reset the Reorder Queue Entry
1446 120 : queueEntryPtr->picture_number += INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH;
1447 120 : queueEntryPtr->parent_pcs_wrapper_ptr = (EbObjectWrapper *)EB_NULL;
1448 :
1449 : // Increment the Reorder Queue head Ptr
1450 120 : encode_context_ptr->initial_rate_control_reorder_queue_head_index =
1451 120 : (encode_context_ptr->initial_rate_control_reorder_queue_head_index == INITIAL_RATE_CONTROL_REORDER_QUEUE_MAX_DEPTH - 1) ? 0 : encode_context_ptr->initial_rate_control_reorder_queue_head_index + 1;
1452 :
1453 120 : queueEntryPtr = encode_context_ptr->initial_rate_control_reorder_queue[encode_context_ptr->initial_rate_control_reorder_queue_head_index];
1454 : }
1455 : }
1456 : }
1457 :
1458 : // Release the Input Results
1459 7200 : eb_release_object(inputResultsWrapperPtr);
1460 : }
1461 : return EB_NULL;
1462 : }
|