ge2d: Add the function of using ge2d hardware to rotate [1/1]
PD#SWPL-40533
Problem:
use ge2d support rotation
Solution:
Add the function of using ge2d hardware to rotate
Verify:
W400 + buildroot
Change-Id: If4f75f14f8593d5ed3cb2e647aeab6480b9dd909
Signed-off-by: bo.li6 <bo.li6@amlogic.com>
diff --git a/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d.c b/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d.c
new file mode 100644
index 0000000..a26a1af
--- /dev/null
+++ b/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d.c
@@ -0,0 +1,37 @@
+/*
+ * gst_ge2d.c
+ *
+ * Created on: 2020年11月3日
+ * Author: tao
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "gst_ge2d_flip.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ gboolean ret = FALSE;
+ ret |= gst_element_register(plugin, "ge2d_flip",
+ GST_RANK_PRIMARY,
+ GST_TYPE_GE2D_FLIP);
+ return ret;
+}
+
+#define PACKAGE "gst-aml-drm-plugins"
+#define GST_PACKAGE_ORIGIN "http://amlogic.com"
+
+GST_PLUGIN_DEFINE (
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ ge2d,
+ "Amlogic plugin for ge2d",
+ plugin_init,
+ VERSION,
+ "LGPL",
+ PACKAGE_NAME,
+ GST_PACKAGE_ORIGIN
+)
diff --git a/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d_flip.c b/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d_flip.c
new file mode 100644
index 0000000..38464b0
--- /dev/null
+++ b/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d_flip.c
@@ -0,0 +1,436 @@
+/*
+ * gst_ge2d_flip.c
+ *
+ * Created on: 2020年11月3日
+ * Author: tao
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gst/allocators/gstdrmallocator.h>
+#include <gst/gstdrmbufferpool.h>
+#include "gst_ge2d_flip.h"
+
+enum
+{
+ PROP_0,
+ PROP_METHOD,
+ PROP_SECURE
+};
+#define ALIGN_PAD(x, y) (((x) + ((y)-1)) & (~((y)-1)))
+
+GST_DEBUG_CATEGORY_STATIC(gst_ge2d_flip_debug);
+#define GST_CAT_DEFAULT gst_ge2d_flip_debug
+
+#define VIDEO_CAPS "{ NV12, NV21 }"
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS(
+ GST_VIDEO_CAPS_MAKE(VIDEO_CAPS)));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE("src",
+ GST_PAD_SRC,
+ GST_PAD_SOMETIMES,
+ GST_STATIC_CAPS(
+ GST_VIDEO_CAPS_MAKE(VIDEO_CAPS)));
+
+#define gst_ge2d_flip_parent_class parent_class
+G_DEFINE_TYPE(GstGe2dFlip, gst_ge2d_flip, GST_TYPE_BASE_TRANSFORM);
+
+#define GST_TYPE_GE2D_FLIP_METHOD (gst_ge2d_flip_method_get_type())
+
+static const GEnumValue ge2d_flip_methods[] = {
+ {GST_VIDEO_ORIENTATION_IDENTITY, "Identity (no rotation)", "none"},
+ {GST_VIDEO_ORIENTATION_90R, "Rotate clockwise 90 degrees", "clockwise"},
+ {GST_VIDEO_ORIENTATION_180, "Rotate 180 degrees", "rotate-180"},
+ {GST_VIDEO_ORIENTATION_90L, "Rotate counter-clockwise 90 degrees",
+ "counterclockwise"},
+ {GST_VIDEO_ORIENTATION_HORIZ, "Flip horizontally", "horizontal-flip"},
+ {GST_VIDEO_ORIENTATION_VERT, "Flip vertically", "vertical-flip"},
+ {0, NULL, NULL},
+};
+
+static GType
+gst_ge2d_flip_method_get_type(void)
+{
+ static GType ge2d_flip_method_type = 0;
+
+ if (!ge2d_flip_method_type)
+ {
+ ge2d_flip_method_type = g_enum_register_static("GstGe2dFlipMethod",
+ ge2d_flip_methods);
+ }
+ return ge2d_flip_method_type;
+}
+
+static void
+gst_ge2d_flip_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(object);
+
+ switch (prop_id)
+ {
+ case PROP_METHOD:
+ GST_OBJECT_LOCK(plugin);
+ plugin->method = g_value_get_enum(value);
+ GST_OBJECT_UNLOCK(plugin);
+ break;
+ case PROP_SECURE:
+ GST_OBJECT_LOCK(plugin);
+ plugin->secure = g_value_get_boolean(value);
+ GST_OBJECT_UNLOCK(plugin);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_ge2d_flip_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(object);
+
+ switch (prop_id)
+ {
+ case PROP_METHOD:
+ GST_OBJECT_LOCK(plugin);
+ g_value_set_enum(value, plugin->method);
+ GST_OBJECT_UNLOCK(plugin);
+ break;
+ case PROP_SECURE:
+ GST_OBJECT_LOCK(plugin);
+ g_value_set_boolean(value, plugin->secure);
+ GST_OBJECT_UNLOCK(plugin);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gst_ge2d_flip_start(GstBaseTransform *trans)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+
+ int ret = 0;
+ plugin->pge2dinfo = &(plugin->amlge2d.ge2dinfo);
+
+ memset(&plugin->amlge2d, 0, sizeof(aml_ge2d_t));
+
+ /* ge2d init */
+ ret = aml_ge2d_init(&plugin->amlge2d);
+ if (ret < 0)
+ {
+ GST_ERROR("ge2d init failed");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+gst_ge2d_flip_stop(GstBaseTransform *trans)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+
+ //ge2d release exit
+ aml_ge2d_exit(&plugin->amlge2d);
+ return TRUE;
+}
+
+static gboolean
+gst_ge2d_flip_set_caps(GstBaseTransform *trans, GstCaps *incaps, GstCaps *outcaps)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+ if (!gst_video_info_from_caps(&plugin->in_info, incaps))
+ return FALSE;
+ if (!gst_video_info_from_caps(&plugin->out_info, outcaps))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+gst_ge2d_flip_propose_allocation(GstBaseTransform *trans, GstQuery *decide_query,
+ GstQuery *query)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+ GstCaps *caps;
+ GstBufferPool *pool = NULL;
+ gboolean need_pool;
+
+ gst_query_parse_allocation(query, &caps, &need_pool);
+
+ if (need_pool)
+ {
+ pool = gst_drm_bufferpool_new(plugin->secure, GST_DRM_BUFFERPOOL_TYPE_VIDEO_PLANE);
+ }
+
+ gst_query_add_allocation_pool(query, pool, 0, 2, 0);
+ if (pool)
+ g_object_unref(pool);
+
+ gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
+ return TRUE;
+}
+
+static gboolean
+gst_ge2d_flip_decide_allocation(GstBaseTransform *trans, GstQuery *query)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+ GstCaps *caps;
+ GstBufferPool *pool = NULL;
+ GstStructure *config;
+ guint size, min, max;
+
+ if (gst_query_get_n_allocation_pools(query) > 0)
+ {
+ gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min, &max);
+ if (pool)
+ g_object_unref(pool);
+ }
+ gst_query_parse_allocation(query, &caps, NULL);
+
+ pool = gst_drm_bufferpool_new(plugin->secure, GST_DRM_BUFFERPOOL_TYPE_VIDEO_PLANE);
+ if (pool)
+ {
+ config = gst_buffer_pool_get_config(pool);
+ gst_buffer_pool_config_set_params(config, caps, size, min, max);
+ gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META);
+ gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
+ gst_buffer_pool_set_config(pool, config);
+ gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max);
+ gst_object_unref(pool);
+ }
+ if (!gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL))
+ {
+ gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
+ };
+
+ return TRUE;
+}
+
+static GstCaps *
+gst_ge2d_flip_transform_caps(GstBaseTransform *trans, GstPadDirection direction,
+ GstCaps *caps, GstCaps *filter)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+ GstCaps *ret = NULL;
+ gint width, height, i;
+
+ ret = gst_caps_copy(caps);
+
+ GST_DEBUG_OBJECT(plugin, "transform_caps direction:%d caps:%" GST_PTR_FORMAT, direction, caps);
+
+ for (i = 0; i < gst_caps_get_size(ret); i++)
+ {
+ GstStructure *structure = gst_caps_get_structure(ret, i);
+ gint par_n, par_d;
+
+ if (gst_structure_get_int(structure, "width", &width) &&
+ gst_structure_get_int(structure, "height", &height))
+ {
+ switch (plugin->method)
+ {
+ case GST_VIDEO_ORIENTATION_90R:
+ case GST_VIDEO_ORIENTATION_90L:
+ gst_structure_set(structure, "width", G_TYPE_INT, height,
+ "height", G_TYPE_INT, width, NULL);
+ if (gst_structure_get_fraction(structure, "pixel-aspect-ratio",
+ &par_n, &par_d))
+ {
+ if (par_n != 1 || par_d != 1)
+ {
+ GValue val = {
+ 0,
+ };
+
+ g_value_init(&val, GST_TYPE_FRACTION);
+ gst_value_set_fraction(&val, par_d, par_n);
+ gst_structure_set_value(structure, "pixel-aspect-ratio", &val);
+ g_value_unset(&val);
+ }
+ }
+ break;
+ case GST_VIDEO_ORIENTATION_IDENTITY:
+ case GST_VIDEO_ORIENTATION_180:
+ case GST_VIDEO_ORIENTATION_HORIZ:
+ case GST_VIDEO_ORIENTATION_VERT:
+ gst_structure_set(structure, "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height, NULL);
+
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+ }
+ GST_DEBUG_OBJECT(plugin, "transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, ret);
+
+ if (filter)
+ {
+ GstCaps *intersection;
+
+ GST_DEBUG_OBJECT(plugin, "Using filter caps %" GST_PTR_FORMAT, filter);
+ intersection =
+ gst_caps_intersect_full(filter, ret, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref(ret);
+ ret = intersection;
+ GST_DEBUG_OBJECT(plugin, "Intersection %" GST_PTR_FORMAT, ret);
+ }
+
+ return ret;
+}
+
+static GE2D_ROTATION pluginOriMethod2ge2d(GstVideoOrientationMethod pluginRotation)
+{
+ GE2D_ROTATION ge2dratation;
+ switch (pluginRotation)
+ {
+ case GST_VIDEO_ORIENTATION_90R:
+ ge2dratation = GE2D_ROTATION_90;
+ break;
+ case GST_VIDEO_ORIENTATION_180:
+ ge2dratation = GE2D_ROTATION_180;
+ break;
+ case GST_VIDEO_ORIENTATION_90L:
+ ge2dratation = GE2D_ROTATION_270;
+ break;
+ default:
+ ge2dratation = GE2D_ROTATION_0;
+ break;
+ }
+ return ge2dratation;
+}
+
+static GstFlowReturn
+gst_ge2d_flip_transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf)
+{
+ GstGe2dFlip *plugin = GST_GE2D_FLIP(trans);
+ GstFlowReturn ret = GST_FLOW_ERROR;
+ GstMemory *mem;
+ guint inbuf_n, outbuf_n;
+ int i;
+ int plane = GST_VIDEO_INFO_N_PLANES(&plugin->in_info);
+
+ aml_ge2d_info_t *pge2dinfo = plugin->pge2dinfo;
+
+ inbuf_n = gst_buffer_n_memory(inbuf);
+ outbuf_n = gst_buffer_n_memory(outbuf);
+
+ g_return_val_if_fail(inbuf_n == plane, ret);
+ g_return_val_if_fail(outbuf_n == plane, ret);
+
+ for (i = 0; i < plane; i++)
+ {
+ mem = gst_buffer_peek_memory(inbuf, i);
+ g_return_val_if_fail(gst_is_drm_memory(mem), ret);
+ pge2dinfo->src_info[0].shared_fd[i] = gst_fd_memory_get_fd(mem); /* input memory fd array, related to xx.plane_number */
+
+ mem = gst_buffer_peek_memory(outbuf, i);
+ g_return_val_if_fail(gst_is_drm_memory(mem), ret);
+ pge2dinfo->dst_info.shared_fd[i] = gst_fd_memory_get_fd(mem);
+ }
+
+ pge2dinfo->mem_sec = 1;
+
+ g_return_val_if_fail(inbuf_n == outbuf_n && inbuf_n > 0, ret);
+
+ pge2dinfo->src_info[0].memtype = GE2D_CANVAS_ALLOC;
+ pge2dinfo->src_info[0].mem_alloc_type = AML_GE2D_MEM_DMABUF;
+ pge2dinfo->src_info[0].plane_number = plane; /* When allocating memory, it is a continuous block or separate multiple blocks */
+ pge2dinfo->src_info[0].canvas_w = ALIGN_PAD(GST_VIDEO_INFO_WIDTH(&plugin->in_info), 64); /* input width */
+ pge2dinfo->src_info[0].canvas_h = ALIGN_PAD(GST_VIDEO_INFO_HEIGHT(&plugin->in_info), 64); /* input height */
+ pge2dinfo->src_info[0].format = PIXEL_FORMAT_YCbCr_420_SP_NV12;
+ pge2dinfo->src_info[0].rect.x = 0; /* input process area x */
+ pge2dinfo->src_info[0].rect.y = 0; /* input process area y */
+ pge2dinfo->src_info[0].rect.w = GST_VIDEO_INFO_WIDTH(&plugin->in_info); /* input process area w */
+ pge2dinfo->src_info[0].rect.h = GST_VIDEO_INFO_HEIGHT(&plugin->in_info); /* input process area h */
+ pge2dinfo->src_info[0].plane_alpha = 0xFF; /* global plane alpha*/
+
+ pge2dinfo->dst_info.memtype = GE2D_CANVAS_ALLOC;
+ pge2dinfo->dst_info.mem_alloc_type = AML_GE2D_MEM_DMABUF;
+ pge2dinfo->dst_info.plane_number = plane; /* When allocating memory, it is a continuous block or separate multiple blocks */
+ pge2dinfo->dst_info.canvas_w = ALIGN_PAD(GST_VIDEO_INFO_WIDTH(&plugin->out_info), 64); /* output width */
+ pge2dinfo->dst_info.canvas_h = ALIGN_PAD(GST_VIDEO_INFO_HEIGHT(&plugin->out_info), 64); /* output width */
+ pge2dinfo->dst_info.format = PIXEL_FORMAT_YCbCr_420_SP_NV12;
+ pge2dinfo->dst_info.rect.x = 0; /* output process area x */
+ pge2dinfo->dst_info.rect.y = 0; /* output process area y */
+ pge2dinfo->dst_info.rect.w = GST_VIDEO_INFO_WIDTH(&plugin->out_info); /* output process area w */
+ pge2dinfo->dst_info.rect.h = GST_VIDEO_INFO_HEIGHT(&plugin->out_info); /* output process area h */
+ pge2dinfo->dst_info.plane_alpha = 0xFF; /* global plane alpha*/
+
+ pge2dinfo->dst_info.rotation = pluginOriMethod2ge2d(plugin->method);
+ pge2dinfo->ge2d_op = AML_GE2D_STRETCHBLIT;
+
+ //ge2d begin rotation
+ ret = aml_ge2d_process(pge2dinfo);
+
+ if (ret < 0){
+ GST_ERROR("ge2d process failed, %s (%d)", __func__, __LINE__);
+ goto beach;
+ }
+
+ ret = GST_FLOW_OK;
+beach:
+ GST_ERROR("%s %d", __FUNCTION__, __LINE__);
+ return ret;
+}
+
+static void
+gst_ge2d_flip_class_init(GstGe2dFlipClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *)klass;
+ GstElementClass *element_class = (GstElementClass *)klass;
+ GstBaseTransformClass *base_class = GST_BASE_TRANSFORM_CLASS(klass);
+
+ GST_DEBUG_CATEGORY_INIT(gst_ge2d_flip_debug, "ge2d_flip", 0, "GE2D Flip");
+
+ gobject_class->set_property = gst_ge2d_flip_set_property;
+ gobject_class->get_property = gst_ge2d_flip_get_property;
+
+ base_class->start = GST_DEBUG_FUNCPTR(gst_ge2d_flip_start);
+ base_class->stop = GST_DEBUG_FUNCPTR(gst_ge2d_flip_stop);
+ base_class->set_caps = GST_DEBUG_FUNCPTR(gst_ge2d_flip_set_caps);
+ base_class->propose_allocation = GST_DEBUG_FUNCPTR(gst_ge2d_flip_propose_allocation);
+ base_class->decide_allocation = GST_DEBUG_FUNCPTR(gst_ge2d_flip_decide_allocation);
+ base_class->transform_caps = GST_DEBUG_FUNCPTR(gst_ge2d_flip_transform_caps);
+ base_class->transform = GST_DEBUG_FUNCPTR(gst_ge2d_flip_transform);
+ base_class->passthrough_on_same_caps = FALSE;
+ base_class->transform_ip_on_passthrough = FALSE;
+
+ gst_element_class_add_pad_template(element_class,
+ gst_static_pad_template_get(&sinktemplate));
+ gst_element_class_add_pad_template(element_class,
+ gst_static_pad_template_get(&srctemplate));
+
+ g_object_class_install_property(gobject_class, PROP_METHOD,
+ g_param_spec_enum("method", "method",
+ "method (deprecated, use video-direction instead)",
+ GST_TYPE_GE2D_FLIP_METHOD, GST_VIDEO_ORIENTATION_IDENTITY,
+ GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property(gobject_class, PROP_SECURE,
+ g_param_spec_boolean("secure", "Use Secure",
+ "Use Secure DRM based memory for allocation",
+ FALSE, G_PARAM_WRITABLE));
+
+ gst_element_class_set_details_simple(element_class,
+ "Amlogic GE2D Plugin",
+ "Filter/Effect/Video",
+ "GE2D Plugin",
+ "mm@amlogic.com");
+}
+
+static void
+gst_ge2d_flip_init(GstGe2dFlip *plugin)
+{
+ GstBaseTransform *base = GST_BASE_TRANSFORM(plugin);
+ gst_base_transform_set_passthrough(base, FALSE);
+ gst_base_transform_set_in_place(base, FALSE);
+
+ plugin->secure = FALSE;
+}
diff --git a/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d_flip.h b/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d_flip.h
new file mode 100644
index 0000000..a4f5fc1
--- /dev/null
+++ b/gst-aml-drm-plugins-1.0/src/ge2d/gst_ge2d_flip.h
@@ -0,0 +1,60 @@
+/*
+ * gst_ge2d_flip.h
+ *
+ * Created on: 2020年11月3日
+ * Author: tao
+ */
+
+#ifndef _GST_GE2D_FLIP_H_
+#define _GST_GE2D_FLIP_H_
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/video/video.h>
+#include <aml_ge2d.h>
+
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_GE2D_FLIP \
+ (gst_ge2d_flip_get_type())
+#define GST_GE2D_FLIP(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GE2D_FLIP,GstGe2dFlip))
+#define GST_GE2D_FLIP_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GE2D_FLIP,GstGe2dFlipClass))
+ #define GST_GE2D_FLIP_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_GE2D_FLIP,GstGe2dFlipClass))
+#define GST_IS_GE2D_FLIP(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GE2D_FLIP))
+#define GST_IS_GE2D_FLIP_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GE2D_FLIP))
+
+
+typedef struct _GstGe2dFlip GstGe2dFlip;
+typedef struct _GstGe2dFlipClass GstGe2dFlipClass;
+
+
+struct _GstGe2dFlip
+{
+ GstBaseTransform videofilter;
+
+ GstVideoOrientationMethod method;
+ gboolean secure;
+ GstVideoInfo in_info;
+ GstVideoInfo out_info;
+
+ int ret;
+ aml_ge2d_info_t *pge2dinfo;
+ aml_ge2d_t amlge2d;
+};
+
+struct _GstGe2dFlipClass {
+ GstBaseTransformClass parent_class;
+};
+
+
+GType gst_ge2d_flip_get_type (void);
+
+G_END_DECLS
+
+#endif /* _GST_GE2D_FLIP_H_ */