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
d865e74e
Commit
d865e74e
authored
Jun 04, 2016
by
Timo Rothenpieler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ffmpeg: Add cuvid hwaccel support
parent
88e8aef9
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
249 additions
and
0 deletions
+249
-0
Makefile
Makefile
+1
-0
ffmpeg.c
ffmpeg.c
+5
-0
ffmpeg.h
ffmpeg.h
+3
-0
ffmpeg_cuvid.c
ffmpeg_cuvid.c
+237
-0
ffmpeg_opt.c
ffmpeg_opt.c
+3
-0
No files found.
Makefile
View file @
d865e74e
...
...
@@ -36,6 +36,7 @@ OBJS-ffmpeg-$(CONFIG_VAAPI) += ffmpeg_vaapi.o
ifndef
CONFIG_VIDEOTOOLBOX
OBJS-ffmpeg-$(CONFIG_VDA)
+=
ffmpeg_videotoolbox.o
endif
OBJS-ffmpeg-$(CONFIG_CUVID)
+=
ffmpeg_cuvid.o
OBJS-ffmpeg-$(HAVE_DXVA2_LIB)
+=
ffmpeg_dxva2.o
OBJS-ffmpeg-$(HAVE_VDPAU_X11)
+=
ffmpeg_vdpau.o
OBJS-ffserver
+=
ffserver_config.o
...
...
ffmpeg.c
View file @
d865e74e
...
...
@@ -3063,6 +3063,11 @@ static int transcode_init(void)
exit_program
(
1
);
#endif
#if CONFIG_CUVID
if
(
cuvid_transcode_init
(
ost
))
exit_program
(
1
);
#endif
if
(
!
ost
->
filter
&&
(
enc_ctx
->
codec_type
==
AVMEDIA_TYPE_VIDEO
||
enc_ctx
->
codec_type
==
AVMEDIA_TYPE_AUDIO
))
{
...
...
ffmpeg.h
View file @
d865e74e
...
...
@@ -66,6 +66,7 @@ enum HWAccelID {
HWACCEL_VIDEOTOOLBOX
,
HWACCEL_QSV
,
HWACCEL_VAAPI
,
HWACCEL_CUVID
,
};
typedef
struct
HWAccel
{
...
...
@@ -585,5 +586,7 @@ int qsv_init(AVCodecContext *s);
int
qsv_transcode_init
(
OutputStream
*
ost
);
int
vaapi_decode_init
(
AVCodecContext
*
avctx
);
int
vaapi_device_init
(
const
char
*
device
);
int
cuvid_init
(
AVCodecContext
*
s
);
int
cuvid_transcode_init
(
OutputStream
*
ost
);
#endif
/* FFMPEG_H */
ffmpeg_cuvid.c
0 → 100644
View file @
d865e74e
/*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_cuda.h"
#include "ffmpeg.h"
#include <cuda.h>
#include <nvcuvid.h>
typedef
struct
CUVIDContext
{
AVBufferRef
*
hw_frames_ctx
;
}
CUVIDContext
;
static
void
cuvid_uninit
(
AVCodecContext
*
avctx
)
{
InputStream
*
ist
=
avctx
->
opaque
;
CUVIDContext
*
ctx
=
ist
->
hwaccel_ctx
;
if
(
ctx
)
{
av_buffer_unref
(
&
ctx
->
hw_frames_ctx
);
av_freep
(
&
ctx
);
}
av_buffer_unref
(
&
ist
->
hw_frames_ctx
);
ist
->
hwaccel_ctx
=
0
;
ist
->
hwaccel_uninit
=
0
;
}
int
cuvid_init
(
AVCodecContext
*
avctx
)
{
InputStream
*
ist
=
avctx
->
opaque
;
CUVIDContext
*
ctx
=
ist
->
hwaccel_ctx
;
av_log
(
NULL
,
AV_LOG_TRACE
,
"Initializing cuvid hwaccel
\n
"
);
if
(
!
ctx
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"CUVID transcoding is not initialized. "
"-hwaccel cuvid should only be used for one-to-one CUVID transcoding "
"with no (software) filters.
\n
"
);
return
AVERROR
(
EINVAL
);
}
return
0
;
}
static
void
cuvid_ctx_free
(
AVHWDeviceContext
*
ctx
)
{
AVCUDADeviceContext
*
hwctx
=
ctx
->
hwctx
;
cuCtxDestroy
(
hwctx
->
cuda_ctx
);
}
int
cuvid_transcode_init
(
OutputStream
*
ost
)
{
InputStream
*
ist
;
const
enum
AVPixelFormat
*
pix_fmt
;
AVCUDADeviceContext
*
device_hwctx
;
AVHWDeviceContext
*
device_ctx
;
AVHWFramesContext
*
hwframe_ctx
;
CUVIDContext
*
ctx
=
NULL
;
CUdevice
device
;
CUcontext
cuda_ctx
=
NULL
;
CUcontext
dummy
;
CUresult
err
;
int
ret
=
0
;
av_log
(
NULL
,
AV_LOG_TRACE
,
"Initializing cuvid transcoding
\n
"
);
if
(
ost
->
source_index
<
0
)
return
0
;
ist
=
input_streams
[
ost
->
source_index
];
/* check if the encoder supports CUVID */
if
(
!
ost
->
enc
->
pix_fmts
)
goto
cancel
;
for
(
pix_fmt
=
ost
->
enc
->
pix_fmts
;
*
pix_fmt
!=
AV_PIX_FMT_NONE
;
pix_fmt
++
)
if
(
*
pix_fmt
==
AV_PIX_FMT_CUDA
)
break
;
if
(
*
pix_fmt
==
AV_PIX_FMT_NONE
)
goto
cancel
;
/* check if the decoder supports CUVID */
if
(
ist
->
hwaccel_id
!=
HWACCEL_CUVID
||
!
ist
->
dec
||
!
ist
->
dec
->
pix_fmts
)
goto
cancel
;
for
(
pix_fmt
=
ist
->
dec
->
pix_fmts
;
*
pix_fmt
!=
AV_PIX_FMT_NONE
;
pix_fmt
++
)
if
(
*
pix_fmt
==
AV_PIX_FMT_CUDA
)
break
;
if
(
*
pix_fmt
==
AV_PIX_FMT_NONE
)
goto
cancel
;
av_log
(
NULL
,
AV_LOG_VERBOSE
,
"Setting up CUVID transcoding
\n
"
);
if
(
ist
->
hwaccel_ctx
)
{
ctx
=
ist
->
hwaccel_ctx
;
}
else
{
ctx
=
av_mallocz
(
sizeof
(
*
ctx
));
if
(
!
ctx
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
error
;
}
}
if
(
!
hw_device_ctx
)
{
hw_device_ctx
=
av_hwdevice_ctx_alloc
(
AV_HWDEVICE_TYPE_CUDA
);
if
(
!
hw_device_ctx
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA) failed
\n
"
);
ret
=
AVERROR
(
ENOMEM
);
goto
error
;
}
err
=
cuInit
(
0
);
if
(
err
!=
CUDA_SUCCESS
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Could not initialize the CUDA driver API
\n
"
);
ret
=
AVERROR_UNKNOWN
;
goto
error
;
}
err
=
cuDeviceGet
(
&
device
,
0
);
///TODO: Make device index configurable
if
(
err
!=
CUDA_SUCCESS
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Could not get the device number %d
\n
"
,
0
);
ret
=
AVERROR_UNKNOWN
;
goto
error
;
}
err
=
cuCtxCreate
(
&
cuda_ctx
,
CU_CTX_SCHED_BLOCKING_SYNC
,
device
);
if
(
err
!=
CUDA_SUCCESS
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error creating a CUDA context
\n
"
);
ret
=
AVERROR_UNKNOWN
;
goto
error
;
}
device_ctx
=
(
AVHWDeviceContext
*
)
hw_device_ctx
->
data
;
device_ctx
->
free
=
cuvid_ctx_free
;
device_hwctx
=
device_ctx
->
hwctx
;
device_hwctx
->
cuda_ctx
=
cuda_ctx
;
err
=
cuCtxPopCurrent
(
&
dummy
);
if
(
err
!=
CUDA_SUCCESS
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"cuCtxPopCurrent failed
\n
"
);
ret
=
AVERROR_UNKNOWN
;
goto
error
;
}
ret
=
av_hwdevice_ctx_init
(
hw_device_ctx
);
if
(
ret
<
0
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"av_hwdevice_ctx_init failed
\n
"
);
goto
error
;
}
}
else
{
device_ctx
=
(
AVHWDeviceContext
*
)
hw_device_ctx
->
data
;
device_hwctx
=
device_ctx
->
hwctx
;
cuda_ctx
=
device_hwctx
->
cuda_ctx
;
}
if
(
device_ctx
->
type
!=
AV_HWDEVICE_TYPE_CUDA
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"Hardware device context is already initialized for a diffrent hwaccel.
\n
"
);
ret
=
AVERROR
(
EINVAL
);
goto
error
;
}
if
(
!
ctx
->
hw_frames_ctx
)
{
ctx
->
hw_frames_ctx
=
av_hwframe_ctx_alloc
(
hw_device_ctx
);
if
(
!
ctx
->
hw_frames_ctx
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"av_hwframe_ctx_alloc failed
\n
"
);
ret
=
AVERROR
(
ENOMEM
);
goto
error
;
}
}
/* This is a bit hacky, av_hwframe_ctx_init is called by the cuvid decoder
* once it has probed the neccesary format information. But as filters/nvenc
* need to know the format/sw_format, set them here so they are happy.
* This is fine as long as CUVID doesn't add another supported pix_fmt.
*/
hwframe_ctx
=
(
AVHWFramesContext
*
)
ctx
->
hw_frames_ctx
->
data
;
hwframe_ctx
->
format
=
AV_PIX_FMT_CUDA
;
hwframe_ctx
->
sw_format
=
AV_PIX_FMT_NV12
;
ost
->
hwaccel_ctx
=
ctx
;
ost
->
enc_ctx
->
hw_frames_ctx
=
av_buffer_ref
(
ctx
->
hw_frames_ctx
);
ost
->
enc_ctx
->
pix_fmt
=
AV_PIX_FMT_CUDA
;
if
(
!
ost
->
enc_ctx
->
hw_frames_ctx
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"av_buffer_ref failed
\n
"
);
ret
=
AVERROR
(
ENOMEM
);
goto
error
;
}
if
(
!
ist
->
hwaccel_ctx
)
{
ist
->
hwaccel_ctx
=
ctx
;
ist
->
hw_frames_ctx
=
av_buffer_ref
(
ctx
->
hw_frames_ctx
);
ist
->
dec_ctx
->
hw_frames_ctx
=
av_buffer_ref
(
ctx
->
hw_frames_ctx
);
ist
->
dec_ctx
->
pix_fmt
=
AV_PIX_FMT_CUDA
;
ist
->
resample_pix_fmt
=
AV_PIX_FMT_CUDA
;
ist
->
hwaccel_uninit
=
cuvid_uninit
;
if
(
!
ist
->
hw_frames_ctx
||
!
ist
->
dec_ctx
->
hw_frames_ctx
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"av_buffer_ref failed
\n
"
);
ret
=
AVERROR
(
ENOMEM
);
goto
error
;
}
}
return
0
;
error:
av_freep
(
&
ctx
);
return
ret
;
cancel:
if
(
ist
->
hwaccel_id
==
HWACCEL_CUVID
)
{
av_log
(
NULL
,
AV_LOG_ERROR
,
"CUVID hwaccel requested, but impossible to achive.
\n
"
);
return
AVERROR
(
EINVAL
);
}
return
0
;
}
ffmpeg_opt.c
View file @
d865e74e
...
...
@@ -83,6 +83,9 @@ const HWAccel hwaccels[] = {
#endif
#if CONFIG_VAAPI
{
"vaapi"
,
vaapi_decode_init
,
HWACCEL_VAAPI
,
AV_PIX_FMT_VAAPI
},
#endif
#if CONFIG_CUVID
{
"cuvid"
,
cuvid_init
,
HWACCEL_CUVID
,
AV_PIX_FMT_CUDA
},
#endif
{
0
},
};
...
...
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