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