-
Notifications
You must be signed in to change notification settings - Fork 3
/
OVstuff.h
423 lines (356 loc) · 14.5 KB
/
OVstuff.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
/*******************************************************************************
* This file is part of AvsVCEh264.
* Contains declaration & functions for encoding with OpenVideo\OVEncode
*
* Copyright (C) 2013 David González García <[email protected]>
*******************************************************************************/
#include <stdio.h>
// Input surface used for encoder
#define MAX_INPUT_SURFACE 1
typedef struct OVDeviceHandle
{
ovencode_device_info *deviceInfo;
unsigned int numDevices;
cl_platform_id platform;
} OVDeviceHandle;
// Encoder Hanlde for sharing context between create process and destroy
typedef struct OVEncodeHandle
{
ove_session session; // Pointer to encoder session
OPMemHandle inputSurfaces[MAX_INPUT_SURFACE]; // input buffer
cl_command_queue clCmdQueue; // command queue
} OVEncodeHandle;
/*******************************************************************************
* @fn getPlatform
* @brief Get platform to run
* @param[in] platform : Platform id
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool getPlatform(cl_platform_id &platform)
{
cl_uint numPlatforms;
cl_int err = clGetPlatformIDs(0, NULL, &numPlatforms);
if (CL_SUCCESS != err)
{
fputs("clGetPlatformIDs() failed", stderr);
return false;
}
// If there are platforms, make sure they are AMD.
if (0 < numPlatforms)
{
cl_platform_id* platforms = new cl_platform_id[numPlatforms];
err = clGetPlatformIDs(numPlatforms, platforms, NULL);
if (CL_SUCCESS != err)
{
fputs("clGetPlatformIDs() failed", stderr);
delete [] platforms;
return false;
}
// Loop through all the platforms looking for an AMD system.
for (unsigned int i = 0; i < numPlatforms; ++i)
{
char pbuf[100];
err = clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, sizeof(pbuf), pbuf, NULL);
// Stop at the first platform that is an AMD system.
if (strcmp(pbuf, "Advanced Micro Devices, Inc.") == 0)
{
platform = platforms[i];
break;
}
}
delete [] platforms;
}
if (NULL == platform)
{
puts("Couldn't find AMD platform, cannot proceed.\n");
return false;
}
return true;
}
/*******************************************************************************
* @fn gpuCheck
* @brief Checks for GPU present or not
* @param[in] platform : Platform id
* @param[out] dType : Device type returned GPU/CPU
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool gpuCheck(cl_platform_id platform,cl_device_type* dType)
{
cl_int err;
cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};
cl_context context = clCreateContextFromType(cps, (*dType), NULL, NULL, &err);
if(err == CL_DEVICE_NOT_FOUND)
*dType = CL_DEVICE_TYPE_CPU;
clReleaseContext(context);
return true;
}
/*******************************************************************************
* @fn getDeviceInfo
* @brief returns device information
* @param[out] deviceInfo : Device info
* @param[out] numDevices : Number of devices present
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool getDeviceInfo(ovencode_device_info **deviceInfo, unsigned int *numDevices)
{
bool status = OVEncodeGetDeviceInfo(numDevices, 0);
if(status)
{
if(*numDevices == 0)
{
puts("No suitable devices found!\n");
return false;
}
}
else
{
puts("OVEncodeGetDeviceInfo failed!\n");
return false;
}
// Get information about each device found
*deviceInfo = new ovencode_device_info[*numDevices];
memset(*deviceInfo,0,sizeof(ovencode_device_info)* (*numDevices));
status = OVEncodeGetDeviceInfo(numDevices, *deviceInfo);
if(!status)
{
puts("OVEncodeGetDeviceInfo failed!\n");
return false;
}
return true;
}
/*******************************************************************************
* @fn getDevice
* @brief returns the platform and devices found
* @param[in/out] deviceHandle : Hanlde for the device information
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool getDevice(OVDeviceHandle *deviceHandle)
{
bool status;
// Get the Platform
deviceHandle->platform = NULL;
status = getPlatform(deviceHandle->platform);
if (status == false)
return false;
// Check for GPU
cl_device_type dType = CL_DEVICE_TYPE_GPU;
status = gpuCheck(deviceHandle->platform, &dType);
if (status == false)
return false;
// Get the number of devices
deviceHandle->numDevices = 0;
deviceHandle->deviceInfo = NULL;
// Memory for deviceInfo gets allocated inside the getDeviceInfo function
// depending on numDevices. This needs to be freed after the usage.
status = getDeviceInfo(&deviceHandle->deviceInfo,&deviceHandle->numDevices);
return status;
}
/*******************************************************************************
* @fn getDeviceCap
* @brief This function returns the device capabilities.
* @param[in] oveContext : Encoder context
* @param[in] oveDeviceID : Device ID
* @param[out] encodeCaps : pointer to encoder capabilities structure
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool getDeviceCap(OPContextHandle oveContext,unsigned int oveDeviceID, OVE_ENCODE_CAPS *encodeCaps)
{
unsigned int numCaps = 1;
// initialize the encode capabilities variable
encodeCaps->EncodeModes = OVE_AVC_FULL;
encodeCaps->encode_cap_size = sizeof(OVE_ENCODE_CAPS);
encodeCaps->caps.encode_cap_full->max_picture_size_in_MB = 0;
encodeCaps->caps.encode_cap_full->min_picture_size_in_MB = 0;
encodeCaps->caps.encode_cap_full->num_picture_formats = 0;
encodeCaps->caps.encode_cap_full->num_Profile_level = 0;
encodeCaps->caps.encode_cap_full->max_bit_rate = 0;
encodeCaps->caps.encode_cap_full->min_bit_rate = 0;
encodeCaps->caps.encode_cap_full->supported_task_priority = OVE_ENCODE_TASK_PRIORITY_NONE;
for (int j = 0; j < OVE_MAX_NUM_PICTURE_FORMATS_H264; j++)
encodeCaps->caps.encode_cap_full->supported_picture_formats[j] = OVE_PICTURE_FORMAT_NONE;
for (int j = 0; j < OVE_MAX_NUM_PROFILE_LEVELS_H264; j++)
{
encodeCaps->caps.encode_cap_full->supported_profile_level[j].profile = 0;
encodeCaps->caps.encode_cap_full->supported_profile_level[j].level = 0;
}
// Get the device capabilities & return
return OVEncodeGetDeviceCap(oveContext, oveDeviceID, encodeCaps->encode_cap_size, &numCaps, encodeCaps);
}
/*******************************************************************************
* @fn encodeCreate
* @brief Creates encoder context
* @param[in/out] oveContext : Hanlde to the encoder context
* @param[in] deviceID : Device on which encoder context to be created
* @param[in] deviceHandle : Hanlde for the device information
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool encodeCreate(OPContextHandle *oveContext, unsigned int deviceId, OVDeviceHandle *deviceHandle)
{
cl_device_id clDeviceID;
bool status;
cl_int err;
*oveContext = NULL;
// 1. Create the CL Context - nothing works without a context handle.
// Create a variable for the open video encoder device id
intptr_t properties[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)deviceHandle->platform, 0};
// Create OpenCL context from device's id
clDeviceID = reinterpret_cast<cl_device_id>(deviceId);
*oveContext = clCreateContext(properties, 1, &clDeviceID, 0, 0, &err);
if (*oveContext == (cl_context)0)
{
puts("\nCannot create cl_context\n");
return false;
}
if (err != CL_SUCCESS)
{
printf("Error in clCreateContext: %d\n", err);
return false;
}
if (deviceId == 0)
{
puts("No suitable devices found!\n");
return false;
}
// 2. Read the device capabilities.
// Device capabilities should be used to validate against the configuration set by the user for the codec
OVE_ENCODE_CAPS encodeCaps;
OVE_ENCODE_CAPS_H264 encode_cap_full;
encodeCaps.caps.encode_cap_full = (OVE_ENCODE_CAPS_H264 *)&encode_cap_full;
status = getDeviceCap(*oveContext, deviceId, &encodeCaps);
if(!status)
{
puts("OVEncodeGetDeviceCap failed!\n");
return false;
}
return(0);
}
/*******************************************************************************
* @fn setEncodeConfig
* @brief This function sets the encoder configuration by using user supplied configuration information from .cfg file
* @param[in] session : Encoder session for which encoder configuration to be set
* @param[in] pConfig : pointer to the user configuration from .cfg file
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool setEncodeConfig(ove_session session, OvConfigCtrl *pConfig)
{
unsigned int numOfConfigBuffers = 4;
OVE_CONFIG oveConfig[4];
// send configuration values for this session
oveConfig[0].config.pPictureControl = &(pConfig->pictControl);
oveConfig[0].configType = OVE_CONFIG_TYPE_PICTURE_CONTROL;
oveConfig[1].config.pRateControl = &(pConfig->rateControl);
oveConfig[1].configType = OVE_CONFIG_TYPE_RATE_CONTROL;
oveConfig[2].config.pMotionEstimation = &(pConfig->meControl);
oveConfig[2].configType = OVE_CONFIG_TYPE_MOTION_ESTIMATION;
oveConfig[3].config.pRDO = &(pConfig->rdoControl);
oveConfig[3].configType = OVE_CONFIG_TYPE_RDO;
if (!(OVresult)OVEncodeSendConfig(session, numOfConfigBuffers, oveConfig))
{
printf("OVEncodeSendConfig returned error\n");
return false;
}
// Just verifying that the values have been set in the encoding engine.
/*OVE_CONFIG_PICTURE_CONTROL pictureControlConfig;
OVE_CONFIG_RATE_CONTROL rateControlConfig;
OVE_CONFIG_MOTION_ESTIMATION meControlConfig;
OVE_CONFIG_RDO rdoControlConfig;
// Get the picture control configuration.
memset(&pictureControlConfig, 0, sizeof(OVE_CONFIG_PICTURE_CONTROL));
pictureControlConfig.size = sizeof(OVE_CONFIG_PICTURE_CONTROL);
if (!(OVresult)OVEncodeGetPictureControlConfig(session, &pictureControlConfig))
{
printf("OVEncodeGetPictureControlConfig returned error\n");
return false;
}
// Get the rate control configuration
memset(&rateControlConfig, 0, sizeof(OVE_CONFIG_RATE_CONTROL));
rateControlConfig.size = sizeof(OVE_CONFIG_RATE_CONTROL);
if (!(OVresult)OVEncodeGetRateControlConfig(session, &rateControlConfig))
{
printf("OVEncodeGetRateControlConfig returned error\n");
return false;
}
// Get the MotionEstimation configuration
memset(&meControlConfig, 0, sizeof(OVE_CONFIG_MOTION_ESTIMATION));
meControlConfig.size = sizeof(OVE_CONFIG_MOTION_ESTIMATION);
if (!(OVresult)OVEncodeGetMotionEstimationConfig(session, &meControlConfig))
{
printf("OVEncodeGetMotionEstimationConfig returned error\n");
return false;
}
// Get the RDO configuration
memset(&rdoControlConfig, 0, sizeof(OVE_CONFIG_RDO));
rdoControlConfig.size = sizeof(OVE_CONFIG_RDO);
if (!OVEncodeGetRDOControlConfig(session, &rdoControlConfig))
{
printf("OVEncodeGetRDOControlConfig returned error\n");
return false;
}*/
return true;
}
/*******************************************************************************
* @fn waitForEvent
* @brief This function waits for the event completion
* @param[in] inMapEvt : Event for which it has to wait for completion
* @return bool : true if successful; otherwise false.
******************************************************************************/
inline void waitForEvent(cl_event inMapEvt)
{
cl_int eventStatus = CL_QUEUED;
while (eventStatus != CL_COMPLETE)
{
clGetEventInfo(inMapEvt, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &eventStatus, NULL);
}
}
/*******************************************************************************
* @fn encodeClose
* @brief This function destroys the resources used by the encoder session
* @param[in] encodeHandle : Handle for the encoder context
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool encodeClose(OVEncodeHandle *encodeHandle)
{
cl_int err;
OPMemHandle *inputSurfaces = encodeHandle->inputSurfaces;
for (int i = 0; i < MAX_INPUT_SURFACE; i++)
{
err = clReleaseMemObject((cl_mem)inputSurfaces[i]);
if (err != CL_SUCCESS)
{
printf("clReleaseMemObject returned error %d\n", err);
return false;
}
}
err = clReleaseCommandQueue(encodeHandle->clCmdQueue);
if(err != CL_SUCCESS)
{
puts("Error releasing Command queue\n");
return false;
}
bool oveErr = OVEncodeDestroySession(encodeHandle->session);
if (!oveErr)
{
puts("Error releasing OVE Session\n");
return false;
}
return true;
}
/******************************************************************************
* @fn encodeDestroy
* @brief Destroy encoder context
* @param[in] oveContext : Handle for the encoder context
* @return bool : true if successful; otherwise false.
******************************************************************************/
bool encodeDestroy(OPContextHandle oveContext)
{
if ((cl_context)oveContext)
{
cl_int err = clReleaseContext((cl_context)oveContext);
if (err != CL_SUCCESS)
{
puts("Error releasing cl context\n");
return false;
}
}
return true;
}