blob: 31b7ee16854c7ae9854db2f103c95c7fcb321bea [file] [log] [blame]
/*
* 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 <john.ye@intel.com>
* Author: Wind Yuan <feng.yuan@intel.com>
*/
/**
* SECTION:element-xcambufferpool
*
* FIXME:Describe xcambufferpool here.
*
* <refsect2>
* <title>Example launch line</title>
* |[
* gst-launch -v -m fakesrc ! xcambufferpool ! fakesink silent=TRUE
* ]|
* </refsect2>
*/
#include "gstxcambufferpool.h"
#include "gstxcambuffermeta.h"
#include <gst/video/gstvideopool.h>
#include <gst/allocators/gstdmabuf.h>
#include <gst/gstmeta.h>
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<MainDeviceManager>);
}
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<MainDeviceManager>);
}
static gboolean
gst_xcam_buffer_pool_start (GstBufferPool *base_pool)
{
GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool);
XCAM_ASSERT (pool);
SmartPtr<MainDeviceManager> 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<MainDeviceManager> 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<MainDeviceManager> device_manager = pool->device_manager;
SmartPtr<VideoBuffer> 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<MainDeviceManager> &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);
}