1 /*
2 * Copyright(c) 2019 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5
6 /***************************************
7 * Includes
8 ***************************************/
9
10 #include <stdlib.h>
11
12 #include "EbAppContext.h"
13 #include "EbAppConfig.h"
14
15 #define INPUT_SIZE_576p_TH 0x90000 // 0.58 Million
16 #define INPUT_SIZE_1080i_TH 0xB71B0 // 0.75 Million
17 #define INPUT_SIZE_1080p_TH 0x1AB3F0 // 1.75 Million
18 #define INPUT_SIZE_4K_TH 0x29F630 // 2.75 Million
19
20 #define SIZE_OF_ONE_FRAME_IN_BYTES(width, height,is16bit) ( ( ((width)*(height)*3)>>1 )<<is16bit)
21 #define IS_16_BIT(bit_depth) (bit_depth==10?1:0)
22 #define EB_OUTPUTSTREAMBUFFERSIZE_MACRO(ResolutionSize) ((ResolutionSize) < (INPUT_SIZE_1080i_TH) ? 0x1E8480 : (ResolutionSize) < (INPUT_SIZE_1080p_TH) ? 0x2DC6C0 : (ResolutionSize) < (INPUT_SIZE_4K_TH) ? 0x2DC6C0 : 0x2DC6C0 )
23
24 /***************************************
25 * Variables Defining a memory table
26 * hosting all allocated pointers
27 ***************************************/
28 EbMemoryMapEntry *app_memory_map;
29 uint32_t *app_memory_map_index;
30 uint64_t *total_app_memory;
31 uint32_t app_malloc_count = 0;
32 static EbMemoryMapEntry *app_memory_map_all_channels[MAX_CHANNEL_NUMBER];
33 static uint32_t app_memory_map_index_all_channels[MAX_CHANNEL_NUMBER];
34 static uint64_t app_memory_mallocd_all_channels[MAX_CHANNEL_NUMBER];
35
36 /***************************************
37 * Allocation and initializing a memory table
38 * hosting all allocated pointers
39 ***************************************/
allocate_memory_table(uint32_t instance_idx)40 void allocate_memory_table(
41 uint32_t instance_idx)
42 {
43 // Malloc Memory Table for the instance @ instance_idx
44 app_memory_map_all_channels[instance_idx] = (EbMemoryMapEntry*)malloc(sizeof(EbMemoryMapEntry) * MAX_APP_NUM_PTR);
45
46 // Init the table index
47 app_memory_map_index_all_channels[instance_idx] = 0;
48
49 // Size of the table
50 app_memory_mallocd_all_channels[instance_idx] = sizeof(EbMemoryMapEntry) * MAX_APP_NUM_PTR;
51 total_app_memory = &app_memory_mallocd_all_channels[instance_idx];
52
53 // Set pointer to the first entry
54 app_memory_map = app_memory_map_all_channels[instance_idx];
55
56 // Set index to the first entry
57 app_memory_map_index = &app_memory_map_index_all_channels[instance_idx];
58
59 // Init Number of pointers
60 app_malloc_count = 0;
61
62 return;
63 }
64
65 /*************************************
66 **************************************
67 *** Helper functions Input / Output **
68 **************************************
69 **************************************/
70 /******************************************************
71 * Copy fields from the stream to the input buffer
72 Input : stream
73 Output : valid input buffer
74 ******************************************************/
process_input_field_buffering_mode(uint64_t processed_frame_count,int * filled_len,FILE * input_file,uint8_t * luma_input_ptr,uint8_t * cb_input_ptr,uint8_t * cr_input_ptr,uint32_t input_padded_width,uint32_t input_padded_height,unsigned char is16bit)75 void process_input_field_buffering_mode(
76 uint64_t processed_frame_count,
77 int *filled_len,
78 FILE *input_file,
79 uint8_t *luma_input_ptr,
80 uint8_t *cb_input_ptr,
81 uint8_t *cr_input_ptr,
82 uint32_t input_padded_width,
83 uint32_t input_padded_height,
84 unsigned char is16bit)
85 {
86 uint64_t source_luma_row_size = (uint64_t)(input_padded_width << is16bit);
87 uint64_t source_chroma_row_size = source_luma_row_size >> 1;
88
89 uint8_t *eb_input_ptr;
90 uint32_t input_row_index;
91
92 // Y
93 eb_input_ptr = luma_input_ptr;
94 // Skip 1 luma row if bottom field (point to the bottom field)
95 if (processed_frame_count % 2 != 0)
96 fseeko64(input_file, (long)source_luma_row_size, SEEK_CUR);
97
98 for (input_row_index = 0; input_row_index < input_padded_height; input_row_index++) {
99
100 *filled_len += (uint32_t)fread(eb_input_ptr, 1, source_luma_row_size, input_file);
101 // Skip 1 luma row (only fields)
102 fseeko64(input_file, (long)source_luma_row_size, SEEK_CUR);
103 eb_input_ptr += source_luma_row_size;
104 }
105
106 // U
107 eb_input_ptr = cb_input_ptr;
108 // Step back 1 luma row if bottom field (undo the previous jump), and skip 1 chroma row if bottom field (point to the bottom field)
109 if (processed_frame_count % 2 != 0) {
110 fseeko64(input_file, -(long)source_luma_row_size, SEEK_CUR);
111 fseeko64(input_file, (long)source_chroma_row_size, SEEK_CUR);
112 }
113
114 for (input_row_index = 0; input_row_index < input_padded_height >> 1; input_row_index++) {
115
116 *filled_len += (uint32_t)fread(eb_input_ptr, 1, source_chroma_row_size, input_file);
117 // Skip 1 chroma row (only fields)
118 fseeko64(input_file, (long)source_chroma_row_size, SEEK_CUR);
119 eb_input_ptr += source_chroma_row_size;
120 }
121
122 // V
123 eb_input_ptr = cr_input_ptr;
124 // Step back 1 chroma row if bottom field (undo the previous jump), and skip 1 chroma row if bottom field (point to the bottom field)
125 // => no action
126
127 for (input_row_index = 0; input_row_index < input_padded_height >> 1; input_row_index++) {
128
129 *filled_len += (uint32_t)fread(eb_input_ptr, 1, source_chroma_row_size, input_file);
130 // Skip 1 chroma row (only fields)
131 fseeko64(input_file, (long)source_chroma_row_size, SEEK_CUR);
132 eb_input_ptr += source_chroma_row_size;
133 }
134
135 // Step back 1 chroma row if bottom field (undo the previous jump)
136 if (processed_frame_count % 2 != 0) {
137 fseeko64(input_file, -(long)source_chroma_row_size, SEEK_CUR);
138 }
139 }
140
141 /***********************************************
142 * Copy configuration parameters from
143 * The config structure, to the
144 * callback structure to send to the library
145 ***********************************************/
copy_configuration_parameters(EbConfig * config,EbAppContext * callback_data,uint32_t instance_idx)146 EbErrorType copy_configuration_parameters(
147 EbConfig *config,
148 EbAppContext *callback_data,
149 uint32_t instance_idx)
150 {
151 EbErrorType return_error = EB_ErrorNone;
152
153 // Assign Instance index to the library
154 callback_data->eb_enc_parameters.channel_id = (uint8_t)instance_idx;
155
156 // Initialize Port Activity Flags
157 callback_data->output_stream_port_active = APP_PortActive;
158 callback_data->eb_enc_parameters.source_width = config->source_width;
159 callback_data->eb_enc_parameters.source_height = config->source_height;
160 callback_data->eb_enc_parameters.intra_period = config->intra_period;
161 callback_data->eb_enc_parameters.base_layer_switch_mode = config->base_layer_switch_mode;
162 callback_data->eb_enc_parameters.enc_mode = (uint8_t)config->enc_mode;
163 callback_data->eb_enc_parameters.frame_rate = config->frame_rate;
164 callback_data->eb_enc_parameters.frame_rate_denominator = config->frame_rate_denominator;
165 callback_data->eb_enc_parameters.frame_rate_numerator = config->frame_rate_numerator;
166 callback_data->eb_enc_parameters.pred_structure = (uint8_t)config->pred_structure;
167 callback_data->eb_enc_parameters.rate_control_mode = config->rate_control_mode;
168 callback_data->eb_enc_parameters.target_bit_rate = config->target_bit_rate;
169 callback_data->eb_enc_parameters.max_qp_allowed = config->max_qp_allowed;
170 callback_data->eb_enc_parameters.min_qp_allowed = config->min_qp_allowed;
171 callback_data->eb_enc_parameters.qp = config->qp;
172 callback_data->eb_enc_parameters.vbv_max_rate = config->vbv_max_rate;
173 callback_data->eb_enc_parameters.vbv_buf_size = config->vbv_buf_size;
174 callback_data->eb_enc_parameters.frames_to_be_encoded = config->frames_to_be_encoded;
175 callback_data->eb_enc_parameters.use_qp_file = (uint8_t)config->use_qp_file;
176 callback_data->eb_enc_parameters.loop_filter = (uint8_t)config->loop_filter;
177 callback_data->eb_enc_parameters.use_default_me_hme = (uint8_t)config->use_default_me_hme;
178 callback_data->eb_enc_parameters.enable_hme_flag = (uint8_t)config->enable_hme_flag;
179 callback_data->eb_enc_parameters.search_area_width = config->search_area_width;
180 callback_data->eb_enc_parameters.search_area_height = config->search_area_height;
181 callback_data->eb_enc_parameters.tune = config->tune;
182 callback_data->eb_enc_parameters.recon_file = (config->recon_file) ? (uint32_t)EB_TRUE : (uint32_t)EB_FALSE;
183 callback_data->eb_enc_parameters.channel_id = config->channel_id;
184 callback_data->eb_enc_parameters.active_channel_count = config->active_channel_count;
185 callback_data->eb_enc_parameters.encoder_bit_depth = config->encoder_bit_depth;
186 callback_data->eb_enc_parameters.profile = config->profile;
187 callback_data->eb_enc_parameters.level = config->level;
188 callback_data->eb_enc_parameters.injector_frame_rate = config->injector_frame_rate;
189 callback_data->eb_enc_parameters.speed_control_flag = config->speed_control_flag;
190 callback_data->eb_enc_parameters.asm_type = config->asm_type;
191 callback_data->eb_enc_parameters.logical_processors = config->logical_processors;
192 callback_data->eb_enc_parameters.target_socket = config->target_socket;
193
194 return return_error;
195
196 }
197
allocate_frame_buffer(EbConfig * config,uint8_t * p_buffer)198 static EbErrorType allocate_frame_buffer(
199 EbConfig *config,
200 uint8_t *p_buffer)
201 {
202 EbErrorType return_error = EB_ErrorNone;
203
204 const int ten_bit_packed_mode = (config->encoder_bit_depth > 8) ? 1 : 0;
205
206 // Determine size of each plane
207 const size_t luma8bit_size =
208
209 config->source_width *
210 config->source_height *
211
212 (1 << ten_bit_packed_mode);
213
214 const size_t chroma8bit_size = luma8bit_size >> 2;
215 const size_t luma10bit_size = (config->encoder_bit_depth > 8 && ten_bit_packed_mode == 0) ? luma8bit_size : 0;
216 const size_t chroma10bit_size = (config->encoder_bit_depth > 8 && ten_bit_packed_mode == 0) ? chroma8bit_size : 0;
217
218 // Determine
219 EbSvtEncInput* input_ptr = (EbSvtEncInput*)p_buffer;
220
221 input_ptr->y_stride = config->source_width;
222 input_ptr->cr_stride = config->source_width >> 1;
223 input_ptr->cb_stride = config->source_width >> 1;
224
225 if (luma8bit_size) {
226 EB_APP_MALLOC(unsigned char*, input_ptr->luma, luma8bit_size, EB_N_PTR, EB_ErrorInsufficientResources);
227 }
228 else {
229 input_ptr->luma = 0;
230 }
231 if (chroma8bit_size) {
232 EB_APP_MALLOC(unsigned char*, input_ptr->cb, chroma8bit_size, EB_N_PTR, EB_ErrorInsufficientResources);
233 }
234 else {
235 input_ptr->cb = 0;
236 }
237
238 if (chroma8bit_size) {
239 EB_APP_MALLOC(unsigned char*, input_ptr->cr, chroma8bit_size, EB_N_PTR, EB_ErrorInsufficientResources);
240 }
241 else {
242 input_ptr->cr = 0;
243 }
244
245 if (luma10bit_size) {
246 EB_APP_MALLOC(unsigned char*, input_ptr->luma_ext, luma10bit_size, EB_N_PTR, EB_ErrorInsufficientResources);
247 }
248 else {
249 input_ptr->luma_ext = 0;
250 }
251
252 if (chroma10bit_size) {
253 EB_APP_MALLOC(unsigned char*, input_ptr->cb_ext, chroma10bit_size, EB_N_PTR, EB_ErrorInsufficientResources);
254 }
255 else {
256 input_ptr->cb_ext = 0;
257 }
258
259 if (chroma10bit_size) {
260 EB_APP_MALLOC(unsigned char*, input_ptr->cr_ext, chroma10bit_size, EB_N_PTR, EB_ErrorInsufficientResources);
261
262 }
263 else {
264 input_ptr->cr_ext = 0;
265 }
266
267 return return_error;
268 }
269
AllocateInputBuffers(EbConfig * config,EbAppContext * callback_data)270 EbErrorType AllocateInputBuffers(
271 EbConfig *config,
272 EbAppContext *callback_data)
273 {
274 EbErrorType return_error = EB_ErrorNone;
275 {
276 EB_APP_MALLOC(EbBufferHeaderType*, callback_data->input_buffer_pool, sizeof(EbBufferHeaderType), EB_N_PTR, EB_ErrorInsufficientResources);
277
278 // Initialize Header
279 callback_data->input_buffer_pool->size = sizeof(EbBufferHeaderType);
280
281 EB_APP_MALLOC(uint8_t*, callback_data->input_buffer_pool->p_buffer, sizeof(EbSvtEncInput), EB_N_PTR, EB_ErrorInsufficientResources);
282
283 if (config->buffered_input == -1) {
284
285 // Allocate frame buffer for the p_buffer
286 allocate_frame_buffer(
287 config,
288 callback_data->input_buffer_pool->p_buffer);
289 }
290
291 // Assign the variables
292 callback_data->input_buffer_pool->p_app_private = NULL;
293 callback_data->input_buffer_pool->pic_type = EB_INVALID_PICTURE;
294 }
295
296 return return_error;
297 }
allocate_output_recon_buffers(EbConfig * config,EbAppContext * callback_data)298 EbErrorType allocate_output_recon_buffers(
299 EbConfig *config,
300 EbAppContext *callback_data)
301 {
302
303 EbErrorType return_error = EB_ErrorNone;
304 const size_t luma_size =
305 config->source_width *
306 config->source_height;
307 // both u and v
308 const size_t chroma_size = luma_size >> 1;
309 const size_t ten_bit = (config->encoder_bit_depth > 8);
310 const size_t frame_size = (luma_size + chroma_size) << ten_bit;
311
312 // ... Recon Port
313 EB_APP_MALLOC(EbBufferHeaderType*, callback_data->recon_buffer, sizeof(EbBufferHeaderType), EB_N_PTR, EB_ErrorInsufficientResources);
314
315 // Initialize Header
316 callback_data->recon_buffer->size = sizeof(EbBufferHeaderType);
317
318 EB_APP_MALLOC(uint8_t*, callback_data->recon_buffer->p_buffer, frame_size, EB_N_PTR, EB_ErrorInsufficientResources);
319
320 callback_data->recon_buffer->n_alloc_len = (uint32_t)frame_size;
321 callback_data->recon_buffer->p_app_private = NULL;
322 return return_error;
323 }
324
preload_frames_into_ram(EbConfig * config)325 EbErrorType preload_frames_into_ram(
326 EbConfig *config)
327 {
328 EbErrorType return_error = EB_ErrorNone;
329 int processed_frame_count;
330
331 int filled_len;
332
333 int input_padded_width = config->source_width;
334 int input_padded_height = config->source_height;
335
336 int read_size;
337 unsigned char *eb_input_ptr;
338 FILE *input_file = config->input_file;
339
340 read_size = input_padded_width * input_padded_height * 3 * (config->encoder_bit_depth > 8 ? 2 : 1) / 2;
341
342 EB_APP_MALLOC(unsigned char **, config->sequence_buffer, sizeof(unsigned char*) * config->buffered_input, EB_N_PTR, EB_ErrorInsufficientResources);
343
344 for (processed_frame_count = 0; processed_frame_count < config->buffered_input; ++processed_frame_count) {
345 EB_APP_MALLOC(unsigned char*, config->sequence_buffer[processed_frame_count], read_size, EB_N_PTR, EB_ErrorInsufficientResources);
346
347 // Fill the buffer with a complete frame
348 filled_len = 0;
349 eb_input_ptr = config->sequence_buffer[processed_frame_count];
350 filled_len += (uint32_t)fread(eb_input_ptr, 1, read_size, input_file);
351
352 if (read_size != filled_len) {
353 fseek(config->input_file, 0, SEEK_SET);
354 // Fill the buffer with a complete frame
355 filled_len = 0;
356 eb_input_ptr = config->sequence_buffer[processed_frame_count];
357 filled_len += (uint32_t)fread(eb_input_ptr, 1, read_size, input_file);
358 }
359 }
360
361 return return_error;
362 }
363
364 /***************************************
365 * Functions Implementation
366 ***************************************/
367
368 /***********************************
369 * Initialize Core & Component
370 ***********************************/
init_encoder(EbConfig * config,EbAppContext * callback_data,uint32_t instance_idx)371 EbErrorType init_encoder(
372 EbConfig *config,
373 EbAppContext *callback_data,
374 uint32_t instance_idx)
375 {
376 EbErrorType return_error = EB_ErrorNone;
377
378 // Allocate a memory table hosting all allocated pointers
379 allocate_memory_table(instance_idx);
380
381 ///************************* LIBRARY INIT [START] *********************///
382 // STEP 1: Call the library to construct a Component Handle
383 return_error = eb_vp9_svt_init_handle(&callback_data->svt_encoder_handle, callback_data, &callback_data->eb_enc_parameters);
384
385 if (return_error != EB_ErrorNone) {
386 return return_error;
387 }
388
389 // STEP 3: Copy all configuration parameters into the callback structure
390 return_error = copy_configuration_parameters(
391 config,
392 callback_data,
393 instance_idx);
394
395 if (return_error != EB_ErrorNone) {
396 return return_error;
397 }
398
399 // STEP 4: Send over all configuration parameters
400 // Set the Parameters
401 return_error = eb_vp9_svt_enc_set_parameter(
402 callback_data->svt_encoder_handle,
403 &callback_data->eb_enc_parameters);
404
405 if (return_error != EB_ErrorNone) {
406 return return_error;
407 }
408
409 // STEP 5: Init Encoder
410 return_error = eb_vp9_init_encoder(callback_data->svt_encoder_handle);
411 if (return_error != EB_ErrorNone) { return return_error; }
412
413 ///************************* LIBRARY INIT [END] *********************///
414
415 ///********************** APPLICATION INIT [START] ******************///
416
417 // STEP 6: Allocate input buffers carrying the yuv frames in
418 return_error = AllocateInputBuffers(
419 config,
420 callback_data);
421
422 if (return_error != EB_ErrorNone) {
423 return return_error;
424 }
425
426 // STEP 7: Allocate output Recon Buffer
427 return_error = allocate_output_recon_buffers(
428 config,
429 callback_data);
430
431 if (return_error != EB_ErrorNone) {
432 return return_error;
433 }
434
435 // Allocate the Sequence Buffer
436 if (config->buffered_input != -1) {
437
438 // Preload frames into the ram for a faster yuv access time
439 preload_frames_into_ram(
440 config);
441 }
442 else {
443 config->sequence_buffer = 0;
444 }
445
446 if (return_error != EB_ErrorNone) {
447 return return_error;
448 }
449
450 ///********************** APPLICATION INIT [END] ******************////////
451
452 return return_error;
453 }
454
455 /***********************************
456 * Deinit Components
457 ***********************************/
de_init_encoder(EbAppContext * callback_data_ptr,uint32_t instance_index)458 EbErrorType de_init_encoder(
459 EbAppContext *callback_data_ptr,
460 uint32_t instance_index)
461 {
462 EbErrorType return_error = EB_ErrorNone;
463 int32_t ptr_index = 0;
464 EbMemoryMapEntry* memory_entry = (EbMemoryMapEntry*)0;
465
466 if (((EbComponentType*)(callback_data_ptr->svt_encoder_handle)) != NULL) {
467 return_error = eb_vp9_deinit_encoder(callback_data_ptr->svt_encoder_handle);
468 }
469
470 // Destruct the buffer memory pool
471 if (return_error != EB_ErrorNone) {
472 return return_error;
473 }
474
475 // Loop through the ptr table and free all malloc'd pointers per channel
476 for (ptr_index = app_memory_map_index_all_channels[instance_index] - 1; ptr_index >= 0; --ptr_index) {
477 memory_entry = &app_memory_map_all_channels[instance_index][ptr_index];
478 switch (memory_entry->ptr_type) {
479 case EB_N_PTR:
480 free(memory_entry->ptr);
481 break;
482 default:
483 return_error = EB_ErrorMax;
484 break;
485 }
486 }
487 free(app_memory_map_all_channels[instance_index]);
488
489 // Destruct the component
490 eb_vp9_deinit_handle(callback_data_ptr->svt_encoder_handle);
491
492 return return_error;
493 }
494