Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
170c6533
Commit
170c6533
authored
Sep 02, 2017
by
Mark Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hwcontext_vaapi: Add DRM to VAAPI mapping
parent
9cb23cd9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
228 additions
and
1 deletion
+228
-1
hwcontext_vaapi.c
libavutil/hwcontext_vaapi.c
+228
-1
No files found.
libavutil/hwcontext_vaapi.c
View file @
170c6533
...
@@ -25,6 +25,11 @@
...
@@ -25,6 +25,11 @@
# include <va/va_drm.h>
# include <va/va_drm.h>
#endif
#endif
#if CONFIG_LIBDRM
# include <va/va_drmcommon.h>
# include <drm_fourcc.h>
#endif
#include <fcntl.h>
#include <fcntl.h>
#if HAVE_UNISTD_H
#if HAVE_UNISTD_H
# include <unistd.h>
# include <unistd.h>
...
@@ -41,6 +46,10 @@
...
@@ -41,6 +46,10 @@
#include "pixdesc.h"
#include "pixdesc.h"
#include "pixfmt.h"
#include "pixfmt.h"
#if CONFIG_LIBDRM
# include "hwcontext_drm.h"
#endif
typedef
struct
VAAPIDevicePriv
{
typedef
struct
VAAPIDevicePriv
{
#if HAVE_VAAPI_X11
#if HAVE_VAAPI_X11
Display
*
x11_display
;
Display
*
x11_display
;
...
@@ -897,6 +906,173 @@ static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
...
@@ -897,6 +906,173 @@ static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
return
0
;
return
0
;
}
}
#if CONFIG_LIBDRM
#define DRM_MAP(va, layers, ...) { \
VA_FOURCC_ ## va, \
layers, \
{ __VA_ARGS__ } \
}
static
const
struct
{
uint32_t
va_fourcc
;
int
nb_layer_formats
;
uint32_t
layer_formats
[
AV_DRM_MAX_PLANES
];
}
vaapi_drm_format_map
[]
=
{
DRM_MAP
(
NV12
,
2
,
DRM_FORMAT_R8
,
DRM_FORMAT_RG88
),
DRM_MAP
(
NV12
,
1
,
DRM_FORMAT_NV12
),
#ifdef VA_FOURCC_P010
DRM_MAP
(
P010
,
2
,
DRM_FORMAT_R16
,
DRM_FORMAT_RG1616
),
#endif
DRM_MAP
(
BGRA
,
1
,
DRM_FORMAT_BGRA8888
),
DRM_MAP
(
BGRX
,
1
,
DRM_FORMAT_BGRX8888
),
DRM_MAP
(
RGBA
,
1
,
DRM_FORMAT_RGBA8888
),
DRM_MAP
(
RGBX
,
1
,
DRM_FORMAT_RGBX8888
),
#ifdef VA_FOURCC_ABGR
DRM_MAP
(
ABGR
,
1
,
DRM_FORMAT_ABGR8888
),
DRM_MAP
(
XBGR
,
1
,
DRM_FORMAT_XBGR8888
),
#endif
DRM_MAP
(
ARGB
,
1
,
DRM_FORMAT_ARGB8888
),
DRM_MAP
(
XRGB
,
1
,
DRM_FORMAT_XRGB8888
),
};
#undef DRM_MAP
static
void
vaapi_unmap_from_drm
(
AVHWFramesContext
*
dst_fc
,
HWMapDescriptor
*
hwmap
)
{
AVVAAPIDeviceContext
*
dst_dev
=
dst_fc
->
device_ctx
->
hwctx
;
VASurfaceID
surface_id
=
(
VASurfaceID
)(
uintptr_t
)
hwmap
->
priv
;
av_log
(
dst_fc
,
AV_LOG_DEBUG
,
"Destroy surface %#x.
\n
"
,
surface_id
);
vaDestroySurfaces
(
dst_dev
->
display
,
&
surface_id
,
1
);
}
static
int
vaapi_map_from_drm
(
AVHWFramesContext
*
src_fc
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
flags
)
{
AVHWFramesContext
*
dst_fc
=
(
AVHWFramesContext
*
)
dst
->
hw_frames_ctx
->
data
;
AVVAAPIDeviceContext
*
dst_dev
=
dst_fc
->
device_ctx
->
hwctx
;
const
AVDRMFrameDescriptor
*
desc
;
VASurfaceID
surface_id
;
VAStatus
vas
;
uint32_t
va_fourcc
,
va_rt_format
;
int
err
,
i
,
j
,
k
;
unsigned
long
buffer_handle
;
VASurfaceAttribExternalBuffers
buffer_desc
;
VASurfaceAttrib
attrs
[
2
]
=
{
{
.
type
=
VASurfaceAttribMemoryType
,
.
flags
=
VA_SURFACE_ATTRIB_SETTABLE
,
.
value
.
type
=
VAGenericValueTypeInteger
,
.
value
.
value
.
i
=
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
,
},
{
.
type
=
VASurfaceAttribExternalBufferDescriptor
,
.
flags
=
VA_SURFACE_ATTRIB_SETTABLE
,
.
value
.
type
=
VAGenericValueTypePointer
,
.
value
.
value
.
p
=
&
buffer_desc
,
}
};
desc
=
(
AVDRMFrameDescriptor
*
)
src
->
data
[
0
];
if
(
desc
->
nb_objects
!=
1
)
{
av_log
(
dst_fc
,
AV_LOG_ERROR
,
"VAAPI can only map frames "
"made from a single DRM object.
\n
"
);
return
AVERROR
(
EINVAL
);
}
va_fourcc
=
0
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
vaapi_drm_format_map
);
i
++
)
{
if
(
desc
->
nb_layers
!=
vaapi_drm_format_map
[
i
].
nb_layer_formats
)
continue
;
for
(
j
=
0
;
j
<
desc
->
nb_layers
;
j
++
)
{
if
(
desc
->
layers
[
j
].
format
!=
vaapi_drm_format_map
[
i
].
layer_formats
[
j
])
break
;
}
if
(
j
!=
desc
->
nb_layers
)
continue
;
va_fourcc
=
vaapi_drm_format_map
[
i
].
va_fourcc
;
break
;
}
if
(
!
va_fourcc
)
{
av_log
(
dst_fc
,
AV_LOG_ERROR
,
"DRM format not supported "
"by VAAPI.
\n
"
);
return
AVERROR
(
EINVAL
);
}
av_log
(
dst_fc
,
AV_LOG_DEBUG
,
"Map DRM object %d to VAAPI as "
"%08x.
\n
"
,
desc
->
objects
[
0
].
fd
,
va_fourcc
);
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
vaapi_format_map
);
i
++
)
{
if
(
vaapi_format_map
[
i
].
fourcc
==
va_fourcc
)
va_rt_format
=
vaapi_format_map
[
i
].
rt_format
;
}
buffer_handle
=
desc
->
objects
[
0
].
fd
;
buffer_desc
.
pixel_format
=
va_fourcc
;
buffer_desc
.
width
=
src_fc
->
width
;
buffer_desc
.
height
=
src_fc
->
height
;
buffer_desc
.
data_size
=
desc
->
objects
[
0
].
size
;
buffer_desc
.
buffers
=
&
buffer_handle
;
buffer_desc
.
num_buffers
=
1
;
buffer_desc
.
flags
=
0
;
k
=
0
;
for
(
i
=
0
;
i
<
desc
->
nb_layers
;
i
++
)
{
for
(
j
=
0
;
j
<
desc
->
layers
[
i
].
nb_planes
;
j
++
)
{
buffer_desc
.
pitches
[
k
]
=
desc
->
layers
[
i
].
planes
[
j
].
pitch
;
buffer_desc
.
offsets
[
k
]
=
desc
->
layers
[
i
].
planes
[
j
].
offset
;
++
k
;
}
}
buffer_desc
.
num_planes
=
k
;
vas
=
vaCreateSurfaces
(
dst_dev
->
display
,
va_rt_format
,
src
->
width
,
src
->
height
,
&
surface_id
,
1
,
attrs
,
FF_ARRAY_ELEMS
(
attrs
));
if
(
vas
!=
VA_STATUS_SUCCESS
)
{
av_log
(
dst_fc
,
AV_LOG_ERROR
,
"Failed to create surface from DRM "
"object: %d (%s).
\n
"
,
vas
,
vaErrorStr
(
vas
));
return
AVERROR
(
EIO
);
}
av_log
(
dst_fc
,
AV_LOG_DEBUG
,
"Create surface %#x.
\n
"
,
surface_id
);
err
=
ff_hwframe_map_create
(
dst
->
hw_frames_ctx
,
dst
,
src
,
&
vaapi_unmap_from_drm
,
(
void
*
)(
uintptr_t
)
surface_id
);
if
(
err
<
0
)
return
err
;
dst
->
width
=
src
->
width
;
dst
->
height
=
src
->
height
;
dst
->
data
[
3
]
=
(
uint8_t
*
)(
uintptr_t
)
surface_id
;
av_log
(
dst_fc
,
AV_LOG_DEBUG
,
"Mapped DRM object %d to "
"surface %#x.
\n
"
,
desc
->
objects
[
0
].
fd
,
surface_id
);
return
0
;
}
#endif
static
int
vaapi_map_to
(
AVHWFramesContext
*
hwfc
,
AVFrame
*
dst
,
const
AVFrame
*
src
,
int
flags
)
{
switch
(
src
->
format
)
{
#if CONFIG_LIBDRM
case
AV_PIX_FMT_DRM_PRIME
:
return
vaapi_map_from_drm
(
hwfc
,
dst
,
src
,
flags
);
#endif
default:
return
AVERROR
(
ENOSYS
);
}
}
static
void
vaapi_device_free
(
AVHWDeviceContext
*
ctx
)
static
void
vaapi_device_free
(
AVHWDeviceContext
*
ctx
)
{
{
AVVAAPIDeviceContext
*
hwctx
=
ctx
->
hwctx
;
AVVAAPIDeviceContext
*
hwctx
=
ctx
->
hwctx
;
...
@@ -999,6 +1175,56 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
...
@@ -999,6 +1175,56 @@ static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
return
0
;
return
0
;
}
}
static
int
vaapi_device_derive
(
AVHWDeviceContext
*
ctx
,
AVHWDeviceContext
*
src_ctx
,
int
flags
)
{
#if CONFIG_LIBDRM
if
(
src_ctx
->
type
==
AV_HWDEVICE_TYPE_DRM
)
{
AVDRMDeviceContext
*
src_hwctx
=
src_ctx
->
hwctx
;
AVVAAPIDeviceContext
*
hwctx
=
ctx
->
hwctx
;
VADisplay
*
display
;
VAStatus
vas
;
VAAPIDevicePriv
*
priv
;
int
major
,
minor
;
if
(
src_hwctx
->
fd
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"DRM instance requires an associated "
"device to derive a VA display from.
\n
"
);
return
AVERROR
(
EINVAL
);
}
priv
=
av_mallocz
(
sizeof
(
*
priv
));
if
(
!
priv
)
return
AVERROR
(
ENOMEM
);
// Inherits the fd from the source context, which will close it.
priv
->
drm_fd
=
-
1
;
ctx
->
user_opaque
=
priv
;
ctx
->
free
=
&
vaapi_device_free
;
display
=
vaGetDisplayDRM
(
src_hwctx
->
fd
);
if
(
!
display
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to open a VA display from "
"DRM device.
\n
"
);
return
AVERROR
(
EIO
);
}
hwctx
->
display
=
display
;
vas
=
vaInitialize
(
display
,
&
major
,
&
minor
);
if
(
vas
!=
VA_STATUS_SUCCESS
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to initialise VAAPI "
"connection: %d (%s).
\n
"
,
vas
,
vaErrorStr
(
vas
));
return
AVERROR
(
EIO
);
}
return
0
;
}
#endif
return
AVERROR
(
ENOSYS
);
}
const
HWContextType
ff_hwcontext_type_vaapi
=
{
const
HWContextType
ff_hwcontext_type_vaapi
=
{
.
type
=
AV_HWDEVICE_TYPE_VAAPI
,
.
type
=
AV_HWDEVICE_TYPE_VAAPI
,
.
name
=
"VAAPI"
,
.
name
=
"VAAPI"
,
...
@@ -1010,6 +1236,7 @@ const HWContextType ff_hwcontext_type_vaapi = {
...
@@ -1010,6 +1236,7 @@ const HWContextType ff_hwcontext_type_vaapi = {
.
frames_priv_size
=
sizeof
(
VAAPIFramesContext
),
.
frames_priv_size
=
sizeof
(
VAAPIFramesContext
),
.
device_create
=
&
vaapi_device_create
,
.
device_create
=
&
vaapi_device_create
,
.
device_derive
=
&
vaapi_device_derive
,
.
device_init
=
&
vaapi_device_init
,
.
device_init
=
&
vaapi_device_init
,
.
device_uninit
=
&
vaapi_device_uninit
,
.
device_uninit
=
&
vaapi_device_uninit
,
.
frames_get_constraints
=
&
vaapi_frames_get_constraints
,
.
frames_get_constraints
=
&
vaapi_frames_get_constraints
,
...
@@ -1019,7 +1246,7 @@ const HWContextType ff_hwcontext_type_vaapi = {
...
@@ -1019,7 +1246,7 @@ const HWContextType ff_hwcontext_type_vaapi = {
.
transfer_get_formats
=
&
vaapi_transfer_get_formats
,
.
transfer_get_formats
=
&
vaapi_transfer_get_formats
,
.
transfer_data_to
=
&
vaapi_transfer_data_to
,
.
transfer_data_to
=
&
vaapi_transfer_data_to
,
.
transfer_data_from
=
&
vaapi_transfer_data_from
,
.
transfer_data_from
=
&
vaapi_transfer_data_from
,
.
map_to
=
NULL
,
.
map_to
=
&
vaapi_map_to
,
.
map_from
=
&
vaapi_map_from
,
.
map_from
=
&
vaapi_map_from
,
.
pix_fmts
=
(
const
enum
AVPixelFormat
[])
{
.
pix_fmts
=
(
const
enum
AVPixelFormat
[])
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment