1 /*
2 * Copyright(c) 2019 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5
6 #include <stdlib.h>
7
8 #include "EbEntropyCodingProcess.h"
9 #include "EbEncDecResults.h"
10 #include "EbEntropyCodingResults.h"
11 #include "EbRateControlTasks.h"
12
13 #include "vp9_blockd.h"
14 #include "vp9_encoder.h"
15 #include "stdint.h"//#include "bitwriter_buffer.h"
16 #include "vp9_bitstream.h"
17 #include "vp9_enums.h"
18 #include "bitwriter.h"
19 #if SEG_SUPPORT
20 #include "vp9_segmentation.h"
21
22 #endif
23 /******************************************************
24 * Enc Dec Context Constructor
25 ******************************************************/
eb_vp9_entropy_coding_context_ctor(EntropyCodingContext ** context_dbl_ptr,EbFifo * enc_dec_input_fifo_ptr,EbFifo * packetization_output_fifo_ptr,EbFifo * rate_control_output_fifo_ptr,EB_BOOL is16bit)26 EbErrorType eb_vp9_entropy_coding_context_ctor(
27 EntropyCodingContext **context_dbl_ptr,
28 EbFifo *enc_dec_input_fifo_ptr,
29 EbFifo *packetization_output_fifo_ptr,
30 EbFifo *rate_control_output_fifo_ptr,
31 EB_BOOL is16bit)
32 {
33 EntropyCodingContext *context_ptr;
34 EB_MALLOC(EntropyCodingContext*, context_ptr, sizeof(EntropyCodingContext), EB_N_PTR);
35 *context_dbl_ptr = context_ptr;
36
37 context_ptr->is16bit = is16bit;
38
39 // Input/Output System Resource Manager FIFOs
40 context_ptr->enc_dec_input_fifo_ptr = enc_dec_input_fifo_ptr;
41 context_ptr->entropy_coding_output_fifo_ptr = packetization_output_fifo_ptr;
42 context_ptr->rate_control_output_fifo_ptr = rate_control_output_fifo_ptr;
43
44 EB_MALLOC(MACROBLOCKD*, context_ptr->e_mbd , sizeof(MACROBLOCKD), EB_N_PTR);
45 EB_MALLOC(ModeInfo **, context_ptr->e_mbd->mi , sizeof(ModeInfo *), EB_N_PTR);
46
47 EB_MALLOC(ENTROPY_CONTEXT*, context_ptr->e_mbd->plane[0].above_context, sizeof(ENTROPY_CONTEXT) * 16, EB_N_PTR);
48 EB_MALLOC(ENTROPY_CONTEXT*, context_ptr->e_mbd->plane[0].left_context , sizeof(ENTROPY_CONTEXT) * 16, EB_N_PTR);
49
50 EB_MALLOC(ENTROPY_CONTEXT*, context_ptr->e_mbd->plane[1].above_context, sizeof(ENTROPY_CONTEXT) * 16, EB_N_PTR);
51 EB_MALLOC(ENTROPY_CONTEXT*, context_ptr->e_mbd->plane[1].left_context , sizeof(ENTROPY_CONTEXT) * 16, EB_N_PTR);
52
53 EB_MALLOC(ENTROPY_CONTEXT*, context_ptr->e_mbd->plane[2].above_context, sizeof(ENTROPY_CONTEXT) * 16, EB_N_PTR);
54 EB_MALLOC(ENTROPY_CONTEXT*, context_ptr->e_mbd->plane[2].left_context , sizeof(ENTROPY_CONTEXT) * 16, EB_N_PTR);
55 // Hsan - how many token do we really need ?
56 EB_MALLOC(TOKENEXTRA*, context_ptr->tok, sizeof(TOKENEXTRA) * MAX_CU_SIZE * MAX_CU_SIZE * MAX_MB_PLANE, EB_N_PTR);
57
58 return EB_ErrorNone;
59 }
60
61 /**********************************************
62 * Entropy Coding SB
63 **********************************************/
EntropyCodingSb(PictureControlSet * picture_control_set_ptr,EntropyCodingContext * context_ptr,SbUnit * sb_ptr,EntropyCoder * entropy_coder_ptr)64 EbErrorType EntropyCodingSb(
65 PictureControlSet *picture_control_set_ptr,
66 EntropyCodingContext *context_ptr,
67 SbUnit *sb_ptr,
68 EntropyCoder *entropy_coder_ptr)
69 {
70 EbErrorType return_error = EB_ErrorNone;
71
72 SequenceControlSet *sequence_control_set_ptr = (SequenceControlSet *)picture_control_set_ptr->sequence_control_set_wrapper_ptr->object_ptr;
73
74 VpxWriter *residual_bc = &(entropy_coder_ptr->residual_bc);
75 VP9_COMP *cpi = picture_control_set_ptr->parent_pcs_ptr->cpi;
76 VP9_COMMON *const cm = &cpi->common;
77 MACROBLOCKD *const xd = context_ptr->e_mbd;
78 OutputBitstreamUnit *output_bitstream_ptr = (OutputBitstreamUnit *)(picture_control_set_ptr->entropy_coder_ptr->ec_output_bitstream_ptr);
79
80 uint32_t block_index = 0;
81 uint32_t rasterScanIndex;
82 uint16_t valid_block_index;
83
84 // Set mi_grid_visible
85 cm->mi_grid_visible = picture_control_set_ptr->mode_info_array;
86
87 // Get SB Params
88 SbParams * lcuParam = &sequence_control_set_ptr->sb_params_array[sb_ptr->sb_index];
89
90 // Reset residual_bc each SB
91 uint8_t *data = output_bitstream_ptr->buffer;
92 size_t total_size = 0;
93
94 // Reset above context @ the 1st SB
95 if (sb_ptr->sb_index == 0) {
96
97 eb_vp9_start_encode(residual_bc, data + total_size);
98
99 // Note: this memset assumes above_context[0], [1] and [2]
100 // are allocated as part of the same buffer.
101 memset(cm->above_context, 0, sizeof(*cm->above_context) * MAX_MB_PLANE * 2 * mi_cols_aligned_to_sb(cm->mi_cols));
102 memset(cm->above_seg_context, 0, sizeof(*cm->above_seg_context) * mi_cols_aligned_to_sb(cm->mi_cols));
103 }
104
105 // Reset left context @ each row of SB
106 if (sb_ptr->origin_x == 0) {
107 // Initialize the left context for the new SB row
108 memset(&xd->left_context, 0, sizeof(xd->left_context));
109 memset(xd->left_seg_context, 0, sizeof(xd->left_seg_context));
110 set_partition_probs(cm, xd);
111 }
112 #if VP9_PERFORM_EP
113 sb_ptr->quantized_coeff_buffer_block_offset[0] = sb_ptr->quantized_coeff_buffer_block_offset[1] = sb_ptr->quantized_coeff_buffer_block_offset[2] = 0;
114 #endif
115 do {
116
117 context_ptr->block_ptr = sb_ptr->coded_block_array_ptr[block_index];
118 context_ptr->ep_block_stats_ptr = ep_get_block_stats(block_index);
119 rasterScanIndex = ep_scan_to_raster_scan[block_index];
120 context_ptr->block_width = context_ptr->ep_block_stats_ptr->bwidth;
121 context_ptr->block_height = context_ptr->ep_block_stats_ptr->bheight;
122 context_ptr->block_origin_x = (uint16_t)sb_ptr->origin_x + context_ptr->ep_block_stats_ptr->origin_x;
123 context_ptr->block_origin_y = (uint16_t)sb_ptr->origin_y + context_ptr->ep_block_stats_ptr->origin_y;
124 context_ptr->mi_col = context_ptr->block_origin_x >> MI_SIZE_LOG2;
125 context_ptr->mi_row = context_ptr->block_origin_y >> MI_SIZE_LOG2;
126
127 // Derive partition using block validity and split_flag
128 // ec_scan_block_valid_block holds the block index for the first valid block/subblock
129 // covered by the block (at any depth). A block is valid if it is within the frame boundary.
130 valid_block_index = lcuParam->ec_scan_block_valid_block[block_index];
131
132 PARTITION_TYPE partition;
133 if (valid_block_index == (uint16_t)~0) {
134 partition = PARTITION_INVALID;
135 }
136 else {
137 if (valid_block_index == block_index) {
138 if(context_ptr->block_ptr->split_flag == EB_TRUE)
139 partition = PARTITION_SPLIT;
140 else
141 partition = PARTITION_NONE;
142 }
143 else {
144 partition = PARTITION_SPLIT;
145 }
146 }
147
148 if (partition != PARTITION_INVALID) {
149 const int bsl = eb_vp9_b_width_log2_lookup[context_ptr->ep_block_stats_ptr->bsize];
150 const int bs = (1 << bsl) / 4;
151 BLOCK_SIZE subsize = get_subsize(context_ptr->ep_block_stats_ptr->bsize, partition);
152
153 // From SVT to WebM (symbols)
154 xd->mi[0] = cm->mi_grid_visible[context_ptr->mi_col + context_ptr->mi_row * cm->mi_stride];
155
156 vp9_init_macroblockd(cm, xd, NULL);
157
158 // Write partition
159 write_partition(cm, xd, bs, context_ptr->mi_row, context_ptr->mi_col, partition, context_ptr->ep_block_stats_ptr->bsize, residual_bc);
160
161 // Write mode info for final partitioning
162 if (partition == PARTITION_NONE || (partition == PARTITION_SPLIT && ep_get_block_stats(block_index)->bsize == BLOCK_8X8)) {
163
164 // Set above_mi and left_mi
165 context_ptr->e_mbd->above_mi = (context_ptr->mi_row > 0) ? cm->mi_grid_visible[context_ptr->mi_col + context_ptr->mi_row * cm->mi_stride - cm->mi_stride] : NULL;
166 context_ptr->e_mbd->left_mi = (context_ptr->mi_col > 0) ? cm->mi_grid_visible[context_ptr->mi_col + context_ptr->mi_row * cm->mi_stride - 1] : NULL;
167
168 // Set WebM relevant fields
169 xd->mb_to_top_edge = -((context_ptr->mi_row * MI_SIZE) * 8);
170 xd->mb_to_bottom_edge = ((picture_control_set_ptr->parent_pcs_ptr->cpi->common.mi_rows - eb_vp9_num_8x8_blocks_high_lookup[context_ptr->ep_block_stats_ptr->bsize] - context_ptr->mi_row) * MI_SIZE) * 8;
171 xd->mb_to_left_edge = -((context_ptr->mi_col * MI_SIZE) * 8);
172 xd->mb_to_right_edge = ((picture_control_set_ptr->parent_pcs_ptr->cpi->common.mi_cols - eb_vp9_num_8x8_blocks_wide_lookup[context_ptr->ep_block_stats_ptr->bsize] - context_ptr->mi_col) * MI_SIZE) * 8;
173
174 xd->plane[0].subsampling_x = xd->plane[0].subsampling_y = 0;
175 xd->plane[1].subsampling_x = xd->plane[1].subsampling_y = 1;
176 xd->plane[2].subsampling_x = xd->plane[2].subsampling_y = 1;
177
178 xd->lossless = 0;
179
180 // Get eobs
181 if (xd->mi[0]->sb_type < BLOCK_8X8) {
182 cpi->td.mb.plane[0].eobs[0] = sb_ptr->coded_block_array_ptr[block_index + ep_inter_depth_offset ]->eob[0][0];
183 cpi->td.mb.plane[0].eobs[1] = sb_ptr->coded_block_array_ptr[block_index + ep_inter_depth_offset + 1]->eob[0][0];
184 cpi->td.mb.plane[0].eobs[2] = sb_ptr->coded_block_array_ptr[block_index + ep_inter_depth_offset + 2]->eob[0][0];
185 cpi->td.mb.plane[0].eobs[3] = sb_ptr->coded_block_array_ptr[block_index + ep_inter_depth_offset + 3]->eob[0][0];
186
187 cpi->td.mb.plane[1].eobs[0] = sb_ptr->coded_block_array_ptr[block_index + ep_inter_depth_offset + 3]->eob[1][0];
188 cpi->td.mb.plane[2].eobs[0] = sb_ptr->coded_block_array_ptr[block_index + ep_inter_depth_offset + 3]->eob[2][0];
189 }
190 else {
191 for (uint8_t tu_index = 0; tu_index < ((context_ptr->ep_block_stats_ptr->sq_size == MAX_SB_SIZE) ? 4 : 1); tu_index++) {
192 cpi->td.mb.plane[0].eobs[tu_index * 64] = context_ptr->block_ptr->eob[0][tu_index];
193 }
194 cpi->td.mb.plane[1].eobs[0] = context_ptr->block_ptr->eob[1][0];
195 cpi->td.mb.plane[2].eobs[0] = context_ptr->block_ptr->eob[2][0];
196 }
197
198 // From SVT to WebM (coeff)
199 #if VP9_PERFORM_EP
200 cpi->td.mb.plane[0].qcoeff = &(((int16_t*)sb_ptr->quantized_coeff_buffer[0])[sb_ptr->quantized_coeff_buffer_block_offset[0]]);
201 cpi->td.mb.plane[1].qcoeff = &(((int16_t*)sb_ptr->quantized_coeff_buffer[1])[sb_ptr->quantized_coeff_buffer_block_offset[1]]);
202 cpi->td.mb.plane[2].qcoeff = &(((int16_t*)sb_ptr->quantized_coeff_buffer[2])[sb_ptr->quantized_coeff_buffer_block_offset[2]]);
203
204 sb_ptr->quantized_coeff_buffer_block_offset[0] += (context_ptr->ep_block_stats_ptr->sq_size * context_ptr->ep_block_stats_ptr->sq_size );
205 sb_ptr->quantized_coeff_buffer_block_offset[1] += (context_ptr->ep_block_stats_ptr->sq_size * context_ptr->ep_block_stats_ptr->sq_size ) >> 2;
206 sb_ptr->quantized_coeff_buffer_block_offset[2] += (context_ptr->ep_block_stats_ptr->sq_size * context_ptr->ep_block_stats_ptr->sq_size ) >> 2;
207 #else
208 if (xd->mi[0]->skip == EB_FALSE)
209 {
210
211 if (xd->mi[0]->sb_type < BLOCK_8X8) {
212
213 // Y: 1st mbi
214 {
215 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_y)[context_ptr->ep_block_stats_ptr->origin_x + context_ptr->ep_block_stats_ptr->origin_y * sb_ptr->quantized_coeff->stride_y]);
216 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[0].qcoeff)[0]);
217
218 for (int j = 0; j < 4; j++) {
219 EB_MEMCPY(dst_ptr, src_ptr, 4 * sizeof(int16_t));
220 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_y;
221 dst_ptr = dst_ptr + 4;
222 }
223 }
224
225 // Y: 2nd mbi
226 {
227 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_y)[context_ptr->ep_block_stats_ptr->origin_x + 4 + context_ptr->ep_block_stats_ptr->origin_y * sb_ptr->quantized_coeff->stride_y]);
228 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[0].qcoeff)[16]);
229
230 for (int j = 0; j < 4; j++) {
231 EB_MEMCPY(dst_ptr, src_ptr, 4 * sizeof(int16_t));
232 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_y;
233 dst_ptr = dst_ptr + 4;
234 }
235 }
236
237 // Y: 3rd mbi
238 {
239 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_y)[context_ptr->ep_block_stats_ptr->origin_x + (context_ptr->ep_block_stats_ptr->origin_y + 4) * sb_ptr->quantized_coeff->stride_y]);
240 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[0].qcoeff)[32]);
241
242 for (int j = 0; j < 4; j++) {
243 EB_MEMCPY(dst_ptr, src_ptr, 4 * sizeof(int16_t));
244 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_y;
245 dst_ptr = dst_ptr + 4;
246 }
247 }
248
249 // Y: 4th mbi
250 {
251 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_y)[context_ptr->ep_block_stats_ptr->origin_x + 4 + (context_ptr->ep_block_stats_ptr->origin_y + 4) * sb_ptr->quantized_coeff->stride_y]);
252 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[0].qcoeff)[48]);
253
254 for (int j = 0; j < 4; j++) {
255 EB_MEMCPY(dst_ptr, src_ptr, 4 * sizeof(int16_t));
256 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_y;
257 dst_ptr = dst_ptr + 4;
258 }
259 }
260
261 #if 1
262 //Cb
263 {
264 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_cb)[(context_ptr->ep_block_stats_ptr->origin_x >> 1) + (context_ptr->ep_block_stats_ptr->origin_y >> 1) * sb_ptr->quantized_coeff->stride_cb]);
265 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[1].qcoeff)[0]);
266
267 for (int j = 0; j < context_ptr->ep_block_stats_ptr->sq_size_uv; j++) {
268 EB_MEMCPY(dst_ptr, src_ptr, context_ptr->ep_block_stats_ptr->sq_size_uv * sizeof(int16_t));
269 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_cb;
270 dst_ptr = dst_ptr + context_ptr->ep_block_stats_ptr->sq_size_uv;
271 }
272 }
273
274 //Cr
275 {
276 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_cr)[(context_ptr->ep_block_stats_ptr->origin_x >> 1) + (context_ptr->ep_block_stats_ptr->origin_y >> 1) * sb_ptr->quantized_coeff->stride_cr]);
277 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[2].qcoeff)[0]);
278
279 for (int j = 0; j < context_ptr->ep_block_stats_ptr->sq_size_uv; j++) {
280 EB_MEMCPY(dst_ptr, src_ptr, context_ptr->ep_block_stats_ptr->sq_size_uv * sizeof(int16_t));
281 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_cr;
282 dst_ptr = dst_ptr + context_ptr->ep_block_stats_ptr->sq_size_uv;
283 }
284 }
285 #endif
286
287 }
288 else {
289 //Y
290 {
291 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_y)[context_ptr->ep_block_stats_ptr->origin_x + context_ptr->ep_block_stats_ptr->origin_y * sb_ptr->quantized_coeff->stride_y]);
292 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[0].qcoeff)[0]);
293
294 for (int j = 0; j < context_ptr->ep_block_stats_ptr->sq_size; j++) {
295 EB_MEMCPY(dst_ptr, src_ptr, context_ptr->ep_block_stats_ptr->sq_size * sizeof(int16_t));
296 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_y;
297 dst_ptr = dst_ptr + context_ptr->ep_block_stats_ptr->sq_size;
298 }
299 }
300
301 //Cb
302 {
303 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_cb)[(context_ptr->ep_block_stats_ptr->origin_x >> 1) + (context_ptr->ep_block_stats_ptr->origin_y >> 1) * sb_ptr->quantized_coeff->stride_cb]);
304 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[1].qcoeff)[0]);
305
306 for (int j = 0; j < context_ptr->ep_block_stats_ptr->sq_size_uv; j++) {
307 EB_MEMCPY(dst_ptr, src_ptr, context_ptr->ep_block_stats_ptr->sq_size_uv * sizeof(int16_t));
308 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_cb;
309 dst_ptr = dst_ptr + context_ptr->ep_block_stats_ptr->sq_size_uv;
310 }
311 }
312
313 //Cr
314 {
315 int16_t* src_ptr = &(((int16_t*)sb_ptr->quantized_coeff->buffer_cr)[(context_ptr->ep_block_stats_ptr->origin_x >> 1) + (context_ptr->ep_block_stats_ptr->origin_y >> 1) * sb_ptr->quantized_coeff->stride_cr]);
316 tran_low_t* dst_ptr = &(((tran_low_t*)cpi->td.mb.plane[2].qcoeff)[0]);
317
318 for (int j = 0; j < context_ptr->ep_block_stats_ptr->sq_size_uv; j++) {
319 EB_MEMCPY(dst_ptr, src_ptr, context_ptr->ep_block_stats_ptr->sq_size_uv * sizeof(int16_t));
320 src_ptr = src_ptr + sb_ptr->quantized_coeff->stride_cr;
321 dst_ptr = dst_ptr + context_ptr->ep_block_stats_ptr->sq_size_uv;
322 }
323 }
324 }
325 }
326 #endif
327
328 // Set skip context
329 set_skip_context(xd, context_ptr->mi_row, context_ptr->mi_col);
330
331 // Track the head of the tok buffer
332 context_ptr->tok_start = context_ptr->tok;
333
334 // Tokonize the SB
335 eb_vp9_tokenize_sb(cpi, xd, &cpi->td, &context_ptr->tok, 0, 0, VPXMAX(context_ptr->ep_block_stats_ptr->bsize, BLOCK_8X8));
336
337 // Add EOSB_TOKEN
338 context_ptr->tok->token = EOSB_TOKEN;
339 context_ptr->tok_end = context_ptr->tok + 1;
340
341 // Reset the tok buffer
342 context_ptr->tok = context_ptr->tok_start;
343
344 // Write mode info
345 eb_vp9_write_modes_b(context_ptr, cpi, xd, (TileInfo *)EB_NULL, residual_bc, &context_ptr->tok, context_ptr->tok_end, context_ptr->mi_row, context_ptr->mi_col, &cpi->max_mv_magnitude, cpi->interp_filter_selected);
346
347 // Reset the tok buffer
348 context_ptr->tok = context_ptr->tok_start;
349
350 // Update partition context
351 if (context_ptr->ep_block_stats_ptr->bsize >= BLOCK_8X8 && (context_ptr->ep_block_stats_ptr->bsize == BLOCK_8X8 || partition != PARTITION_SPLIT))
352 update_partition_context(xd, context_ptr->mi_row, context_ptr->mi_col, subsize, context_ptr->ep_block_stats_ptr->bsize);
353
354 // Next CU in the current depth
355 block_index += ep_intra_depth_offset[ep_raster_scan_block_depth[rasterScanIndex]];
356 }
357 else {
358 // Next CU in the next depth
359 block_index = block_index + ep_inter_depth_offset;
360 }
361 }
362 else {
363
364 if (context_ptr->block_origin_x >= sequence_control_set_ptr->luma_width || context_ptr->block_origin_y >= sequence_control_set_ptr->luma_height) {
365 // Next CU in the current depth
366 block_index += ep_intra_depth_offset[ep_raster_scan_block_depth[rasterScanIndex]];
367 }
368 else {
369 // Next CU in the next depth
370 block_index = block_index + ep_inter_depth_offset;
371 }
372 }
373
374 } while (block_index < EP_BLOCK_MAX_COUNT);
375
376 // Stop writing
377 if (sb_ptr->sb_index == (unsigned) picture_control_set_ptr->sb_total_count - 1) {
378 eb_vp9_stop_encode(residual_bc);
379 }
380
381 return return_error;
382 }
383
384 /******************************************************
385 * Update Entropy Coding Rows
386 *
387 * This function is responsible for synchronizing the
388 * processing of Entropy Coding LCU-rows and starts
389 * processing of LCU-rows as soon as their inputs are
390 * available and the previous LCU-row has completed.
391 * At any given time, only one segment row per picture
392 * is being processed.
393 *
394 * The function has two parts:
395 *
396 * (1) Update the available row index which tracks
397 * which LCU Row-inputs are available.
398 *
399 * (2) Increment the lcu-row counter as the segment-rows
400 * are completed.
401 *
402 * Since there is the potentential for thread collusion,
403 * a MUTEX a used to protect the sensitive data and
404 * the execution flow is separated into two paths
405 *
406 * (A) Initial update.
407 * -Update the Completion Mask [see (1) above]
408 * -If the picture is not currently being processed,
409 * check to see if the next segment-row is available
410 * and start processing.
411 * (B) Continued processing
412 * -Upon the completion of a segment-row, check
413 * to see if the next segment-row's inputs have
414 * become available and begin processing if so.
415 *
416 * On last important point is that the thread-safe
417 * code section is kept minimally short. The MUTEX
418 * should NOT be locked for the entire processing
419 * of the segment-row (B) as this would block other
420 * threads from performing an update (A).
421 ******************************************************/
update_entropy_coding_rows(PictureControlSet * picture_control_set_ptr,uint32_t * row_index,uint32_t row_count,EB_BOOL * initial_process_call)422 static EB_BOOL update_entropy_coding_rows(
423 PictureControlSet *picture_control_set_ptr,
424 uint32_t *row_index,
425 uint32_t row_count,
426 EB_BOOL *initial_process_call)
427 {
428 EB_BOOL process_next_row = EB_FALSE;
429
430 // Note, any writes & reads to status variables (e.g. in_progress) in MD-CTRL must be thread-safe
431 eb_vp9_block_on_mutex(picture_control_set_ptr->entropy_coding_mutex);
432
433 // Update availability mask
434 if (*initial_process_call == EB_TRUE) {
435 unsigned i;
436
437 for(i=*row_index; i < *row_index + row_count; ++i) {
438 picture_control_set_ptr->entropy_coding_row_array[i] = EB_TRUE;
439 }
440
441 while(picture_control_set_ptr->entropy_coding_row_array[picture_control_set_ptr->entropy_coding_current_available_row] == EB_TRUE &&
442 picture_control_set_ptr->entropy_coding_current_available_row < picture_control_set_ptr->entropy_coding_row_count)
443 {
444 ++picture_control_set_ptr->entropy_coding_current_available_row;
445 }
446 }
447
448 // Release in_progress token
449 if(*initial_process_call == EB_FALSE && picture_control_set_ptr->entropy_coding_in_progress == EB_TRUE) {
450 picture_control_set_ptr->entropy_coding_in_progress = EB_FALSE;
451 }
452
453 // Test if the picture is not already complete AND not currently being worked on by another ENCDEC process
454 if(picture_control_set_ptr->entropy_coding_current_row < picture_control_set_ptr->entropy_coding_row_count &&
455 picture_control_set_ptr->entropy_coding_row_array[picture_control_set_ptr->entropy_coding_current_row] == EB_TRUE &&
456 picture_control_set_ptr->entropy_coding_in_progress == EB_FALSE)
457 {
458 // Test if the next LCU-row is ready to go
459 if(picture_control_set_ptr->entropy_coding_current_row <= picture_control_set_ptr->entropy_coding_current_available_row)
460 {
461 picture_control_set_ptr->entropy_coding_in_progress = EB_TRUE;
462 *row_index = picture_control_set_ptr->entropy_coding_current_row++;
463 process_next_row = EB_TRUE;
464 }
465 }
466
467 *initial_process_call = EB_FALSE;
468
469 eb_vp9_release_mutex(picture_control_set_ptr->entropy_coding_mutex);
470
471 return process_next_row;
472 }
473
474 /******************************************************
475 * Entropy Coding Kernel
476 ******************************************************/
eb_vp9_entropy_coding_kernel(void * input_ptr)477 void* eb_vp9_entropy_coding_kernel(void *input_ptr)
478 {
479 // Context & SCS & PCS
480 EntropyCodingContext *context_ptr = (EntropyCodingContext*) input_ptr;
481 PictureControlSet *picture_control_set_ptr;
482 SequenceControlSet *sequence_control_set_ptr;
483
484 // Input
485 EbObjectWrapper *enc_dec_results_wrapper_ptr;
486 EncDecResults *enc_dec_results_ptr;
487
488 // Output
489 EbObjectWrapper *entropy_coding_results_wrapper_ptr;
490 EntropyCodingResults *entropy_coding_results_ptr;
491
492 // LCU Loop variables
493 SbUnit *sb_ptr;
494 uint16_t sb_index;
495 uint32_t xsb_index;
496 uint32_t ysb_index;
497 uint32_t picture_width_in_sb;
498 // Variables
499 EB_BOOL initial_process_call;
500
501 for(;;) {
502
503 // Get Mode Decision Results
504 eb_vp9_get_full_object(
505 context_ptr->enc_dec_input_fifo_ptr,
506 &enc_dec_results_wrapper_ptr);
507 enc_dec_results_ptr = (EncDecResults*) enc_dec_results_wrapper_ptr->object_ptr;
508 picture_control_set_ptr = (PictureControlSet *) enc_dec_results_ptr->picture_control_set_wrapper_ptr->object_ptr;
509 sequence_control_set_ptr = (SequenceControlSet *) picture_control_set_ptr->sequence_control_set_wrapper_ptr->object_ptr;
510
511 // LCU Constants
512 picture_width_in_sb = (sequence_control_set_ptr->luma_width + MAX_SB_SIZE_MINUS_1) >> LOG2F_MAX_SB_SIZE;
513 {
514 initial_process_call = EB_TRUE;
515 ysb_index = enc_dec_results_ptr->completed_sb_row_index_start;
516
517 // LCU-loops
518 while(update_entropy_coding_rows(picture_control_set_ptr, &ysb_index, enc_dec_results_ptr->completed_sb_row_count, &initial_process_call) == EB_TRUE)
519 {
520 uint32_t rowsb_total_bits = 0;
521
522 if(ysb_index == 0) {
523 picture_control_set_ptr->entropy_coding_pic_done = EB_FALSE;
524 }
525
526 for(xsb_index = 0; xsb_index < picture_width_in_sb; ++xsb_index)
527 {
528
529 sb_index = (uint16_t)(xsb_index + ysb_index * picture_width_in_sb);
530 sb_ptr = picture_control_set_ptr->sb_ptr_array[sb_index];
531
532 sb_ptr->sb_total_bits = 0;
533 #if VP9_RC
534 uint32_t prev_pos = sb_index ? picture_control_set_ptr->entropy_coder_ptr->residual_bc.pos : 0;
535 #endif
536 #if SEG_SUPPORT
537 if (sb_index == 0) {
538 MACROBLOCKD *xd = NULL;
539 VP9_COMMON *const cm = &picture_control_set_ptr->parent_pcs_ptr->cpi->common;
540
541 struct segmentation *seg = &cm->seg;
542 if (seg->update_map) {
543 vpx_prob no_pred_tree[SEG_TREE_PROBS];
544 memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
545 memset(seg->pred_probs, 255, sizeof(seg->pred_probs));
546 // Work out probability tree for coding segments without prediction
547 calc_segtree_probs(picture_control_set_ptr->segment_counts, no_pred_tree);
548 seg->temporal_update = 0;
549 EB_MEMCPY(seg->tree_probs, no_pred_tree, sizeof(no_pred_tree));
550
551 }
552 }
553 #endif
554 // Entropy Coding
555 EntropyCodingSb(
556 picture_control_set_ptr,
557 context_ptr,
558 sb_ptr,
559 picture_control_set_ptr->entropy_coder_ptr);
560 #if VP9_RC
561 sb_ptr->sb_total_bits = (picture_control_set_ptr->entropy_coder_ptr->residual_bc.pos - prev_pos)<<3;
562 picture_control_set_ptr->parent_pcs_ptr->quantized_coeff_num_bits += sb_ptr->sb_total_bits;
563 #endif
564
565 rowsb_total_bits += sb_ptr->sb_total_bits;
566 }
567
568 // At the end of each LCU-row, send the updated bit-count to Entropy Coding
569 {
570 EbObjectWrapper *rate_control_task_wrapper_ptr;
571 RateControlTasks *rate_control_task_ptr;
572
573 // Get Empty EncDec Results
574 eb_vp9_get_empty_object(
575 context_ptr->rate_control_output_fifo_ptr,
576 &rate_control_task_wrapper_ptr);
577 rate_control_task_ptr = (RateControlTasks*) rate_control_task_wrapper_ptr->object_ptr;
578 rate_control_task_ptr->task_type = RC_ENTROPY_CODING_ROW_FEEDBACK_RESULT;
579 rate_control_task_ptr->picture_number = picture_control_set_ptr->picture_number;
580 rate_control_task_ptr->row_number = ysb_index;
581 rate_control_task_ptr->bit_count = rowsb_total_bits;
582
583 rate_control_task_ptr->picture_control_set_wrapper_ptr = 0;
584 rate_control_task_ptr->segment_index = ~0u;
585
586 // Post EncDec Results
587 eb_vp9_post_full_object(rate_control_task_wrapper_ptr);
588 }
589
590 eb_vp9_block_on_mutex(picture_control_set_ptr->entropy_coding_mutex);
591 if (picture_control_set_ptr->entropy_coding_pic_done == EB_FALSE) {
592
593 // If the picture is complete, terminate the slice
594 if (picture_control_set_ptr->entropy_coding_current_row == picture_control_set_ptr->entropy_coding_row_count)
595 {
596 uint32_t ref_idx;
597
598 picture_control_set_ptr->entropy_coding_pic_done = EB_TRUE;
599
600 // Release the List 0 Reference Pictures
601 for (ref_idx = 0; ref_idx < picture_control_set_ptr->parent_pcs_ptr->ref_list0_count; ++ref_idx) {
602 if (picture_control_set_ptr->ref_pic_ptr_array[0] != EB_NULL) {
603
604 eb_vp9_release_object(picture_control_set_ptr->ref_pic_ptr_array[0]);
605 }
606 }
607
608 // Release the List 1 Reference Pictures
609 for (ref_idx = 0; ref_idx < picture_control_set_ptr->parent_pcs_ptr->ref_list1_count; ++ref_idx) {
610 if (picture_control_set_ptr->ref_pic_ptr_array[1] != EB_NULL) {
611
612 eb_vp9_release_object(picture_control_set_ptr->ref_pic_ptr_array[1]);
613 }
614 }
615
616 // Get Empty Entropy Coding Results
617 eb_vp9_get_empty_object(
618 context_ptr->entropy_coding_output_fifo_ptr,
619 &entropy_coding_results_wrapper_ptr);
620 entropy_coding_results_ptr = (EntropyCodingResults*)entropy_coding_results_wrapper_ptr->object_ptr;
621 entropy_coding_results_ptr->picture_control_set_wrapper_ptr = enc_dec_results_ptr->picture_control_set_wrapper_ptr;
622
623 // Post EntropyCoding Results
624 eb_vp9_post_full_object(entropy_coding_results_wrapper_ptr);
625
626 } // End if(PictureCompleteFlag)
627 }
628 eb_vp9_release_mutex(picture_control_set_ptr->entropy_coding_mutex);
629
630 }
631 }
632 // Release Mode Decision Results
633 eb_vp9_release_object(enc_dec_results_wrapper_ptr);
634
635 }
636
637 return EB_NULL;
638 }
639