Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
eb3e9f46
F
Ffmpeg
项目概览
小白菜888
/
Ffmpeg
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Ffmpeg
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
eb3e9f46
编写于
3月 04, 2017
作者:
M
Mark Thompson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
hwcontext_opencl: VAAPI to OpenCL mapping for Intel i965+beignet
Supports all surface formats in common between the two.
上级
b25d8ef0
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
304 addition
and
0 deletion
+304
-0
configure
configure
+6
-0
libavutil/hwcontext_opencl.c
libavutil/hwcontext_opencl.c
+298
-0
未找到文件。
configure
浏览文件 @
eb3e9f46
...
...
@@ -2120,6 +2120,7 @@ HAVE_LIST="
$TYPES_LIST
makeinfo
makeinfo_html
opencl_vaapi_beignet
perl
pod2man
texi2html
...
...
@@ -6155,6 +6156,11 @@ enabled vaapi &&
check_cpp_condition
"va/va.h"
"VA_CHECK_VERSION(1, 0, 0)"
&&
enable
vaapi_1
if
enabled_all opencl vaapi
;
then
check_type
"CL/cl_intel.h"
"clCreateImageFromFdINTEL_fn"
&&
enable
opencl_vaapi_beignet
fi
enabled vdpau
&&
check_cpp_condition vdpau/vdpau.h
"defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP"
||
disable vdpau
...
...
libavutil/hwcontext_opencl.c
浏览文件 @
eb3e9f46
...
...
@@ -29,6 +29,14 @@
#include "mem.h"
#include "pixdesc.h"
#if HAVE_OPENCL_VAAPI_BEIGNET
#include <unistd.h>
#include <va/va.h>
#include <va/va_drmcommon.h>
#include <CL/cl_intel.h>
#include "hwcontext_vaapi.h"
#endif
typedef
struct
OpenCLDeviceContext
{
// Default command queue to use for transfer/mapping operations on
...
...
@@ -41,6 +49,10 @@ typedef struct OpenCLDeviceContext {
cl_platform_id
platform_id
;
// Platform/device-specific functions.
#if HAVE_OPENCL_VAAPI_BEIGNET
int
vaapi_mapping_usable
;
clCreateImageFromFdINTEL_fn
clCreateImageFromFdINTEL
;
#endif
}
OpenCLDeviceContext
;
typedef
struct
OpenCLFramesContext
{
...
...
@@ -589,6 +601,40 @@ static int opencl_device_init(AVHWDeviceContext *hwdev)
return
AVERROR
(
EIO
);
}
#define CL_FUNC(name, desc) do { \
if (fail) \
break; \
priv->name = clGetExtensionFunctionAddressForPlatform( \
priv->platform_id, #name); \
if (!priv->name) { \
av_log(hwdev, AV_LOG_VERBOSE, \
desc " function not found (%s).\n", #name); \
fail = 1; \
} else { \
av_log(hwdev, AV_LOG_VERBOSE, \
desc " function found (%s).\n", #name); \
} \
} while (0)
#if HAVE_OPENCL_VAAPI_BEIGNET
{
int
fail
=
0
;
CL_FUNC
(
clCreateImageFromFdINTEL
,
"Intel DRM to OpenCL image mapping"
);
if
(
fail
)
{
av_log
(
hwdev
,
AV_LOG_WARNING
,
"VAAPI to OpenCL mapping "
"not usable.
\n
"
);
priv
->
vaapi_mapping_usable
=
0
;
}
else
{
priv
->
vaapi_mapping_usable
=
1
;
}
}
#endif
#undef CL_FUNC
return
0
;
}
...
...
@@ -606,6 +652,52 @@ static void opencl_device_uninit(AVHWDeviceContext *hwdev)
}
}
static
int
opencl_device_derive
(
AVHWDeviceContext
*
hwdev
,
AVHWDeviceContext
*
src_ctx
,
int
flags
)
{
int
err
;
switch
(
src_ctx
->
type
)
{
#if HAVE_OPENCL_VAAPI_BEIGNET
case
AV_HWDEVICE_TYPE_VAAPI
:
{
// Surface mapping works via DRM PRIME fds with no special
// initialisation required in advance. This just finds the
// Beignet ICD by name.
AVDictionary
*
opts
=
NULL
;
err
=
av_dict_set
(
&
opts
,
"platform_vendor"
,
"Intel"
,
0
);
if
(
err
>=
0
)
err
=
av_dict_set
(
&
opts
,
"platform_version"
,
"beignet"
,
0
);
if
(
err
>=
0
)
{
OpenCLDeviceSelector
selector
=
{
.
platform_index
=
-
1
,
.
device_index
=
0
,
.
context
=
opts
,
.
enumerate_platforms
=
&
opencl_enumerate_platforms
,
.
filter_platform
=
&
opencl_filter_platform
,
.
enumerate_devices
=
&
opencl_enumerate_devices
,
.
filter_device
=
NULL
,
};
err
=
opencl_device_create_internal
(
hwdev
,
&
selector
,
NULL
);
}
av_dict_free
(
&
opts
);
}
break
;
#endif
default:
err
=
AVERROR
(
ENOSYS
);
break
;
}
if
(
err
<
0
)
return
err
;
return
opencl_device_init
(
hwdev
);
}
static
int
opencl_get_plane_format
(
enum
AVPixelFormat
pixfmt
,
int
plane
,
int
width
,
int
height
,
cl_image_format
*
image_format
,
...
...
@@ -1263,6 +1355,177 @@ fail:
return
err
;
}
#if HAVE_OPENCL_VAAPI_BEIGNET
typedef
struct
VAAPItoOpenCLMapping
{
VAImage
va_image
;
VABufferInfo
va_buffer_info
;
AVOpenCLFrameDescriptor
frame
;
}
VAAPItoOpenCLMapping
;
static
void
opencl_unmap_from_vaapi
(
AVHWFramesContext
*
src_fc
,
HWMapDescriptor
*
hwmap
)
{
VAAPItoOpenCLMapping
*
mapping
=
hwmap
->
priv
;
AVVAAPIDeviceContext
*
src_dev
=
src_fc
->
device_ctx
->
hwctx
;
VASurfaceID
surface_id
;
VAStatus
vas
;
cl_int
cle
;
int
i
;
surface_id
=
(
VASurfaceID
)(
uintptr_t
)
hwmap
->
source
->
data
[
3
];
av_log
(
src_fc
,
AV_LOG_DEBUG
,
"Unmap VAAPI surface %#x from OpenCL.
\n
"
,
surface_id
);
for
(
i
=
0
;
i
<
mapping
->
frame
.
nb_planes
;
i
++
)
{
cle
=
clReleaseMemObject
(
mapping
->
frame
.
planes
[
i
]);
if
(
cle
!=
CL_SUCCESS
)
{
av_log
(
src_fc
,
AV_LOG_ERROR
,
"Failed to release CL "
"buffer of plane %d of VA image %#x (derived "
"from surface %#x): %d.
\n
"
,
i
,
mapping
->
va_image
.
buf
,
surface_id
,
cle
);
}
}
vas
=
vaReleaseBufferHandle
(
src_dev
->
display
,
mapping
->
va_image
.
buf
);
if
(
vas
!=
VA_STATUS_SUCCESS
)
{
av_log
(
src_fc
,
AV_LOG_ERROR
,
"Failed to release buffer "
"handle of image %#x (derived from surface %#x): "
"%d (%s).
\n
"
,
mapping
->
va_image
.
buf
,
surface_id
,
vas
,
vaErrorStr
(
vas
));
}
vas
=
vaDestroyImage
(
src_dev
->
display
,
mapping
->
va_image
.
image_id
);
if
(
vas
!=
VA_STATUS_SUCCESS
)
{
av_log
(
src_fc
,
AV_LOG_ERROR
,
"Failed to destroy image "
"derived from surface %#x: %d (%s).
\n
"
,
surface_id
,
vas
,
vaErrorStr
(
vas
));
}
av_free
(
mapping
);
}
static
int
opencl_map_from_vaapi
(
AVHWFramesContext
*
dst_fc
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
flags
)
{
AVHWFramesContext
*
src_fc
=
(
AVHWFramesContext
*
)
src
->
hw_frames_ctx
->
data
;
AVVAAPIDeviceContext
*
src_dev
=
src_fc
->
device_ctx
->
hwctx
;
AVOpenCLDeviceContext
*
dst_dev
=
dst_fc
->
device_ctx
->
hwctx
;
OpenCLDeviceContext
*
priv
=
dst_fc
->
device_ctx
->
internal
->
priv
;
VAAPItoOpenCLMapping
*
mapping
=
NULL
;
VASurfaceID
surface_id
;
VAStatus
vas
;
cl_int
cle
;
int
err
,
p
;
surface_id
=
(
VASurfaceID
)(
uintptr_t
)
src
->
data
[
3
];
av_log
(
src_fc
,
AV_LOG_DEBUG
,
"Map VAAPI surface %#x to OpenCL.
\n
"
,
surface_id
);
mapping
=
av_mallocz
(
sizeof
(
*
mapping
));
if
(
!
mapping
)
return
AVERROR
(
ENOMEM
);
vas
=
vaDeriveImage
(
src_dev
->
display
,
surface_id
,
&
mapping
->
va_image
);
if
(
vas
!=
VA_STATUS_SUCCESS
)
{
av_log
(
src_fc
,
AV_LOG_ERROR
,
"Failed to derive image from "
"surface %#x: %d (%s).
\n
"
,
surface_id
,
vas
,
vaErrorStr
(
vas
));
err
=
AVERROR
(
EIO
);
goto
fail
;
}
mapping
->
va_buffer_info
.
mem_type
=
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
;
vas
=
vaAcquireBufferHandle
(
src_dev
->
display
,
mapping
->
va_image
.
buf
,
&
mapping
->
va_buffer_info
);
if
(
vas
!=
VA_STATUS_SUCCESS
)
{
av_log
(
src_fc
,
AV_LOG_ERROR
,
"Failed to get buffer "
"handle from image %#x (derived from surface %#x): "
"%d (%s).
\n
"
,
mapping
->
va_image
.
buf
,
surface_id
,
vas
,
vaErrorStr
(
vas
));
vaDestroyImage
(
src_dev
->
display
,
mapping
->
va_image
.
buf
);
err
=
AVERROR
(
EIO
);
goto
fail_derived
;
}
av_log
(
dst_fc
,
AV_LOG_DEBUG
,
"DRM PRIME fd is %ld.
\n
"
,
mapping
->
va_buffer_info
.
handle
);
mapping
->
frame
.
nb_planes
=
mapping
->
va_image
.
num_planes
;
for
(
p
=
0
;
p
<
mapping
->
frame
.
nb_planes
;
p
++
)
{
cl_import_image_info_intel
image_info
=
{
.
fd
=
mapping
->
va_buffer_info
.
handle
,
.
size
=
mapping
->
va_buffer_info
.
mem_size
,
.
type
=
CL_MEM_OBJECT_IMAGE2D
,
.
offset
=
mapping
->
va_image
.
offsets
[
p
],
.
row_pitch
=
mapping
->
va_image
.
pitches
[
p
],
};
cl_image_desc
image_desc
;
err
=
opencl_get_plane_format
(
src_fc
->
sw_format
,
p
,
mapping
->
va_image
.
width
,
mapping
->
va_image
.
height
,
&
image_info
.
fmt
,
&
image_desc
);
if
(
err
<
0
)
{
av_log
(
dst_fc
,
AV_LOG_ERROR
,
"VA %#x (derived from "
"surface %#x) has invalid parameters: %d.
\n
"
,
mapping
->
va_image
.
buf
,
surface_id
,
err
);
goto
fail_mapped
;
}
image_info
.
width
=
image_desc
.
image_width
;
image_info
.
height
=
image_desc
.
image_height
;
mapping
->
frame
.
planes
[
p
]
=
priv
->
clCreateImageFromFdINTEL
(
dst_dev
->
context
,
&
image_info
,
&
cle
);
if
(
!
mapping
->
frame
.
planes
[
p
])
{
av_log
(
dst_fc
,
AV_LOG_ERROR
,
"Failed to create CL image "
"from plane %d of VA image %#x (derived from "
"surface %#x): %d.
\n
"
,
p
,
mapping
->
va_image
.
buf
,
surface_id
,
cle
);
err
=
AVERROR
(
EIO
);
goto
fail_mapped
;
}
dst
->
data
[
p
]
=
(
uint8_t
*
)
mapping
->
frame
.
planes
[
p
];
}
err
=
ff_hwframe_map_create
(
src
->
hw_frames_ctx
,
dst
,
src
,
&
opencl_unmap_from_vaapi
,
mapping
);
if
(
err
<
0
)
goto
fail_mapped
;
dst
->
width
=
src
->
width
;
dst
->
height
=
src
->
height
;
return
0
;
fail_mapped:
for
(
p
=
0
;
p
<
mapping
->
frame
.
nb_planes
;
p
++
)
{
if
(
mapping
->
frame
.
planes
[
p
])
clReleaseMemObject
(
mapping
->
frame
.
planes
[
p
]);
}
vaReleaseBufferHandle
(
src_dev
->
display
,
mapping
->
va_image
.
buf
);
fail_derived:
vaDestroyImage
(
src_dev
->
display
,
mapping
->
va_image
.
image_id
);
fail:
av_freep
(
&
mapping
);
return
err
;
}
#endif
static
int
opencl_map_from
(
AVHWFramesContext
*
hwfc
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
flags
)
{
...
...
@@ -1272,6 +1535,38 @@ static int opencl_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
return
opencl_map_frame
(
hwfc
,
dst
,
src
,
flags
);
}
static
int
opencl_map_to
(
AVHWFramesContext
*
hwfc
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
flags
)
{
OpenCLDeviceContext
*
priv
=
hwfc
->
device_ctx
->
internal
->
priv
;
av_assert0
(
dst
->
format
==
AV_PIX_FMT_OPENCL
);
switch
(
src
->
format
)
{
#if HAVE_OPENCL_VAAPI_BEIGNET
case
AV_PIX_FMT_VAAPI
:
if
(
priv
->
vaapi_mapping_usable
)
return
opencl_map_from_vaapi
(
hwfc
,
dst
,
src
,
flags
);
#endif
}
return
AVERROR
(
ENOSYS
);
}
static
int
opencl_frames_derive_to
(
AVHWFramesContext
*
dst_fc
,
AVHWFramesContext
*
src_fc
,
int
flags
)
{
OpenCLDeviceContext
*
priv
=
dst_fc
->
device_ctx
->
internal
->
priv
;
switch
(
src_fc
->
device_ctx
->
type
)
{
#if HAVE_OPENCL_VAAPI_BEIGNET
case
AV_HWDEVICE_TYPE_VAAPI
:
if
(
!
priv
->
vaapi_mapping_usable
)
return
AVERROR
(
ENOSYS
);
break
;
#endif
default:
return
AVERROR
(
ENOSYS
);
}
return
opencl_frames_init_command_queue
(
dst_fc
);
}
const
HWContextType
ff_hwcontext_type_opencl
=
{
.
type
=
AV_HWDEVICE_TYPE_OPENCL
,
.
name
=
"OpenCL"
,
...
...
@@ -1282,6 +1577,7 @@ const HWContextType ff_hwcontext_type_opencl = {
.
frames_priv_size
=
sizeof
(
OpenCLFramesContext
),
.
device_create
=
&
opencl_device_create
,
.
device_derive
=
&
opencl_device_derive
,
.
device_init
=
&
opencl_device_init
,
.
device_uninit
=
&
opencl_device_uninit
,
...
...
@@ -1295,6 +1591,8 @@ const HWContextType ff_hwcontext_type_opencl = {
.
transfer_data_from
=
&
opencl_transfer_data_from
,
.
map_from
=
&
opencl_map_from
,
.
map_to
=
&
opencl_map_to
,
.
frames_derive_to
=
&
opencl_frames_derive_to
,
.
pix_fmts
=
(
const
enum
AVPixelFormat
[])
{
AV_PIX_FMT_OPENCL
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录