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