1 /*
2 * gstxcambufferpool.cpp - bufferpool
3 *
4 * Copyright (c) 2015 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: John Ye <john.ye@intel.com>
19 * Author: Wind Yuan <feng.yuan@intel.com>
20 */
21
22 /**
23 * SECTION:element-xcambufferpool
24 *
25 * FIXME:Describe xcambufferpool here.
26 *
27 * <refsect2>
28 * <title>Example launch line</title>
29 * |[
30 * gst-launch -v -m fakesrc ! xcambufferpool ! fakesink silent=TRUE
31 * ]|
32 * </refsect2>
33 */
34
35 #include "gstxcambufferpool.h"
36 #include "gstxcambuffermeta.h"
37
38 #include <gst/video/gstvideopool.h>
39 #include <gst/allocators/gstdmabuf.h>
40 #include <gst/gstmeta.h>
41
42 using namespace XCam;
43 using namespace GstXCam;
44
45 XCAM_BEGIN_DECLARE
46
47 GST_DEBUG_CATEGORY_EXTERN (gst_xcam_src_debug);
48 #define GST_CAT_DEFAULT gst_xcam_src_debug
49
50 G_DEFINE_TYPE (GstXCamBufferPool, gst_xcam_buffer_pool, GST_TYPE_BUFFER_POOL);
51 #define parent_class gst_xcam_buffer_pool_parent_class
52
53 static void
54 gst_xcam_buffer_pool_finalize (GObject * object);
55
56 static gboolean
57 gst_xcam_buffer_pool_start (GstBufferPool *pool);
58
59 static gboolean
60 gst_xcam_buffer_pool_stop (GstBufferPool *pool);
61
62 static gboolean
63 gst_xcam_buffer_pool_set_config (GstBufferPool *pool, GstStructure *config);
64
65 static GstFlowReturn
66 gst_xcam_buffer_pool_acquire_buffer (
67 GstBufferPool *bpool,
68 GstBuffer **buffer,
69 GstBufferPoolAcquireParams *params);
70
71 static void
72 gst_xcam_buffer_pool_release_buffer (GstBufferPool *bpool, GstBuffer *buffer);
73
74
75 XCAM_END_DECLARE
76
77 static void
gst_xcam_buffer_pool_class_init(GstXCamBufferPoolClass * class_self)78 gst_xcam_buffer_pool_class_init (GstXCamBufferPoolClass * class_self)
79 {
80 GObjectClass *object_class;
81 GstBufferPoolClass *bufferpool_class;
82
83 object_class = G_OBJECT_CLASS (class_self);
84 bufferpool_class = GST_BUFFER_POOL_CLASS (class_self);
85
86 object_class->finalize = gst_xcam_buffer_pool_finalize;
87
88 bufferpool_class->start = gst_xcam_buffer_pool_start;
89 bufferpool_class->stop = gst_xcam_buffer_pool_stop;
90 bufferpool_class->set_config = gst_xcam_buffer_pool_set_config;
91 bufferpool_class->acquire_buffer = gst_xcam_buffer_pool_acquire_buffer;
92 bufferpool_class->release_buffer = gst_xcam_buffer_pool_release_buffer;
93
94 }
95
96 static void
gst_xcam_buffer_pool_init(GstXCamBufferPool * pool)97 gst_xcam_buffer_pool_init (GstXCamBufferPool *pool)
98 {
99 pool->need_video_meta = FALSE;
100 XCAM_CONSTRUCTOR (pool->device_manager, SmartPtr<MainDeviceManager>);
101 }
102
103 static void
gst_xcam_buffer_pool_finalize(GObject * object)104 gst_xcam_buffer_pool_finalize (GObject * object)
105 {
106 GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (object);
107 XCAM_ASSERT (pool);
108
109 if (pool->src)
110 gst_object_unref (pool->src);
111 if (pool->allocator)
112 gst_object_unref (pool->allocator);
113 XCAM_DESTRUCTOR (pool->device_manager, SmartPtr<MainDeviceManager>);
114 }
115
116 static gboolean
gst_xcam_buffer_pool_start(GstBufferPool * base_pool)117 gst_xcam_buffer_pool_start (GstBufferPool *base_pool)
118 {
119 GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool);
120 XCAM_ASSERT (pool);
121 SmartPtr<MainDeviceManager> device_manager = pool->device_manager;
122 XCAM_ASSERT (device_manager.ptr ());
123 device_manager->resume_dequeue ();
124 return TRUE;
125 }
126
127 static gboolean
gst_xcam_buffer_pool_stop(GstBufferPool * base_pool)128 gst_xcam_buffer_pool_stop (GstBufferPool *base_pool)
129 {
130 GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool);
131 XCAM_ASSERT (pool);
132 SmartPtr<MainDeviceManager> device_manager = pool->device_manager;
133 XCAM_ASSERT (device_manager.ptr ());
134
135 device_manager->pause_dequeue ();
136 return TRUE;
137 }
138
139 gboolean
gst_xcam_buffer_pool_set_config(GstBufferPool * base_pool,GstStructure * config)140 gst_xcam_buffer_pool_set_config (GstBufferPool *base_pool, GstStructure *config)
141 {
142 GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool);
143
144 XCAM_ASSERT (pool);
145 pool->need_video_meta = gst_buffer_pool_config_has_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
146
147 pool->allocator = gst_dmabuf_allocator_new ();
148 if (pool->allocator == NULL) {
149 GST_WARNING ("xcam buffer pool get allocator failed");
150 return FALSE;
151 }
152
153 return TRUE;
154 }
155
156 static GstFlowReturn
gst_xcam_buffer_pool_acquire_buffer(GstBufferPool * base_pool,GstBuffer ** buffer,GstBufferPoolAcquireParams * params)157 gst_xcam_buffer_pool_acquire_buffer (
158 GstBufferPool *base_pool,
159 GstBuffer **buffer,
160 GstBufferPoolAcquireParams *params)
161 {
162 GstXCamBufferPool *pool = GST_XCAM_BUFFER_POOL (base_pool);
163 XCAM_ASSERT (pool);
164 GstBuffer *out_buf = NULL;
165 GstMemory *mem = NULL;
166 GstXCamBufferMeta *meta = NULL;
167 SmartPtr<MainDeviceManager> device_manager = pool->device_manager;
168 SmartPtr<VideoBuffer> video_buf = device_manager->dequeue_buffer ();
169 VideoBufferInfo video_info;
170 gsize offsets[XCAM_VIDEO_MAX_COMPONENTS];
171
172 XCAM_UNUSED (params);
173
174 if (!video_buf.ptr ())
175 return GST_FLOW_ERROR;
176
177 video_info = video_buf->get_video_info ();
178 for (int i = 0; i < XCAM_VIDEO_MAX_COMPONENTS; i++) {
179 offsets[i] = video_info.offsets[i];
180 }
181
182 out_buf = gst_buffer_new ();
183 meta = gst_buffer_add_xcam_buffer_meta (out_buf, video_buf);
184 XCAM_ASSERT (meta);
185 ((GstMeta *)(meta))->flags = (GstMetaFlags)(GST_META_FLAG_POOLED | GST_META_FLAG_LOCKED | GST_META_FLAG_READONLY);
186 //GST_META_FLAG_SET (meta, (GST_META_FLAG_POOLED | GST_META_FLAG_LOCKED | GST_META_FLAG_READONLY));
187
188 if (GST_XCAM_SRC_MEM_MODE (pool->src) == V4L2_MEMORY_DMABUF) {
189 mem = gst_dmabuf_allocator_alloc (
190 pool->allocator, dup (video_buf->get_fd ()), video_buf->get_size ());
191 } else if (GST_XCAM_SRC_MEM_MODE (pool->src) == V4L2_MEMORY_MMAP) {
192 mem = gst_memory_new_wrapped (
193 (GstMemoryFlags)(GST_MEMORY_FLAG_READONLY | GST_MEMORY_FLAG_NO_SHARE),
194 video_buf->map (), video_buf->get_size (),
195 video_info.offsets[0], video_info.size,
196 NULL, NULL);
197 } else {
198 GST_WARNING ("xcam buffer pool acquire buffer failed since mem_type not supported");
199 return GST_FLOW_ERROR;
200 }
201
202 XCAM_ASSERT (mem);
203 gst_buffer_append_memory (out_buf, mem);
204 if (pool->need_video_meta) {
205 GstVideoMeta *video_meta =
206 gst_buffer_add_video_meta_full (
207 out_buf, GST_VIDEO_FRAME_FLAG_NONE,
208 GST_VIDEO_INFO_FORMAT (GST_XCAM_SRC_OUT_VIDEO_INFO (pool->src)),
209 video_info.width,
210 video_info.height,
211 video_info.components,
212 offsets,
213 (gint*)(video_info.strides));
214 XCAM_ASSERT (video_meta);
215 // TODO, consider map and unmap later
216 video_meta->map = NULL;
217 video_meta->unmap = NULL;
218 }
219
220 GST_BUFFER_TIMESTAMP (out_buf) = video_buf->get_timestamp () * 1000; //us to ns
221
222 *buffer = out_buf;
223 return GST_FLOW_OK;
224 }
225
226 static void
gst_xcam_buffer_pool_release_buffer(GstBufferPool * base_pool,GstBuffer * buffer)227 gst_xcam_buffer_pool_release_buffer (GstBufferPool *base_pool, GstBuffer *buffer)
228 {
229 XCAM_UNUSED (base_pool);
230 gst_buffer_unref (buffer);
231 }
232
233 GstBufferPool *
gst_xcam_buffer_pool_new(GstXCamSrc * src,GstCaps * caps,SmartPtr<MainDeviceManager> & device_manager)234 gst_xcam_buffer_pool_new (GstXCamSrc *src, GstCaps *caps, SmartPtr<MainDeviceManager> &device_manager)
235 {
236 GstXCamBufferPool *pool;
237 GstStructure *structure;
238
239 pool = (GstXCamBufferPool *)g_object_new (GST_TYPE_XCAM_BUFFER_POOL, NULL);
240 XCAM_ASSERT (pool);
241
242 structure = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
243 XCAM_ASSERT (structure);
244 gst_buffer_pool_config_set_params (
245 structure, caps,
246 GST_VIDEO_INFO_SIZE (GST_XCAM_SRC_OUT_VIDEO_INFO (src)),
247 GST_XCAM_SRC_BUF_COUNT (src),
248 GST_XCAM_SRC_BUF_COUNT (src));
249 gst_buffer_pool_config_add_option (structure, GST_BUFFER_POOL_OPTION_VIDEO_META);
250 gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), structure);
251
252 pool->src = src;
253 gst_object_ref (src);
254 pool->device_manager = device_manager;
255 return GST_BUFFER_POOL (pool);
256 }
257