FFmpeg
Loading...
Searching...
No Matches
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
29static int test_format(AVBufferRef *device_ref, enum AVPixelFormat fmt)
30{
31 AVBufferRef *frames_ref = NULL;
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 ret = av_hwframe_get_buffer(frames_ref, hw_frame, 0);
84 if (ret < 0)
85 goto fail;
86
87 ret = av_hwframe_transfer_data(hw_frame, sw_frame, 0);
88 if (ret < 0)
89 goto fail;
90
91 download->format = fmt;
92 download->width = 64;
93 download->height = 64;
94 ret = av_frame_get_buffer(download, 0);
95 if (ret < 0)
96 goto fail;
97
98 ret = av_hwframe_transfer_data(download, hw_frame, 0);
99 if (ret < 0)
100 goto fail;
101
102 {
103 int linesizes[4];
104 av_image_fill_linesizes(linesizes, fmt, 64);
105
106 for (int i = 0; i < FF_ARRAY_ELEMS(download->data) && download->data[i]; i++) {
107 int shift = (i == 1 || i == 2) && desc ? desc->log2_chroma_h : 0;
108 int h = AV_CEIL_RSHIFT(64, shift);
109
110 for (int y = 0; y < h; y++) {
111 int off = y * FFMIN(sw_frame->linesize[i], download->linesize[i]);
112 if (memcmp(sw_frame->data[i] + off,
113 download->data[i] + off,
114 linesizes[i])) {
115 printf("fail: %-16s plane %d row %d mismatch\n",
116 av_get_pix_fmt_name(fmt), i, y);
117 ret = AVERROR(EINVAL);
118 goto fail;
119 }
120 }
121 }
122 }
123
124fail:
125 av_frame_free(&sw_frame);
126 av_frame_free(&hw_frame);
127 av_frame_free(&download);
128 av_buffer_unref(&frames_ref);
129 return ret;
130}
131
132/* Verify that an unsupported sw_format is refused at init time. Returns 0 when
133 * the format is correctly rejected, and an error when it is wrongly accepted. */
134static int test_rejected(AVBufferRef *device_ref, enum AVPixelFormat fmt)
135{
136 AVBufferRef *frames_ref = av_hwframe_ctx_alloc(device_ref);
137 AVHWFramesContext *hwfc;
138 int ret;
139
140 if (!frames_ref)
141 return AVERROR(ENOMEM);
142
143 hwfc = (AVHWFramesContext *)frames_ref->data;
144 hwfc->format = AV_PIX_FMT_CUDA;
145 hwfc->sw_format = fmt;
146 hwfc->width = 64;
147 hwfc->height = 64;
148
149 /* Init is expected to fail; silence the resulting error log. */
151 ret = av_hwframe_ctx_init(frames_ref);
153
154 av_buffer_unref(&frames_ref);
155
156 return ret >= 0 ? AVERROR(EINVAL) : 0;
157}
158
159int main(void)
160{
161 AVBufferRef *device_ref = NULL;
162 enum AVPixelFormat fmt;
163 int ret, failures = 0, total = 0;
164
165 ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_CUDA, NULL, NULL, 0);
166 if (ret < 0) {
167 /* CONFIG_CUDA only requires the ffnvcodec headers and a dynamic
168 * loader; a FATE host that compiled CUDA support need not have an
169 * NVIDIA GPU or usable driver. Skip cleanly in that case so that
170 * make fate does not fail for an unavailable test environment. A real
171 * transfer mismatch below still returns a nonzero exit status. */
172 printf("No CUDA device available, skipping.\n");
173 return 0;
174 }
175
176 for (fmt = 0; fmt < AV_PIX_FMT_NB; fmt++) {
178 if (!desc || (desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
179 continue;
180
181 total++;
182 /* Palette formats must be refused rather than silently dropping the
183 * palette across a transfer; every other format must round-trip. */
184 if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
185 if (test_rejected(device_ref, fmt) < 0) {
186 printf("fail: %-16s wrongly accepted\n",
188 failures++;
189 }
190 } else {
191 ret = test_format(device_ref, fmt);
192 if (ret < 0) {
193 printf("fail: %-16s %s\n",
195 av_err2str(ret));
196 failures++;
197 }
198 }
199 }
200
201 av_buffer_unref(&device_ref);
202
203 if (failures)
204 printf("%d / %d tests failed.\n", failures, total);
205 else
206 printf("%d tests passed.\n", total);
207
208 return !!failures;
209}
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
__device__ int printf(const char *,...)
#define fail
Definition test.h:479
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
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition frame.c:206
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#define AV_LOG_QUIET
Print no output.
Definition log.h:192
#define AV_LOG_INFO
Standard information.
Definition log.h:221
void av_log_set_level(int level)
Set the log level.
Definition log.c:476
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
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
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:337
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:263
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition hwcontext.c:448
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_HWDEVICE_TYPE_CUDA
Definition hwcontext.h:30
misc image utilities
static int shift(int a, int b)
Definition bonk.c:261
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
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
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition pixdesc.h:128
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition pixdesc.h:120
pixel format definitions
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ 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_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition pixfmt.h:260
static int failures
Definition probetest.c:33
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
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
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:559
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
int main(void)
static int test_format(AVBufferRef *device_ref, enum AVPixelFormat fmt)
static int test_rejected(AVBufferRef *device_ref, enum AVPixelFormat fmt)