History

lavu: add a framework for handling hwaccel frames

Anton Khirnov committed 10 years ago

Commit 89923e41 parent 721a4ef7 files · +834 −0Browse files

Unified · Split

7 files
  1. doc/APIchanges +2 −0
  2. libavutil/Makefile +2 −0
  3. libavutil/frame.c +11 −0
  4. libavutil/frame.h +6 −0
  5. libavutil/hwcontext.c +396 −0
  6. libavutil/hwcontext.h +328 −0
  7. libavutil/hwcontext_internal.h +89 −0
doc/APIchanges+2−0
@@ -15,6 +15,8 @@ API changes, most recent first: · 14 unmodified lines
1515
1616 2016-xx-xx - lavu 55.6.0
1717 xxxxxxx buffer.h - Add av_buffer_pool_init2().
18+ xxxxxxx hwcontext.h - Add a new installed header hwcontext.h with a new API
19+ for handling hwaccel frames.
1820
1921 2016-xx-xx - xxxxxxx - lavf 57.3.0 - avformat.h
2022 Add AVFormatContext.opaque, io_open and io_close, allowing custom IO
libavutil/Makefile+2−0
@@ -23,6 +23,7 @@ HEADERS = adler32.h \ · 22 unmodified lines
2323 file.h \
2424 frame.h \
2525 hmac.h \
26+ hwcontext.h \
2627 imgutils.h \
2728 intfloat.h \
2829 intreadwrite.h \
@@ -78,6 +79,7 @@ OBJS = adler32.o \ · 49 unmodified lines
7879 float_dsp.o \
7980 frame.o \
8081 hmac.o \
82+ hwcontext.o \
8183 imgutils.o \
8284 intmath.o \
8385 lfg.o \
libavutil/frame.c+11−0
@@ -251,6 +251,14 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) · 250 unmodified lines
251251 }
252252 }
253253
254+ if (src->hw_frames_ctx) {
255+ dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
256+ if (!dst->hw_frames_ctx) {
257+ ret = AVERROR(ENOMEM);
258+ goto fail;
259+ }
260+ }
261+
254262 /* duplicate extended data */
255263 if (src->extended_data != src->data) {
256264 int ch = av_get_channel_layout_nb_channels(src->channel_layout);
@@ -303,6 +311,9 @@ void av_frame_unref(AVFrame *frame) · 46 unmodified lines
303311 for (i = 0; i < frame->nb_extended_buf; i++)
304312 av_buffer_unref(&frame->extended_buf[i]);
305313 av_freep(&frame->extended_buf);
314+
315+ av_buffer_unref(&frame->hw_frames_ctx);
316+
306317 get_frame_defaults(frame);
307318 }
308319
libavutil/frame.h+6−0
@@ -354,6 +354,12 @@ typedef struct AVFrame { · 353 unmodified lines
354354 enum AVColorSpace colorspace;
355355
356356 enum AVChromaLocation chroma_location;
357+
358+ /**
359+ * For hwaccel-format frames, this should be a reference to the
360+ * AVHWFramesContext describing the frame.
361+ */
362+ AVBufferRef *hw_frames_ctx;
357363 } AVFrame;
358364
359365 /**
libavutil/hwcontext.c+396−0
@@ -0,0 +1,396 @@
1+/*
2+ * This file is part of Libav.
3+ *
4+ * Libav 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+ * Libav 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 Libav; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#include "config.h"
20+
21+#include "buffer.h"
22+#include "common.h"
23+#include "hwcontext.h"
24+#include "hwcontext_internal.h"
25+#include "imgutils.h"
26+#include "log.h"
27+#include "mem.h"
28+#include "pixdesc.h"
29+#include "pixfmt.h"
30+
31+static const HWContextType *hw_table[] = {
32+ NULL,
33+};
34+
35+static const AVClass hwdevice_ctx_class = {
36+ .class_name = "AVHWDeviceContext",
37+ .item_name = av_default_item_name,
38+ .version = LIBAVUTIL_VERSION_INT,
39+};
40+
41+static void hwdevice_ctx_free(void *opaque, uint8_t *data)
42+{
43+ AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
44+
45+ /* uninit might still want access the hw context and the user
46+ * free() callback might destroy it, so uninit has to be called first */
47+ if (ctx->internal->hw_type->device_uninit)
48+ ctx->internal->hw_type->device_uninit(ctx);
49+
50+ if (ctx->free)
51+ ctx->free(ctx);
52+
53+ av_freep(&ctx->hwctx);
54+ av_freep(&ctx->internal->priv);
55+ av_freep(&ctx->internal);
56+ av_freep(&ctx);
57+}
58+
59+AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
60+{
61+ AVHWDeviceContext *ctx;
62+ AVBufferRef *buf;
63+ const HWContextType *hw_type = NULL;
64+ int i;
65+
66+ for (i = 0; hw_table[i]; i++) {
67+ if (hw_table[i]->type == type) {
68+ hw_type = hw_table[i];
69+ break;
70+ }
71+ }
72+ if (!hw_type)
73+ return NULL;
74+
75+ ctx = av_mallocz(sizeof(*ctx));
76+ if (!ctx)
77+ return NULL;
78+
79+ ctx->internal = av_mallocz(sizeof(*ctx->internal));
80+ if (!ctx->internal)
81+ goto fail;
82+
83+ if (hw_type->device_priv_size) {
84+ ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
85+ if (!ctx->internal->priv)
86+ goto fail;
87+ }
88+
89+ if (hw_type->device_hwctx_size) {
90+ ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
91+ if (!ctx->hwctx)
92+ goto fail;
93+ }
94+
95+ buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
96+ hwdevice_ctx_free, NULL,
97+ AV_BUFFER_FLAG_READONLY);
98+ if (!buf)
99+ goto fail;
100+
101+ ctx->type = type;
102+ ctx->av_class = &hwdevice_ctx_class;
103+
104+ ctx->internal->hw_type = hw_type;
105+
106+ return buf;
107+
108+fail:
109+ if (ctx->internal)
110+ av_freep(&ctx->internal->priv);
111+ av_freep(&ctx->internal);
112+ av_freep(&ctx->hwctx);
113+ av_freep(&ctx);
114+ return NULL;
115+}
116+
117+int av_hwdevice_ctx_init(AVBufferRef *ref)
118+{
119+ AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
120+ int ret;
121+
122+ if (ctx->internal->hw_type->device_init) {
123+ ret = ctx->internal->hw_type->device_init(ctx);
124+ if (ret < 0)
125+ goto fail;
126+ }
127+
128+ return 0;
129+fail:
130+ if (ctx->internal->hw_type->device_uninit)
131+ ctx->internal->hw_type->device_uninit(ctx);
132+ return ret;
133+}
134+
135+static const AVClass hwframe_ctx_class = {
136+ .class_name = "AVHWFramesContext",
137+ .item_name = av_default_item_name,
138+ .version = LIBAVUTIL_VERSION_INT,
139+};
140+
141+static void hwframe_ctx_free(void *opaque, uint8_t *data)
142+{
143+ AVHWFramesContext *ctx = (AVHWFramesContext*)data;
144+
145+ if (ctx->internal->pool_internal)
146+ av_buffer_pool_uninit(&ctx->internal->pool_internal);
147+
148+ if (ctx->internal->hw_type->frames_uninit)
149+ ctx->internal->hw_type->frames_uninit(ctx);
150+
151+ if (ctx->free)
152+ ctx->free(ctx);
153+
154+ av_buffer_unref(&ctx->device_ref);
155+
156+ av_freep(&ctx->hwctx);
157+ av_freep(&ctx->internal->priv);
158+ av_freep(&ctx->internal);
159+ av_freep(&ctx);
160+}
161+
162+AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
163+{
164+ AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
165+ const HWContextType *hw_type = device_ctx->internal->hw_type;
166+ AVHWFramesContext *ctx;
167+ AVBufferRef *buf, *device_ref = NULL;;
168+
169+ ctx = av_mallocz(sizeof(*ctx));
170+ if (!ctx)
171+ return NULL;
172+
173+ ctx->internal = av_mallocz(sizeof(*ctx->internal));
174+ if (!ctx->internal)
175+ goto fail;
176+
177+ if (hw_type->frames_priv_size) {
178+ ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
179+ if (!ctx->internal->priv)
180+ goto fail;
181+ }
182+
183+ if (hw_type->frames_hwctx_size) {
184+ ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
185+ if (!ctx->hwctx)
186+ goto fail;
187+ }
188+
189+ device_ref = av_buffer_ref(device_ref_in);
190+ if (!device_ref)
191+ goto fail;
192+
193+ buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
194+ hwframe_ctx_free, NULL,
195+ AV_BUFFER_FLAG_READONLY);
196+ if (!buf)
197+ goto fail;
198+
199+ ctx->av_class = &hwframe_ctx_class;
200+ ctx->device_ref = device_ref;
201+ ctx->device_ctx = device_ctx;
202+ ctx->format = AV_PIX_FMT_NONE;
203+
204+ ctx->internal->hw_type = hw_type;
205+
206+ return buf;
207+
208+fail:
209+ if (device_ref)
210+ av_buffer_unref(&device_ref);
211+ if (ctx->internal)
212+ av_freep(&ctx->internal->priv);
213+ av_freep(&ctx->internal);
214+ av_freep(&ctx->hwctx);
215+ av_freep(&ctx);
216+ return NULL;
217+}
218+
219+static int hwframe_pool_prealloc(AVBufferRef *ref)
220+{
221+ AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
222+ AVFrame **frames;
223+ int i, ret = 0;
224+
225+ frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
226+ if (!frames)
227+ return AVERROR(ENOMEM);
228+
229+ for (i = 0; i < ctx->initial_pool_size; i++) {
230+ frames[i] = av_frame_alloc();
231+ if (!frames[i])
232+ goto fail;
233+
234+ ret = av_hwframe_get_buffer(ref, frames[i], 0);
235+ if (ret < 0)
236+ goto fail;
237+ }
238+
239+fail:
240+ for (i = 0; i < ctx->initial_pool_size; i++)
241+ av_frame_free(&frames[i]);
242+ av_freep(&frames);
243+
244+ return ret;
245+}
246+
247+int av_hwframe_ctx_init(AVBufferRef *ref)
248+{
249+ AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
250+ const enum AVPixelFormat *pix_fmt;
251+ int ret;
252+
253+ /* validate the pixel format */
254+ for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
255+ if (*pix_fmt == ctx->format)
256+ break;
257+ }
258+ if (*pix_fmt == AV_PIX_FMT_NONE) {
259+ av_log(ctx, AV_LOG_ERROR,
260+ "The hardware pixel format '%s' is not supported by the device type '%s'\n",
261+ av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
262+ return AVERROR(ENOSYS);
263+ }
264+
265+ /* validate the dimensions */
266+ ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
267+ if (ret < 0)
268+ return ret;
269+
270+ /* format-specific init */
271+ if (ctx->internal->hw_type->frames_init) {
272+ ret = ctx->internal->hw_type->frames_init(ctx);
273+ if (ret < 0)
274+ goto fail;
275+ }
276+
277+ if (ctx->internal->pool_internal && !ctx->pool)
278+ ctx->pool = ctx->internal->pool_internal;
279+
280+ /* preallocate the frames in the pool, if requested */
281+ if (ctx->initial_pool_size > 0) {
282+ ret = hwframe_pool_prealloc(ref);
283+ if (ret < 0)
284+ goto fail;
285+ }
286+
287+ return 0;
288+fail:
289+ if (ctx->internal->hw_type->frames_uninit)
290+ ctx->internal->hw_type->frames_uninit(ctx);
291+ return ret;
292+}
293+
294+int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
295+ enum AVHWFrameTransferDirection dir,
296+ enum AVPixelFormat **formats, int flags)
297+{
298+ AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
299+
300+ if (!ctx->internal->hw_type->transfer_get_formats)
301+ return AVERROR(ENOSYS);
302+
303+ return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
304+}
305+
306+static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
307+{
308+ AVFrame *frame_tmp;
309+ int ret = 0;
310+
311+ frame_tmp = av_frame_alloc();
312+ if (!frame_tmp)
313+ return AVERROR(ENOMEM);
314+
315+ /* if the format is set, use that
316+ * otherwise pick the first supported one */
317+ if (dst->format >= 0) {
318+ frame_tmp->format = dst->format;
319+ } else {
320+ enum AVPixelFormat *formats;
321+
322+ ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
323+ AV_HWFRAME_TRANSFER_DIRECTION_FROM,
324+ &formats, 0);
325+ if (ret < 0)
326+ goto fail;
327+ frame_tmp->format = formats[0];
328+ av_freep(&formats);
329+ }
330+ frame_tmp->width = src->width;
331+ frame_tmp->height = src->height;
332+
333+ ret = av_frame_get_buffer(frame_tmp, 32);
334+ if (ret < 0)
335+ goto fail;
336+
337+ ret = av_hwframe_transfer_data(frame_tmp, src, flags);
338+ if (ret < 0)
339+ goto fail;
340+
341+ av_frame_move_ref(dst, frame_tmp);
342+
343+fail:
344+ av_frame_free(&frame_tmp);
345+ return ret;
346+}
347+
348+int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
349+{
350+ AVHWFramesContext *ctx;
351+ int ret;
352+
353+ if (!dst->buf[0])
354+ return transfer_data_alloc(dst, src, flags);
355+
356+ if (src->hw_frames_ctx) {
357+ ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
358+
359+ ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
360+ if (ret < 0)
361+ return ret;
362+ } else if (dst->hw_frames_ctx) {
363+ ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
364+
365+ ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
366+ if (ret < 0)
367+ return ret;
368+ } else
369+ return AVERROR(ENOSYS);
370+
371+ return 0;
372+}
373+
374+int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
375+{
376+ AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
377+ int ret;
378+
379+ if (!ctx->internal->hw_type->frames_get_buffer)
380+ return AVERROR(ENOSYS);
381+
382+ if (!ctx->pool)
383+ return AVERROR(EINVAL);
384+
385+ frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
386+ if (!frame->hw_frames_ctx)
387+ return AVERROR(ENOMEM);
388+
389+ ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
390+ if (ret < 0) {
391+ av_buffer_unref(&frame->hw_frames_ctx);
392+ return ret;
393+ }
394+
395+ return 0;
396+}
libavutil/hwcontext.h+328−0
@@ -0,0 +1,328 @@
1+/*
2+ * This file is part of Libav.
3+ *
4+ * Libav 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+ * Libav 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 Libav; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#ifndef AVUTIL_HWCONTEXT_H
20+#define AVUTIL_HWCONTEXT_H
21+
22+#include "buffer.h"
23+#include "frame.h"
24+#include "log.h"
25+#include "pixfmt.h"
26+
27+enum AVHWDeviceType {
28+ AV_HWDEVICE_TYPE_VDPAU,
29+};
30+
31+typedef struct AVHWDeviceInternal AVHWDeviceInternal;
32+
33+/**
34+ * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
35+ * i.e. state that is not tied to a concrete processing configuration.
36+ * E.g., in an API that supports hardware-accelerated encoding and decoding,
37+ * this struct will (if possible) wrap the state that is common to both encoding
38+ * and decoding and from which specific instances of encoders or decoders can be
39+ * derived.
40+ *
41+ * This struct is reference-counted with the AVBuffer mechanism. The
42+ * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
43+ * points to the actual AVHWDeviceContext. Further objects derived from
44+ * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with
45+ * specific properties) will hold an internal reference to it. After all the
46+ * references are released, the AVHWDeviceContext itself will be freed,
47+ * optionally invoking a user-specified callback for uninitializing the hardware
48+ * state.
49+ */
50+typedef struct AVHWDeviceContext {
51+ /**
52+ * A class for logging. Set by av_hwdevice_ctx_alloc().
53+ */
54+ const AVClass *av_class;
55+
56+ /**
57+ * Private data used internally by libavutil. Must not be accessed in any
58+ * way by the caller.
59+ */
60+ AVHWDeviceInternal *internal;
61+
62+ /**
63+ * This field identifies the underlying API used for hardware access.
64+ *
65+ * This field is set when this struct is allocated and never changed
66+ * afterwards.
67+ */
68+ enum AVHWDeviceType type;
69+
70+ /**
71+ * The format-specific data, allocated and freed by libavutil along with
72+ * this context.
73+ *
74+ * Should be cast by the user to the format-specific context defined in the
75+ * corresponding header (hwcontext_*.h) and filled as described in the
76+ * documentation before calling av_hwdevice_ctx_init().
77+ *
78+ * After calling av_hwdevice_ctx_init() this struct should not be modified
79+ * by the caller.
80+ */
81+ void *hwctx;
82+
83+ /**
84+ * This field may be set by the caller before calling av_hwdevice_ctx_init().
85+ *
86+ * If non-NULL, this callback will be called when the last reference to
87+ * this context is unreferenced, immediately before it is freed.
88+ *
89+ * @note when other objects (e.g an AVHWFramesContext) are derived from this
90+ * struct, this callback will be invoked after all such child objects
91+ * are fully uninitialized and their respective destructors invoked.
92+ */
93+ void (*free)(struct AVHWDeviceContext *ctx);
94+
95+ /**
96+ * Arbitrary user data, to be used e.g. by the free() callback.
97+ */
98+ void *user_opaque;
99+} AVHWDeviceContext;
100+
101+typedef struct AVHWFramesInternal AVHWFramesInternal;
102+
103+/**
104+ * This struct describes a set or pool of "hardware" frames (i.e. those with
105+ * data not located in normal system memory). All the frames in the pool are
106+ * assumed to be allocated in the same way and interchangeable.
107+ *
108+ * This struct is reference-counted with the AVBuffer mechanism and tied to a
109+ * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
110+ * yields a reference, whose data field points to the actual AVHWFramesContext
111+ * struct.
112+ */
113+typedef struct AVHWFramesContext {
114+ /**
115+ * A class for logging.
116+ */
117+ const AVClass *av_class;
118+
119+ /**
120+ * Private data used internally by libavutil. Must not be accessed in any
121+ * way by the caller.
122+ */
123+ AVHWFramesInternal *internal;
124+
125+ /**
126+ * A reference to the parent AVHWDeviceContext. This reference is owned and
127+ * managed by the enclosing AVHWFramesContext, but the caller may derive
128+ * additional references from it.
129+ */
130+ AVBufferRef *device_ref;
131+
132+ /**
133+ * The parent AVHWDeviceContext. This is simply a pointer to
134+ * device_ref->data provided for convenience.
135+ *
136+ * Set by libavutil in av_hwframe_ctx_init().
137+ */
138+ AVHWDeviceContext *device_ctx;
139+
140+ /**
141+ * The format-specific data, allocated and freed automatically along with
142+ * this context.
143+ *
144+ * Should be cast by the user to the format-specific context defined in the
145+ * corresponding header (hwframe_*.h) and filled as described in the
146+ * documentation before calling av_hwframe_ctx_init().
147+ *
148+ * After any frames using this context are created, the contents of this
149+ * struct should not be modified by the caller.
150+ */
151+ void *hwctx;
152+
153+ /**
154+ * This field may be set by the caller before calling av_hwframe_ctx_init().
155+ *
156+ * If non-NULL, this callback will be called when the last reference to
157+ * this context is unreferenced, immediately before it is freed.
158+ */
159+ void (*free)(struct AVHWFramesContext *ctx);
160+
161+ /**
162+ * Arbitrary user data, to be used e.g. by the free() callback.
163+ */
164+ void *user_opaque;
165+
166+ /**
167+ * A pool from which the frames are allocated by av_hwframe_get_buffer().
168+ * This field may be set by the caller before calling av_hwframe_ctx_init().
169+ * The buffers returned by calling av_buffer_pool_get() on this pool must
170+ * have the properties described in the documentation in the correponding hw
171+ * type's header (hwcontext_*.h). The pool will be freed strictly before
172+ * this struct's free() callback is invoked.
173+ *
174+ * This field may be NULL, then libavutil will attempt to allocate a pool
175+ * internally. Note that certain device types enforce pools allocated at
176+ * fixed size (frame count), which cannot be extended dynamically. In such a
177+ * case, initial_pool_size must be set appropriately.
178+ */
179+ AVBufferPool *pool;
180+
181+ /**
182+ * Initial size of the frame pool. If a device type does not support
183+ * dynamically resizing the pool, then this is also the maximum pool size.
184+ *
185+ * May be set by the caller before calling av_hwframe_ctx_init(). Must be
186+ * set if pool is NULL and the device type does not support dynamic pools.
187+ */
188+ int initial_pool_size;
189+
190+ /**
191+ * The pixel format identifying the underlying HW surface type.
192+ *
193+ * Must be a hwaccel format, i.e. the corresponding descriptor must have the
194+ * AV_PIX_FMT_FLAG_HWACCEL flag set.
195+ *
196+ * Must be set by the user before calling av_hwframe_ctx_init().
197+ */
198+ enum AVPixelFormat format;
199+
200+ /**
201+ * The pixel format identifying the actual data layout of the hardware
202+ * frames.
203+ *
204+ * Must be set by the caller before calling av_hwframe_ctx_init().
205+ *
206+ * @note when the underlying API does not provide the exact data layout, but
207+ * only the colorspace/bit depth, this field should be set to the fully
208+ * planar version of that format (e.g. for 8-bit 420 YUV it should be
209+ * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else).
210+ */
211+ enum AVPixelFormat sw_format;
212+
213+ /**
214+ * The allocated dimensions of the frames in this pool.
215+ *
216+ * Must be set by the user before calling av_hwframe_ctx_init().
217+ */
218+ int width, height;
219+} AVHWFramesContext;
220+
221+/**
222+ * Allocate an AVHWDeviceContext for a given pixel format.
223+ *
224+ * @param format a hwaccel pixel format (AV_PIX_FMT_FLAG_HWACCEL must be set
225+ * on the corresponding format descriptor)
226+ * @return a reference to the newly created AVHWDeviceContext on success or NULL
227+ * on failure.
228+ */
229+AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type);
230+
231+/**
232+ * Finalize the device context before use. This function must be called after
233+ * the context is filled with all the required information and before it is
234+ * used in any way.
235+ *
236+ * @param ref a reference to the AVHWDeviceContext
237+ * @return 0 on success, a negative AVERROR code on failure
238+ */
239+int av_hwdevice_ctx_init(AVBufferRef *ref);
240+
241+/**
242+ * Allocate an AVHWFramesContext tied to a given device context.
243+ *
244+ * @param device_ctx a reference to a AVHWDeviceContext. This function will make
245+ * a new reference for internal use, the one passed to the
246+ * function remains owned by the caller.
247+ * @return a reference to the newly created AVHWFramesContext on success or NULL
248+ * on failure.
249+ */
250+AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx);
251+
252+/**
253+ * Finalize the context before use. This function must be called after the
254+ * context is filled with all the required information and before it is attached
255+ * to any frames.
256+ *
257+ * @param ref a reference to the AVHWFramesContext
258+ * @return 0 on success, a negative AVERROR code on failure
259+ */
260+int av_hwframe_ctx_init(AVBufferRef *ref);
261+
262+/**
263+ * Allocate a new frame attached to the given AVHWFramesContext.
264+ *
265+ * @param hwframe_ctx a reference to an AVHWFramesContext
266+ * @param frame an empty (freshly allocated or unreffed) frame to be filled with
267+ * newly allocated buffers.
268+ * @param flags currently unused, should be set to zero
269+ * @return 0 on success, a negative AVERROR code on failure
270+ */
271+int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);
272+
273+/**
274+ * Copy data to or from a hw surface. At least one of dst/src must have an
275+ * AVHWFramesContext attached.
276+ *
277+ * If src has an AVHWFramesContext attached, then the format of dst (if set)
278+ * must use one of the formats returned by av_hwframe_transfer_get_formats(src,
279+ * AV_HWFRAME_TRANSFER_DIRECTION_FROM).
280+ * If dst has an AVHWFramesContext attached, then the format of src must use one
281+ * of the formats returned by av_hwframe_transfer_get_formats(dst,
282+ * AV_HWFRAME_TRANSFER_DIRECTION_TO)
283+ *
284+ * dst may be "clean" (i.e. with data/buf pointers unset), in which case the
285+ * data buffers will be allocated by this function using av_frame_get_buffer().
286+ * If dst->format is set, then this format will be used, otherwise (when
287+ * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen.
288+ *
289+ * @param dst the destination frame. dst is not touched on failure.
290+ * @param src the source frame.
291+ * @param flags currently unused, should be set to zero
292+ * @return 0 on success, a negative AVERROR error code on failure.
293+ */
294+int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags);
295+
296+enum AVHWFrameTransferDirection {
297+ /**
298+ * Transfer the data from the queried hw frame.
299+ */
300+ AV_HWFRAME_TRANSFER_DIRECTION_FROM,
301+
302+ /**
303+ * Transfer the data to the queried hw frame.
304+ */
305+ AV_HWFRAME_TRANSFER_DIRECTION_TO,
306+};
307+
308+/**
309+ * Get a list of possible source or target formats usable in
310+ * av_hwframe_transfer_data().
311+ *
312+ * @param hwframe_ctx the frame context to obtain the information for
313+ * @param dir the direction of the transfer
314+ * @param formats the pointer to the output format list will be written here.
315+ * The list is terminated with AV_PIX_FMT_NONE and must be freed
316+ * by the caller when no longer needed using av_free().
317+ * If this function returns successfully, the format list will
318+ * have at least one item (not counting the terminator).
319+ * On failure, the contents of this pointer are unspecified.
320+ * @param flags currently unused, should be set to zero
321+ * @return 0 on success, a negative AVERROR code on failure.
322+ */
323+int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx,
324+ enum AVHWFrameTransferDirection dir,
325+ enum AVPixelFormat **formats, int flags);
326+
327+
328+#endif /* AVUTIL_HWCONTEXT_H */
libavutil/hwcontext_internal.h+89−0
@@ -0,0 +1,89 @@
1+/*
2+ * This file is part of Libav.
3+ *
4+ * Libav 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+ * Libav 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 Libav; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#ifndef AVUTIL_HWCONTEXT_INTERNAL_H
20+#define AVUTIL_HWCONTEXT_INTERNAL_H
21+
22+#include <stddef.h>
23+
24+#include "buffer.h"
25+#include "hwcontext.h"
26+#include "frame.h"
27+#include "pixfmt.h"
28+
29+typedef struct HWContextType {
30+ enum AVHWDeviceType type;
31+ const char *name;
32+
33+ /**
34+ * An array of pixel formats supported by the AVHWFramesContext instances
35+ * Terminated by AV_PIX_FMT_NONE.
36+ */
37+ const enum AVPixelFormat *pix_fmts;
38+
39+ /**
40+ * size of the public hardware-specific context,
41+ * i.e. AVHWDeviceContext.hwctx
42+ */
43+ size_t device_hwctx_size;
44+ /**
45+ * size of the private data, i.e.
46+ * AVHWDeviceInternal.priv
47+ */
48+ size_t device_priv_size;
49+
50+ /**
51+ * size of the public frame pool hardware-specific context,
52+ * i.e. AVHWFramesContext.hwctx
53+ */
54+ size_t frames_hwctx_size;
55+ /**
56+ * size of the private data, i.e.
57+ * AVHWFramesInternal.priv
58+ */
59+ size_t frames_priv_size;
60+
61+ int (*device_init)(AVHWDeviceContext *ctx);
62+ void (*device_uninit)(AVHWDeviceContext *ctx);
63+
64+ int (*frames_init)(AVHWFramesContext *ctx);
65+ void (*frames_uninit)(AVHWFramesContext *ctx);
66+
67+ int (*frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame);
68+ int (*transfer_get_formats)(AVHWFramesContext *ctx,
69+ enum AVHWFrameTransferDirection dir,
70+ enum AVPixelFormat **formats);
71+ int (*transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst,
72+ const AVFrame *src);
73+ int (*transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst,
74+ const AVFrame *src);
75+} HWContextType;
76+
77+struct AVHWDeviceInternal {
78+ const HWContextType *hw_type;
79+ void *priv;
80+};
81+
82+struct AVHWFramesInternal {
83+ const HWContextType *hw_type;
84+ void *priv;
85+
86+ AVBufferPool *pool_internal;
87+};
88+
89+#endif /* AVUTIL_HWCONTEXT_INTERNAL_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t