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
59e7361c
Commit
59e7361c
authored
Jan 13, 2016
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hwcontext: add a QSV implementation
parent
6f19bbcf
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
857 additions
and
1 deletion
+857
-1
APIchanges
doc/APIchanges
+4
-0
Makefile
libavutil/Makefile
+3
-0
hwcontext.c
libavutil/hwcontext.c
+3
-0
hwcontext.h
libavutil/hwcontext.h
+1
-0
hwcontext_internal.h
libavutil/hwcontext_internal.h
+1
-0
hwcontext_qsv.c
libavutil/hwcontext_qsv.c
+791
-0
hwcontext_qsv.h
libavutil/hwcontext_qsv.h
+53
-0
version.h
libavutil/version.h
+1
-1
No files found.
doc/APIchanges
View file @
59e7361c
...
...
@@ -13,6 +13,10 @@ libavutil: 2015-08-28
API changes, most recent first:
2016-xx-xx - xxxxxxx - lavu 55.16.0 - hwcontext.h hwcontext_qsv.h
Add AV_HWDEVICE_TYPE_QSV and a new installed header with QSV-specific
hwcontext definitions.
2016-xx-xx - xxxxxxx - lavc 57.23.0 - avcodec.h
AVCodecContext.hw_frames_ctx now may be used by decoders.
...
...
libavutil/Makefile
View file @
59e7361c
...
...
@@ -27,6 +27,7 @@ HEADERS = adler32.h \
hwcontext.h
\
hwcontext_cuda.h
\
hwcontext_dxva2.h
\
hwcontext_qsv.h
\
hwcontext_vaapi.h
\
hwcontext_vdpau.h
\
imgutils.h
\
...
...
@@ -110,6 +111,7 @@ OBJS = adler32.o \
OBJS-$(CONFIG_CUDA)
+=
hwcontext_cuda.o
OBJS-$(CONFIG_DXVA2)
+=
hwcontext_dxva2.o
OBJS-$(CONFIG_LIBMFX)
+=
hwcontext_qsv.o
OBJS-$(CONFIG_LZO)
+=
lzo.o
OBJS-$(CONFIG_VAAPI)
+=
hwcontext_vaapi.o
OBJS-$(CONFIG_VDPAU)
+=
hwcontext_vdpau.o
...
...
@@ -118,6 +120,7 @@ OBJS += $(COMPAT_OBJS:%=../compat/%)
SKIPHEADERS-$(CONFIG_CUDA)
+=
hwcontext_cuda.h
SKIPHEADERS-$(CONFIG_DXVA2)
+=
hwcontext_dxva2.h
SKIPHEADERS-$(CONFIG_LIBMFX)
+=
hwcontext_qsv.h
SKIPHEADERS-$(CONFIG_VAAPI)
+=
hwcontext_vaapi.h
SKIPHEADERS-$(CONFIG_VDPAU)
+=
hwcontext_vdpau.h
SKIPHEADERS-$(HAVE_ATOMICS_GCC)
+=
atomic_gcc.h
...
...
libavutil/hwcontext.c
View file @
59e7361c
...
...
@@ -35,6 +35,9 @@ static const HWContextType *hw_table[] = {
#if CONFIG_DXVA2
&
ff_hwcontext_type_dxva2
,
#endif
#if CONFIG_LIBMFX
&
ff_hwcontext_type_qsv
,
#endif
#if CONFIG_VAAPI
&
ff_hwcontext_type_vaapi
,
#endif
...
...
libavutil/hwcontext.h
View file @
59e7361c
...
...
@@ -29,6 +29,7 @@ enum AVHWDeviceType {
AV_HWDEVICE_TYPE_CUDA
,
AV_HWDEVICE_TYPE_VAAPI
,
AV_HWDEVICE_TYPE_DXVA2
,
AV_HWDEVICE_TYPE_QSV
,
};
typedef
struct
AVHWDeviceInternal
AVHWDeviceInternal
;
...
...
libavutil/hwcontext_internal.h
View file @
59e7361c
...
...
@@ -101,6 +101,7 @@ struct AVHWFramesInternal {
extern
const
HWContextType
ff_hwcontext_type_cuda
;
extern
const
HWContextType
ff_hwcontext_type_dxva2
;
extern
const
HWContextType
ff_hwcontext_type_qsv
;
extern
const
HWContextType
ff_hwcontext_type_vaapi
;
extern
const
HWContextType
ff_hwcontext_type_vdpau
;
...
...
libavutil/hwcontext_qsv.c
0 → 100644
View file @
59e7361c
/*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <string.h>
#include <mfx/mfxvideo.h>
#include "config.h"
#if CONFIG_VAAPI
#include "hwcontext_vaapi.h"
#endif
#if CONFIG_DXVA2
#include "hwcontext_dxva2.h"
#endif
#include "buffer.h"
#include "common.h"
#include "hwcontext.h"
#include "hwcontext_internal.h"
#include "hwcontext_qsv.h"
#include "mem.h"
#include "pixfmt.h"
#include "pixdesc.h"
#include "time.h"
typedef
struct
QSVDevicePriv
{
AVBufferRef
*
child_device_ctx
;
}
QSVDevicePriv
;
typedef
struct
QSVDeviceContext
{
mfxHDL
handle
;
mfxHandleType
handle_type
;
mfxVersion
ver
;
mfxIMPL
impl
;
enum
AVHWDeviceType
child_device_type
;
enum
AVPixelFormat
child_pix_fmt
;
}
QSVDeviceContext
;
typedef
struct
QSVFramesContext
{
mfxSession
session_download
;
mfxSession
session_upload
;
AVBufferRef
*
child_frames_ref
;
mfxFrameSurface1
*
surfaces_internal
;
int
nb_surfaces_used
;
// used in the frame allocator for non-opaque surfaces
mfxMemId
*
mem_ids
;
// used in the opaque alloc request for opaque surfaces
mfxFrameSurface1
**
surface_ptrs
;
mfxExtOpaqueSurfaceAlloc
opaque_alloc
;
mfxExtBuffer
*
ext_buffers
[
1
];
}
QSVFramesContext
;
static
const
struct
{
mfxHandleType
handle_type
;
enum
AVHWDeviceType
device_type
;
enum
AVPixelFormat
pix_fmt
;
}
supported_handle_types
[]
=
{
#if CONFIG_VAAPI
{
MFX_HANDLE_VA_DISPLAY
,
AV_HWDEVICE_TYPE_VAAPI
,
AV_PIX_FMT_VAAPI
},
#endif
#if CONFIG_DXVA2
{
MFX_HANDLE_D3D9_DEVICE_MANAGER
,
AV_HWDEVICE_TYPE_DXVA2
,
AV_PIX_FMT_DXVA2_VLD
},
#endif
{
0
},
};
static
const
struct
{
enum
AVPixelFormat
pix_fmt
;
uint32_t
fourcc
;
}
supported_pixel_formats
[]
=
{
{
AV_PIX_FMT_NV12
,
MFX_FOURCC_NV12
},
};
static
int
qsv_device_init
(
AVHWDeviceContext
*
ctx
)
{
AVQSVDeviceContext
*
hwctx
=
ctx
->
hwctx
;
QSVDeviceContext
*
s
=
ctx
->
internal
->
priv
;
mfxStatus
err
;
int
i
;
for
(
i
=
0
;
supported_handle_types
[
i
].
handle_type
;
i
++
)
{
err
=
MFXVideoCORE_GetHandle
(
hwctx
->
session
,
supported_handle_types
[
i
].
handle_type
,
&
s
->
handle
);
if
(
err
==
MFX_ERR_NONE
)
{
s
->
handle_type
=
supported_handle_types
[
i
].
handle_type
;
s
->
child_device_type
=
supported_handle_types
[
i
].
device_type
;
s
->
child_pix_fmt
=
supported_handle_types
[
i
].
pix_fmt
;
break
;
}
}
if
(
!
s
->
handle
)
{
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"No supported hw handle could be retrieved "
"from the session
\n
"
);
}
err
=
MFXQueryIMPL
(
hwctx
->
session
,
&
s
->
impl
);
if
(
err
==
MFX_ERR_NONE
)
err
=
MFXQueryVersion
(
hwctx
->
session
,
&
s
->
ver
);
if
(
err
!=
MFX_ERR_NONE
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error querying the session attributes
\n
"
);
return
AVERROR_UNKNOWN
;
}
return
0
;
}
static
void
qsv_frames_uninit
(
AVHWFramesContext
*
ctx
)
{
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
if
(
s
->
session_download
)
{
MFXVideoVPP_Close
(
s
->
session_download
);
MFXClose
(
s
->
session_download
);
}
s
->
session_download
=
NULL
;
if
(
s
->
session_upload
)
{
MFXVideoVPP_Close
(
s
->
session_upload
);
MFXClose
(
s
->
session_upload
);
}
s
->
session_upload
=
NULL
;
av_freep
(
&
s
->
mem_ids
);
av_freep
(
&
s
->
surface_ptrs
);
av_freep
(
&
s
->
surfaces_internal
);
av_buffer_unref
(
&
s
->
child_frames_ref
);
}
static
void
qsv_pool_release_dummy
(
void
*
opaque
,
uint8_t
*
data
)
{
}
static
AVBufferRef
*
qsv_pool_alloc
(
void
*
opaque
,
int
size
)
{
AVHWFramesContext
*
ctx
=
(
AVHWFramesContext
*
)
opaque
;
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
AVQSVFramesContext
*
hwctx
=
ctx
->
hwctx
;
if
(
s
->
nb_surfaces_used
<
hwctx
->
nb_surfaces
)
{
s
->
nb_surfaces_used
++
;
return
av_buffer_create
((
uint8_t
*
)(
s
->
surfaces_internal
+
s
->
nb_surfaces_used
-
1
),
sizeof
(
*
hwctx
->
surfaces
),
qsv_pool_release_dummy
,
NULL
,
0
);
}
return
NULL
;
}
static
int
qsv_init_child_ctx
(
AVHWFramesContext
*
ctx
)
{
AVQSVFramesContext
*
hwctx
=
ctx
->
hwctx
;
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
QSVDeviceContext
*
device_priv
=
ctx
->
device_ctx
->
internal
->
priv
;
AVBufferRef
*
child_device_ref
=
NULL
;
AVBufferRef
*
child_frames_ref
=
NULL
;
AVHWDeviceContext
*
child_device_ctx
;
AVHWFramesContext
*
child_frames_ctx
;
int
i
,
ret
=
0
;
if
(
!
device_priv
->
handle
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Cannot create a non-opaque internal surface pool without "
"a hardware handle
\n
"
);
return
AVERROR
(
EINVAL
);
}
child_device_ref
=
av_hwdevice_ctx_alloc
(
device_priv
->
child_device_type
);
if
(
!
child_device_ref
)
return
AVERROR
(
ENOMEM
);
child_device_ctx
=
(
AVHWDeviceContext
*
)
child_device_ref
->
data
;
#if CONFIG_VAAPI
if
(
child_device_ctx
->
type
==
AV_HWDEVICE_TYPE_VAAPI
)
{
AVVAAPIDeviceContext
*
child_device_hwctx
=
child_device_ctx
->
hwctx
;
child_device_hwctx
->
display
=
(
VADisplay
)
device_priv
->
handle
;
}
#endif
#if CONFIG_DXVA2
if
(
child_device_ctx
->
type
==
AV_HWDEVICE_TYPE_DXVA2
)
{
AVDXVA2DeviceContext
*
child_device_hwctx
=
child_device_ctx
->
hwctx
;
child_device_hwctx
->
devmgr
=
(
IDirect3DDeviceManager9
*
)
device_priv
->
handle
;
}
#endif
ret
=
av_hwdevice_ctx_init
(
child_device_ref
);
if
(
ret
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error initializing a child device context
\n
"
);
goto
fail
;
}
child_frames_ref
=
av_hwframe_ctx_alloc
(
child_device_ref
);
if
(
!
child_frames_ref
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
child_frames_ctx
=
(
AVHWFramesContext
*
)
child_frames_ref
->
data
;
child_frames_ctx
->
format
=
device_priv
->
child_pix_fmt
;
child_frames_ctx
->
sw_format
=
ctx
->
sw_format
;
child_frames_ctx
->
initial_pool_size
=
ctx
->
initial_pool_size
;
child_frames_ctx
->
width
=
ctx
->
width
;
child_frames_ctx
->
height
=
ctx
->
height
;
#if CONFIG_DXVA2
if
(
child_device_ctx
->
type
==
AV_HWDEVICE_TYPE_DXVA2
)
{
AVDXVA2FramesContext
*
child_frames_hwctx
=
child_frames_ctx
->
hwctx
;
if
(
hwctx
->
frame_type
&
MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET
)
child_frames_hwctx
->
surface_type
=
DXVA2_VideoProcessorRenderTarget
;
else
child_frames_hwctx
->
surface_type
=
DXVA2_VideoDecoderRenderTarget
;
}
#endif
ret
=
av_hwframe_ctx_init
(
child_frames_ref
);
if
(
ret
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error initializing a child frames context
\n
"
);
goto
fail
;
}
#if CONFIG_VAAPI
if
(
child_device_ctx
->
type
==
AV_HWDEVICE_TYPE_VAAPI
)
{
AVVAAPIFramesContext
*
child_frames_hwctx
=
child_frames_ctx
->
hwctx
;
for
(
i
=
0
;
i
<
ctx
->
initial_pool_size
;
i
++
)
s
->
surfaces_internal
[
i
].
Data
.
MemId
=
child_frames_hwctx
->
surface_ids
+
i
;
hwctx
->
frame_type
=
MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET
;
}
#endif
#if CONFIG_DXVA2
if
(
child_device_ctx
->
type
==
AV_HWDEVICE_TYPE_DXVA2
)
{
AVDXVA2FramesContext
*
child_frames_hwctx
=
child_frames_ctx
->
hwctx
;
for
(
i
=
0
;
i
<
ctx
->
initial_pool_size
;
i
++
)
s
->
surfaces_internal
[
i
].
Data
.
MemId
=
(
mfxMemId
)
child_frames_hwctx
->
surfaces
[
i
];
if
(
child_frames_hwctx
->
surface_type
==
DXVA2_VideoProcessorRenderTarget
)
hwctx
->
frame_type
=
MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET
;
else
hwctx
->
frame_type
=
MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET
;
}
#endif
s
->
child_frames_ref
=
child_frames_ref
;
child_frames_ref
=
NULL
;
fail:
av_buffer_unref
(
&
child_device_ref
);
av_buffer_unref
(
&
child_frames_ref
);
return
ret
;
}
static
int
qsv_init_pool
(
AVHWFramesContext
*
ctx
,
uint32_t
fourcc
)
{
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
AVQSVFramesContext
*
frames_hwctx
=
ctx
->
hwctx
;
const
AVPixFmtDescriptor
*
desc
;
int
i
,
ret
=
0
;
desc
=
av_pix_fmt_desc_get
(
ctx
->
sw_format
);
if
(
!
desc
)
return
AVERROR_BUG
;
if
(
ctx
->
initial_pool_size
<=
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"QSV requires a fixed frame pool size
\n
"
);
return
AVERROR
(
EINVAL
);
}
s
->
surfaces_internal
=
av_mallocz_array
(
ctx
->
initial_pool_size
,
sizeof
(
*
s
->
surfaces_internal
));
if
(
!
s
->
surfaces_internal
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
ctx
->
initial_pool_size
;
i
++
)
{
mfxFrameSurface1
*
surf
=
&
s
->
surfaces_internal
[
i
];
surf
->
Info
.
BitDepthLuma
=
desc
->
comp
[
0
].
depth
;
surf
->
Info
.
BitDepthChroma
=
desc
->
comp
[
0
].
depth
;
surf
->
Info
.
Shift
=
desc
->
comp
[
0
].
depth
>
8
;
if
(
desc
->
log2_chroma_w
&&
desc
->
log2_chroma_h
)
surf
->
Info
.
ChromaFormat
=
MFX_CHROMAFORMAT_YUV420
;
else
if
(
desc
->
log2_chroma_w
)
surf
->
Info
.
ChromaFormat
=
MFX_CHROMAFORMAT_YUV422
;
else
surf
->
Info
.
ChromaFormat
=
MFX_CHROMAFORMAT_YUV444
;
surf
->
Info
.
FourCC
=
fourcc
;
surf
->
Info
.
Width
=
ctx
->
width
;
surf
->
Info
.
CropW
=
ctx
->
width
;
surf
->
Info
.
Height
=
ctx
->
height
;
surf
->
Info
.
CropH
=
ctx
->
height
;
surf
->
Info
.
FrameRateExtN
=
25
;
surf
->
Info
.
FrameRateExtD
=
1
;
}
if
(
!
(
frames_hwctx
->
frame_type
&
MFX_MEMTYPE_OPAQUE_FRAME
))
{
ret
=
qsv_init_child_ctx
(
ctx
);
if
(
ret
<
0
)
return
ret
;
}
ctx
->
internal
->
pool_internal
=
av_buffer_pool_init2
(
sizeof
(
mfxFrameSurface1
),
ctx
,
qsv_pool_alloc
,
NULL
);
if
(
!
ctx
->
internal
->
pool_internal
)
return
AVERROR
(
ENOMEM
);
frames_hwctx
->
surfaces
=
s
->
surfaces_internal
;
frames_hwctx
->
nb_surfaces
=
ctx
->
initial_pool_size
;
return
0
;
}
static
mfxStatus
frame_alloc
(
mfxHDL
pthis
,
mfxFrameAllocRequest
*
req
,
mfxFrameAllocResponse
*
resp
)
{
AVHWFramesContext
*
ctx
=
pthis
;
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
AVQSVFramesContext
*
hwctx
=
ctx
->
hwctx
;
mfxFrameInfo
*
i
=
&
req
->
Info
;
mfxFrameInfo
*
i1
=
&
hwctx
->
surfaces
[
0
].
Info
;
if
(
!
(
req
->
Type
&
MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET
)
||
!
(
req
->
Type
&
(
MFX_MEMTYPE_FROM_VPPIN
|
MFX_MEMTYPE_FROM_VPPOUT
))
||
!
(
req
->
Type
&
MFX_MEMTYPE_EXTERNAL_FRAME
))
return
MFX_ERR_UNSUPPORTED
;
if
(
i
->
Width
!=
i1
->
Width
||
i
->
Height
!=
i1
->
Height
||
i
->
FourCC
!=
i1
->
FourCC
||
i
->
ChromaFormat
!=
i1
->
ChromaFormat
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Mismatching surface properties in an "
"allocation request: %dx%d %d %d vs %dx%d %d %d
\n
"
,
i
->
Width
,
i
->
Height
,
i
->
FourCC
,
i
->
ChromaFormat
,
i1
->
Width
,
i1
->
Height
,
i1
->
FourCC
,
i1
->
ChromaFormat
);
return
MFX_ERR_UNSUPPORTED
;
}
resp
->
mids
=
s
->
mem_ids
;
resp
->
NumFrameActual
=
hwctx
->
nb_surfaces
;
return
MFX_ERR_NONE
;
}
static
mfxStatus
frame_free
(
mfxHDL
pthis
,
mfxFrameAllocResponse
*
resp
)
{
return
MFX_ERR_NONE
;
}
static
mfxStatus
frame_lock
(
mfxHDL
pthis
,
mfxMemId
mid
,
mfxFrameData
*
ptr
)
{
return
MFX_ERR_UNSUPPORTED
;
}
static
mfxStatus
frame_unlock
(
mfxHDL
pthis
,
mfxMemId
mid
,
mfxFrameData
*
ptr
)
{
return
MFX_ERR_UNSUPPORTED
;
}
static
mfxStatus
frame_get_hdl
(
mfxHDL
pthis
,
mfxMemId
mid
,
mfxHDL
*
hdl
)
{
*
hdl
=
mid
;
return
MFX_ERR_NONE
;
}
static
int
qsv_init_internal_session
(
AVHWFramesContext
*
ctx
,
mfxSession
*
session
,
int
upload
)
{
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
AVQSVFramesContext
*
frames_hwctx
=
ctx
->
hwctx
;
QSVDeviceContext
*
device_priv
=
ctx
->
device_ctx
->
internal
->
priv
;
int
opaque
=
!!
(
frames_hwctx
->
frame_type
&
MFX_MEMTYPE_OPAQUE_FRAME
);
mfxFrameAllocator
frame_allocator
=
{
.
pthis
=
ctx
,
.
Alloc
=
frame_alloc
,
.
Lock
=
frame_lock
,
.
Unlock
=
frame_unlock
,
.
GetHDL
=
frame_get_hdl
,
.
Free
=
frame_free
,
};
mfxVideoParam
par
;
mfxStatus
err
;
err
=
MFXInit
(
device_priv
->
impl
,
&
device_priv
->
ver
,
session
);
if
(
err
!=
MFX_ERR_NONE
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error initializing an internal session
\n
"
);
return
AVERROR_UNKNOWN
;
}
if
(
device_priv
->
handle
)
{
err
=
MFXVideoCORE_SetHandle
(
*
session
,
device_priv
->
handle_type
,
device_priv
->
handle
);
if
(
err
!=
MFX_ERR_NONE
)
return
AVERROR_UNKNOWN
;
}
if
(
!
opaque
)
{
err
=
MFXVideoCORE_SetFrameAllocator
(
*
session
,
&
frame_allocator
);
if
(
err
!=
MFX_ERR_NONE
)
return
AVERROR_UNKNOWN
;
}
memset
(
&
par
,
0
,
sizeof
(
par
));
if
(
opaque
)
{
par
.
ExtParam
=
s
->
ext_buffers
;
par
.
NumExtParam
=
FF_ARRAY_ELEMS
(
s
->
ext_buffers
);
par
.
IOPattern
=
upload
?
MFX_IOPATTERN_OUT_OPAQUE_MEMORY
:
MFX_IOPATTERN_IN_OPAQUE_MEMORY
;
}
else
{
par
.
IOPattern
=
upload
?
MFX_IOPATTERN_OUT_VIDEO_MEMORY
:
MFX_IOPATTERN_IN_VIDEO_MEMORY
;
}
par
.
IOPattern
|=
upload
?
MFX_IOPATTERN_IN_SYSTEM_MEMORY
:
MFX_IOPATTERN_OUT_SYSTEM_MEMORY
;
par
.
AsyncDepth
=
1
;
par
.
vpp
.
In
=
frames_hwctx
->
surfaces
[
0
].
Info
;
/* Apparently VPP requires the frame rate to be set to some value, otherwise
* init will fail (probably for the framerate conversion filter). Since we
* are only doing data upload/download here, we just invent an arbitrary
* value */
par
.
vpp
.
In
.
FrameRateExtN
=
25
;
par
.
vpp
.
In
.
FrameRateExtD
=
1
;
par
.
vpp
.
Out
=
par
.
vpp
.
In
;
err
=
MFXVideoVPP_Init
(
*
session
,
&
par
);
if
(
err
!=
MFX_ERR_NONE
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error opening the internal VPP session
\n
"
);
return
AVERROR_UNKNOWN
;
}
return
0
;
}
static
int
qsv_frames_init
(
AVHWFramesContext
*
ctx
)
{
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
AVQSVFramesContext
*
frames_hwctx
=
ctx
->
hwctx
;
int
opaque
=
!!
(
frames_hwctx
->
frame_type
&
MFX_MEMTYPE_OPAQUE_FRAME
);
uint32_t
fourcc
=
0
;
int
i
,
ret
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
supported_pixel_formats
);
i
++
)
{
if
(
supported_pixel_formats
[
i
].
pix_fmt
==
ctx
->
sw_format
)
{
fourcc
=
supported_pixel_formats
[
i
].
fourcc
;
break
;
}
}
if
(
!
fourcc
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported pixel format
\n
"
);
return
AVERROR
(
ENOSYS
);
}
if
(
!
ctx
->
pool
)
{
ret
=
qsv_init_pool
(
ctx
,
fourcc
);
if
(
ret
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error creating an internal frame pool
\n
"
);
return
ret
;
}
}
if
(
opaque
)
{
s
->
surface_ptrs
=
av_mallocz_array
(
frames_hwctx
->
nb_surfaces
,
sizeof
(
*
s
->
surface_ptrs
));
if
(
!
s
->
surface_ptrs
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
frames_hwctx
->
nb_surfaces
;
i
++
)
s
->
surface_ptrs
[
i
]
=
frames_hwctx
->
surfaces
+
i
;
s
->
opaque_alloc
.
In
.
Surfaces
=
s
->
surface_ptrs
;
s
->
opaque_alloc
.
In
.
NumSurface
=
frames_hwctx
->
nb_surfaces
;
s
->
opaque_alloc
.
In
.
Type
=
frames_hwctx
->
frame_type
;
s
->
opaque_alloc
.
Out
=
s
->
opaque_alloc
.
In
;
s
->
opaque_alloc
.
Header
.
BufferId
=
MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION
;
s
->
opaque_alloc
.
Header
.
BufferSz
=
sizeof
(
s
->
opaque_alloc
);
s
->
ext_buffers
[
0
]
=
(
mfxExtBuffer
*
)
&
s
->
opaque_alloc
;
}
else
{
s
->
mem_ids
=
av_mallocz_array
(
frames_hwctx
->
nb_surfaces
,
sizeof
(
*
s
->
mem_ids
));
if
(
!
s
->
mem_ids
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
frames_hwctx
->
nb_surfaces
;
i
++
)
s
->
mem_ids
[
i
]
=
frames_hwctx
->
surfaces
[
i
].
Data
.
MemId
;
}
ret
=
qsv_init_internal_session
(
ctx
,
&
s
->
session_download
,
0
);
if
(
ret
<
0
)
return
ret
;
ret
=
qsv_init_internal_session
(
ctx
,
&
s
->
session_upload
,
1
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
qsv_get_buffer
(
AVHWFramesContext
*
ctx
,
AVFrame
*
frame
)
{
frame
->
buf
[
0
]
=
av_buffer_pool_get
(
ctx
->
pool
);
if
(
!
frame
->
buf
[
0
])
return
AVERROR
(
ENOMEM
);
frame
->
data
[
3
]
=
frame
->
buf
[
0
]
->
data
;
frame
->
format
=
AV_PIX_FMT_QSV
;
frame
->
width
=
ctx
->
width
;
frame
->
height
=
ctx
->
height
;
return
0
;
}
static
int
qsv_transfer_get_formats
(
AVHWFramesContext
*
ctx
,
enum
AVHWFrameTransferDirection
dir
,
enum
AVPixelFormat
**
formats
)
{
enum
AVPixelFormat
*
fmts
;
fmts
=
av_malloc_array
(
2
,
sizeof
(
*
fmts
));
if
(
!
fmts
)
return
AVERROR
(
ENOMEM
);
fmts
[
0
]
=
ctx
->
sw_format
;
fmts
[
1
]
=
AV_PIX_FMT_NONE
;
*
formats
=
fmts
;
return
0
;
}
static
int
qsv_transfer_data_from
(
AVHWFramesContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
)
{
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
mfxFrameSurface1
out
=
{{
0
}};
mfxFrameSurface1
*
in
=
(
mfxFrameSurface1
*
)
src
->
data
[
3
];
mfxSyncPoint
sync
=
NULL
;
mfxStatus
err
;
out
.
Info
=
in
->
Info
;
out
.
Data
.
PitchLow
=
dst
->
linesize
[
0
];
out
.
Data
.
Y
=
dst
->
data
[
0
];
out
.
Data
.
U
=
dst
->
data
[
1
];
out
.
Data
.
V
=
dst
->
data
[
2
];
out
.
Data
.
A
=
dst
->
data
[
3
];
do
{
err
=
MFXVideoVPP_RunFrameVPPAsync
(
s
->
session_download
,
in
,
&
out
,
NULL
,
&
sync
);
if
(
err
==
MFX_WRN_DEVICE_BUSY
)
av_usleep
(
1
);
}
while
(
err
==
MFX_WRN_DEVICE_BUSY
);
if
(
err
<
0
||
!
sync
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error downloading the surface
\n
"
);
return
AVERROR_UNKNOWN
;
}
do
{
err
=
MFXVideoCORE_SyncOperation
(
s
->
session_download
,
sync
,
1000
);
}
while
(
err
==
MFX_WRN_IN_EXECUTION
);
if
(
err
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error synchronizing the operation: %d
\n
"
,
err
);
return
AVERROR_UNKNOWN
;
}
return
0
;
}
static
int
qsv_transfer_data_to
(
AVHWFramesContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
)
{
QSVFramesContext
*
s
=
ctx
->
internal
->
priv
;
mfxFrameSurface1
in
=
{{
0
}};
mfxFrameSurface1
*
out
=
(
mfxFrameSurface1
*
)
dst
->
data
[
3
];
mfxSyncPoint
sync
=
NULL
;
mfxStatus
err
;
in
.
Info
=
out
->
Info
;
in
.
Data
.
PitchLow
=
src
->
linesize
[
0
];
in
.
Data
.
Y
=
src
->
data
[
0
];
in
.
Data
.
U
=
src
->
data
[
1
];
in
.
Data
.
V
=
src
->
data
[
2
];
in
.
Data
.
A
=
src
->
data
[
3
];
do
{
err
=
MFXVideoVPP_RunFrameVPPAsync
(
s
->
session_upload
,
&
in
,
out
,
NULL
,
&
sync
);
if
(
err
==
MFX_WRN_DEVICE_BUSY
)
av_usleep
(
1
);
}
while
(
err
==
MFX_WRN_DEVICE_BUSY
);
if
(
err
<
0
||
!
sync
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error uploading the surface
\n
"
);
return
AVERROR_UNKNOWN
;
}
do
{
err
=
MFXVideoCORE_SyncOperation
(
s
->
session_upload
,
sync
,
1000
);
}
while
(
err
==
MFX_WRN_IN_EXECUTION
);
if
(
err
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error synchronizing the operation
\n
"
);
return
AVERROR_UNKNOWN
;
}
return
0
;
}
static
int
qsv_frames_get_constraints
(
AVHWDeviceContext
*
ctx
,
const
void
*
hwconfig
,
AVHWFramesConstraints
*
constraints
)
{
int
i
;
constraints
->
valid_sw_formats
=
av_malloc_array
(
FF_ARRAY_ELEMS
(
supported_pixel_formats
)
+
1
,
sizeof
(
*
constraints
->
valid_sw_formats
));
if
(
!
constraints
->
valid_sw_formats
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
supported_pixel_formats
);
i
++
)
constraints
->
valid_sw_formats
[
i
]
=
supported_pixel_formats
[
i
].
pix_fmt
;
constraints
->
valid_sw_formats
[
FF_ARRAY_ELEMS
(
supported_pixel_formats
)]
=
AV_PIX_FMT_NONE
;
constraints
->
valid_hw_formats
=
av_malloc_array
(
2
,
sizeof
(
*
constraints
->
valid_hw_formats
));
if
(
!
constraints
->
valid_hw_formats
)
return
AVERROR
(
ENOMEM
);
constraints
->
valid_hw_formats
[
0
]
=
AV_PIX_FMT_QSV
;
constraints
->
valid_hw_formats
[
1
]
=
AV_PIX_FMT_NONE
;
return
0
;
}
static
void
qsv_device_free
(
AVHWDeviceContext
*
ctx
)
{
AVQSVDeviceContext
*
hwctx
=
ctx
->
hwctx
;
QSVDevicePriv
*
priv
=
ctx
->
user_opaque
;
if
(
hwctx
->
session
)
MFXClose
(
hwctx
->
session
);
av_buffer_unref
(
&
priv
->
child_device_ctx
);
av_freep
(
&
priv
);
}
static
mfxIMPL
choose_implementation
(
const
char
*
device
)
{
static
const
struct
{
const
char
*
name
;
mfxIMPL
impl
;
}
impl_map
[]
=
{
{
"auto"
,
MFX_IMPL_AUTO
},
{
"sw"
,
MFX_IMPL_SOFTWARE
},
{
"hw"
,
MFX_IMPL_HARDWARE
},
{
"auto_any"
,
MFX_IMPL_AUTO_ANY
},
{
"hw_any"
,
MFX_IMPL_HARDWARE_ANY
},
{
"hw2"
,
MFX_IMPL_HARDWARE2
},
{
"hw3"
,
MFX_IMPL_HARDWARE3
},
{
"hw4"
,
MFX_IMPL_HARDWARE4
},
};
mfxIMPL
impl
=
MFX_IMPL_AUTO_ANY
;
int
i
;
if
(
device
)
{
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
impl_map
);
i
++
)
if
(
!
strcmp
(
device
,
impl_map
[
i
].
name
))
{
impl
=
impl_map
[
i
].
impl
;
break
;
}
if
(
i
==
FF_ARRAY_ELEMS
(
impl_map
))
impl
=
strtol
(
device
,
NULL
,
0
);
}
return
impl
;
}
static
int
qsv_device_create
(
AVHWDeviceContext
*
ctx
,
const
char
*
device
,
AVDictionary
*
opts
,
int
flags
)
{
AVQSVDeviceContext
*
hwctx
=
ctx
->
hwctx
;
QSVDevicePriv
*
priv
;
enum
AVHWDeviceType
child_device_type
;
AVDictionaryEntry
*
e
;
mfxVersion
ver
=
{
{
3
,
1
}
};
mfxIMPL
impl
;
mfxHDL
handle
;
mfxHandleType
handle_type
;
mfxStatus
err
;
int
ret
;
priv
=
av_mallocz
(
sizeof
(
*
priv
));
if
(
!
priv
)
return
AVERROR
(
ENOMEM
);
ctx
->
user_opaque
=
priv
;
ctx
->
free
=
qsv_device_free
;
e
=
av_dict_get
(
opts
,
"child_device"
,
NULL
,
0
);
if
(
CONFIG_VAAPI
)
child_device_type
=
AV_HWDEVICE_TYPE_VAAPI
;
else
if
(
CONFIG_DXVA2
)
child_device_type
=
AV_HWDEVICE_TYPE_DXVA2
;
else
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"No supported child device type is enabled
\n
"
);
return
AVERROR
(
ENOSYS
);
}
ret
=
av_hwdevice_ctx_create
(
&
priv
->
child_device_ctx
,
child_device_type
,
e
?
e
->
value
:
NULL
,
NULL
,
0
);
if
(
ret
<
0
)
return
ret
;
{
AVHWDeviceContext
*
child_device_ctx
=
(
AVHWDeviceContext
*
)
priv
->
child_device_ctx
->
data
;
#if CONFIG_VAAPI
AVVAAPIDeviceContext
*
child_device_hwctx
=
child_device_ctx
->
hwctx
;
handle_type
=
MFX_HANDLE_VA_DISPLAY
;
handle
=
(
mfxHDL
)
child_device_hwctx
->
display
;
#elif CONFIG_DXVA2
AVDXVA2DeviceContext
*
child_device_hwctx
=
child_device_ctx
->
hwctx
;
handle_type
=
MFX_HANDLE_D3D9_DEVICE_MANAGER
;
handle
=
(
mfxHDL
)
child_device_hwctx
->
devmgr
;
#endif
}
impl
=
choose_implementation
(
device
);
err
=
MFXInit
(
impl
,
&
ver
,
&
hwctx
->
session
);
if
(
err
!=
MFX_ERR_NONE
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error initializing an MFX session
\n
"
);
return
AVERROR_UNKNOWN
;
}
err
=
MFXVideoCORE_SetHandle
(
hwctx
->
session
,
handle_type
,
handle
);
if
(
err
!=
MFX_ERR_NONE
)
return
AVERROR_UNKNOWN
;
return
0
;
}
const
HWContextType
ff_hwcontext_type_qsv
=
{
.
type
=
AV_HWDEVICE_TYPE_QSV
,
.
name
=
"QSV"
,
.
device_hwctx_size
=
sizeof
(
AVQSVDeviceContext
),
.
device_priv_size
=
sizeof
(
QSVDeviceContext
),
.
frames_hwctx_size
=
sizeof
(
AVQSVFramesContext
),
.
frames_priv_size
=
sizeof
(
QSVFramesContext
),
.
device_create
=
qsv_device_create
,
.
device_init
=
qsv_device_init
,
.
frames_get_constraints
=
qsv_frames_get_constraints
,
.
frames_init
=
qsv_frames_init
,
.
frames_uninit
=
qsv_frames_uninit
,
.
frames_get_buffer
=
qsv_get_buffer
,
.
transfer_get_formats
=
qsv_transfer_get_formats
,
.
transfer_data_to
=
qsv_transfer_data_to
,
.
transfer_data_from
=
qsv_transfer_data_from
,
.
pix_fmts
=
(
const
enum
AVPixelFormat
[]){
AV_PIX_FMT_QSV
,
AV_PIX_FMT_NONE
},
};
libavutil/hwcontext_qsv.h
0 → 100644
View file @
59e7361c
/*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_HWCONTEXT_QSV_H
#define AVUTIL_HWCONTEXT_QSV_H
#include <mfx/mfxvideo.h>
/**
* @file
* An API-specific header for AV_HWDEVICE_TYPE_QSV.
*
* This API does not support dynamic frame pools. AVHWFramesContext.pool must
* contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct.
*/
/**
* This struct is allocated as AVHWDeviceContext.hwctx
*/
typedef
struct
AVQSVDeviceContext
{
mfxSession
session
;
}
AVQSVDeviceContext
;
/**
* This struct is allocated as AVHWFramesContext.hwctx
*/
typedef
struct
AVQSVFramesContext
{
mfxFrameSurface1
*
surfaces
;
int
nb_surfaces
;
/**
* A combination of MFX_MEMTYPE_* describing the frame pool.
*/
int
frame_type
;
}
AVQSVFramesContext
;
#endif
/* AVUTIL_HWCONTEXT_QSV_H */
libavutil/version.h
View file @
59e7361c
...
...
@@ -54,7 +54,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 55
#define LIBAVUTIL_VERSION_MINOR 1
5
#define LIBAVUTIL_VERSION_MINOR 1
6
#define LIBAVUTIL_VERSION_MICRO 0
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
...
...
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