FFmpeg
hwcontext_cuda.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "libavutil/hwcontext.h"
23 #include "libavutil/imgutils.h"
24 #include "libavutil/log.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/pixdesc.h"
27 #include "libavutil/pixfmt.h"
28 
29 static int test_format(AVBufferRef *device_ref, enum AVPixelFormat fmt)
30 {
31  AVBufferRef *frames_ref = NULL;
32  AVHWFramesContext *hwfc;
33  AVFrame *sw_frame = NULL, *hw_frame = NULL, *download = NULL;
35  int ret;
36 
37  frames_ref = av_hwframe_ctx_alloc(device_ref);
38  if (!frames_ref) {
39  ret = AVERROR(ENOMEM);
40  goto fail;
41  }
42 
43  hwfc = (AVHWFramesContext *)frames_ref->data;
44  hwfc->format = AV_PIX_FMT_CUDA;
45  hwfc->sw_format = fmt;
46  hwfc->width = 64;
47  hwfc->height = 64;
48 
49  ret = av_hwframe_ctx_init(frames_ref);
50  if (ret < 0)
51  goto fail;
52 
53  sw_frame = av_frame_alloc();
54  hw_frame = av_frame_alloc();
55  download = av_frame_alloc();
56  if (!sw_frame || !hw_frame || !download) {
57  ret = AVERROR(ENOMEM);
58  goto fail;
59  }
60 
61  sw_frame->format = fmt;
62  sw_frame->width = 64;
63  sw_frame->height = 64;
64  ret = av_frame_get_buffer(sw_frame, 0);
65  if (ret < 0)
66  goto fail;
67 
68  {
69  int linesizes[4];
70  av_image_fill_linesizes(linesizes, fmt, 64);
71 
72  for (int i = 0; i < FF_ARRAY_ELEMS(sw_frame->data) && sw_frame->data[i]; i++) {
73  int shift = (i == 1 || i == 2) && desc ? desc->log2_chroma_h : 0;
74  int h = AV_CEIL_RSHIFT(64, shift);
75 
76  for (int y = 0; y < h; y++)
77  for (int x = 0; x < linesizes[i]; x++)
78  sw_frame->data[i][y * sw_frame->linesize[i] + x] =
79  (uint8_t)(x + y * 3 + i * 17);
80  }
81  }
82 
83  hw_frame->hw_frames_ctx = av_buffer_ref(frames_ref);
84  if (!hw_frame->hw_frames_ctx) {
85  ret = AVERROR(ENOMEM);
86  goto fail;
87  }
88 
89  ret = av_hwframe_get_buffer(frames_ref, hw_frame, 0);
90  if (ret < 0)
91  goto fail;
92 
93  ret = av_hwframe_transfer_data(hw_frame, sw_frame, 0);
94  if (ret < 0)
95  goto fail;
96 
97  download->format = fmt;
98  download->width = 64;
99  download->height = 64;
100  ret = av_frame_get_buffer(download, 0);
101  if (ret < 0)
102  goto fail;
103 
104  ret = av_hwframe_transfer_data(download, hw_frame, 0);
105  if (ret < 0)
106  goto fail;
107 
108  {
109  int linesizes[4];
110  av_image_fill_linesizes(linesizes, fmt, 64);
111 
112  for (int i = 0; i < FF_ARRAY_ELEMS(download->data) && download->data[i]; i++) {
113  int shift = (i == 1 || i == 2) && desc ? desc->log2_chroma_h : 0;
114  int h = AV_CEIL_RSHIFT(64, shift);
115 
116  for (int y = 0; y < h; y++) {
117  int off = y * FFMIN(sw_frame->linesize[i], download->linesize[i]);
118  if (memcmp(sw_frame->data[i] + off,
119  download->data[i] + off,
120  linesizes[i])) {
121  printf("fail: %-16s plane %d row %d mismatch\n",
122  av_get_pix_fmt_name(fmt), i, y);
123  ret = AVERROR(EINVAL);
124  goto fail;
125  }
126  }
127  }
128  }
129 
130 fail:
131  av_frame_free(&sw_frame);
132  av_frame_free(&hw_frame);
133  av_frame_free(&download);
134  av_buffer_unref(&frames_ref);
135  return ret;
136 }
137 
138 /* Verify that an unsupported sw_format is refused at init time. Returns 0 when
139  * the format is correctly rejected, and an error when it is wrongly accepted. */
140 static int test_rejected(AVBufferRef *device_ref, enum AVPixelFormat fmt)
141 {
142  AVBufferRef *frames_ref = av_hwframe_ctx_alloc(device_ref);
143  AVHWFramesContext *hwfc;
144  int ret;
145 
146  if (!frames_ref)
147  return AVERROR(ENOMEM);
148 
149  hwfc = (AVHWFramesContext *)frames_ref->data;
150  hwfc->format = AV_PIX_FMT_CUDA;
151  hwfc->sw_format = fmt;
152  hwfc->width = 64;
153  hwfc->height = 64;
154 
155  /* Init is expected to fail; silence the resulting error log. */
157  ret = av_hwframe_ctx_init(frames_ref);
159 
160  av_buffer_unref(&frames_ref);
161 
162  return ret >= 0 ? AVERROR(EINVAL) : 0;
163 }
164 
165 int main(void)
166 {
167  AVBufferRef *device_ref = NULL;
168  enum AVPixelFormat fmt;
169  int ret, failures = 0, total = 0;
170 
172  if (ret < 0) {
173  /* CONFIG_CUDA only requires the ffnvcodec headers and a dynamic
174  * loader; a FATE host that compiled CUDA support need not have an
175  * NVIDIA GPU or usable driver. Skip cleanly in that case so that
176  * make fate does not fail for an unavailable test environment. A real
177  * transfer mismatch below still returns a nonzero exit status. */
178  printf("No CUDA device available, skipping.\n");
179  return 0;
180  }
181 
182  for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) {
184  if (!desc || (desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
185  continue;
186 
187  total++;
188  /* Palette formats must be refused rather than silently dropping the
189  * palette across a transfer; every other format must round-trip. */
190  if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
191  if (test_rejected(device_ref, fmt) < 0) {
192  printf("fail: %-16s wrongly accepted\n",
193  av_get_pix_fmt_name(fmt));
194  failures++;
195  }
196  } else {
197  ret = test_format(device_ref, fmt);
198  if (ret < 0) {
199  printf("fail: %-16s %s\n",
200  av_get_pix_fmt_name(fmt),
201  av_err2str(ret));
202  failures++;
203  }
204  }
205  }
206 
207  av_buffer_unref(&device_ref);
208 
209  if (failures)
210  printf("%d / %d tests failed.\n", failures, total);
211  else
212  printf("%d tests passed.\n", total);
213 
214  return !!failures;
215 }
AV_PIX_FMT_CUDA
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition: pixfmt.h:260
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
printf
__device__ int printf(const char *,...)
av_frame_get_buffer
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:206
AV_LOG_QUIET
#define AV_LOG_QUIET
Print no output.
Definition: log.h:192
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3460
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:200
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:337
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:472
pixdesc.h
AVFrame::width
int width
Definition: frame.h:544
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:263
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:493
AV_PIX_FMT_NB
@ AV_PIX_FMT_NB
number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of...
Definition: pixfmt.h:508
AV_HWDEVICE_TYPE_CUDA
@ AV_HWDEVICE_TYPE_CUDA
Definition: hwcontext.h:30
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:128
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
av_image_fill_linesizes
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
Fill plane linesizes for an image with pixel format pix_fmt and width width.
Definition: imgutils.c:89
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
fail
#define fail
Definition: test.h:478
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
shift
static int shift(int a, int b)
Definition: bonk.c:261
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:559
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:477
log.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
main
int main(void)
Definition: hwcontext_cuda.c:165
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
ret
ret
Definition: filter_design.txt:187
pixfmt.h
av_hwdevice_ctx_create
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition: hwcontext.c:615
av_hwframe_transfer_data
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:448
test_rejected
static int test_rejected(AVBufferRef *device_ref, enum AVPixelFormat fmt)
Definition: hwcontext_cuda.c:140
AVFrame::height
int height
Definition: frame.h:544
failures
static int failures
Definition: probetest.c:33
desc
const char * desc
Definition: libsvtav1.c:83
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
test_format
static int test_format(AVBufferRef *device_ref, enum AVPixelFormat fmt)
Definition: hwcontext_cuda.c:29
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
imgutils.h
hwcontext.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:517
h
h
Definition: vp9dsp_template.c:2070
AV_PIX_FMT_FLAG_PAL
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition: pixdesc.h:120
av_hwframe_get_buffer
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:506
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:3380