---
 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

Reply via email to