videosink: CB1 videosink support ge2d rotation [1/1]
PD#SWPL-164873
Problem:
videosink support ge2d rotation
Solution:
videosink support ge2d rotation
Verify:
AH212
Change-Id: Idf255b8c8ea8f63e5999f1575706e5f7057cb77a
Signed-off-by: kaiqiang.xiang <kaiqiang.xiang@amlogic.com>
diff --git a/src/Makefile.am b/src/Makefile.am
index 820c7f6..8aa2125 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,13 +14,13 @@
##############################################################################
# sources used to compile this plug-in
-libgstamlvideosink_la_SOURCES = gstamlvideosink.c
+libgstamlvideosink_la_SOURCES = gstamlvideosink.c ge2drotation.c
# compiler and linker flags used to compile this plugin, set in configure.ac
libgstamlvideosink_la_CFLAGS = $(GST_CFLAGS)
libgstamlvideosink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstamlvideosink_la_LIBADD = $(GST_LIBS)
-libgstamlvideosink_la_LIBADD += -L$(TARGET_DIR)/usr/lib -lmediahal_videorender
+libgstamlvideosink_la_LIBADD += -L$(TARGET_DIR)/usr/lib -lmediahal_videorender -lge2d
libgstamlvideosink_la_LIBADD += -L$(TARGET_DIR)/usr/lib/gstreamer-1.0 -lmediahal_videorender -lgstvideo-1.0 -lgstdrmbufferpool -lgstdrmallocator
libgstamlvideosink_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/src/ge2drotation.c b/src/ge2drotation.c
new file mode 100644
index 0000000..66afd0a
--- /dev/null
+++ b/src/ge2drotation.c
@@ -0,0 +1,387 @@
+/* GStreamer
+ * Copyright (C) 2022 amlogic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/utsname.h>
+#include "resourcemanage.h"
+#include "meson_drm.h"
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <drm/drm_fourcc.h>
+#include "ge2drotation.h"
+//#include <gst/gstdrmbufferpool.h>
+#include <gst/allocators/gstdmabuf.h>
+
+#define DUMP_ROTATION_DATA 0
+
+static int mdrmFd = -1;
+
+static void destroy_gem_buffer(int drmFd, GemBuffer *gemBuf)
+{
+ int rc;
+ struct drm_gem_close gclose;
+
+ for (int i= 0; i < gemBuf->planeCount; ++i)
+ {
+ if (gemBuf->fd[i] >= 0)
+ {
+ close(gemBuf->fd[i]);
+ gemBuf->fd[i]= -1;
+ }
+ if (gemBuf->handle[i] > 0)
+ {
+ memset(&gclose, 0, sizeof(gclose));
+ gclose.handle= gemBuf->handle[i];
+ rc= ioctl(drmFd, DRM_IOCTL_GEM_CLOSE, &gclose);
+ if (rc < 0)
+ {
+ GST_ERROR("Failed to release gem buffer handle %d: DRM_IOCTL_MODE_DESTROY_DUMB rc %d errno %d",
+ gemBuf->handle[i], rc, errno );
+ }
+ gemBuf->handle[i]= 0;
+ }
+ }
+}
+
+void rotation_buffer_teardown(ROTBuffer *ROTbuf, int numBuffer)
+{
+ if (NULL == ROTbuf || 0 == numBuffer)
+ {
+ return;
+ }
+
+ for (int i= 0; i < numBuffer; ++i)
+ {
+ destroy_gem_buffer(mdrmFd, &ROTbuf[i].gemBuf);
+ }
+ free(ROTbuf);
+ ROTbuf = NULL;
+
+ if (mdrmFd >= 0)
+ {
+ close(mdrmFd);
+ mdrmFd= -1;
+ }
+
+}
+
+#define DEFAULT_DRM_NAME "/dev/dri/renderD128"
+static bool creat_gem_buffer(int drmFd, GemBuffer *gemBuf)
+{
+ bool result= false;
+ int rc;
+ struct drm_meson_gem_create gc;
+
+ for (int i= 0; i < gemBuf->planeCount; ++i)
+ {
+ gemBuf->fd[i]= -1;
+ memset(&gc, 0, sizeof(gc));
+ // NV12M
+ {
+ gc.flags= MESON_USE_VIDEO_PLANE;
+ if (i == 0)
+ {
+ gc.size= gemBuf->width*gemBuf->height;
+ }
+ else
+ {
+ gc.size= gemBuf->width*gemBuf->height/2;
+ }
+ gemBuf->stride[i]= gemBuf->width;
+ }
+ gemBuf->size[i]= gc.size;
+
+ rc= ioctl(drmFd, DRM_IOCTL_MESON_GEM_CREATE, &gc);
+ if (rc < 0)
+ {
+ GST_ERROR("Failed to create gem buffer: plane %d DRM_IOCTL_MESON_GEM_CREATE rc %d", i, rc);
+ goto exit;
+ }
+
+ gemBuf->handle[i]= gc.handle;
+ gemBuf->offset[i]= 0;
+
+ rc= drmPrimeHandleToFD(drmFd, gemBuf->handle[i], DRM_CLOEXEC | DRM_RDWR, &gemBuf->fd[i]);
+ if (rc < 0)
+ {
+ GST_ERROR("Failed to get fd for gem buf plane %d: handle %d drmPrimeHandleToFD rc %d",
+ i, gemBuf->handle[i], rc );
+ goto exit;
+ }
+
+ GST_DEBUG("create gem buf plane %d size (%dx%d) %u bytes stride %d offset %d handle %d fd %d",
+ i, gemBuf->width, gemBuf->height, gemBuf->size[i],
+ gemBuf->stride[i], gemBuf->offset[i], gemBuf->handle[i], gemBuf->fd[i] );
+ }
+
+ result= true;
+
+exit:
+
+ return result;
+}
+
+
+
+ROTBuffer* rotation_buffer_setup(int numPlanes, int width, int height, int numBuffer)
+{
+ bool result= false;
+ if (0 == numBuffer)
+ {
+ return NULL;
+ }
+ ROTBuffer* ROTbuf = (ROTBuffer*)calloc(numBuffer, sizeof(ROTBuffer));
+ if (!ROTbuf)
+ {
+ GST_ERROR("no memory for GemBuffer" );
+ return NULL;
+ }
+
+ char *drmName = DEFAULT_DRM_NAME;
+ mdrmFd= open(drmName, O_RDWR|O_CLOEXEC);
+ if (mdrmFd < 0)
+ {
+ GST_ERROR("Failed to open drm render node: %d", errno);
+ goto exit;
+ }
+
+ for (int i= 0; i < numBuffer; ++i)
+ {
+ ROTbuf[i].used = FALSE;
+ ROTbuf[i].gemBuf.planeCount= numPlanes;
+ ROTbuf[i].gemBuf.width= width;
+ ROTbuf[i].gemBuf.height= height;
+ for (int j= 0; j < MAX_PLANES; ++j)
+ {
+ ROTbuf[i].gemBuf.fd[j]= -1;
+ }
+ if (!creat_gem_buffer(mdrmFd, &ROTbuf[i].gemBuf))
+ {
+ GST_ERROR("Failed to allocate gem buffer");
+ goto exit;
+ }
+ }
+
+ result= true;
+
+exit:
+ if (!result)
+ {
+ rotation_buffer_teardown(ROTbuf, numBuffer);
+ ROTbuf = NULL;
+ }
+ return ROTbuf;
+}
+
+gboolean rotation_init(aml_ge2d_t* pAmlge2d, aml_ge2d_info_t **pge2dinfo)
+{
+ int ret = 0;
+ if (NULL == pAmlge2d)
+ {
+ return FALSE;
+ }
+
+ *pge2dinfo = &(pAmlge2d->ge2dinfo);
+ memset(pAmlge2d, 0, sizeof(aml_ge2d_t));
+
+ /* ge2d init */
+ ret = aml_ge2d_init(pAmlge2d);
+ if (ret < 0)
+ {
+ GST_ERROR("ge2d init failed");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean rotation_exit(aml_ge2d_t* pAmlge2d)
+{
+ if (NULL == pAmlge2d)
+ {
+ return FALSE;
+ }
+
+ //ge2d release exit
+ aml_ge2d_exit(pAmlge2d);
+ return TRUE;
+}
+
+#if DUMP_ROTATION_DATA
+static int aml_write_file(int shared_fd, const char* file_name, int write_bytes)
+{
+ int fd = -1;
+ int write_num = 0;
+ char *vaddr = NULL;
+
+ if (shared_fd < 0 || !file_name || !write_bytes) {
+ printf("wrong params, read failed");
+ return -1;
+ }
+
+ vaddr = (char*)mmap(NULL, write_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0);
+ if (!vaddr) {
+ printf("%s,%d,mmap failed,Not enough memory\n",__func__, __LINE__);
+ return -1;
+ }
+
+ fd = open(file_name, O_RDWR | O_CREAT | O_APPEND, 0660);
+ if (fd < 0) {
+ printf("write file:%s open error\n", file_name);
+ return -1;
+ }
+
+ write_num = write(fd, vaddr, write_bytes);
+ if (write_num <= 0) {
+ printf("write file write_num=%d error\n", write_num);
+ }
+
+ close(fd);
+ munmap(vaddr, write_bytes);
+
+ return 0;
+}
+#endif
+
+gboolean get_rotation_size(int src_w, int src_h, int* dst_w, int* dst_h)
+{
+ if (NULL == dst_w || NULL == dst_h)
+ {
+ return FALSE;
+ }
+
+ int dst_width = src_w;
+ int dst_height = src_h;
+ // reduce to 720p
+ if (dst_width > 1280 || dst_height > 720)
+ {
+ int ratio = dst_width * 100 / dst_height;
+ if (ratio > 100)
+ {
+ dst_width = 1280;
+ dst_height = dst_width *100 / ratio;
+ }
+ else
+ {
+ dst_height = 720;
+ dst_width = dst_height * ratio / 100;
+ }
+ GST_DEBUG("ratio:%d, w:%d, h:%d\n", ratio, dst_width, dst_height);
+ }
+ *dst_w = dst_width/32*32;
+ *dst_h = dst_height;
+ return TRUE;
+}
+
+GstFlowReturn rotation_transform(aml_ge2d_info_t *pge2dinfo, GstBuffer *inbuf, ROTBuffer *ROTbuf, ROTATION_DEGREE ROTDegree)
+{
+ GstFlowReturn ret = GST_FLOW_ERROR;
+ GstMemory *mem;
+ int i;
+ int plane = 2;
+
+ GstVideoMeta *meta_data = NULL;
+
+ if (NULL == pge2dinfo || NULL == inbuf || NULL == ROTbuf)
+ {
+ return GST_FLOW_ERROR;
+ }
+
+ plane = gst_buffer_n_memory(inbuf);
+ 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);
+ pge2dinfo->dst_info.shared_fd[i] = ROTbuf->gemBuf.fd[i];
+ }
+
+ meta_data = gst_buffer_get_video_meta(inbuf);
+ // pge2dinfo->mem_sec = plugin->secure ? 1 : 0;
+ int src_width = meta_data->width;
+ int src_height = meta_data->height;
+
+ int dst_width = ROTbuf->gemBuf.width;
+ int dst_height = ROTbuf->gemBuf.height;
+
+ // Align to 32-bit
+ dst_width = dst_width/32*32;
+
+ 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 = src_width; /* input width */
+ pge2dinfo->src_info[0].canvas_h = src_height; /* 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 = src_width; /* input process area w */
+ pge2dinfo->src_info[0].rect.h = src_height; /* 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 = dst_width; /* output width */
+ pge2dinfo->dst_info.canvas_h = dst_height; /* output height */
+ 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 = dst_width; /* output process area w */
+ pge2dinfo->dst_info.rect.h = dst_height; /* output process area h */
+ pge2dinfo->dst_info.plane_alpha = 0xFF; /* global plane alpha*/
+
+ pge2dinfo->dst_info.rotation = ROTDegree;
+ pge2dinfo->ge2d_op = AML_GE2D_STRETCHBLIT;
+
+ if (pge2dinfo->src_info[0].format == -1 || pge2dinfo->dst_info.format == -1) {
+ GST_ERROR("ge2d not support format src_info[0].format %d, dst_info.format %d",pge2dinfo->src_info[0].format, pge2dinfo->dst_info.format);
+ goto beach;
+ }
+
+#if DUMP_ROTATION_DATA
+ // DEBUG: dump src data
+ aml_write_file(pge2dinfo->src_info[0].shared_fd[0], "/tmp/input.yuv", src_width*src_height);
+ aml_write_file(pge2dinfo->src_info[0].shared_fd[1], "/tmp/input.yuv", src_width*src_height/2);
+#endif
+
+ GST_DEBUG("pge2dinfo: in_rect_w %d in_rect_h %d canvas_w %d canvas_h %d" , \
+ pge2dinfo->src_info[0].rect.w, pge2dinfo->src_info[0].rect.h, \
+ pge2dinfo->src_info[0].canvas_w,pge2dinfo->src_info[0].canvas_h);
+ ret = aml_ge2d_process(pge2dinfo);
+ if (ret < 0) {
+ GST_ERROR("ge2d process failed");
+ goto beach;
+ }
+ GST_DEBUG("pge2dinfo: out_rect_w %d out_rect_h %d canvas_w %d canvas_h %d" , \
+ pge2dinfo->dst_info.rect.w, pge2dinfo->dst_info.rect.h,\
+ pge2dinfo->dst_info.canvas_w,pge2dinfo->dst_info.canvas_h);
+#if DUMP_ROTATION_DATA
+ // DEBUG: dump dst data
+ aml_write_file(pge2dinfo->dst_info.shared_fd[0], "/tmp/output.yuv", dst_width*dst_height);
+ aml_write_file(pge2dinfo->dst_info.shared_fd[1], "/tmp/output.yuv", dst_width*dst_height/2);
+#endif
+ ret = GST_FLOW_OK;
+beach:
+ return ret;
+}
diff --git a/src/ge2drotation.h b/src/ge2drotation.h
new file mode 100644
index 0000000..3a18b09
--- /dev/null
+++ b/src/ge2drotation.h
@@ -0,0 +1,57 @@
+/* GStreamer
+ * Copyright (C) 2022 amlogic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+
+#include <gst/gst.h>
+#include <aml_ge2d.h>
+#include <gst/video/video.h>
+
+#define MAX_PLANES (3)
+typedef struct _GemBuffer
+{
+ gint width;
+ gint height;
+ gint planeCount;
+ guint handle[MAX_PLANES];
+ guint stride[MAX_PLANES];
+ guint offset[MAX_PLANES];
+ guint size[MAX_PLANES];
+ gint fd[MAX_PLANES];
+} GemBuffer;
+
+typedef struct _ROTBuffer{
+ gint index;
+ gboolean used;
+ GemBuffer gemBuf;
+}ROTBuffer;
+
+typedef enum
+{
+ WST_ROTATION_0 = 0,
+ WST_ROTATION_90 = 1,
+ WST_ROTATION_180 = 2,
+ WST_ROTATION_270 = 3,
+}ROTATION_DEGREE;
+
+
+ROTBuffer* rotation_buffer_setup(int numPlanes, int width, int height, int numBuffer);
+void rotation_buffer_teardown(ROTBuffer *pROTbuf, int numBuffer);
+GstFlowReturn rotation_transform(aml_ge2d_info_t *pge2dinfo, GstBuffer *inbuf, ROTBuffer *pROTbuf, ROTATION_DEGREE ROTDegree);
+gboolean rotation_init(aml_ge2d_t* pAmlge2d, aml_ge2d_info_t **pge2dinfo);
+gboolean rotation_exit(aml_ge2d_t* pAmlge2d);
+gboolean get_rotation_size(int src_w, int src_h, int* dst_w, int* dst_h);
diff --git a/src/gstamlvideosink.c b/src/gstamlvideosink.c
index 471a0da..77d440c 100644
--- a/src/gstamlvideosink.c
+++ b/src/gstamlvideosink.c
@@ -39,6 +39,7 @@
#include <unistd.h>
// #endif
// #endif
+#include "ge2drotation.h"
#ifdef GST_OBJECT_LOCK
#undef GST_OBJECT_LOCK
@@ -124,6 +125,7 @@
PROP_LGE_DISH_TRICK,
PROP_LGE_DISH_TRICK_IGNORE_RATE,
#endif
+ PROP_VIDEO_ROTATION,
};
typedef enum {
@@ -150,6 +152,9 @@
#define PTS_90K (90000)
+#define ROT_BUFFER_MAX (5)
+#define ROT_QUEUE_MAX (20)
+
typedef struct _GstAmlVideoSinkWindowSet
{
gboolean window_change;
@@ -224,6 +229,14 @@
gint video_latency;
gboolean set_video_latency;
+ /* rotation and ge2d */
+ aml_ge2d_info_t *pge2dinfo;
+ aml_ge2d_t amlge2d;
+ ROTBuffer* rot_buffer;
+ ROTATION_DEGREE rot_degree;
+ gboolean rot_changed;
+ gboolean rot_enable_property;
+
#if GST_IMPORT_LGE_PROP
GstAmlVideoSinkLgeCtxt lge_ctxt;
#endif
@@ -264,6 +277,7 @@
GstCaps *filter);
static gboolean gst_aml_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps);
static gboolean gst_aml_video_sink_show_frame(GstVideoSink *bsink, GstBuffer *buffer);
+static GstFlowReturn gst_aml_video_sink_show_frame_ex(GstVideoSink *vsink, GstBuffer *buffer);
static gboolean gst_aml_video_sink_pad_event (GstBaseSink *basesink, GstEvent *event);
static gboolean gst_aml_video_sink_send_event(GstElement *element, GstEvent *event);
@@ -275,6 +289,7 @@
static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap);
static gboolean gst_get_mediasync_instanceid(GstAmlVideoSink *vsink);
static void gst_set_report_info(void *userData, RenderMsgType type, int64_t pts, int64_t duration);
+static int get_rotation_buffer_idx(GstAmlVideoSink *vsink);
#if GST_USE_PLAYBIN
static GstElement *gst_aml_video_sink_find_audio_sink(GstAmlVideoSink *sink);
@@ -316,7 +331,7 @@
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_aml_video_sink_set_caps);
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_aml_video_sink_pad_event);
- gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR(gst_aml_video_sink_show_frame);
+ gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR(gst_aml_video_sink_show_frame_ex);
g_object_class_install_property(
gobject_class, PROP_FULLSCREEN,
@@ -540,6 +555,12 @@
"H15, M16",
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#endif
+
+ g_object_class_install_property (
+ G_OBJECT_CLASS (klass), PROP_VIDEO_ROTATION,
+ g_param_spec_int ("video-rotation", "video-rotation",
+ "video rotation",
+ 0, 3, 0, G_PARAM_WRITABLE));
}
static void gst_aml_video_sink_init(GstAmlVideoSink *sink)
@@ -561,6 +582,9 @@
sink->secure_mode = FALSE;
sink->detect_thread_handle = NULL;
sink->quit_eos_detect_thread = FALSE;
+ sink->rotation_thread_handle = NULL;
+ sink->quit_rotation_thread = FALSE;
+ sink->buffer_queue = gst_queue_array_new (ROT_QUEUE_MAX);
sink->frame_rate_num = 0;
sink->frame_rate_denom = 0;
sink->frame_rate_changed = FALSE;
@@ -574,6 +598,7 @@
g_mutex_init(&sink->eos_lock);
g_cond_init(&sink->eos_cond);
g_mutex_init(&sink->report_info_lock);
+ g_mutex_init(&sink->rotation_buffer_lock);
GST_AML_VIDEO_SINK_GET_PRIVATE(sink) = malloc(sizeof(GstAmlVideoSinkPrivate));
gst_aml_video_sink_reset_private(sink);
@@ -957,6 +982,18 @@
break;
}
#endif
+ case PROP_VIDEO_ROTATION:
+ {
+ int rotationDegree = g_value_get_int(value);
+ if (rotationDegree >= WST_ROTATION_0 && rotationDegree <= WST_ROTATION_270)
+ {
+ GST_DEBUG_OBJECT(sink, "set rotation degree %d", rotationDegree);
+ sink_priv->rot_degree = (ROTATION_DEGREE)rotationDegree;
+ sink_priv->rot_changed = TRUE;
+ sink_priv->rot_enable_property = TRUE;
+ }
+ break;
+ }
default:
// G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -966,12 +1003,18 @@
static void gst_aml_video_sink_finalize(GObject *object)
{
GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(object);
-
GST_DEBUG_OBJECT(sink, "Finalizing aml video sink..");
+ if (sink->buffer_queue)
+ {
+ gst_queue_array_free (sink->buffer_queue);
+ sink->buffer_queue = NULL;
+ }
+
g_mutex_clear(&sink->eos_lock);
g_cond_clear(&sink->eos_cond);
g_mutex_clear(&sink->report_info_lock);
+ g_mutex_clear(&sink->rotation_buffer_lock);
gst_aml_video_sink_reset_private(sink);
if (GST_AML_VIDEO_SINK_GET_PRIVATE(sink))
@@ -1057,6 +1100,7 @@
GST_ERROR_OBJECT(sink, "render lib pause device fail when first into paused state");
goto error;
}
+ rotation_init(&sink_priv->amlge2d, &sink_priv->pge2dinfo);
break;
}
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
@@ -1122,11 +1166,26 @@
g_thread_join(sink->detect_thread_handle);
sink->detect_thread_handle = NULL;
}
+ if (sink->rotation_thread_handle)
+ {
+ sink->quit_rotation_thread = TRUE;
+ GST_OBJECT_UNLOCK(sink);
+ g_thread_join(sink->rotation_thread_handle);
+ GST_OBJECT_LOCK(sink);
+ sink->rotation_thread_handle = NULL;
+ }
GST_DEBUG_OBJECT(sink, "before disconnect rlib");
render_disconnect(sink_priv->render_device_handle);
GST_DEBUG_OBJECT(sink, "after disconnect rlib");
GST_DEBUG_OBJECT(sink, "buf stat | queued:%d, dequeued:%d, dropped:%d, rendered:%d",
sink->queued, sink->dequeued, sink->dropped, sink->rendered);
+
+ if (sink_priv->rot_buffer)
+ {
+ rotation_buffer_teardown(sink_priv->rot_buffer, ROT_BUFFER_MAX);
+ sink_priv->rot_buffer = NULL;
+ }
+ rotation_exit(&sink_priv->amlge2d);
break;
}
case GST_STATE_CHANGE_READY_TO_NULL:
@@ -1431,6 +1490,100 @@
return TRUE;
}
+static void rotation_flush_buffer(GstAmlVideoSink *vsink)
+{
+ GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
+
+ g_mutex_lock(&sink->rotation_buffer_lock);
+ if (sink->buffer_queue)
+ {
+ while (!gst_queue_array_is_empty(sink->buffer_queue))
+ {
+ GstBuffer* buffer = (GstBuffer *)gst_queue_array_pop_head(sink->buffer_queue);
+ gst_buffer_unref(buffer);
+ GST_DEBUG_OBJECT(sink, "reset pop head buffer_queue len:%d", gst_queue_array_get_length(sink->buffer_queue));
+ }
+ }
+ g_mutex_unlock(&sink->rotation_buffer_lock);
+ GST_DEBUG_OBJECT(sink, "flush over buffer_queue len:%d", gst_queue_array_get_length(sink->buffer_queue));
+}
+
+static gpointer rotation_thread(gpointer data)
+{
+ GstAmlVideoSink *sink = (GstAmlVideoSink *)data;
+ GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
+
+ while (!sink->quit_rotation_thread)
+ {
+ if (sink_priv->rot_buffer && -1 == get_rotation_buffer_idx(sink))
+ {
+ usleep(5000);
+ continue;
+ }
+
+ if (sink->buffer_queue && !gst_queue_array_is_empty(sink->buffer_queue))
+ {
+ // pop queue
+ g_mutex_lock(&sink->rotation_buffer_lock);
+ GstBuffer *buffer = (GstBuffer *)gst_queue_array_pop_head(sink->buffer_queue);
+ g_mutex_unlock(&sink->rotation_buffer_lock);
+
+ // show frame
+ gst_aml_video_sink_show_frame((GstVideoSink*)sink, buffer);
+ gst_buffer_unref(buffer);
+ }
+ else
+ {
+ usleep(10000);
+ }
+ }
+
+ // thread join, unref all gst buffer
+ rotation_flush_buffer(sink);
+
+ if (!sink->quit_rotation_thread)
+ {
+ g_thread_unref( sink->rotation_thread_handle );
+ sink->rotation_thread_handle= NULL;
+ }
+ GST_DEBUG("rotation_thread: exit");
+ return NULL;
+}
+
+static GstFlowReturn gst_aml_video_sink_push_queue(GstVideoSink *vsink, GstBuffer *buffer)
+{
+ GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
+ if (sink->rotation_thread_handle == NULL )
+ {
+ sink->quit_rotation_thread = FALSE;
+ GST_DEBUG_OBJECT(sink, "start rotation thread");
+ sink->rotation_thread_handle = g_thread_new("video_sink_rotation", rotation_thread, sink);
+ }
+
+ g_mutex_lock(&sink->rotation_buffer_lock);
+ // push queue
+ if (sink->buffer_queue)
+ {
+ gst_queue_array_push_tail (sink->buffer_queue, buffer);
+ gst_buffer_ref(buffer);
+ }
+ g_mutex_unlock(&sink->rotation_buffer_lock);
+ return GST_FLOW_OK;
+}
+
+
+static GstFlowReturn gst_aml_video_sink_show_frame_ex(GstVideoSink *vsink, GstBuffer *buffer)
+{
+ GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
+ GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
+
+ if (sink_priv->rot_degree == WST_ROTATION_90 || sink_priv->rot_degree == WST_ROTATION_270)
+ {
+ return gst_aml_video_sink_push_queue(vsink, buffer);
+ }
+ return gst_aml_video_sink_show_frame(vsink, buffer);
+}
+
static GstFlowReturn gst_aml_video_sink_show_frame(GstVideoSink *vsink, GstBuffer *buffer)
{
GstAmlVideoSink *sink = GST_AML_VIDEO_SINK(vsink);
@@ -1603,6 +1756,39 @@
return ret;
}
+void gst_aml_video_sink_tag_event(GstAmlVideoSink *vsink, GstTagList *list )
+{
+ if (NULL == vsink || NULL == list)
+ {
+ return;
+ }
+
+ GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
+ gchar *rotation_tag = NULL;
+ gint tagDegree = 0;
+ ROTATION_DEGREE rotationDegree = WST_ROTATION_0;
+
+ if ((!sink_priv->rot_enable_property) &&
+ (gst_tag_list_get_string(list, GST_TAG_IMAGE_ORIENTATION, &rotation_tag)))
+ {
+ if (sscanf(rotation_tag, "rotate-%d", &tagDegree))
+ {
+ rotationDegree = (ROTATION_DEGREE)(tagDegree/90);
+
+ if (rotationDegree >= WST_ROTATION_0 && rotationDegree <= WST_ROTATION_270)
+ {
+ sink_priv->rot_changed = TRUE;
+ sink_priv->rot_degree = rotationDegree;
+ GST_DEBUG_OBJECT(vsink, "set rotation degree %d", rotationDegree);
+ }
+ }
+ else if (sscanf(rotation_tag, "flip-rotate-%d", &tagDegree))
+ {
+ // not support flip right now, need support later
+ }
+ }
+}
+
static gboolean gst_aml_video_sink_pad_event (GstBaseSink *basesink, GstEvent *event)
{
gboolean result = TRUE;
@@ -1620,6 +1806,8 @@
sink_priv->is_flushing = TRUE;
render_set_value(sink_priv->render_device_handle, KEY_KEEP_LAST_FRAME_ON_FLUSH, &sink->keep_last_frame_on_flush);
+ rotation_flush_buffer(sink);
+
if (render_flush(sink_priv->render_device_handle) == 0)
{
GST_INFO_OBJECT(sink, "recv flush start and set render lib flushing succ");
@@ -1690,6 +1878,16 @@
}
break;
}
+ case GST_EVENT_TAG:
+ {
+ GstTagList *list = NULL;
+ gst_event_parse_tag (event, &list);
+ if (list)
+ {
+ gst_aml_video_sink_tag_event(sink, list);
+ }
+ break;
+ }
case GST_EVENT_CAPS:
{
GstCaps *caps;
@@ -1916,6 +2114,10 @@
sink_priv->fps_d = 0;
sink_priv->video_latency = 0;
sink_priv->set_video_latency = FALSE;
+ sink_priv->rot_buffer = NULL;
+ sink_priv->rot_degree = WST_ROTATION_0;
+ sink_priv->rot_changed = FALSE;
+ sink_priv->rot_enable_property = FALSE;
}
static void gst_set_report_info(void *userData, RenderMsgType type, int64_t pts, int64_t duration)
@@ -1932,6 +2134,28 @@
g_mutex_unlock(&sink->report_info_lock);
}
+static gboolean is_rotation_buffer(void *userData, void* pbuf)
+{
+ GstAmlVideoSink *sink = (GstAmlVideoSink *)userData;
+ GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
+
+ // no rotation buffer
+ if (!sink_priv->rot_buffer)
+ {
+ return FALSE;
+ }
+
+ ROTBuffer* rotation_buffer = (ROTBuffer*)pbuf;
+ for (int i = 0; i < ROT_BUFFER_MAX; i++)
+ {
+ if (rotation_buffer == &sink_priv->rot_buffer[i])
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static void gst_render_msg_callback(void *userData, RenderMsgType type, void *msg)
{
GstAmlVideoSink *sink = (GstAmlVideoSink *)userData;
@@ -1943,30 +2167,29 @@
{
RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
RenderDmaBuffer *dmabuf = &tunnel_lib_buf_wrap->dma;
- GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
- if (buffer)
- {
- sink->last_displayed_buf_pts = GST_BUFFER_PTS(buffer);
- if (type == MSG_DROPED_BUFFER)
- {
- GST_LOG_OBJECT(sink, "get message: MSG_DROPED_BUFFER from tunnel lib");
- sink->dropped++;
- gst_set_report_info(userData, type, GST_BUFFER_PTS(buffer), 0);
- }
- else if (type == MSG_DISPLAYED_BUFFER)
- {
- GST_LOG_OBJECT(sink, "get message: MSG_DISPLAYED_BUFFER from tunnel lib");
- sink->rendered++;
- if (sink_priv->frame_step_on_preroll && sink->video_playing == FALSE) {
- render_pause(sink_priv->render_device_handle);
- }
- }
- GST_DEBUG_OBJECT(sink, "buf:%p planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d pts:%lld, buf stat | queued:%d, dequeued:%d, dropped:%d, rendered:%d",
- buffer,
- dmabuf->planeCnt, dmabuf->fd[0], dmabuf->fd[1],
- buffer ? GST_BUFFER_PTS(buffer) : -1, sink->queued, sink->dequeued, sink->dropped, sink->rendered);
- //gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
+ if (tunnel_lib_buf_wrap->priv)
+ {
+ sink->last_displayed_buf_pts = tunnel_lib_buf_wrap->pts;
+ if (type == MSG_DROPED_BUFFER)
+ {
+ GST_LOG_OBJECT(sink, "get message: MSG_DROPED_BUFFER from tunnel lib");
+ sink->dropped++;
+ gst_set_report_info(userData, type, tunnel_lib_buf_wrap->pts, 0);
+ }
+ else if (type == MSG_DISPLAYED_BUFFER)
+ {
+ GST_LOG_OBJECT(sink, "get message: MSG_DISPLAYED_BUFFER from tunnel lib");
+ sink->rendered++;
+ if (sink_priv->frame_step_on_preroll && sink->video_playing == FALSE) {
+ render_pause(sink_priv->render_device_handle);
+ }
+ }
+ GST_DEBUG_OBJECT(sink, "buf:%p planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d pts:%lld, buf stat | queued:%d, dequeued:%d, dropped:%d, rendered:%d",
+ tunnel_lib_buf_wrap->priv,
+ dmabuf->planeCnt, dmabuf->fd[0], dmabuf->fd[1],
+ tunnel_lib_buf_wrap->priv ? tunnel_lib_buf_wrap->pts : -1, sink->queued, sink->dequeued, sink->dropped, sink->rendered);
+ //gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
}
else
{
@@ -1978,20 +2201,30 @@
{
GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(sink);
RenderBuffer *tunnel_lib_buf_wrap = (RenderBuffer *)msg;
- GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
- GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib,%p, pts:%lld ns",buffer, tunnel_lib_buf_wrap->pts);
-
- if (buffer)
+ GST_LOG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib,%p, pts:%lld ns",tunnel_lib_buf_wrap->priv, tunnel_lib_buf_wrap->pts);
+ if (tunnel_lib_buf_wrap->priv)
{
+ if (is_rotation_buffer(userData, tunnel_lib_buf_wrap->priv))
+ {
+ ROTBuffer* rotation_buffer = (ROTBuffer*)tunnel_lib_buf_wrap->priv;
+ rotation_buffer->used = FALSE;
+ /*printf("release [%d][%d][%d][%d][%d]\n", sink_priv->rot_buffer[0].used, sink_priv->rot_buffer[1].used,
+ sink_priv->rot_buffer[2].used, sink_priv->rot_buffer[3].used, sink_priv->rot_buffer[4].used);*/
+ }
+ else
+ {
+ GstBuffer *buffer = (GstBuffer *)tunnel_lib_buf_wrap->priv;
GST_DEBUG_OBJECT(sink, "get message: MSG_RELEASE_BUFFER from tunnel lib, buffer:%p, from pool:%p", buffer, buffer->pool);
gst_buffer_unref(buffer);
- sink->dequeued++;
- //gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
+ }
+ sink->dequeued++;
+ //gst_aml_video_sink_dump_stat(sink, GST_DUMP_STAT_FILENAME);
}
else
{
- GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_RELEASE_BUFFER");
+ GST_ERROR_OBJECT(sink, "tunnel lib: return void GstBuffer when MSG_RELEASE_BUFFER");
}
+
render_free_render_buffer_wrap(sink_priv->render_device_handle, tunnel_lib_buf_wrap);
break;
}
@@ -2066,6 +2299,44 @@
return ret;
}
+static int get_rotation_buffer_idx(GstAmlVideoSink *vsink)
+{
+ GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
+
+ if (sink_priv->rot_buffer)
+ {
+ for (int i = 0; i < ROT_BUFFER_MAX; i++)
+ {
+ if (!sink_priv->rot_buffer[i].used)
+ {
+ /*printf("ok [%d][%d][%d][%d][%d]\n", sink_priv->rot_buffer[0].used, sink_priv->rot_buffer[1].used,
+ sink_priv->rot_buffer[2].used, sink_priv->rot_buffer[3].used, sink_priv->rot_buffer[4].used);*/
+ return i;
+ }
+ }
+ /*printf("fail [%d][%d][%d][%d][%d]\n", sink_priv->rot_buffer[0].used, sink_priv->rot_buffer[1].used,
+ sink_priv->rot_buffer[2].used, sink_priv->rot_buffer[3].used, sink_priv->rot_buffer[4].used);*/
+ }
+
+ return -1;
+}
+
+static void set_video_reversal(GstAmlVideoSink *vsink)
+{
+ GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
+ sink_priv->video_info_changed = TRUE;
+ int degree = (sink_priv->rot_degree == WST_ROTATION_180 ? 180 : 0);
+ if (render_set_value(sink_priv->render_device_handle, KEY_ROTATE_VIDEO, °ree) != -1)
+ {
+ GST_ERROR_OBJECT(vsink, "tunnel lib: set render video rotation success:%d", degree);
+ sink_priv->rot_changed = FALSE;
+ }
+ else
+ {
+ GST_ERROR_OBJECT(vsink, "tunnel lib: set render video rotation failed:%d", degree);
+ }
+}
+
static gboolean gst_aml_video_sink_tunnel_buf(GstAmlVideoSink *vsink, GstBuffer *gst_buf, RenderBuffer *tunnel_lib_buf_wrap)
{
GstAmlVideoSinkPrivate *sink_priv = GST_AML_VIDEO_SINK_GET_PRIVATE(vsink);
@@ -2096,68 +2367,113 @@
GST_ERROR_OBJECT(vsink, "too many memorys in gst buffer");
goto error;
}
- //GST_DEBUG_OBJECT(vsink, "dbg3-0, dmabuf:%p", dmabuf);
- dmabuf->planeCnt = n_mem;
- dmabuf->width = vmeta->width;
- dmabuf->height = vmeta->height;
- if (sink_priv->dw_mode == 0) {
- dmabuf->width = sink_priv->src_width;
- dmabuf->height = sink_priv->src_height;
- }
-
- //GST_DEBUG_OBJECT(vsink, "dbgjxs, vmeta->width:%d, dmabuf->width:%d", vmeta->width, dmabuf->width);
-
- for (guint i = 0; i < n_mem; i++)
+ // weston do rotation, set rotation 180 or 0
+ if (sink_priv->rot_changed)
{
- gint dmafd;
- gsize size, offset, maxsize;
- dma_mem = gst_buffer_peek_memory(gst_buf, i);
- guint mem_idx = 0;
- guint length = 0;
- gsize skip = 0;
+ set_video_reversal(vsink);
+ }
+ dmabuf->planeCnt = n_mem;
+ if (sink_priv->rot_degree == WST_ROTATION_90 || sink_priv->rot_degree == WST_ROTATION_270)
+ {
+ // get output size, and align 32byte
+ get_rotation_size(vmeta->height, vmeta->width, &dmabuf->width, &dmabuf->height);
+ // create ROT buf
+ if (!sink_priv->rot_buffer)
+ {
+ sink_priv->video_info_changed = TRUE;
+ GST_ERROR_OBJECT(vsink, "planeCnt:%d, width:%d, height:%d", dmabuf->planeCnt, dmabuf->width, dmabuf->height);
+ sink_priv->rot_buffer = rotation_buffer_setup(dmabuf->planeCnt, dmabuf->width, dmabuf->height, ROT_BUFFER_MAX);
+ }
- if (!gst_is_dmabuf_memory(dma_mem))
- {
- GST_ERROR_OBJECT(vsink, "not support non-dma buf");
- ret = FALSE;
- goto error;
- }
- size = gst_memory_get_sizes(dma_mem, &offset, &maxsize);
- GST_LOG_OBJECT(vsink, "get memory size:%d, offeset:%d, maxsize:%d", size, offset, maxsize);
+ // get ROT buf
+ int index = get_rotation_buffer_idx(vsink);
+ if (-1 == index)
+ {
+ GST_ERROR_OBJECT(vsink, "cant get rotation buffer");
+ vsink->dropped++;
+ goto error;
+ }
+ // do transform
+ if (GST_FLOW_OK == rotation_transform(sink_priv->pge2dinfo, gst_buf, &sink_priv->rot_buffer[index], sink_priv->rot_degree))
+ {
+ sink_priv->rot_buffer[index].used = TRUE;
+ }
- dmafd = gst_dmabuf_memory_get_fd(dma_mem);
+ // ROT buffer trans to RenderBuffer
+ for (guint i = 0; i < dmabuf->planeCnt; i++)
+ {
dmabuf->handle[i] = 0;
- dmabuf->fd[i] = dmafd;
- dmabuf->size[i] = dma_mem->size;
- dmabuf->stride[i] = vmeta->stride[i];
- if (sink_priv->dw_mode == 0) {
- dmabuf->stride[i] = sink_priv->stride;
- }
- if (gst_buffer_find_memory(gst_buf, vmeta->offset[i], 1, &mem_idx, &length, &skip) && mem_idx == i)
+ dmabuf->fd[i] = sink_priv->rot_buffer[index].gemBuf.fd[i];
+ if ( i == 0 )
{
- dmabuf->offset[i] = dma_mem->offset + skip;
- //GST_DEBUG_OBJECT(vsink, "get skip from buffer:%d, offset[%d]:%d", skip, i, dmabuf->offset[i]);
+ dmabuf->size[i] = sink_priv->rot_buffer[index].gemBuf.width * sink_priv->rot_buffer[index].gemBuf.height;
}
else
{
- GST_ERROR_OBJECT(vsink, "get skip from buffer error");
+ dmabuf->size[i] = sink_priv->rot_buffer[index].gemBuf.width * sink_priv->rot_buffer[index].gemBuf.height/2;
}
-
- GST_LOG_OBJECT(vsink, "dma buffer layer:%d, handle:%d, fd:%d, size:%d, offset:%d, stride:%d",
- i, dmabuf->handle[i], dmabuf->fd[i], dmabuf->size[i], dmabuf->offset[i], dmabuf->stride[i]);
+ dmabuf->stride[i] = sink_priv->rot_buffer[index].gemBuf.stride[i];
+ dmabuf->offset[i] = sink_priv->rot_buffer[index].gemBuf.offset[i];
+ }
+ tunnel_lib_buf_wrap->flag = BUFFER_FLAG_DMA_BUFFER;
+ tunnel_lib_buf_wrap->priv = (void *)&sink_priv->rot_buffer[index];
+ tunnel_lib_buf_wrap->pts = GST_BUFFER_PTS(gst_buf);
+ // unref gstbuf
+ gst_buffer_unref(gst_buf);
}
- tunnel_lib_buf_wrap->flag = BUFFER_FLAG_DMA_BUFFER;
- tunnel_lib_buf_wrap->pts = GST_BUFFER_PTS(gst_buf);
- tunnel_lib_buf_wrap->priv = (void *)gst_buf;
- GST_LOG_OBJECT(vsink, "set tunnel lib buf priv:%p from pool:%p, pts:%lld", tunnel_lib_buf_wrap->priv, gst_buf->pool, tunnel_lib_buf_wrap->pts);
- // GST_LOG_OBJECT(vsink, "dbg: buf in:%p, planeCnt:%d, plane[0].fd:%d, plane[1].fd:%d",
- // tunnel_lib_buf_wrap->priv,
- // dmabuf->planeCnt,
- // dmabuf->fd[0],
- // dmabuf->fd[1]);
+ else
+ {
+ dmabuf->width = vmeta->width;
+ dmabuf->height = vmeta->height;
+ if (sink_priv->dw_mode == 0) {
+ dmabuf->width = sink_priv->src_width;
+ dmabuf->height = sink_priv->src_height;
+ }
+ // gstbuffer trans to RenderBuffer
+ for (guint i = 0; i < n_mem; i++)
+ {
+ gint dmafd;
+ gsize size, offset, maxsize;
+ dma_mem = gst_buffer_peek_memory(gst_buf, i);
+ guint mem_idx = 0;
+ guint length = 0;
+ gsize skip = 0;
- return ret;
+ if (!gst_is_dmabuf_memory(dma_mem))
+ {
+ GST_ERROR_OBJECT(vsink, "not support non-dma buf");
+ ret = FALSE;
+ goto error;
+ }
+ size = gst_memory_get_sizes(dma_mem, &offset, &maxsize);
+ GST_LOG_OBJECT(vsink, "get memory size:%d, offset:%d, maxsize:%d", size, offset, maxsize);
+
+ dmafd = gst_dmabuf_memory_get_fd(dma_mem);
+ dmabuf->handle[i] = 0;
+ dmabuf->fd[i] = dmafd;
+ dmabuf->size[i] = dma_mem->size;
+ dmabuf->stride[i] = vmeta->stride[i];
+ if (sink_priv->dw_mode == 0) {
+ dmabuf->stride[i] = sink_priv->stride;
+ }
+ if (gst_buffer_find_memory(gst_buf, vmeta->offset[i], 1, &mem_idx, &length, &skip) && mem_idx == i)
+ {
+ dmabuf->offset[i] = dma_mem->offset + skip;
+ //GST_DEBUG_OBJECT(vsink, "get skip from buffer:%d, offset[%d]:%d", skip, i, dmabuf->offset[i]);
+ }
+ else
+ {
+ GST_ERROR_OBJECT(vsink, "get skip from buffer error");
+ }
+ GST_LOG_OBJECT(vsink, "dma buffer layer:%d, handle:%d, fd:%d, size:%d, offset:%d, stride:%d",
+ i, dmabuf->handle[i], dmabuf->fd[i], dmabuf->size[i], dmabuf->offset[i], dmabuf->stride[i]);
+ }
+ tunnel_lib_buf_wrap->flag = BUFFER_FLAG_DMA_BUFFER;
+ tunnel_lib_buf_wrap->priv = (void *)gst_buf;
+ tunnel_lib_buf_wrap->pts = GST_BUFFER_PTS(gst_buf);
+ GST_LOG_OBJECT(vsink, "set tunnel lib buf priv:%p from pool:%p, pts:%lld", tunnel_lib_buf_wrap->priv, gst_buf->pool, tunnel_lib_buf_wrap->pts);
+ }
error:
return ret;
@@ -2282,6 +2598,12 @@
int tunnelmode = 0; // 1 for tunnel mode; 0 for non-tunnel mode
RenderFrameSize frame_size = {sink_priv->src_width, sink_priv->src_height};
+ if ((sink_priv->rot_degree == WST_ROTATION_90 || sink_priv->rot_degree == WST_ROTATION_270) && sink_priv->rot_buffer)
+ {
+ frame_size.width = sink_priv->rot_buffer[0].gemBuf.width;
+ frame_size.height = sink_priv->rot_buffer[0].gemBuf.height;
+ }
+
GstVideoFormat format = sink_priv->format;
if (render_set_value(sink_priv->render_device_handle, KEY_MEDIASYNC_TUNNEL_MODE, (void *)&tunnelmode) == -1)
diff --git a/src/gstamlvideosink.h b/src/gstamlvideosink.h
index 9fec5c2..e8ffff4 100644
--- a/src/gstamlvideosink.h
+++ b/src/gstamlvideosink.h
@@ -23,6 +23,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "aml_version.h"
+#include <gst/base/gstqueuearray.h>
G_BEGIN_DECLS
@@ -66,6 +67,10 @@
GMutex report_info_lock;
gboolean quit_eos_detect_thread;
GThread *detect_thread_handle;
+ gboolean quit_rotation_thread;
+ GThread *rotation_thread_handle;
+ GstQueueArray* buffer_queue;
+ GMutex rotation_buffer_lock;
gint frame_rate_num;
gint frame_rate_denom;
gboolean frame_rate_changed;