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
bd49be88
Commit
bd49be88
authored
Feb 02, 2016
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avconv_vdpau: use the hwcontext API to simplify code
parent
a001ce31
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
94 additions
and
152 deletions
+94
-152
avconv_vdpau.c
avconv_vdpau.c
+94
-152
No files found.
avconv_vdpau.c
View file @
bd49be88
...
...
@@ -30,29 +30,31 @@
#include "libavutil/avassert.h"
#include "libavutil/buffer.h"
#include "libavutil/frame.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_vdpau.h"
#include "libavutil/pixfmt.h"
typedef
struct
VDPAUContext
{
Display
*
dpy
;
VdpDevice
device
;
VdpDecoder
decoder
;
VdpGetProcAddress
*
get_proc_address
;
AVBufferRef
*
hw_frames_ctx
;
AVFrame
*
tmp_frame
;
}
VDPAUContext
;
VdpGetErrorString
*
get_error_string
;
VdpGetInformationString
*
get_information_string
;
typedef
struct
VDPAUHWDevicePriv
{
VdpDeviceDestroy
*
device_destroy
;
VdpVideoSurfaceCreate
*
video_surface_create
;
VdpVideoSurfaceDestroy
*
video_surface_destroy
;
VdpVideoSurfaceGetBitsYCbCr
*
video_surface_get_bits
;
VdpVideoSurfaceGetParameters
*
video_surface_get_parameters
;
VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities
*
video_surface_query
;
AVFrame
*
tmp_frame
;
Display
*
dpy
;
}
VDPAUHWDevicePriv
;
enum
AVPixelFormat
pix_fmt
;
VdpYCbCrFormat
vdpau_format
;
}
VDPAUContext
;
static
void
device_free
(
AVHWDeviceContext
*
ctx
)
{
AVVDPAUDeviceContext
*
hwctx
=
ctx
->
hwctx
;
VDPAUHWDevicePriv
*
priv
=
ctx
->
user_opaque
;
if
(
priv
->
device_destroy
)
priv
->
device_destroy
(
hwctx
->
device
);
if
(
priv
->
dpy
)
XCloseDisplay
(
priv
->
dpy
);
av_freep
(
&
priv
);
}
static
void
vdpau_uninit
(
AVCodecContext
*
s
)
{
...
...
@@ -63,128 +65,43 @@ static void vdpau_uninit(AVCodecContext *s)
ist
->
hwaccel_get_buffer
=
NULL
;
ist
->
hwaccel_retrieve_data
=
NULL
;
if
(
ctx
->
device_destroy
)
ctx
->
device_destroy
(
ctx
->
device
);
if
(
ctx
->
dpy
)
XCloseDisplay
(
ctx
->
dpy
);
av_buffer_unref
(
&
ctx
->
hw_frames_ctx
);
av_frame_free
(
&
ctx
->
tmp_frame
);
av_freep
(
&
ist
->
hwaccel_ctx
);
av_freep
(
&
s
->
hwaccel_context
);
}
static
void
vdpau_release_buffer
(
void
*
opaque
,
uint8_t
*
data
)
{
VdpVideoSurface
surface
=
*
(
VdpVideoSurface
*
)
data
;
VDPAUContext
*
ctx
=
opaque
;
ctx
->
video_surface_destroy
(
surface
);
av_freep
(
&
data
);
}
static
int
vdpau_get_buffer
(
AVCodecContext
*
s
,
AVFrame
*
frame
,
int
flags
)
{
InputStream
*
ist
=
s
->
opaque
;
VDPAUContext
*
ctx
=
ist
->
hwaccel_ctx
;
VdpVideoSurface
*
surface
;
VdpStatus
err
;
VdpChromaType
chroma
;
uint32_t
width
,
height
;
av_assert0
(
frame
->
format
==
AV_PIX_FMT_VDPAU
);
if
(
av_vdpau_get_surface_parameters
(
s
,
&
chroma
,
&
width
,
&
height
))
return
AVERROR
(
ENOSYS
);
surface
=
av_malloc
(
sizeof
(
*
surface
));
if
(
!
surface
)
return
AVERROR
(
ENOMEM
);
frame
->
buf
[
0
]
=
av_buffer_create
((
uint8_t
*
)
surface
,
sizeof
(
*
surface
),
vdpau_release_buffer
,
ctx
,
AV_BUFFER_FLAG_READONLY
);
if
(
!
frame
->
buf
[
0
])
{
av_freep
(
&
surface
);
return
AVERROR
(
ENOMEM
);
}
// properly we should keep a pool of surfaces instead of creating
// them anew for each frame, but since we don't care about speed
// much in this code, we don't bother
err
=
ctx
->
video_surface_create
(
ctx
->
device
,
chroma
,
width
,
height
,
surface
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error allocating a VDPAU video surface: %s
\n
"
,
ctx
->
get_error_string
(
err
));
av_buffer_unref
(
&
frame
->
buf
[
0
]);
return
AVERROR_UNKNOWN
;
}
frame
->
data
[
3
]
=
(
uint8_t
*
)(
uintptr_t
)
*
surface
;
return
0
;
return
av_hwframe_get_buffer
(
ctx
->
hw_frames_ctx
,
frame
,
0
);
}
static
int
vdpau_retrieve_data
(
AVCodecContext
*
s
,
AVFrame
*
frame
)
{
VdpVideoSurface
surface
=
(
VdpVideoSurface
)(
uintptr_t
)
frame
->
data
[
3
];
InputStream
*
ist
=
s
->
opaque
;
VDPAUContext
*
ctx
=
ist
->
hwaccel_ctx
;
VdpStatus
err
;
int
ret
,
chroma_type
;
int
ret
;
err
=
ctx
->
video_surface_get_parameters
(
surface
,
&
chroma_type
,
&
ctx
->
tmp_frame
->
width
,
&
ctx
->
tmp_frame
->
height
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error getting surface parameters: %s
\n
"
,
ctx
->
get_error_string
(
err
));
return
AVERROR_UNKNOWN
;
}
ctx
->
tmp_frame
->
format
=
ctx
->
pix_fmt
;
ret
=
av_frame_get_buffer
(
ctx
->
tmp_frame
,
32
);
ret
=
av_hwframe_transfer_data
(
ctx
->
tmp_frame
,
frame
,
0
);
if
(
ret
<
0
)
return
ret
;
ctx
->
tmp_frame
->
width
=
frame
->
width
;
ctx
->
tmp_frame
->
height
=
frame
->
height
;
err
=
ctx
->
video_surface_get_bits
(
surface
,
ctx
->
vdpau_format
,
(
void
*
const
*
)
ctx
->
tmp_frame
->
data
,
ctx
->
tmp_frame
->
linesize
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error retrieving frame data from VDPAU: %s
\n
"
,
ctx
->
get_error_string
(
err
));
ret
=
AVERROR_UNKNOWN
;
goto
fail
;
}
if
(
ctx
->
vdpau_format
==
VDP_YCBCR_FORMAT_YV12
)
FFSWAP
(
uint8_t
*
,
ctx
->
tmp_frame
->
data
[
1
],
ctx
->
tmp_frame
->
data
[
2
]);
ret
=
av_frame_copy_props
(
ctx
->
tmp_frame
,
frame
);
if
(
ret
<
0
)
goto
fail
;
if
(
ret
<
0
)
{
av_frame_unref
(
ctx
->
tmp_frame
);
return
ret
;
}
av_frame_unref
(
frame
);
av_frame_move_ref
(
frame
,
ctx
->
tmp_frame
);
return
0
;
fail:
av_frame_unref
(
ctx
->
tmp_frame
);
return
ret
;
return
0
;
}
static
const
int
vdpau_formats
[][
2
]
=
{
{
VDP_YCBCR_FORMAT_YV12
,
AV_PIX_FMT_YUV420P
},
{
VDP_YCBCR_FORMAT_NV12
,
AV_PIX_FMT_NV12
},
{
VDP_YCBCR_FORMAT_YUYV
,
AV_PIX_FMT_YUYV422
},
{
VDP_YCBCR_FORMAT_UYVY
,
AV_PIX_FMT_UYVY422
},
};
static
int
vdpau_alloc
(
AVCodecContext
*
s
)
{
InputStream
*
ist
=
s
->
opaque
;
...
...
@@ -192,12 +109,26 @@ static int vdpau_alloc(AVCodecContext *s)
VDPAUContext
*
ctx
;
const
char
*
display
,
*
vendor
;
VdpStatus
err
;
int
i
;
int
ret
;
VdpDevice
device
;
VdpGetProcAddress
*
get_proc_address
;
VdpGetInformationString
*
get_information_string
;
VDPAUHWDevicePriv
*
device_priv
=
NULL
;
AVBufferRef
*
device_ref
=
NULL
;
AVHWDeviceContext
*
device_ctx
;
AVVDPAUDeviceContext
*
device_hwctx
;
AVHWFramesContext
*
frames_ctx
;
ctx
=
av_mallocz
(
sizeof
(
*
ctx
));
if
(
!
ctx
)
return
AVERROR
(
ENOMEM
);
device_priv
=
av_mallocz
(
sizeof
(
*
device_priv
));
if
(
!
device_priv
)
goto
fail
;
ist
->
hwaccel_ctx
=
ctx
;
ist
->
hwaccel_uninit
=
vdpau_uninit
;
ist
->
hwaccel_get_buffer
=
vdpau_get_buffer
;
...
...
@@ -207,16 +138,16 @@ static int vdpau_alloc(AVCodecContext *s)
if
(
!
ctx
->
tmp_frame
)
goto
fail
;
ctx
->
dpy
=
XOpenDisplay
(
ist
->
hwaccel_device
);
if
(
!
ctx
->
dpy
)
{
device_priv
->
dpy
=
XOpenDisplay
(
ist
->
hwaccel_device
);
if
(
!
device_priv
->
dpy
)
{
av_log
(
NULL
,
loglevel
,
"Cannot open the X11 display %s.
\n
"
,
XDisplayName
(
ist
->
hwaccel_device
));
goto
fail
;
}
display
=
XDisplayString
(
ctx
->
dpy
);
display
=
XDisplayString
(
device_priv
->
dpy
);
err
=
vdp_device_create_x11
(
ctx
->
dpy
,
XDefaultScreen
(
ctx
->
dpy
),
&
ctx
->
device
,
&
ctx
->
get_proc_address
);
err
=
vdp_device_create_x11
(
device_priv
->
dpy
,
XDefaultScreen
(
device_priv
->
dpy
)
,
&
device
,
&
get_proc_address
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
NULL
,
loglevel
,
"VDPAU device creation on X11 display %s failed.
\n
"
,
display
);
...
...
@@ -226,49 +157,52 @@ static int vdpau_alloc(AVCodecContext *s)
#define GET_CALLBACK(id, result) \
do { \
void *tmp; \
err =
ctx->get_proc_address(ctx->device, id, &tmp);
\
err =
get_proc_address(device, id, &tmp);
\
if (err != VDP_STATUS_OK) { \
av_log(NULL, loglevel, "Error getting the " #id " callback.\n"); \
goto fail; \
} \
ctx->result = tmp;
\
result = tmp;
\
} while (0)
GET_CALLBACK
(
VDP_FUNC_ID_GET_ERROR_STRING
,
get_error_string
);
GET_CALLBACK
(
VDP_FUNC_ID_GET_INFORMATION_STRING
,
get_information_string
);
GET_CALLBACK
(
VDP_FUNC_ID_DEVICE_DESTROY
,
device_destroy
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_CREATE
,
video_surface_create
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_DESTROY
,
video_surface_destroy
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR
,
video_surface_get_bits
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS
,
video_surface_get_parameters
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES
,
video_surface_query
);
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
vdpau_formats
);
i
++
)
{
VdpBool
supported
;
err
=
ctx
->
video_surface_query
(
ctx
->
device
,
VDP_CHROMA_TYPE_420
,
vdpau_formats
[
i
][
0
],
&
supported
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
NULL
,
loglevel
,
"Error querying VDPAU surface capabilities: %s
\n
"
,
ctx
->
get_error_string
(
err
));
GET_CALLBACK
(
VDP_FUNC_ID_DEVICE_DESTROY
,
device_priv
->
device_destroy
);
device_ref
=
av_hwdevice_ctx_alloc
(
AV_HWDEVICE_TYPE_VDPAU
);
if
(
!
device_ref
)
goto
fail
;
}
if
(
supported
)
break
;
}
if
(
i
==
FF_ARRAY_ELEMS
(
vdpau_formats
))
{
av_log
(
NULL
,
loglevel
,
"No supported VDPAU format for retrieving the data.
\n
"
);
return
AVERROR
(
EINVAL
);
}
ctx
->
vdpau_format
=
vdpau_formats
[
i
][
0
];
ctx
->
pix_fmt
=
vdpau_formats
[
i
][
1
];
device_ctx
=
(
AVHWDeviceContext
*
)
device_ref
->
data
;
device_hwctx
=
device_ctx
->
hwctx
;
device_ctx
->
user_opaque
=
device_priv
;
device_ctx
->
free
=
device_free
;
device_hwctx
->
device
=
device
;
device_hwctx
->
get_proc_address
=
get_proc_address
;
if
(
av_vdpau_bind_context
(
s
,
ctx
->
device
,
ctx
->
get_proc_address
,
0
))
device_priv
=
NULL
;
ret
=
av_hwdevice_ctx_init
(
device_ref
);
if
(
ret
<
0
)
goto
fail
;
ctx
->
get_information_string
(
&
vendor
);
ctx
->
hw_frames_ctx
=
av_hwframe_ctx_alloc
(
device_ref
);
if
(
!
ctx
->
hw_frames_ctx
)
goto
fail
;
av_buffer_unref
(
&
device_ref
);
frames_ctx
=
(
AVHWFramesContext
*
)
ctx
->
hw_frames_ctx
->
data
;
frames_ctx
->
format
=
AV_PIX_FMT_VDPAU
;
frames_ctx
->
sw_format
=
s
->
sw_pix_fmt
;
frames_ctx
->
width
=
s
->
coded_width
;
frames_ctx
->
height
=
s
->
coded_height
;
ret
=
av_hwframe_ctx_init
(
ctx
->
hw_frames_ctx
);
if
(
ret
<
0
)
goto
fail
;
if
(
av_vdpau_bind_context
(
s
,
device
,
get_proc_address
,
0
))
goto
fail
;
get_information_string
(
&
vendor
);
av_log
(
NULL
,
AV_LOG_VERBOSE
,
"Using VDPAU -- %s -- on X11 display %s, "
"to decode input stream #%d:%d.
\n
"
,
vendor
,
display
,
ist
->
file_index
,
ist
->
st
->
index
);
...
...
@@ -278,6 +212,14 @@ do {
fail:
av_log
(
NULL
,
loglevel
,
"VDPAU init failed for stream #%d:%d.
\n
"
,
ist
->
file_index
,
ist
->
st
->
index
);
if
(
device_priv
)
{
if
(
device_priv
->
device_destroy
)
device_priv
->
device_destroy
(
device
);
if
(
device_priv
->
dpy
)
XCloseDisplay
(
device_priv
->
dpy
);
}
av_freep
(
&
device_priv
);
av_buffer_unref
(
&
device_ref
);
vdpau_uninit
(
s
);
return
AVERROR
(
EINVAL
);
}
...
...
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