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
a001ce31
Commit
a001ce31
authored
Dec 07, 2015
by
Anton Khirnov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hwcontext: add a VDPAU implementation
parent
89923e41
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
461 additions
and
0 deletions
+461
-0
APIchanges
doc/APIchanges
+2
-0
Makefile
libavutil/Makefile
+2
-0
hwcontext.c
libavutil/hwcontext.c
+3
-0
hwcontext_internal.h
libavutil/hwcontext_internal.h
+2
-0
hwcontext_vdpau.c
libavutil/hwcontext_vdpau.c
+408
-0
hwcontext_vdpau.h
libavutil/hwcontext_vdpau.h
+44
-0
No files found.
doc/APIchanges
View file @
a001ce31
...
...
@@ -17,6 +17,8 @@ API changes, most recent first:
xxxxxxx buffer.h - Add av_buffer_pool_init2().
xxxxxxx hwcontext.h - Add a new installed header hwcontext.h with a new API
for handling hwaccel frames.
xxxxxxx hwcontext_vdpau.h - Add a new installed header hwcontext_vdpau.h with
VDPAU-specific hwcontext definitions.
2016-xx-xx - xxxxxxx - lavf 57.3.0 - avformat.h
Add AVFormatContext.opaque, io_open and io_close, allowing custom IO
...
...
libavutil/Makefile
View file @
a001ce31
...
...
@@ -24,6 +24,7 @@ HEADERS = adler32.h \
frame.h
\
hmac.h
\
hwcontext.h
\
hwcontext_vdpau.h
\
imgutils.h
\
intfloat.h
\
intreadwrite.h
\
...
...
@@ -105,6 +106,7 @@ OBJS = adler32.o \
xtea.o
\
OBJS-$(CONFIG_LZO)
+=
lzo.o
OBJS-$(CONFIG_VDPAU)
+=
hwcontext_vdpau.o
OBJS
+=
$
(
COMPAT_OBJS:%
=
../compat/%
)
...
...
libavutil/hwcontext.c
View file @
a001ce31
...
...
@@ -29,6 +29,9 @@
#include "pixfmt.h"
static
const
HWContextType
*
hw_table
[]
=
{
#if CONFIG_VDPAU
&
ff_hwcontext_type_vdpau
,
#endif
NULL
,
};
...
...
libavutil/hwcontext_internal.h
View file @
a001ce31
...
...
@@ -86,4 +86,6 @@ struct AVHWFramesInternal {
AVBufferPool
*
pool_internal
;
};
extern
const
HWContextType
ff_hwcontext_type_vdpau
;
#endif
/* AVUTIL_HWCONTEXT_INTERNAL_H */
libavutil/hwcontext_vdpau.c
0 → 100644
View file @
a001ce31
/*
* 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 <vdpau/vdpau.h>
#include "buffer.h"
#include "common.h"
#include "hwcontext.h"
#include "hwcontext_internal.h"
#include "hwcontext_vdpau.h"
#include "mem.h"
#include "pixfmt.h"
#include "pixdesc.h"
typedef
struct
VDPAUDeviceContext
{
VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities
*
get_transfer_caps
;
VdpVideoSurfaceGetBitsYCbCr
*
get_data
;
VdpVideoSurfacePutBitsYCbCr
*
put_data
;
VdpVideoSurfaceCreate
*
surf_create
;
VdpVideoSurfaceDestroy
*
surf_destroy
;
enum
AVPixelFormat
*
pix_fmts
[
3
];
int
nb_pix_fmts
[
3
];
}
VDPAUDeviceContext
;
typedef
struct
VDPAUFramesContext
{
VdpVideoSurfaceGetBitsYCbCr
*
get_data
;
VdpVideoSurfacePutBitsYCbCr
*
put_data
;
VdpChromaType
chroma_type
;
int
chroma_idx
;
const
enum
AVPixelFormat
*
pix_fmts
;
int
nb_pix_fmts
;
}
VDPAUFramesContext
;
typedef
struct
VDPAUPixFmtMap
{
VdpYCbCrFormat
vdpau_fmt
;
enum
AVPixelFormat
pix_fmt
;
}
VDPAUPixFmtMap
;
static
const
VDPAUPixFmtMap
pix_fmts_420
[]
=
{
{
VDP_YCBCR_FORMAT_NV12
,
AV_PIX_FMT_NV12
},
{
VDP_YCBCR_FORMAT_YV12
,
AV_PIX_FMT_YUV420P
},
{
0
,
AV_PIX_FMT_NONE
,
},
};
static
const
VDPAUPixFmtMap
pix_fmts_422
[]
=
{
{
VDP_YCBCR_FORMAT_NV12
,
AV_PIX_FMT_NV16
},
{
VDP_YCBCR_FORMAT_YV12
,
AV_PIX_FMT_YUV422P
},
{
VDP_YCBCR_FORMAT_UYVY
,
AV_PIX_FMT_UYVY422
},
{
VDP_YCBCR_FORMAT_YUYV
,
AV_PIX_FMT_YUYV422
},
{
0
,
AV_PIX_FMT_NONE
,
},
};
static
const
VDPAUPixFmtMap
pix_fmts_444
[]
=
{
{
VDP_YCBCR_FORMAT_YV12
,
AV_PIX_FMT_YUV444P
},
{
0
,
AV_PIX_FMT_NONE
,
},
};
static
const
struct
{
VdpChromaType
chroma_type
;
const
VDPAUPixFmtMap
*
map
;
}
vdpau_pix_fmts
[]
=
{
{
VDP_CHROMA_TYPE_420
,
pix_fmts_420
},
{
VDP_CHROMA_TYPE_422
,
pix_fmts_422
},
{
VDP_CHROMA_TYPE_444
,
pix_fmts_444
},
};
static
int
count_pixfmts
(
const
VDPAUPixFmtMap
*
map
)
{
int
count
=
0
;
while
(
map
->
pix_fmt
!=
AV_PIX_FMT_NONE
)
{
map
++
;
count
++
;
}
return
count
;
}
static
int
vdpau_init_pixmfts
(
AVHWDeviceContext
*
ctx
)
{
AVVDPAUDeviceContext
*
hwctx
=
ctx
->
hwctx
;
VDPAUDeviceContext
*
priv
=
ctx
->
internal
->
priv
;
int
i
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
priv
->
pix_fmts
);
i
++
)
{
const
VDPAUPixFmtMap
*
map
=
vdpau_pix_fmts
[
i
].
map
;
int
nb_pix_fmts
;
nb_pix_fmts
=
count_pixfmts
(
map
);
priv
->
pix_fmts
[
i
]
=
av_malloc_array
(
nb_pix_fmts
+
1
,
sizeof
(
*
priv
->
pix_fmts
[
i
]));
if
(
!
priv
->
pix_fmts
[
i
])
return
AVERROR
(
ENOMEM
);
nb_pix_fmts
=
0
;
while
(
map
->
pix_fmt
!=
AV_PIX_FMT_NONE
)
{
VdpBool
supported
;
VdpStatus
err
=
priv
->
get_transfer_caps
(
hwctx
->
device
,
vdpau_pix_fmts
[
i
].
chroma_type
,
map
->
vdpau_fmt
,
&
supported
);
if
(
err
==
VDP_STATUS_OK
&&
supported
)
priv
->
pix_fmts
[
i
][
nb_pix_fmts
++
]
=
map
->
pix_fmt
;
map
++
;
}
priv
->
pix_fmts
[
i
][
nb_pix_fmts
++
]
=
AV_PIX_FMT_NONE
;
priv
->
nb_pix_fmts
[
i
]
=
nb_pix_fmts
;
}
return
0
;
}
static
int
vdpau_device_init
(
AVHWDeviceContext
*
ctx
)
{
AVVDPAUDeviceContext
*
hwctx
=
ctx
->
hwctx
;
VDPAUDeviceContext
*
priv
=
ctx
->
internal
->
priv
;
VdpStatus
err
;
int
ret
;
#define GET_CALLBACK(id, result) \
do { \
void *tmp; \
err = hwctx->get_proc_address(hwctx->device, id, &tmp); \
if (err != VDP_STATUS_OK) { \
av_log(ctx, AV_LOG_ERROR, "Error getting the " #id " callback.\n"); \
return AVERROR_UNKNOWN; \
} \
priv->result = tmp; \
} while (0)
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES
,
get_transfer_caps
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR
,
get_data
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR
,
put_data
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_CREATE
,
surf_create
);
GET_CALLBACK
(
VDP_FUNC_ID_VIDEO_SURFACE_DESTROY
,
surf_destroy
);
ret
=
vdpau_init_pixmfts
(
ctx
);
if
(
ret
<
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error querying the supported pixel formats
\n
"
);
return
ret
;
}
return
0
;
}
static
void
vdpau_device_uninit
(
AVHWDeviceContext
*
ctx
)
{
VDPAUDeviceContext
*
priv
=
ctx
->
internal
->
priv
;
int
i
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
priv
->
pix_fmts
);
i
++
)
av_freep
(
&
priv
->
pix_fmts
[
i
]);
}
static
void
vdpau_buffer_free
(
void
*
opaque
,
uint8_t
*
data
)
{
AVHWFramesContext
*
ctx
=
opaque
;
VDPAUDeviceContext
*
device_priv
=
ctx
->
device_ctx
->
internal
->
priv
;
VdpVideoSurface
surf
=
(
VdpVideoSurface
)(
uintptr_t
)
data
;
device_priv
->
surf_destroy
(
surf
);
}
static
AVBufferRef
*
vdpau_pool_alloc
(
void
*
opaque
,
int
size
)
{
AVHWFramesContext
*
ctx
=
opaque
;
VDPAUFramesContext
*
priv
=
ctx
->
internal
->
priv
;
AVVDPAUDeviceContext
*
device_hwctx
=
ctx
->
device_ctx
->
hwctx
;
VDPAUDeviceContext
*
device_priv
=
ctx
->
device_ctx
->
internal
->
priv
;
AVBufferRef
*
ret
;
VdpVideoSurface
surf
;
VdpStatus
err
;
err
=
device_priv
->
surf_create
(
device_hwctx
->
device
,
priv
->
chroma_type
,
ctx
->
width
,
ctx
->
height
,
&
surf
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error allocating a VDPAU video surface
\n
"
);
return
NULL
;
}
ret
=
av_buffer_create
((
uint8_t
*
)(
uintptr_t
)
surf
,
sizeof
(
surf
),
vdpau_buffer_free
,
ctx
,
AV_BUFFER_FLAG_READONLY
);
if
(
!
ret
)
{
device_priv
->
surf_destroy
(
surf
);
return
NULL
;
}
return
ret
;
}
static
int
vdpau_frames_init
(
AVHWFramesContext
*
ctx
)
{
VDPAUDeviceContext
*
device_priv
=
ctx
->
device_ctx
->
internal
->
priv
;
VDPAUFramesContext
*
priv
=
ctx
->
internal
->
priv
;
int
i
;
switch
(
ctx
->
sw_format
)
{
case
AV_PIX_FMT_YUV420P
:
priv
->
chroma_type
=
VDP_CHROMA_TYPE_420
;
break
;
case
AV_PIX_FMT_YUV422P
:
priv
->
chroma_type
=
VDP_CHROMA_TYPE_422
;
break
;
case
AV_PIX_FMT_YUV444P
:
priv
->
chroma_type
=
VDP_CHROMA_TYPE_444
;
break
;
default:
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported data layout: %s
\n
"
,
av_get_pix_fmt_name
(
ctx
->
sw_format
));
return
AVERROR
(
ENOSYS
);
}
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
vdpau_pix_fmts
);
i
++
)
{
if
(
vdpau_pix_fmts
[
i
].
chroma_type
==
priv
->
chroma_type
)
{
priv
->
chroma_idx
=
i
;
priv
->
pix_fmts
=
device_priv
->
pix_fmts
[
i
];
priv
->
nb_pix_fmts
=
device_priv
->
nb_pix_fmts
[
i
];
break
;
}
}
if
(
!
priv
->
pix_fmts
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported chroma type: %d
\n
"
,
priv
->
chroma_type
);
return
AVERROR
(
ENOSYS
);
}
if
(
!
ctx
->
pool
)
{
ctx
->
internal
->
pool_internal
=
av_buffer_pool_init2
(
sizeof
(
VdpVideoSurface
),
ctx
,
vdpau_pool_alloc
,
NULL
);
if
(
!
ctx
->
internal
->
pool_internal
)
return
AVERROR
(
ENOMEM
);
}
priv
->
get_data
=
device_priv
->
get_data
;
priv
->
put_data
=
device_priv
->
put_data
;
return
0
;
}
static
int
vdpau_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_VDPAU
;
frame
->
width
=
ctx
->
width
;
frame
->
height
=
ctx
->
height
;
return
0
;
}
static
int
vdpau_transfer_get_formats
(
AVHWFramesContext
*
ctx
,
enum
AVHWFrameTransferDirection
dir
,
enum
AVPixelFormat
**
formats
)
{
VDPAUFramesContext
*
priv
=
ctx
->
internal
->
priv
;
enum
AVPixelFormat
*
fmts
;
if
(
priv
->
nb_pix_fmts
==
1
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"No target formats are supported for this chroma type
\n
"
);
return
AVERROR
(
ENOSYS
);
}
fmts
=
av_malloc_array
(
priv
->
nb_pix_fmts
,
sizeof
(
*
fmts
));
if
(
!
fmts
)
return
AVERROR
(
ENOMEM
);
memcpy
(
fmts
,
priv
->
pix_fmts
,
sizeof
(
*
fmts
)
*
(
priv
->
nb_pix_fmts
));
*
formats
=
fmts
;
return
0
;
}
static
int
vdpau_transfer_data_from
(
AVHWFramesContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
)
{
VDPAUFramesContext
*
priv
=
ctx
->
internal
->
priv
;
VdpVideoSurface
surf
=
(
VdpVideoSurface
)(
uintptr_t
)
src
->
data
[
3
];
void
*
data
[
3
];
uint32_t
linesize
[
3
];
const
VDPAUPixFmtMap
*
map
;
VdpYCbCrFormat
vdpau_format
;
VdpStatus
err
;
int
i
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
data
)
&&
dst
->
data
[
i
];
i
++
)
{
data
[
i
]
=
dst
->
data
[
i
];
if
(
dst
->
linesize
[
i
]
<
0
||
(
uint64_t
)
dst
->
linesize
>
UINT32_MAX
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"The linesize %d cannot be represented as uint32
\n
"
,
dst
->
linesize
[
i
]);
return
AVERROR
(
ERANGE
);
}
linesize
[
i
]
=
dst
->
linesize
[
i
];
}
map
=
vdpau_pix_fmts
[
priv
->
chroma_idx
].
map
;
for
(
i
=
0
;
map
[
i
].
pix_fmt
!=
AV_PIX_FMT_NONE
;
i
++
)
{
if
(
map
[
i
].
pix_fmt
==
dst
->
format
)
{
vdpau_format
=
map
[
i
].
vdpau_fmt
;
break
;
}
}
if
(
map
[
i
].
pix_fmt
==
AV_PIX_FMT_NONE
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported target pixel format: %s
\n
"
,
av_get_pix_fmt_name
(
dst
->
format
));
return
AVERROR
(
EINVAL
);
}
if
(
vdpau_format
==
VDP_YCBCR_FORMAT_YV12
)
FFSWAP
(
void
*
,
data
[
1
],
data
[
2
]);
err
=
priv
->
get_data
(
surf
,
vdpau_format
,
data
,
linesize
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error retrieving the data from a VDPAU surface
\n
"
);
return
AVERROR_UNKNOWN
;
}
return
0
;
}
static
int
vdpau_transfer_data_to
(
AVHWFramesContext
*
ctx
,
AVFrame
*
dst
,
const
AVFrame
*
src
)
{
VDPAUFramesContext
*
priv
=
ctx
->
internal
->
priv
;
VdpVideoSurface
surf
=
(
VdpVideoSurface
)(
uintptr_t
)
dst
->
data
[
3
];
const
void
*
data
[
3
];
uint32_t
linesize
[
3
];
const
VDPAUPixFmtMap
*
map
;
VdpYCbCrFormat
vdpau_format
;
VdpStatus
err
;
int
i
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
data
)
&&
src
->
data
[
i
];
i
++
)
{
data
[
i
]
=
src
->
data
[
i
];
if
(
src
->
linesize
[
i
]
<
0
||
(
uint64_t
)
src
->
linesize
>
UINT32_MAX
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"The linesize %d cannot be represented as uint32
\n
"
,
src
->
linesize
[
i
]);
return
AVERROR
(
ERANGE
);
}
linesize
[
i
]
=
src
->
linesize
[
i
];
}
map
=
vdpau_pix_fmts
[
priv
->
chroma_idx
].
map
;
for
(
i
=
0
;
map
[
i
].
pix_fmt
!=
AV_PIX_FMT_NONE
;
i
++
)
{
if
(
map
[
i
].
pix_fmt
==
src
->
format
)
{
vdpau_format
=
map
[
i
].
vdpau_fmt
;
break
;
}
}
if
(
map
[
i
].
pix_fmt
==
AV_PIX_FMT_NONE
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported source pixel format: %s
\n
"
,
av_get_pix_fmt_name
(
src
->
format
));
return
AVERROR
(
EINVAL
);
}
if
(
vdpau_format
==
VDP_YCBCR_FORMAT_YV12
)
FFSWAP
(
const
void
*
,
data
[
1
],
data
[
2
]);
err
=
priv
->
put_data
(
surf
,
vdpau_format
,
data
,
linesize
);
if
(
err
!=
VDP_STATUS_OK
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error uploading the data to a VDPAU surface
\n
"
);
return
AVERROR_UNKNOWN
;
}
return
0
;
}
const
HWContextType
ff_hwcontext_type_vdpau
=
{
.
type
=
AV_HWDEVICE_TYPE_VDPAU
,
.
name
=
"VDPAU"
,
.
device_hwctx_size
=
sizeof
(
AVVDPAUDeviceContext
),
.
device_priv_size
=
sizeof
(
VDPAUDeviceContext
),
.
frames_priv_size
=
sizeof
(
VDPAUFramesContext
),
.
device_init
=
vdpau_device_init
,
.
device_uninit
=
vdpau_device_uninit
,
.
frames_init
=
vdpau_frames_init
,
.
frames_get_buffer
=
vdpau_get_buffer
,
.
transfer_get_formats
=
vdpau_transfer_get_formats
,
.
transfer_data_to
=
vdpau_transfer_data_to
,
.
transfer_data_from
=
vdpau_transfer_data_from
,
.
pix_fmts
=
(
const
enum
AVPixelFormat
[]){
AV_PIX_FMT_VDPAU
,
AV_PIX_FMT_NONE
},
};
libavutil/hwcontext_vdpau.h
0 → 100644
View file @
a001ce31
/*
* 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_VDPAU_H
#define AVUTIL_HWCONTEXT_VDPAU_H
#include <vdpau/vdpau.h>
/**
* @file
* An API-specific header for AV_HWDEVICE_TYPE_VDPAU.
*
* This API supports dynamic frame pools. AVHWFramesContext.pool must return
* AVBufferRefs whose data pointer is a VdpVideoSurface.
*/
/**
* This struct is allocated as AVHWDeviceContext.hwctx
*/
typedef
struct
AVVDPAUDeviceContext
{
VdpDevice
device
;
VdpGetProcAddress
*
get_proc_address
;
}
AVVDPAUDeviceContext
;
/**
* AVHWFramesContext.hwctx is currently not used
*/
#endif
/* AVUTIL_HWCONTEXT_VDPAU_H */
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