/* * gstxcambufferpool.cpp - bufferpool * * Copyright (c) 2015 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: John Ye * Author: Wind Yuan */ /** * SECTION:element-xcambufferpool * * FIXME:Describe xcambufferpool here. * * * Example launch line * |[ * gst-launch -v -m fakesrc ! xcambufferpool ! fakesink silent=TRUE * ]| * */ #include "gstxcambufferpool.h" #include "gstxcambuffermeta.h" #include #include #include using namespace XCam; using namespace GstXCam; XCAM_BEGIN_DECLARE GST_DEBUG_CATEGORY_EXTERN (gst_xcam_src_debug); #define GST_CAT_DEFAULT gst_xcam_src_debug G_DEFINE_TYPE (GstXCamBufferPool, gst_xcam_buffer_pool, GST_TYPE_BUFFER_POOL); #define parent_class gst_xcam_buffer_pool_parent_class static void gst_xcam_buffer_pool_finalize (GObject * object); static gboolean gst_xcam_buffer_pool_start (GstBufferPool *pool); static gboolean gst_xcam_buffer_pool_stop (GstBufferPool *pool); static gboolean gst_xcam_buffer_pool_set_config (GstBufferPool *pool, GstStructure *config); static GstFlowReturn gst_xcam_buffer_pool_acquire_buffer ( GstBufferPool *bpool, GstBuffer **buffer, GstBufferPoolAcquireParams *params); static void gst_xcam_buffer_pool_release_buffer (GstBufferPool *bpool, GstBuffer *buffer); XCAM_END_DECLARE static void gst_xcam_buffer_pool_class_init (GstXCamBufferPoolClass * class_self) { GObjectClass *object_class; GstBufferPoolClass *bufferpool_class; object_class = G_OBJECT_CLASS (class_self); bufferpool_class = GST_BUFFER_POOL_CLASS (class_self); object_class->finalize = gst_xcam_buffer_pool_finalize; bufferpool_class->start = gst_xcam_buffer_pool_start; bufferpool_class->stop = gst_xcam_buffer_pool_stop; bufferpool_class->set_config = gst_xcam_buffer_pool_set_config; bufferpool_class->acquire_buffer = gst_xcam_buffer_pool_acquire_buffer; bufferpool_class->release_buffer = gst_xcam_buffer_pool_release_buffer; } static void gst_xcam_buffer_pool_init (GstXCamBufferPool *pool) { pool->need_video_meta = FALSE; XCAM_CONSTRUCTOR (pool->device_manager, SmartPtr); } static void gst_xcam_buffer_pool_finalize (GObject * object) { GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (object); XCAM_ASSERT (pool); if (pool->src) gst_object_unref (pool->src); if (pool->allocator) gst_object_unref (pool->allocator); XCAM_DESTRUCTOR (pool->device_manager, SmartPtr); } static gboolean gst_xcam_buffer_pool_start (GstBufferPool *base_pool) { GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool); XCAM_ASSERT (pool); SmartPtr device_manager = pool->device_manager; XCAM_ASSERT (device_manager.ptr ()); device_manager->resume_dequeue (); return TRUE; } static gboolean gst_xcam_buffer_pool_stop (GstBufferPool *base_pool) { GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool); XCAM_ASSERT (pool); SmartPtr device_manager = pool->device_manager; XCAM_ASSERT (device_manager.ptr ()); device_manager->pause_dequeue (); return TRUE; } gboolean gst_xcam_buffer_pool_set_config (GstBufferPool *base_pool, GstStructure *config) { GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool); XCAM_ASSERT (pool); pool->need_video_meta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); pool->allocator = gst_dmabuf_allocator_new (); if (pool->allocator == NULL) { GST_WARNING ("xcam buffer pool get allocator failed"); return FALSE; } return TRUE; } static GstFlowReturn gst_xcam_buffer_pool_acquire_buffer ( GstBufferPool *base_pool, GstBuffer **buffer, GstBufferPoolAcquireParams *params) { GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool); XCAM_ASSERT (pool); GstBuffer *out_buf = NULL; GstMemory *mem = NULL; GstXCamBufferMeta *meta = NULL; SmartPtr device_manager = pool->device_manager; SmartPtr video_buf = device_manager->dequeue_buffer (); VideoBufferInfo video_info; gsize offsets[XCAM_VIDEO_MAX_COMPONENTS]; XCAM_UNUSED (params); if (!video_buf.ptr ()) return GST_FLOW_ERROR; video_info = video_buf->get_video_info (); for (int i = 0; i < XCAM_VIDEO_MAX_COMPONENTS; i++) { offsets[i] = video_info.offsets[i]; } out_buf = gst_buffer_new (); meta = gst_buffer_add_xcam_buffer_meta (out_buf, video_buf); XCAM_ASSERT (meta); ((GstMeta *)(meta))->flags = (GstMetaFlags)(GST_META_FLAG_POOLED | GST_META_FLAG_LOCKED | GST_META_FLAG_READONLY); //GST_META_FLAG_SET (meta, (GST_META_FLAG_POOLED | GST_META_FLAG_LOCKED | GST_META_FLAG_READONLY)); if (GST_XCAM_SRC_MEM_MODE (pool->src) == V4L2_MEMORY_DMABUF) { mem = gst_dmabuf_allocator_alloc ( pool->allocator, dup (video_buf->get_fd ()), video_buf->get_size ()); } else if (GST_XCAM_SRC_MEM_MODE (pool->src) == V4L2_MEMORY_MMAP) { mem = gst_memory_new_wrapped ( (GstMemoryFlags)(GST_MEMORY_FLAG_READONLY | GST_MEMORY_FLAG_NO_SHARE), video_buf->map (), video_buf->get_size (), video_info.offsets[0], video_info.size, NULL, NULL); } else { GST_WARNING ("xcam buffer pool acquire buffer failed since mem_type not supported"); return GST_FLOW_ERROR; } XCAM_ASSERT (mem); gst_buffer_append_memory (out_buf, mem); if (pool->need_video_meta) { GstVideoMeta *video_meta = gst_buffer_add_video_meta_full ( out_buf, GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_INFO_FORMAT (GST_XCAM_SRC_OUT_VIDEO_INFO (pool->src)), video_info.width, video_info.height, video_info.components, offsets, (gint*)(video_info.strides)); XCAM_ASSERT (video_meta); // TODO, consider map and unmap later video_meta->map = NULL; video_meta->unmap = NULL; } GST_BUFFER_TIMESTAMP (out_buf) = video_buf->get_timestamp () * 1000; //us to ns *buffer = out_buf; return GST_FLOW_OK; } static void gst_xcam_buffer_pool_release_buffer (GstBufferPool *base_pool, GstBuffer *buffer) { XCAM_UNUSED (base_pool); gst_buffer_unref (buffer); } GstBufferPool * gst_xcam_buffer_pool_new (GstXCamSrc *src, GstCaps *caps, SmartPtr &device_manager) { GstXCamBufferPool *pool; GstStructure *structure; pool = (GstXCamBufferPool *)g_object_new (GST_TYPE_XCAM_BUFFER_POOL, NULL); XCAM_ASSERT (pool); structure = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool)); XCAM_ASSERT (structure); gst_buffer_pool_config_set_params ( structure, caps, GST_VIDEO_INFO_SIZE (GST_XCAM_SRC_OUT_VIDEO_INFO (src)), GST_XCAM_SRC_BUF_COUNT (src), GST_XCAM_SRC_BUF_COUNT (src)); gst_buffer_pool_config_add_option (structure, GST_BUFFER_POOL_OPTION_VIDEO_META); gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), structure); pool->src = src; gst_object_ref (src); pool->device_manager = device_manager; return GST_BUFFER_POOL (pool); }