2 * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gst/video/gstvideometa.h"
21 #include "gst/video/gstvideopool.h"
24 * gst_video_alignment_reset:
25 * @align: a #GstVideoAlignment
27 * Set @align to its default values with no padding and no alignment.
30 gst_video_alignment_reset (GstVideoAlignment * align)
34 g_return_if_fail (align != NULL);
36 align->padding_top = 0;
37 align->padding_bottom = 0;
38 align->padding_left = 0;
39 align->padding_right = 0;
40 for (i = 0; i < GST_VIDEO_MAX_PLANES; i++)
41 align->stride_align[i] = 0;
45 * gst_buffer_pool_config_set_video_alignment:
46 * @config: a #GstStructure
47 * @align: a #GstVideoAlignment
49 * Set the video alignment in @align to the bufferpool configuration
53 gst_buffer_pool_config_set_video_alignment (GstStructure * config,
54 GstVideoAlignment * align)
56 g_return_if_fail (config != NULL);
57 g_return_if_fail (align != NULL);
59 gst_structure_set (config,
60 "padding-top", G_TYPE_UINT, align->padding_top,
61 "padding-bottom", G_TYPE_UINT, align->padding_bottom,
62 "padding-left", G_TYPE_UINT, align->padding_left,
63 "padding-right", G_TYPE_UINT, align->padding_right,
64 "stride-align0", G_TYPE_UINT, align->stride_align[0],
65 "stride-align1", G_TYPE_UINT, align->stride_align[1],
66 "stride-align2", G_TYPE_UINT, align->stride_align[2],
67 "stride-align3", G_TYPE_UINT, align->stride_align[3], NULL);
71 * gst_buffer_pool_config_get_video_alignment:
72 * @config: a #GstStructure
73 * @align: a #GstVideoAlignment
75 * Get the video alignment from the bufferpool configuration @config in
78 * Returns: #TRUE if @config could be parsed correctly.
81 gst_buffer_pool_config_get_video_alignment (GstStructure * config,
82 GstVideoAlignment * align)
84 g_return_val_if_fail (config != NULL, FALSE);
85 g_return_val_if_fail (align != NULL, FALSE);
87 return gst_structure_get (config,
88 "padding-top", G_TYPE_UINT, &align->padding_top,
89 "padding-bottom", G_TYPE_UINT, &align->padding_bottom,
90 "padding-left", G_TYPE_UINT, &align->padding_left,
91 "padding-right", G_TYPE_UINT, &align->padding_right,
92 "stride-align0", G_TYPE_UINT, &align->stride_align[0],
93 "stride-align1", G_TYPE_UINT, &align->stride_align[1],
94 "stride-align2", G_TYPE_UINT, &align->stride_align[2],
95 "stride-align3", G_TYPE_UINT, &align->stride_align[3], NULL);
99 gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
101 const GstVideoFormatInfo *vinfo = info->finfo;
103 gint padded_width, padded_height;
106 width = GST_VIDEO_INFO_WIDTH (info);
107 height = GST_VIDEO_INFO_HEIGHT (info);
109 GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
110 align->padding_left, align->padding_right, align->padding_bottom);
112 /* add the padding */
113 padded_width = width + align->padding_left + align->padding_right;
114 padded_height = height + align->padding_top + align->padding_bottom;
116 gst_video_info_set_format (info, GST_VIDEO_INFO_FORMAT (info),
117 padded_width, padded_height);
120 info->height = height;
122 /* FIXME, not quite correct, NV12 would apply the vedge twice on the second
124 for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++) {
125 gint vedge, hedge, plane;
127 hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
128 vedge = GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, i, align->padding_top);
129 plane = GST_VIDEO_FORMAT_INFO_PLANE (vinfo, i);
131 GST_DEBUG ("plane %d: hedge %d vedge %d align %d", plane, hedge, vedge,
132 align->stride_align[i]);
134 info->offset[plane] += (vedge * info->stride[plane]) + hedge;
139 struct _GstVideoBufferPoolPrivate
143 GstVideoAlignment video_align;
144 gboolean add_videometa;
145 gboolean need_alignment;
146 GstAllocator *allocator;
147 GstAllocationParams params;
150 static void gst_video_buffer_pool_finalize (GObject * object);
152 #define GST_VIDEO_BUFFER_POOL_GET_PRIVATE(obj) \
153 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_VIDEO_BUFFER_POOL, GstVideoBufferPoolPrivate))
155 #define gst_video_buffer_pool_parent_class parent_class
156 G_DEFINE_TYPE (GstVideoBufferPool, gst_video_buffer_pool, GST_TYPE_BUFFER_POOL);
158 static const gchar **
159 video_buffer_pool_get_options (GstBufferPool * pool)
161 static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
162 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT, NULL
168 video_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
170 GstVideoBufferPool *vpool = GST_VIDEO_BUFFER_POOL_CAST (pool);
171 GstVideoBufferPoolPrivate *priv = vpool->priv;
175 GstAllocator *allocator;
176 GstAllocationParams params;
178 if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
184 /* now parse the caps from the config */
185 if (!gst_video_info_from_caps (&info, caps))
188 if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
192 height = info.height;
194 GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, width, height, caps);
197 gst_caps_unref (priv->caps);
198 priv->caps = gst_caps_copy (caps);
200 priv->params = params;
202 gst_allocator_unref (priv->allocator);
203 if ((priv->allocator = allocator))
204 gst_allocator_ref (allocator);
206 /* enable metadata based on config of the pool */
207 priv->add_videometa =
208 gst_buffer_pool_config_has_option (config,
209 GST_BUFFER_POOL_OPTION_VIDEO_META);
211 /* parse extra alignment info */
212 priv->need_alignment = gst_buffer_pool_config_has_option (config,
213 GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
215 if (priv->need_alignment && priv->add_videometa) {
216 /* get an apply the alignment to the info */
217 gst_buffer_pool_config_get_video_alignment (config, &priv->video_align);
218 gst_video_info_align (&info, &priv->video_align);
222 return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
227 GST_WARNING_OBJECT (pool, "invalid config");
232 GST_WARNING_OBJECT (pool, "no caps in config");
237 GST_WARNING_OBJECT (pool,
238 "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
244 video_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
245 GstBufferPoolAcquireParams * params)
247 GstVideoBufferPool *vpool = GST_VIDEO_BUFFER_POOL_CAST (pool);
248 GstVideoBufferPoolPrivate *priv = vpool->priv;
253 GST_DEBUG_OBJECT (pool, "alloc %" G_GSIZE_FORMAT, info->size);
256 gst_buffer_new_allocate (priv->allocator, info->size, &priv->params);
260 if (priv->add_videometa) {
261 GST_DEBUG_OBJECT (pool, "adding GstVideoMeta");
263 gst_buffer_add_video_meta_full (*buffer, 0, GST_VIDEO_INFO_FORMAT (info),
264 GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info),
265 GST_VIDEO_INFO_N_PLANES (info), info->offset, info->stride);
273 GST_WARNING_OBJECT (pool, "can't create memory");
274 return GST_FLOW_ERROR;
279 * gst_video_buffer_pool_new:
281 * Create a new bufferpool that can allocate video frames. This bufferpool
282 * supports all the video bufferpool options.
284 * Returns: a new #GstBufferPool to allocate video frames
287 gst_video_buffer_pool_new ()
289 GstVideoBufferPool *pool;
291 pool = g_object_new (GST_TYPE_VIDEO_BUFFER_POOL, NULL);
293 GST_LOG_OBJECT (pool, "new video buffer pool %p", pool);
295 return GST_BUFFER_POOL_CAST (pool);
299 gst_video_buffer_pool_class_init (GstVideoBufferPoolClass * klass)
301 GObjectClass *gobject_class = (GObjectClass *) klass;
302 GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
304 g_type_class_add_private (klass, sizeof (GstVideoBufferPoolPrivate));
306 gobject_class->finalize = gst_video_buffer_pool_finalize;
308 gstbufferpool_class->get_options = video_buffer_pool_get_options;
309 gstbufferpool_class->set_config = video_buffer_pool_set_config;
310 gstbufferpool_class->alloc_buffer = video_buffer_pool_alloc;
314 gst_video_buffer_pool_init (GstVideoBufferPool * pool)
316 pool->priv = GST_VIDEO_BUFFER_POOL_GET_PRIVATE (pool);
320 gst_video_buffer_pool_finalize (GObject * object)
322 GstVideoBufferPool *pool = GST_VIDEO_BUFFER_POOL_CAST (object);
323 GstVideoBufferPoolPrivate *priv = pool->priv;
325 GST_LOG_OBJECT (pool, "finalize video buffer pool %p", pool);
328 gst_caps_unref (priv->caps);
331 gst_allocator_ref (priv->allocator);
333 G_OBJECT_CLASS (gst_video_buffer_pool_parent_class)->finalize (object);