D3D12转换格式空间,D3D12编码仅支持nv12类型,如输入是RGBA BGRA BGRX等图像各种均可通过改模块进行格式空间的转换。代码为GPU接口handle的传入转换,其他格式改为文件或缓存空间即可
其vaapi接口参考来自https://github.com/intel/libva-utils/blob/master/videoprocess/vavpp.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/time.h>
#include <assert.h>
#include <va/va.h>
#include <va/va_vpp.h>
static VAContextID context_id = 0;
static VAConfigID config_id = 0;
static VASurfaceID g_in_surface_id = VA_INVALID_ID;
static VASurfaceID g_out_surface_id = VA_INVALID_ID;
static uint32_t g_in_pic_width = 352;
static uint32_t g_in_pic_height = 288;
static uint32_t g_out_pic_width = 352;
static uint32_t g_out_pic_height = 288;
static uint32_t g_in_fourcc = VA_FOURCC('N', 'V', '1', '2');
static uint32_t g_in_format = VA_RT_FORMAT_YUV420;
static uint32_t g_out_fourcc = VA_FOURCC('N', 'V', '1', '2');
static uint32_t g_out_format = VA_RT_FORMAT_YUV420;
static get_context(VAContextID &context_id)
{
/* Render target surface format check */
VAConfigAttrib attrib;
attrib.type = VAConfigAttribRTFormat;
va_status = vaGetConfigAttributes(va_dpy,
VAProfileNone,
VAEntrypointVideoProc,
&attrib,
1);
CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
if (!(attrib.value & g_out_format)) {
printf("RT format %d is not supported by VPP !\n", g_out_format);
assert(0);
}
va_status = vaCreateConfig(va_dpy,
VAProfileNone,
VAEntrypointVideoProc,
&attrib,
1,
&config_id);
CHECK_VASTATUS(va_status, "vaCreateConfig");
va_status = vaCreateContext(va_dpy,
config_id,
g_out_pic_width,
g_out_pic_height,
VA_PROGRESSIVE,
&g_out_surface_id,
1,
&context_id);
CHECK_VASTATUS(va_status, "vaCreateContext");
}
static VAStatus
video_frame_process(VAProcFilterType filter_type,
uint32_t frame_idx,
VASurfaceID in_surface_id,
VASurfaceID out_surface_id)
{
VAStatus va_status;
VAProcPipelineParameterBuffer pipeline_param;
VARectangle surface_region, output_region;
VABufferID pipeline_param_buf_id = VA_INVALID_ID;
VABufferID filter_param_buf_id = VA_INVALID_ID;
uint32_t filter_count = 0;
/* Fill pipeline buffer */
surface_region.x = 0;
surface_region.y = 0;
surface_region.width = g_in_pic_width;
surface_region.height = g_in_pic_height;
output_region.x = 0;
output_region.y = 0;
output_region.width = g_out_pic_width;
output_region.height = g_out_pic_height;
memset(&pipeline_param, 0, sizeof(pipeline_param));
pipeline_param.surface = in_surface_id;
pipeline_param.surface_region = &surface_region;
pipeline_param.output_region = &output_region;
pipeline_param.filter_flags = 0;
pipeline_param.filters = &filter_param_buf_id;
pipeline_param.num_filters = filter_count;
va_status = vaCreateBuffer(va_dpy,
context_id,
VAProcPipelineParameterBufferType,
sizeof(pipeline_param),
1,
&pipeline_param,
&pipeline_param_buf_id);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaBeginPicture(va_dpy,
context_id,
out_surface_id);
CHECK_VASTATUS(va_status, "vaBeginPicture");
va_status = vaRenderPicture(va_dpy,
context_id,
&pipeline_param_buf_id,
1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaEndPicture(va_dpy, context_id);
CHECK_VASTATUS(va_status, "vaEndPicture");
va_status = vaSyncSurface(va_dpy, out_surface_id); //wait gpu finish
CHECK_VASTATUS(va_status, "vaEndPicture");
if (filter_param_buf_id != VA_INVALID_ID)
vaDestroyBuffer(va_dpy, filter_param_buf_id);
if (pipeline_param_buf_id != VA_INVALID_ID)
vaDestroyBuffer(va_dpy, pipeline_param_buf_id);
return va_status;
}
int main()
{
// handle is gpu capture
VAStatus va_status;
VASurfaceID surface_id;
VASurfaceID out_surface_id;
HANDLE nt_handle[2];
nt_handles[0] = handle;
VASurfaceAttrib attrs[3];
VASurfaceAttrib attrs_process[2];
attrs[0].type = VASurfaceAttribPixelFormat;
attrs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrs[0].value.type = VAGencericValueTypeTnteger;
attrs[0].value.value.i = VA_FOURCC('B', 'G', 'R', 'A');
attrs[1].type = VASurfaceAttribMemoryType;
attrs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrs[1].value.type = VAGencericValueTypeTnteger;
attrs[1].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_NTHANDLE;
attrs[2].type = VASurfaceAttribPixelFormat;
attrs[2].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrs[2].value.type = VAGencericValueTypePointer;
attrs[2].value.value.p = &nt_handles;
attrs_process[0].type = VASurfaceAttribPixelFormat;
attrs_process[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
attrs_process[0].value.type = VAGencericValueTypeTnteger;
attrs_process[0].value.value.i = VA_FOURCC('N', 'V', '1', '2');
va_status = vaCreateSurface(va_ctx_va_dpy, VA_RT_FORMAT_RGB32, va_ctx->witch, va_ctx_height, &surface_id, 1, attrs, FF_ARRAY_ELEMS(attrs)); //attrs = 3
CHECK_VASTATUS(va_status, "vaCreateSurface");
va_status = vaCreateSurface(va_ctx_va_dpy, VA_RT_FORMAT_YUV420, va_ctx->witch, va_ctx_height, &out_surface_id, 1, attrs_process, FF_ARRAY_ELEMS(attrs_process)); //attrs = 2
CHECK_VASTATUS(va_status, "vaCreateSurface");
video_frame_process(g_filter_type, context_process_id, surface_id, out_surface_id);
vaDestroySurface(va_ctx->va_dpy, &surface_id, 1);
src_surface = out_surface_id;
return 0;
}