1 /*
2 * Copyright(c) 2018 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 
16 #define INPUT_SIZE_576p_TH				0x90000     // 0.58 Million
17 #define INPUT_SIZE_1080i_TH				0xB71B0     // 0.75 Million
18 #define INPUT_SIZE_1080p_TH				0x1AB3F0    // 1.75 Million
19 #define INPUT_SIZE_4K_TH				0x29F630    // 2.75 Million
20 #define INPUT_SIZE_8K_TH				0xB71B00    // 12 Million
21 
22 #define SIZE_OF_ONE_FRAME_IN_BYTES(width, height,is16bit) ( ( ((width)*(height)*3)>>1 )<<is16bit)
23 #define IS_16_BIT(bit_depth) (bit_depth==10?1:0)
24 #define EB_OUTPUTSTREAMBUFFERSIZE_MACRO(ResolutionSize)                ((ResolutionSize) < (INPUT_SIZE_1080i_TH) ? 0x1E8480 : (ResolutionSize) < (INPUT_SIZE_1080p_TH) ? 0x2DC6C0 : (ResolutionSize) < (INPUT_SIZE_4K_TH) ? 0x2DC6C0 : (ResolutionSize) < (INPUT_SIZE_8K_TH) ? 0x2DC6C0:0x5B8D80)
25 
26  /***************************************
27  * Variables Defining a memory table
28  *  hosting all allocated pointers
29  ***************************************/
30 EbMemoryMapEntry                 *appMemoryMap;
31 uint32_t                         *appMemoryMapIndex;
32 uint64_t                         *totalAppMemory;
33 uint32_t                          appMallocCount = 0;
34 static EbMemoryMapEntry          *appMemoryMapAllChannels[MAX_CHANNEL_NUMBER];
35 static uint32_t                   appMemoryMapIndexAllChannels[MAX_CHANNEL_NUMBER];
36 static uint64_t                   appMemoryMallocdAllChannels[MAX_CHANNEL_NUMBER];
37 
38 /***************************************
39 * Allocation and initializing a memory table
40 *  hosting all allocated pointers
41 ***************************************/
AllocateMemoryTable(uint32_t instanceIdx)42 void AllocateMemoryTable(
43     uint32_t	instanceIdx)
44 {
45     // Malloc Memory Table for the instance @ instanceIdx
46     appMemoryMapAllChannels[instanceIdx]        = (EbMemoryMapEntry*)malloc(sizeof(EbMemoryMapEntry) * MAX_APP_NUM_PTR);
47 
48     // Init the table index
49     appMemoryMapIndexAllChannels[instanceIdx]   = 0;
50 
51     // Size of the table
52     appMemoryMallocdAllChannels[instanceIdx]    = sizeof(EbMemoryMapEntry) * MAX_APP_NUM_PTR;
53     totalAppMemory = &appMemoryMallocdAllChannels[instanceIdx];
54 
55     // Set pointer to the first entry
56     appMemoryMap                                = appMemoryMapAllChannels[instanceIdx];
57 
58     // Set index to the first entry
59     appMemoryMapIndex                           = &appMemoryMapIndexAllChannels[instanceIdx];
60 
61     // Init Number of pointers
62     appMallocCount = 0;
63 
64     return;
65 }
66 
67 
68 /*************************************
69 **************************************
70 *** Helper functions Input / Output **
71 **************************************
72 **************************************/
73 /******************************************************
74 * Copy fields from the stream to the input buffer
75     Input   : stream
76     Output  : valid input buffer
77 ******************************************************/
ProcessInputFieldBufferingMode(uint64_t processedFrameCount,int32_t * filledLen,FILE * inputFile,uint8_t * lumaInputPtr,uint8_t * cbInputPtr,uint8_t * crInputPtr,uint32_t inputPaddedWidth,uint32_t inputPaddedHeight,uint8_t is16bit)78 void ProcessInputFieldBufferingMode(
79     uint64_t                      processedFrameCount,
80     int32_t                      *filledLen,
81     FILE                         *inputFile,
82     uint8_t                        *lumaInputPtr,
83     uint8_t                        *cbInputPtr,
84     uint8_t                        *crInputPtr,
85     uint32_t                      inputPaddedWidth,
86     uint32_t                      inputPaddedHeight,
87     uint8_t                       is16bit) {
88 
89 
90     uint64_t  sourceLumaRowSize   = (uint64_t)(inputPaddedWidth << is16bit);
91     uint64_t  sourceChromaRowSize = sourceLumaRowSize >> 1;
92 
93     uint8_t  *ebInputPtr;
94     uint32_t  inputRowIndex;
95 
96     // Y
97     ebInputPtr = lumaInputPtr;
98     // Skip 1 luma row if bottom field (point to the bottom field)
99     if (processedFrameCount % 2 != 0)
100         fseeko64(inputFile, (long)sourceLumaRowSize, SEEK_CUR);
101 
102     for (inputRowIndex = 0; inputRowIndex < inputPaddedHeight; inputRowIndex++) {
103 
104         *filledLen += (uint32_t)fread(ebInputPtr, 1, sourceLumaRowSize, inputFile);
105         // Skip 1 luma row (only fields)
106         fseeko64(inputFile, (long)sourceLumaRowSize, SEEK_CUR);
107         ebInputPtr += sourceLumaRowSize;
108     }
109 
110     // U
111     ebInputPtr = cbInputPtr;
112     // 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)
113     if (processedFrameCount % 2 != 0) {
114         fseeko64(inputFile, -(long)sourceLumaRowSize, SEEK_CUR);
115         fseeko64(inputFile, (long)sourceChromaRowSize, SEEK_CUR);
116     }
117 
118     for (inputRowIndex = 0; inputRowIndex < inputPaddedHeight >> 1; inputRowIndex++) {
119 
120         *filledLen += (uint32_t)fread(ebInputPtr, 1, sourceChromaRowSize, inputFile);
121         // Skip 1 chroma row (only fields)
122         fseeko64(inputFile, (long)sourceChromaRowSize, SEEK_CUR);
123         ebInputPtr += sourceChromaRowSize;
124     }
125 
126     // V
127     ebInputPtr = crInputPtr;
128     // 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)
129     // => no action
130 
131 
132     for (inputRowIndex = 0; inputRowIndex < inputPaddedHeight >> 1; inputRowIndex++) {
133 
134         *filledLen += (uint32_t)fread(ebInputPtr, 1, sourceChromaRowSize, inputFile);
135         // Skip 1 chroma row (only fields)
136         fseeko64(inputFile, (long)sourceChromaRowSize, SEEK_CUR);
137         ebInputPtr += sourceChromaRowSize;
138     }
139 
140     // Step back 1 chroma row if bottom field (undo the previous jump)
141     if (processedFrameCount % 2 != 0) {
142         fseeko64(inputFile, -(long)sourceChromaRowSize, SEEK_CUR);
143     }
144 }
145 
146 
147 /***********************************************
148 * Copy configuration parameters from
149 *  The config structure, to the
150 *  callback structure to send to the library
151 ***********************************************/
CopyConfigurationParameters(EbConfig_t * config,EbAppContext_t * callbackData,uint32_t instanceIdx)152 EB_ERRORTYPE CopyConfigurationParameters(
153     EbConfig_t				*config,
154     EbAppContext_t			*callbackData,
155     uint32_t                 instanceIdx)
156 {
157     EB_ERRORTYPE   return_error = EB_ErrorNone;
158 
159     // Assign Instance index to the library
160     callbackData->instanceIdx = (uint8_t)instanceIdx;
161 
162     // Initialize Port Activity Flags
163     callbackData->outputStreamPortActive = APP_PortActive;
164     callbackData->ebEncParameters.sourceWidth = config->sourceWidth;
165     callbackData->ebEncParameters.sourceHeight = config->sourceHeight;
166     callbackData->ebEncParameters.interlacedVideo = (EB_BOOL)config->interlacedVideo;
167     callbackData->ebEncParameters.rateControlMode = config->rateControlMode;
168     callbackData->ebEncParameters.intraPeriodLength = config->intraPeriod;
169     callbackData->ebEncParameters.intraRefreshType = config->intraRefreshType;
170     if (config->rateControlMode == 0 && config->intraRefreshType > 0)
171     {
172         printf("\nWarning: intraRefreshType >0 is only supported in VBR mode\n");
173         callbackData->ebEncParameters.intraRefreshType = 0;
174     }
175 
176     callbackData->ebEncParameters.baseLayerSwitchMode = config->baseLayerSwitchMode;
177     callbackData->ebEncParameters.encMode = (EB_BOOL)config->encMode;
178     callbackData->ebEncParameters.frameRate = config->frameRate;
179     callbackData->ebEncParameters.frameRateDenominator = config->frameRateDenominator;
180     callbackData->ebEncParameters.frameRateNumerator = config->frameRateNumerator;
181 	callbackData->ebEncParameters.hierarchicalLevels = config->hierarchicalLevels;
182 	callbackData->ebEncParameters.predStructure = (uint8_t)config->predStructure;
183     callbackData->ebEncParameters.sceneChangeDetection = config->sceneChangeDetection;
184     callbackData->ebEncParameters.lookAheadDistance = config->lookAheadDistance;
185     callbackData->ebEncParameters.framesToBeEncoded = config->framesToBeEncoded;
186     callbackData->ebEncParameters.targetBitRate = config->targetBitRate;
187     callbackData->ebEncParameters.maxQpAllowed = config->maxQpAllowed;
188     callbackData->ebEncParameters.minQpAllowed = config->minQpAllowed;
189     callbackData->ebEncParameters.qp = config->qp;
190     callbackData->ebEncParameters.vbvMaxrate = config->vbvMaxRate;
191     callbackData->ebEncParameters.vbvBufsize = config->vbvBufsize;
192     callbackData->ebEncParameters.vbvBufInit = config->vbvBufInit;
193     callbackData->ebEncParameters.useQpFile = (EB_BOOL)config->useQpFile;
194     callbackData->ebEncParameters.tileColumnCount = (EB_BOOL)config->tileColumnCount;
195     callbackData->ebEncParameters.tileRowCount = (EB_BOOL)config->tileRowCount;
196     callbackData->ebEncParameters.tileSliceMode = (EB_BOOL)config->tileSliceMode;
197     callbackData->ebEncParameters.disableDlfFlag = (EB_BOOL)config->disableDlfFlag;
198     callbackData->ebEncParameters.enableSaoFlag = (EB_BOOL)config->enableSaoFlag;
199     callbackData->ebEncParameters.hrdFlag = (EB_BOOL)config->hrdFlag;
200     callbackData->ebEncParameters.useDefaultMeHme = (EB_BOOL)config->useDefaultMeHme;
201     callbackData->ebEncParameters.enableHmeFlag = (EB_BOOL)config->enableHmeFlag;
202     callbackData->ebEncParameters.searchAreaWidth = config->searchAreaWidth;
203     callbackData->ebEncParameters.searchAreaHeight = config->searchAreaHeight;
204     callbackData->ebEncParameters.constrainedIntra = (EB_BOOL)config->constrainedIntra;
205     callbackData->ebEncParameters.tune = config->tune;
206     callbackData->ebEncParameters.channelId = config->channelId;
207     callbackData->ebEncParameters.activeChannelCount = config->activeChannelCount;
208     callbackData->ebEncParameters.logicalProcessors = config->logicalProcessors;
209     callbackData->ebEncParameters.targetSocket = config->targetSocket;
210     if ((config->threadCount > 0) && (config->threadCount < EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR)) {
211         callbackData->ebEncParameters.threadCount = EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_FACTOR;
212         printf("\nWarning: the thread count %u is set too small and is forced to the min value %u\n",
213                 config->threadCount, callbackData->ebEncParameters.threadCount);
214     } else {
215         callbackData->ebEncParameters.threadCount = (config->threadCount + EB_THREAD_COUNT_MIN_CORE - 1)
216                                                     / EB_THREAD_COUNT_MIN_CORE * EB_THREAD_COUNT_MIN_CORE;
217         if (callbackData->ebEncParameters.threadCount != config->threadCount)
218             printf("\nInformation: the thread count %u is rounded to %u\n",
219                     config->threadCount, callbackData->ebEncParameters.threadCount);
220     }
221 
222     callbackData->ebEncParameters.unrestrictedMotionVector = config->unrestrictedMotionVector;
223     callbackData->ebEncParameters.bitRateReduction = (uint8_t)config->bitRateReduction;
224     callbackData->ebEncParameters.improveSharpness = (uint8_t)config->improveSharpness;
225     callbackData->ebEncParameters.videoUsabilityInfo = config->videoUsabilityInfo;
226     callbackData->ebEncParameters.highDynamicRangeInput = config->highDynamicRangeInput;
227     callbackData->ebEncParameters.accessUnitDelimiter = config->accessUnitDelimiter;
228     callbackData->ebEncParameters.bufferingPeriodSEI = config->bufferingPeriodSEI;
229     callbackData->ebEncParameters.pictureTimingSEI = config->pictureTimingSEI;
230     callbackData->ebEncParameters.registeredUserDataSeiFlag = config->registeredUserDataSeiFlag;
231     callbackData->ebEncParameters.unregisteredUserDataSeiFlag = config->unregisteredUserDataSeiFlag;
232     callbackData->ebEncParameters.recoveryPointSeiFlag = config->recoveryPointSeiFlag;
233     callbackData->ebEncParameters.enableTemporalId = config->enableTemporalId;
234     callbackData->ebEncParameters.encoderBitDepth = config->encoderBitDepth;
235     callbackData->ebEncParameters.encoderColorFormat = (EB_COLOR_FORMAT)config->encoderColorFormat;
236     callbackData->ebEncParameters.compressedTenBitFormat = config->compressedTenBitFormat;
237     callbackData->ebEncParameters.profile = config->profile;
238     if(config->encoderColorFormat >= EB_YUV422 && config->profile != 4)
239     {
240         printf("\nWarning: input profile is not correct, force converting it from %d to MainREXT for YUV422 or YUV444 cases \n", config->profile);
241         callbackData->ebEncParameters.profile = 4;
242     }
243     else if(config->encoderBitDepth > 8 && config->profile < 2)
244     {
245         printf("\nWarning: input profile is not correct, force converting it from %d to Main10 for 10 bits cases\n", config->profile);
246         callbackData->ebEncParameters.profile = 2;
247     }
248     callbackData->ebEncParameters.tier = config->tier;
249     callbackData->ebEncParameters.level = config->level;
250     callbackData->ebEncParameters.injectorFrameRate = config->injectorFrameRate;
251     callbackData->ebEncParameters.speedControlFlag = config->speedControlFlag;
252     //callbackData->ebEncParameters.latencyMode = config->latencyMode;
253     callbackData->ebEncParameters.asmType = config->asmType;
254     callbackData->ebEncParameters.reconEnabled = config->reconFile ? EB_TRUE : EB_FALSE;
255     callbackData->ebEncParameters.codeVpsSpsPps = 1;
256     callbackData->ebEncParameters.fpsInVps = config->fpsInVps;
257     callbackData->ebEncParameters.switchThreadsToRtPriority = config->switchThreadsToRtPriority;
258 
259     callbackData->ebEncParameters.maxCLL = config->maxCLL;
260     callbackData->ebEncParameters.maxFALL = config->maxFALL;
261     callbackData->ebEncParameters.useMasteringDisplayColorVolume = config->useMasteringDisplayColorVolume;
262     callbackData->ebEncParameters.dolbyVisionProfile = config->dolbyVisionProfile;
263     callbackData->ebEncParameters.useNaluFile = config->useNaluFile;
264 
265     callbackData->ebEncParameters.displayPrimaryX[0] = config->displayPrimaryX[0];
266     callbackData->ebEncParameters.displayPrimaryX[1] = config->displayPrimaryX[1];
267     callbackData->ebEncParameters.displayPrimaryX[2] = config->displayPrimaryX[2];
268     callbackData->ebEncParameters.displayPrimaryY[0] = config->displayPrimaryY[0];
269     callbackData->ebEncParameters.displayPrimaryY[1] = config->displayPrimaryY[1];
270     callbackData->ebEncParameters.displayPrimaryY[2] = config->displayPrimaryY[2];
271     callbackData->ebEncParameters.whitePointX = config->whitePointX;
272     callbackData->ebEncParameters.whitePointY = config->whitePointY;
273     callbackData->ebEncParameters.maxDisplayMasteringLuminance = config->maxDisplayMasteringLuminance;
274     callbackData->ebEncParameters.minDisplayMasteringLuminance = config->minDisplayMasteringLuminance;
275 
276     callbackData->ebEncParameters.segmentOvEnabled = config->segmentOvEnabled;
277 
278     return return_error;
279 
280 }
281 
282 
AllocateInputBuffer(EbConfig_t * config,uint8_t * pBuffer)283 EB_ERRORTYPE AllocateInputBuffer(
284     EbConfig_t          *config,
285     uint8_t               *pBuffer)
286 {
287     EB_ERRORTYPE   return_error = EB_ErrorNone;
288 
289     const int32_t tenBitPackedMode = (config->encoderBitDepth > 8) && (config->compressedTenBitFormat == 0) ? 1 : 0;
290     const EB_COLOR_FORMAT colorFormat = (EB_COLOR_FORMAT)config->encoderColorFormat;    // Chroma subsampling
291     const uint8_t subWidthCMinus1 = (colorFormat == EB_YUV444 ? 1 : 2) - 1;
292 
293     // Determine size of each plane
294     const size_t luma8bitSize =
295 
296         config->inputPaddedWidth    *
297         config->inputPaddedHeight   *
298 
299         (1 << tenBitPackedMode);
300 
301     const size_t chroma8bitSize = luma8bitSize >> (3 - colorFormat);
302     const size_t luma10bitSize = (config->encoderBitDepth > 8 && tenBitPackedMode == 0) ? luma8bitSize : 0;
303     const size_t chroma10bitSize = (config->encoderBitDepth > 8 && tenBitPackedMode == 0) ? chroma8bitSize : 0;
304 
305     // Determine
306     EB_H265_ENC_INPUT* inputPtr = (EB_H265_ENC_INPUT*)pBuffer;
307     inputPtr->yStride = config->inputPaddedWidth;
308     inputPtr->crStride = config->inputPaddedWidth >> subWidthCMinus1;
309     inputPtr->cbStride = config->inputPaddedWidth >> subWidthCMinus1;
310     if (luma8bitSize) {
311         EB_APP_MALLOC(uint8_t*, inputPtr->luma, luma8bitSize, EB_N_PTR, EB_ErrorInsufficientResources);
312     }
313     else {
314         inputPtr->luma = 0;
315     }
316     if (chroma8bitSize) {
317         EB_APP_MALLOC(uint8_t*, inputPtr->cb, chroma8bitSize, EB_N_PTR, EB_ErrorInsufficientResources);
318     }
319     else {
320         inputPtr->cb = 0;
321     }
322 
323     if (chroma8bitSize) {
324         EB_APP_MALLOC(uint8_t*, inputPtr->cr, chroma8bitSize, EB_N_PTR, EB_ErrorInsufficientResources);
325     }
326     else {
327         inputPtr->cr = 0;
328     }
329 
330     if (luma10bitSize) {
331         EB_APP_MALLOC(uint8_t*, inputPtr->lumaExt, luma10bitSize, EB_N_PTR, EB_ErrorInsufficientResources);
332     }
333     else {
334         inputPtr->lumaExt = 0;
335     }
336 
337     if (chroma10bitSize) {
338         EB_APP_MALLOC(uint8_t*, inputPtr->cbExt, chroma10bitSize, EB_N_PTR, EB_ErrorInsufficientResources);
339     }
340     else {
341         inputPtr->cbExt = 0;
342     }
343 
344     if (chroma10bitSize) {
345         EB_APP_MALLOC(uint8_t*, inputPtr->crExt, chroma10bitSize, EB_N_PTR, EB_ErrorInsufficientResources);
346 
347     }
348     else {
349         inputPtr->crExt = 0;
350     }
351 
352     return return_error;
353 }
354 
355 
AllocateInputBuffers(EbConfig_t * config,EbAppContext_t * callbackData)356 EB_ERRORTYPE AllocateInputBuffers(
357     EbConfig_t				*config,
358     EbAppContext_t			*callbackData)
359 {
360     EB_ERRORTYPE   return_error = EB_ErrorNone;
361     {
362         EB_APP_MALLOC(EB_BUFFERHEADERTYPE*, callbackData->inputBufferPool, sizeof(EB_BUFFERHEADERTYPE), EB_N_PTR, EB_ErrorInsufficientResources);
363 
364         // Initialize Header
365         callbackData->inputBufferPool->nSize                       = sizeof(EB_BUFFERHEADERTYPE);
366 
367         EB_APP_MALLOC(uint8_t*, callbackData->inputBufferPool->pBuffer, sizeof(EB_H265_ENC_INPUT), EB_N_PTR, EB_ErrorInsufficientResources);
368 
369         if (config->bufferedInput == -1) {
370 
371             // Allocate frame buffer for the pBuffer
372             AllocateInputBuffer(
373                     config,
374                     callbackData->inputBufferPool->pBuffer);
375         }
376 
377         // Assign the variables
378         callbackData->inputBufferPool->pAppPrivate = NULL;
379         callbackData->inputBufferPool->sliceType   = EB_INVALID_PICTURE;
380     }
381 
382     if (callbackData->ebEncParameters.segmentOvEnabled) {
383         size_t pictureWidthInLcu = (config->sourceWidth + EB_SEGMENT_BLOCK_SIZE - 1) / EB_SEGMENT_BLOCK_SIZE;
384         size_t pictureHeightInLcu = (config->sourceHeight + EB_SEGMENT_BLOCK_SIZE - 1) / EB_SEGMENT_BLOCK_SIZE;
385         size_t lcuTotalCount = pictureWidthInLcu * pictureHeightInLcu;
386         EB_APP_MALLOC(SegmentOverride_t*, callbackData->inputBufferPool->segmentOvPtr, sizeof(SegmentOverride_t) * lcuTotalCount, EB_N_PTR, EB_ErrorInsufficientResources);
387     }
388     else {
389         callbackData->inputBufferPool->segmentOvPtr = NULL;
390     }
391 
392     return return_error;
393 }
AllocateOutputReconBuffers(EbConfig_t * config,EbAppContext_t * callbackData)394 EB_ERRORTYPE AllocateOutputReconBuffers(
395     EbConfig_t				*config,
396     EbAppContext_t			*callbackData)
397 {
398 
399     EB_ERRORTYPE   return_error = EB_ErrorNone;
400     const size_t lumaSize = config->inputPaddedWidth * config->inputPaddedHeight;
401     // both u and v
402     const size_t chromaSize = lumaSize >> (3 - config->encoderColorFormat);
403     const size_t tenBit = (config->encoderBitDepth > 8);
404     const size_t frameSize = (lumaSize + 2 * chromaSize) << tenBit;
405 
406 // ... Recon Port
407     EB_APP_MALLOC(EB_BUFFERHEADERTYPE*, callbackData->reconBuffer, sizeof(EB_BUFFERHEADERTYPE), EB_N_PTR, EB_ErrorInsufficientResources);
408 
409     // Initialize Header
410     callbackData->reconBuffer->nSize = sizeof(EB_BUFFERHEADERTYPE);
411 
412     EB_APP_MALLOC(uint8_t*, callbackData->reconBuffer->pBuffer, frameSize, EB_N_PTR, EB_ErrorInsufficientResources);
413 
414     callbackData->reconBuffer->nAllocLen = (uint32_t)frameSize;
415     callbackData->reconBuffer->pAppPrivate = NULL;
416     return return_error;
417 }
418 
PreloadFramesIntoRam(EbConfig_t * config)419 EB_ERRORTYPE PreloadFramesIntoRam(
420     EbConfig_t				*config)
421 {
422     EB_ERRORTYPE    return_error = EB_ErrorNone;
423     int32_t processedFrameCount;
424     int32_t filledLen;
425     int32_t inputPaddedWidth = config->inputPaddedWidth;
426     int32_t inputPaddedHeight = config->inputPaddedHeight;
427     int32_t readSize;
428     uint8_t *ebInputPtr;
429 
430     FILE *inputFile = config->inputFile;
431 
432     if (config->encoderBitDepth == 10 && config->compressedTenBitFormat == 1) {
433         readSize = (inputPaddedWidth*inputPaddedHeight * 3) / 2 + (inputPaddedWidth / 4 * inputPaddedHeight * 3) / 2;
434     } else {
435         readSize = inputPaddedWidth * inputPaddedHeight; //Luma
436         readSize += 2 * (readSize >> (3 - config->encoderColorFormat)); // Add Chroma
437         readSize *= (config->encoderBitDepth > 8 ? 2 : 1); //10 bit
438     }
439     EB_APP_MALLOC(uint8_t **, config->sequenceBuffer, sizeof(uint8_t*) * config->bufferedInput, EB_N_PTR, EB_ErrorInsufficientResources);
440 
441     for (processedFrameCount = 0; processedFrameCount < config->bufferedInput; ++processedFrameCount) {
442         EB_APP_MALLOC(uint8_t*, config->sequenceBuffer[processedFrameCount], readSize, EB_N_PTR, EB_ErrorInsufficientResources);
443         // Interlaced Video
444         if (config->separateFields) {
445             EB_BOOL is16bit = config->encoderBitDepth > 8;
446             if (is16bit == 0 || (is16bit == 1 && config->compressedTenBitFormat == 0)) {
447                 const int32_t tenBitPackedMode = (config->encoderBitDepth > 8) && (config->compressedTenBitFormat == 0) ? 1 : 0;
448                 const size_t luma8bitSize =
449                     (config->inputPaddedWidth) *
450                     (config->inputPaddedHeight) *
451                     (1 << tenBitPackedMode);
452 
453                 const size_t chroma8bitSize = luma8bitSize >> 2;
454                 filledLen = 0;
455 
456                 ProcessInputFieldBufferingMode(
457                     processedFrameCount,
458                     &filledLen,
459                     inputFile,
460                     config->sequenceBuffer[processedFrameCount],
461                     config->sequenceBuffer[processedFrameCount] + luma8bitSize,
462                     config->sequenceBuffer[processedFrameCount] + luma8bitSize + chroma8bitSize,
463                     (uint32_t)inputPaddedWidth,
464                     (uint32_t)inputPaddedHeight,
465                     is16bit);
466 
467                 if (readSize != filledLen) {
468                     fseek(inputFile, 0, SEEK_SET);
469                     filledLen = 0;
470 
471                     ProcessInputFieldBufferingMode(
472                         processedFrameCount,
473                         &filledLen,
474                         inputFile,
475                         config->sequenceBuffer[processedFrameCount],
476                         config->sequenceBuffer[processedFrameCount] + luma8bitSize,
477                         config->sequenceBuffer[processedFrameCount] + luma8bitSize + chroma8bitSize,
478                         (uint32_t)inputPaddedWidth,
479                         (uint32_t)inputPaddedHeight,
480                         is16bit);
481                 }
482 
483                 // Reset the pointer position after a top field
484                 if (processedFrameCount % 2 == 0) {
485                     fseek(inputFile, -(long)(readSize << 1), SEEK_CUR);
486                 }
487             }
488             // Unpacked 10 bit
489             else {
490 
491                 const int32_t tenBitPackedMode = (config->encoderBitDepth > 8) && (config->compressedTenBitFormat == 0) ? 1 : 0;
492 
493                 const size_t luma8bitSize =
494                     (config->inputPaddedWidth) *
495                     (config->inputPaddedHeight) *
496                     (1 << tenBitPackedMode);
497 
498                 const size_t chroma8bitSize = luma8bitSize >> 2;
499 
500                 const size_t luma10bitSize = (config->encoderBitDepth > 8 && tenBitPackedMode == 0) ? luma8bitSize : 0;
501                 const size_t chroma10bitSize = (config->encoderBitDepth > 8 && tenBitPackedMode == 0) ? chroma8bitSize : 0;
502 
503                 filledLen = 0;
504 
505                 ProcessInputFieldBufferingMode(
506                     processedFrameCount,
507                     &filledLen,
508                     inputFile,
509                     config->sequenceBuffer[processedFrameCount],
510                     config->sequenceBuffer[processedFrameCount] + luma8bitSize,
511                     config->sequenceBuffer[processedFrameCount] + luma8bitSize + chroma8bitSize,
512                     (uint32_t)inputPaddedWidth,
513                     (uint32_t)inputPaddedHeight,
514                     0);
515 
516                 ProcessInputFieldBufferingMode(
517                     processedFrameCount,
518                     &filledLen,
519                     inputFile,
520                     config->sequenceBuffer[processedFrameCount] + luma8bitSize + (chroma8bitSize << 1),
521                     config->sequenceBuffer[processedFrameCount] + luma8bitSize + (chroma8bitSize << 1) + luma10bitSize,
522                     config->sequenceBuffer[processedFrameCount] + luma8bitSize + (chroma8bitSize << 1) + luma10bitSize + chroma10bitSize,
523                     (uint32_t)inputPaddedWidth,
524                     (uint32_t)inputPaddedHeight,
525                     0);
526 
527                 if (readSize != filledLen) {
528 
529                     fseek(inputFile, 0, SEEK_SET);
530                     filledLen = 0;
531 
532                     ProcessInputFieldBufferingMode(
533                         processedFrameCount,
534                         &filledLen,
535                         inputFile,
536                         config->sequenceBuffer[processedFrameCount],
537                         config->sequenceBuffer[processedFrameCount] + luma8bitSize,
538                         config->sequenceBuffer[processedFrameCount] + luma8bitSize + chroma8bitSize,
539                         (uint32_t)inputPaddedWidth,
540                         (uint32_t)inputPaddedHeight,
541                         0);
542 
543                     ProcessInputFieldBufferingMode(
544                         processedFrameCount,
545                         &filledLen,
546                         inputFile,
547                         config->sequenceBuffer[processedFrameCount] + luma8bitSize + (chroma8bitSize << 1),
548                         config->sequenceBuffer[processedFrameCount] + luma8bitSize + (chroma8bitSize << 1) + luma10bitSize,
549                         config->sequenceBuffer[processedFrameCount] + luma8bitSize + (chroma8bitSize << 1) + luma10bitSize + chroma10bitSize,
550                         (uint32_t)inputPaddedWidth,
551                         (uint32_t)inputPaddedHeight,
552                         0);
553 
554                 }
555 
556                 // Reset the pointer position after a top field
557                 if (processedFrameCount % 2 == 0) {
558                     fseek(inputFile, -(long)(readSize << 1), SEEK_CUR);
559                 }
560             }
561         }
562         else {
563 
564             // Fill the buffer with a complete frame
565             filledLen = 0;
566             ebInputPtr = config->sequenceBuffer[processedFrameCount];
567             filledLen += (uint32_t)fread(ebInputPtr, 1, readSize, inputFile);
568 
569             if (readSize != filledLen) {
570 
571                 fseek(config->inputFile, 0, SEEK_SET);
572 
573                 // Fill the buffer with a complete frame
574                 filledLen = 0;
575                 ebInputPtr = config->sequenceBuffer[processedFrameCount];
576                 filledLen += (uint32_t)fread(ebInputPtr, 1, readSize, inputFile);
577             }
578         }
579     }
580 
581     return return_error;
582 }
583 
584 /***************************************
585 * Functions Implementation
586 ***************************************/
587 
588 /***********************************
589  * Initialize Core & Component
590  ***********************************/
InitEncoder(EbConfig_t * config,EbAppContext_t * callbackData,uint32_t instanceIdx)591 EB_ERRORTYPE InitEncoder(
592     EbConfig_t				*config,
593     EbAppContext_t			*callbackData,
594 	uint32_t				 instanceIdx)
595 {
596     EB_ERRORTYPE        return_error = EB_ErrorNone;
597 
598     // Allocate a memory table hosting all allocated pointers
599     AllocateMemoryTable(instanceIdx);
600 
601     ///************************* LIBRARY INIT [START] *********************///
602     // STEP 1: Call the library to construct a Component Handle
603     return_error = EbInitHandle(&callbackData->svtEncoderHandle, callbackData, &callbackData->ebEncParameters);
604 
605     if (return_error != EB_ErrorNone) {
606         return return_error;
607     }
608 
609     // STEP 3: Copy all configuration parameters into the callback structure
610     return_error = CopyConfigurationParameters(
611                     config,
612                     callbackData,
613                     instanceIdx);
614 
615     if (return_error != EB_ErrorNone) {
616         return return_error;
617     }
618 
619     // STEP 4: Send over all configuration parameters
620     // Set the Parameters
621     return_error = EbH265EncSetParameter(
622                        callbackData->svtEncoderHandle,
623                        &callbackData->ebEncParameters);
624 
625     if (return_error != EB_ErrorNone) {
626         return return_error;
627     }
628 
629     // STEP 5: Init Encoder
630     return_error = EbInitEncoder(callbackData->svtEncoderHandle);
631     if (return_error != EB_ErrorNone) {
632         return return_error;
633     }
634 
635     ///************************* LIBRARY INIT [END] *********************///
636 
637     ///********************** APPLICATION INIT [START] ******************///
638 
639     // STEP 6: Allocate input buffers carrying the yuv frames in
640     return_error = AllocateInputBuffers(
641         config,
642         callbackData);
643 
644     if (return_error != EB_ErrorNone) {
645         return return_error;
646     }
647 
648     // STEP 7: Allocate output Recon Buffer
649     return_error = AllocateOutputReconBuffers(
650         config,
651         callbackData);
652 
653     if (return_error != EB_ErrorNone) {
654         return return_error;
655     }
656 
657 	// Allocate the Sequence Buffer
658     if (config->bufferedInput != -1) {
659 
660         // Preload frames into the ram for a faster yuv access time
661         PreloadFramesIntoRam(
662             config);
663     }
664     else {
665         config->sequenceBuffer = 0;
666     }
667 
668     if (return_error != EB_ErrorNone) {
669         return return_error;
670     }
671 
672 
673     ///********************** APPLICATION INIT [END] ******************////////
674 
675     return return_error;
676 }
677 
678 /***********************************
679  * Deinit Components
680  ***********************************/
DeInitEncoder(EbAppContext_t * callbackDataPtr,uint32_t instanceIndex)681 EB_ERRORTYPE DeInitEncoder(
682     EbAppContext_t *callbackDataPtr,
683     uint32_t        instanceIndex)
684 {
685     EB_ERRORTYPE return_error = EB_ErrorNone;
686     int32_t              ptrIndex        = 0;
687     EbMemoryMapEntry*   memoryEntry     = (EbMemoryMapEntry*)0;
688 
689     if (((EB_COMPONENTTYPE*)(callbackDataPtr->svtEncoderHandle)) != NULL) {
690             return_error = EbDeinitEncoder(callbackDataPtr->svtEncoderHandle);
691     }
692 
693     // Destruct the buffer memory pool
694     if (return_error != EB_ErrorNone) {
695         return return_error;
696     }
697 
698     // Loop through the ptr table and free all malloc'd pointers per channel
699     for (ptrIndex = appMemoryMapIndexAllChannels[instanceIndex] - 1; ptrIndex >= 0; --ptrIndex) {
700         memoryEntry = &appMemoryMapAllChannels[instanceIndex][ptrIndex];
701         switch (memoryEntry->ptrType) {
702         case EB_N_PTR:
703             free(memoryEntry->ptr);
704             break;
705         default:
706             return_error = EB_ErrorMax;
707             break;
708         }
709     }
710     free(appMemoryMapAllChannels[instanceIndex]);
711 
712     // Destruct the component
713     EbDeinitHandle(callbackDataPtr->svtEncoderHandle);
714 
715     return return_error;
716 }
717