---
libavutil/Makefile | 2 +
libavutil/frame.c | 11 +++
libavutil/frame.h | 2 +
libavutil/hwframe.c | 202 +++++++++++++++++++++++++++++++++++++++++++
libavutil/hwframe.h | 97 +++++++++++++++++++++
libavutil/hwframe_internal.h | 54 ++++++++++++
6 files changed, 368 insertions(+)
create mode 100644 libavutil/hwframe.c
create mode 100644 libavutil/hwframe.h
create mode 100644 libavutil/hwframe_internal.h
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 17bd57e..9dd6a78 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -23,6 +23,7 @@ HEADERS = adler32.h
\
file.h \
frame.h \
hmac.h \
+ hwframe.h \
imgutils.h \
intfloat.h \
intreadwrite.h \
@@ -78,6 +79,7 @@ OBJS = adler32.o
\
float_dsp.o \
frame.o \
hmac.o \
+ hwframe.o \
imgutils.o \
intmath.o \
lfg.o \
diff --git a/libavutil/frame.c b/libavutil/frame.c
index e4f6ab3..6e21942 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -251,6 +251,14 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
}
}
+ if (src->hw_ctx) {
+ dst->hw_ctx = av_buffer_ref(src->hw_ctx);
+ if (!dst->hw_ctx) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ }
+
/* duplicate extended data */
if (src->extended_data != src->data) {
int ch = av_get_channel_layout_nb_channels(src->channel_layout);
@@ -303,6 +311,9 @@ void av_frame_unref(AVFrame *frame)
for (i = 0; i < frame->nb_extended_buf; i++)
av_buffer_unref(&frame->extended_buf[i]);
av_freep(&frame->extended_buf);
+
+ av_buffer_unref(&frame->hw_ctx);
+
get_frame_defaults(frame);
}
diff --git a/libavutil/frame.h b/libavutil/frame.h
index c723cb0..14dcabe 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -354,6 +354,8 @@ typedef struct AVFrame {
enum AVColorSpace colorspace;
enum AVChromaLocation chroma_location;
+
+ AVBufferRef *hw_ctx;
} AVFrame;
/**
diff --git a/libavutil/hwframe.c b/libavutil/hwframe.c
new file mode 100644
index 0000000..15fb32c
--- /dev/null
+++ b/libavutil/hwframe.c
@@ -0,0 +1,202 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "buffer.h"
+#include "common.h"
+#include "hwframe.h"
+#include "hwframe_internal.h"
+#include "log.h"
+#include "mem.h"
+
+static const HWFrameType *hw_table[] = {
+};
+
+static const AVClass hwframe_ctx_class = {
+ .class_name = "AVHWFramesContext",
+ .item_name = av_default_item_name,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static void hwframe_ctx_free(void *opaque, uint8_t *data)
+{
+ AVHWFramesContext *ctx = (AVHWFramesContext*)data;
+
+ /* uninit might still want access the hw context and the user
+ * free() callback might destroy it, so uninit has to be called first */
+ if (ctx->internal->hw_type->uninit)
+ ctx->internal->hw_type->uninit(ctx);
+
+ if (ctx->free)
+ ctx->free(ctx);
+
+ av_freep(&ctx->hwctx);
+ av_freep(&ctx->internal->priv);
+ av_freep(&ctx->internal);
+ av_freep(&ctx);
+}
+
+AVBufferRef *av_hwframe_ctx_alloc(enum AVPixelFormat format)
+{
+ AVHWFramesContext *ctx;
+ AVBufferRef *buf;
+ const HWFrameType *hw_type = NULL;
+ int i;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(hw_table); i++) {
+ if (hw_table[i]->format == format) {
+ hw_type = hw_table[i];
+ break;
+ }
+ }
+ if (!hw_type)
+ return NULL;
+
+ ctx = av_mallocz(sizeof(*ctx));
+ if (!ctx)
+ return NULL;
+
+ ctx->internal = av_mallocz(sizeof(*ctx->internal));
+ if (!ctx->internal)
+ goto fail;
+
+ if (hw_type->priv_size) {
+ ctx->internal->priv = av_mallocz(hw_type->priv_size);
+ if (!ctx->internal->priv)
+ goto fail;
+ }
+
+ if (hw_type->hwctx_size) {
+ ctx->hwctx = av_mallocz(hw_type->hwctx_size);
+ if (!ctx->hwctx)
+ goto fail;
+ }
+
+ buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
+ hwframe_ctx_free, NULL,
+ AV_BUFFER_FLAG_READONLY);
+ if (!buf)
+ goto fail;
+
+ ctx->format = format;
+ ctx->av_class = &hwframe_ctx_class;
+
+ ctx->internal->hw_type = hw_type;
+
+ return buf;
+
+fail:
+ if (ctx->internal)
+ av_freep(&ctx->internal->priv);
+ av_freep(&ctx->internal);
+ av_freep(&ctx->hwctx);
+ av_freep(&ctx);
+ return NULL;
+}
+
+int av_hwframe_ctx_init(AVBufferRef *ref)
+{
+ AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
+ int ret;
+
+ if (ctx->internal->hw_type->init) {
+ ret = ctx->internal->hw_type->init(ctx);
+ if (ret < 0)
+ goto fail;
+ }
+
+ return 0;
+fail:
+ if (ctx->internal->hw_type->uninit)
+ ctx->internal->hw_type->uninit(ctx);
+ return ret;
+}
+
+int av_hwframe_get_target_formats(const AVFrame *frame, enum AVPixelFormat
**formats)
+{
+ AVHWFramesContext *ctx;
+
+ if (!frame->hw_ctx)
+ return AVERROR(EINVAL);
+
+ ctx = (AVHWFramesContext*)frame->hw_ctx->data;
+
+ if (!ctx->internal->hw_type->get_target_formats)
+ return AVERROR(ENOSYS);
+
+ return ctx->internal->hw_type->get_target_formats(ctx, frame, formats);
+}
+
+static int retrieve_data_alloc(AVFrame *dst, const AVFrame *src)
+{
+ AVFrame *frame_tmp;
+ int ret = 0;
+
+ frame_tmp = av_frame_alloc();
+ if (!frame_tmp)
+ return AVERROR(ENOMEM);
+
+ /* if the format is set, use that
+ * otherwise pick the first supported one */
+ if (dst->format >= 0) {
+ frame_tmp->format = dst->format;
+ } else {
+ enum AVPixelFormat *formats;
+
+ ret = av_hwframe_get_target_formats(src, &formats);
+ if (ret < 0)
+ goto fail;
+ frame_tmp->format = formats[0];
+ av_freep(&formats);
+ }
+ frame_tmp->width = src->width;
+ frame_tmp->height = src->height;
+
+ ret = av_frame_get_buffer(frame_tmp, 32);
+ if (ret < 0)
+ goto fail;
+
+ ret = av_hwframe_retrieve_data(frame_tmp, src);
+ if (ret < 0)
+ goto fail;
+
+ av_frame_move_ref(dst, frame_tmp);
+
+fail:
+ av_frame_free(&frame_tmp);
+ return ret;
+}
+
+int av_hwframe_retrieve_data(AVFrame *dst, const AVFrame *src)
+{
+ AVHWFramesContext *ctx;
+
+ if (!dst->buf[0])
+ return retrieve_data_alloc(dst, src);
+
+ if (!src->hw_ctx)
+ return AVERROR(EINVAL);
+
+ ctx = (AVHWFramesContext*)src->hw_ctx->data;
+
+ if (!ctx->internal->hw_type->retrieve_data)
+ return AVERROR(ENOSYS);
+
+ return ctx->internal->hw_type->retrieve_data(ctx, dst, src);
+}
diff --git a/libavutil/hwframe.h b/libavutil/hwframe.h
new file mode 100644
index 0000000..3e33aa5
--- /dev/null
+++ b/libavutil/hwframe.h
@@ -0,0 +1,97 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWFRAME_H
+#define AVUTIL_HWFRAME_H
+
+#include "buffer.h"
+#include "frame.h"
+#include "log.h"
+#include "pixfmt.h"
+
+typedef struct AVHWFramesInternal AVHWFramesInternal;
+
+/**
+ * This struct aggregates any state necessary for handling "hardware" frames
+ * (i.e. those with data not located in normal system memory).
+ *
+ * This struct is reference-counted with the AVBuffer mechanism. The
+ * av_hwframe_ctx_alloc() constructor yields a reference, whose data field
+ * points to the actual AVHWFramesContext struct.
+ */
+typedef struct AVHWFramesContext {
+ /**
+ * A class for logging.
+ */
+ const AVClass *av_class;
+
+ /**
+ * The pixel format identifying the underlying HW surface type.
+ *
+ * Must be a hwaccel format, i.e. the corresponding descriptor must have
the
+ * AV_PIX_FMT_FLAG_HWACCEL flag set.
+ *
+ * This field is set when this struct is allocated and never changed
+ * afterwards.
+ */
+ enum AVPixelFormat format;
+
+ /**
+ * The format-specific data, allocated and freed automatically along with
+ * this context.
+ *
+ * Should be cast by the user to the format-specific context defined in the
+ * corresponding header (hwframe_*.h) and filled as described in the
+ * documentation before creating any frames using this context.
+ *
+ * After any frames using this context are created, the contents of this
+ * struct should not be modified by the caller.
+ */
+ void *hwctx;
+
+ /**
+ * Private data used internally by libavutil. Must not be accessed in any
+ * way by the caller.
+ */
+ AVHWFramesInternal *internal;
+
+ /**
+ * This field may be set by the caller immediately after allocating this
+ * context.
+ *
+ * If non-NULL, this callback will be called when the last reference to
+ * this context is unreferences, immediately before it is freed.
+ */
+ void (*free)(struct AVHWFramesContext *ctx);
+
+ /**
+ * Arbitrary user data, to be used e.g. by the free() callback.
+ */
+ void *user_opaque;
+} AVHWFramesContext;
+
+AVBufferRef *av_hwframe_ctx_alloc(enum AVPixelFormat format);
+
+int av_hwframe_ctx_init(AVBufferRef *ref);
+
+int av_hwframe_get_target_formats(const AVFrame *frame,
+ enum AVPixelFormat **formats);
+
+int av_hwframe_retrieve_data(AVFrame *dst, const AVFrame *src);
+
+#endif /* AVUTIL_HWFRAME_H */
diff --git a/libavutil/hwframe_internal.h b/libavutil/hwframe_internal.h
new file mode 100644
index 0000000..cae6ef9
--- /dev/null
+++ b/libavutil/hwframe_internal.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWFRAME_INTERNAL_H
+#define AVUTIL_HWFRAME_INTERNAL_H
+
+#include <stddef.h>
+
+#include "hwframe.h"
+#include "frame.h"
+#include "pixfmt.h"
+
+typedef struct HWFrameType {
+ enum AVPixelFormat format;
+ const char *name;
+ /**
+ * size of the public hardware-specific context,
+ * i.e. AVHWFramesContext.hwctx
+ */
+ size_t hwctx_size;
+ /**
+ * size of the private data, i.e.
+ * AVHWFramesInternal.priv
+ */
+ size_t priv_size;
+ int (*init)(AVHWFramesContext *ctx);
+ void (*uninit)(AVHWFramesContext *ctx);
+ int (*get_target_formats)(AVHWFramesContext *ctx, const
AVFrame *frame,
+ enum AVPixelFormat **formats);
+ int (*retrieve_data)(AVHWFramesContext *ctx, AVFrame *dst,
+ const AVFrame *src);
+} HWFrameType;
+
+struct AVHWFramesInternal {
+ const HWFrameType *hw_type;
+ void *priv;
+};
+
+#endif /* AVUTIL_HWFRAME_INTERNAL_H */
--
2.0.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel