2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "libavutil/buffer.h"
20 #include "libavutil/hwcontext.h"
21 #include "libavutil/log.h"
22 #include "libavutil/opt.h"
29 typedef struct CudaUploadContext {
33 AVBufferRef *hwdevice;
37 static av_cold int cudaupload_init(AVFilterContext *ctx)
39 CudaUploadContext *s = ctx->priv;
42 snprintf(buf, sizeof(buf), "%d", s->device_idx);
44 return av_hwdevice_ctx_create(&s->hwdevice, AV_HWDEVICE_TYPE_CUDA, buf, NULL, 0);
47 static av_cold void cudaupload_uninit(AVFilterContext *ctx)
49 CudaUploadContext *s = ctx->priv;
51 av_buffer_unref(&s->hwframe);
52 av_buffer_unref(&s->hwdevice);
55 static int cudaupload_query_formats(AVFilterContext *ctx)
59 static const enum AVPixelFormat input_pix_fmts[] = {
60 AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P,
63 static const enum AVPixelFormat output_pix_fmts[] = {
64 AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE,
66 AVFilterFormats *in_fmts = ff_make_format_list(input_pix_fmts);
67 AVFilterFormats *out_fmts;
69 ret = ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats);
73 out_fmts = ff_make_format_list(output_pix_fmts);
75 ret = ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats);
82 static int cudaupload_config_output(AVFilterLink *outlink)
84 AVFilterContext *ctx = outlink->src;
85 AVFilterLink *inlink = ctx->inputs[0];
86 CudaUploadContext *s = ctx->priv;
88 AVHWFramesContext *hwframe_ctx;
91 av_buffer_unref(&s->hwframe);
92 s->hwframe = av_hwframe_ctx_alloc(s->hwdevice);
94 return AVERROR(ENOMEM);
96 hwframe_ctx = (AVHWFramesContext*)s->hwframe->data;
97 hwframe_ctx->format = AV_PIX_FMT_CUDA;
98 hwframe_ctx->sw_format = inlink->format;
99 hwframe_ctx->width = inlink->w;
100 hwframe_ctx->height = inlink->h;
102 ret = av_hwframe_ctx_init(s->hwframe);
106 outlink->hw_frames_ctx = av_buffer_ref(s->hwframe);
107 if (!outlink->hw_frames_ctx)
108 return AVERROR(ENOMEM);
113 static int cudaupload_filter_frame(AVFilterLink *link, AVFrame *in)
115 AVFilterContext *ctx = link->dst;
116 AVFilterLink *outlink = ctx->outputs[0];
121 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
123 ret = AVERROR(ENOMEM);
127 out->width = in->width;
128 out->height = in->height;
130 ret = av_hwframe_transfer_data(out, in, 0);
132 av_log(ctx, AV_LOG_ERROR, "Error transferring data to the GPU\n");
136 ret = av_frame_copy_props(out, in);
142 return ff_filter_frame(ctx->outputs[0], out);
149 #define OFFSET(x) offsetof(CudaUploadContext, x)
150 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
151 static const AVOption cudaupload_options[] = {
152 { "device", "Number of the device to use", OFFSET(device_idx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
156 AVFILTER_DEFINE_CLASS(cudaupload);
158 static const AVFilterPad cudaupload_inputs[] = {
161 .type = AVMEDIA_TYPE_VIDEO,
162 .filter_frame = cudaupload_filter_frame,
167 static const AVFilterPad cudaupload_outputs[] = {
170 .type = AVMEDIA_TYPE_VIDEO,
171 .config_props = cudaupload_config_output,
176 AVFilter ff_vf_hwupload_cuda = {
177 .name = "hwupload_cuda",
178 .description = NULL_IF_CONFIG_SMALL("Upload a system memory frame to a CUDA device."),
180 .init = cudaupload_init,
181 .uninit = cudaupload_uninit,
183 .query_formats = cudaupload_query_formats,
185 .priv_size = sizeof(CudaUploadContext),
186 .priv_class = &cudaupload_class,
188 .inputs = cudaupload_inputs,
189 .outputs = cudaupload_outputs,
191 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,