/* * 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 int frame = 0; static int frameindex = 0; 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); SmartPtr video_buf_proxy = video_buf.dynamic_cast_ptr (); //XCAM_LOG_DEBUG ("xcam buffer pool acquire buffer index: %d", video_buf_proxy->get_v4l2_buf_index()); 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]; } //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) { out_buf = gst_buffer_new (); mem = gst_dmabuf_allocator_alloc ( pool->allocator, dup (video_buf->get_fd ()), video_buf->get_size ()); XCAM_ASSERT (mem); gst_buffer_append_memory (out_buf, mem); } else if (GST_XCAM_SRC_MEM_MODE (pool->src) == V4L2_MEMORY_MMAP) { #if 0 if (frame%2 == 0) memset(video_buf->map (), 100, video_buf->get_size () / 2); else memset(video_buf->map () + video_buf->get_size () / 2, 100, video_buf->get_size () / 2); frame++; #endif XCAM_LOG_DEBUG ("xcam buffer pool acquire buffer(%.8x) size: %d", video_buf->map (), video_buf->get_size ()); out_buf = gst_buffer_new_allocate (NULL, video_buf->get_size (), NULL); gst_buffer_fill (out_buf, 0, video_buf->map (), video_buf->get_size ()); /* 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; } //gst_buffer_replace_all_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 = gst_buffer_copy(out_buf); *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); }