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 "gstvideometa.h"
23 gst_video_meta_transform (GstBuffer * dest, GstMeta * meta,
24 GstBuffer * buffer, GQuark type, gpointer data)
26 GstVideoMeta *dmeta, *smeta;
29 smeta = (GstVideoMeta *) meta;
31 if (GST_META_TRANSFORM_IS_COPY (type)) {
32 GstMetaTransformCopy *copy = data;
35 /* only copy if the complete data is copied as well */
37 (GstVideoMeta *) gst_buffer_add_meta (dest, GST_VIDEO_META_INFO,
41 GST_DEBUG ("copy video metadata");
42 dmeta->flags = smeta->flags;
43 dmeta->format = smeta->format;
44 dmeta->id = smeta->id;
45 dmeta->width = smeta->width;
46 dmeta->height = smeta->height;
48 dmeta->n_planes = smeta->n_planes;
49 for (i = 0; i < dmeta->n_planes; i++) {
50 dmeta->offset[i] = smeta->offset[i];
51 dmeta->stride[i] = smeta->stride[i];
53 dmeta->map = smeta->map;
54 dmeta->unmap = smeta->unmap;
61 gst_video_meta_api_get_type (void)
63 static volatile GType type = 0;
64 static const gchar *tags[] = { "memory", "colorspace", "size", NULL };
66 if (g_once_init_enter (&type)) {
67 GType _type = gst_meta_api_type_register ("GstVideoMetaAPI", tags);
68 g_once_init_leave (&type, _type);
75 gst_video_meta_get_info (void)
77 static const GstMetaInfo *video_meta_info = NULL;
79 if (video_meta_info == NULL) {
81 gst_meta_register (GST_VIDEO_META_API_TYPE, "GstVideoMeta",
82 sizeof (GstVideoMeta), (GstMetaInitFunction) NULL,
83 (GstMetaFreeFunction) NULL, gst_video_meta_transform);
85 return video_meta_info;
89 * gst_buffer_get_video_meta_id:
90 * @buffer: a #GstBuffer
93 * Find the #GstVideoMeta on @buffer with the given @id.
95 * Buffers can contain multiple #GstVideoMeta metadata items when dealing with
98 * Returns: the #GstVideoMeta with @id or %NULL when there is no such metadata
102 gst_buffer_get_video_meta_id (GstBuffer * buffer, gint id)
104 gpointer state = NULL;
106 const GstMetaInfo *info = GST_VIDEO_META_INFO;
108 while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
109 if (meta->info->api == info->api) {
110 GstVideoMeta *vmeta = (GstVideoMeta *) meta;
119 default_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
120 gpointer * data, gint * stride, GstMapFlags flags)
124 GstBuffer *buffer = meta->buffer;
126 offset = meta->offset[plane];
128 /* find the memory block for this plane, this is the memory block containing
129 * the plane offset. FIXME use plane size */
130 if (!gst_buffer_find_memory (buffer, offset, 1, &idx, &length, &skip))
133 if (!gst_buffer_map_range (buffer, idx, length, info, flags))
136 *stride = meta->stride[plane];
137 *data = (guint8 *) info->data + skip;
144 GST_DEBUG ("plane %u, no memory at offset %" G_GSIZE_FORMAT, plane, offset);
149 GST_DEBUG ("cannot map memory range %u-%u", idx, length);
155 default_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
157 GstBuffer *buffer = meta->buffer;
159 gst_buffer_unmap (buffer, info);
165 * gst_buffer_add_video_meta:
166 * @buffer: a #GstBuffer
167 * @flags: #GstVideoFrameFlags
168 * @format: a #GstVideoFormat
170 * @height: the height
172 * Attaches GstVideoMeta metadata to @buffer with the given parameters and the
173 * default offsets and strides for @format and @width x @height.
175 * This function calculates the default offsets and strides and then calls
176 * gst_buffer_add_video_meta_full() with them.
178 * Returns: the #GstVideoMeta on @buffer.
181 gst_buffer_add_video_meta (GstBuffer * buffer,
182 GstVideoFrameFlags flags, GstVideoFormat format, guint width, guint height)
187 gst_video_info_set_format (&info, format, width, height);
190 gst_buffer_add_video_meta_full (buffer, flags, format, width,
191 height, info.finfo->n_planes, info.offset, info.stride);
197 * gst_buffer_add_video_meta_full:
198 * @buffer: a #GstBuffer
199 * @flags: #GstVideoFrameFlags
200 * @format: a #GstVideoFormat
202 * @height: the height
203 * @n_planes: number of planes
204 * @offset: offset of each plane
205 * @stride: stride of each plane
207 * Attaches GstVideoMeta metadata to @buffer with the given parameters.
209 * Returns: the #GstVideoMeta on @buffer.
212 gst_buffer_add_video_meta_full (GstBuffer * buffer,
213 GstVideoFrameFlags flags, GstVideoFormat format, guint width,
214 guint height, guint n_planes, gsize offset[GST_VIDEO_MAX_PLANES],
215 gint stride[GST_VIDEO_MAX_PLANES])
221 (GstVideoMeta *) gst_buffer_add_meta (buffer, GST_VIDEO_META_INFO, NULL);
224 meta->format = format;
227 meta->height = height;
228 meta->buffer = buffer;
230 meta->n_planes = n_planes;
231 for (i = 0; i < n_planes; i++) {
232 meta->offset[i] = offset[i];
233 meta->stride[i] = stride[i];
234 GST_LOG ("plane %d, offset %u, stride %d", i, offset[i], stride[i]);
236 meta->map = default_map;
237 meta->unmap = default_unmap;
243 * gst_video_meta_map:
244 * @meta: a #GstVideoMeta
246 * @info: a #GstMapInfo
247 * @data: the data of @plane
248 * @stride: the stride of @plane
249 * @flags: @GstMapFlags
251 * Map the video plane with index @plane in @meta and return a pointer to the
252 * first byte of the plane and the stride of the plane.
254 * Returns: TRUE if the map operation was successful.
257 gst_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
258 gpointer * data, gint * stride, GstMapFlags flags)
260 g_return_val_if_fail (meta != NULL, FALSE);
261 g_return_val_if_fail (meta->map != NULL, FALSE);
262 g_return_val_if_fail (plane < meta->n_planes, FALSE);
263 g_return_val_if_fail (info != NULL, FALSE);
264 g_return_val_if_fail (data != NULL, FALSE);
265 g_return_val_if_fail (stride != NULL, FALSE);
266 g_return_val_if_fail (meta->buffer != NULL, FALSE);
267 g_return_val_if_fail (!(flags & GST_MAP_WRITE)
268 || gst_buffer_is_writable (meta->buffer), FALSE);
270 return meta->map (meta, plane, info, data, stride, flags);
274 * gst_video_meta_unmap:
275 * @meta: a #GstVideoMeta
277 * @info: a #GstMapInfo
279 * Unmap a previously mapped plane with gst_video_meta_map().
281 * Returns: TRUE if the memory was successfully unmapped.
284 gst_video_meta_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
286 g_return_val_if_fail (meta != NULL, FALSE);
287 g_return_val_if_fail (meta->unmap != NULL, FALSE);
288 g_return_val_if_fail (plane < meta->n_planes, FALSE);
289 g_return_val_if_fail (info != NULL, FALSE);
291 return meta->unmap (meta, plane, info);
295 gst_video_crop_meta_transform (GstBuffer * dest, GstMeta * meta,
296 GstBuffer * buffer, GQuark type, gpointer data)
298 GstVideoCropMeta *dmeta, *smeta;
300 if (GST_META_TRANSFORM_IS_COPY (type)) {
301 smeta = (GstVideoCropMeta *) meta;
302 dmeta = gst_buffer_add_video_crop_meta (dest);
304 GST_DEBUG ("copy crop metadata");
307 dmeta->width = smeta->width;
308 dmeta->height = smeta->height;
309 } else if (GST_VIDEO_META_TRANSFORM_IS_SCALE (type)) {
310 GstVideoMetaTransform *trans = data;
313 smeta = (GstVideoCropMeta *) meta;
314 dmeta = gst_buffer_add_video_crop_meta (dest);
316 ow = GST_VIDEO_INFO_WIDTH (trans->in_info);
317 nw = GST_VIDEO_INFO_WIDTH (trans->out_info);
318 oh = GST_VIDEO_INFO_HEIGHT (trans->in_info);
319 nh = GST_VIDEO_INFO_HEIGHT (trans->out_info);
321 GST_DEBUG ("scaling crop metadata %dx%d -> %dx%d", ow, oh, nw, nh);
322 dmeta->x = (smeta->x * nw) / ow;
323 dmeta->y = (smeta->y * nh) / oh;
324 dmeta->width = (smeta->width * nw) / ow;
325 dmeta->height = (smeta->height * nh) / oh;
326 GST_DEBUG ("crop offset %dx%d -> %dx%d", smeta->x, smeta->y, dmeta->x,
328 GST_DEBUG ("crop size %dx%d -> %dx%d", smeta->width, smeta->height,
329 dmeta->width, dmeta->height);
335 gst_video_crop_meta_api_get_type (void)
337 static volatile GType type = 0;
338 static const gchar *tags[] = { "size", "orientation", NULL };
340 if (g_once_init_enter (&type)) {
341 GType _type = gst_meta_api_type_register ("GstVideoCropMetaAPI", tags);
342 g_once_init_leave (&type, _type);
348 gst_video_crop_meta_get_info (void)
350 static const GstMetaInfo *video_crop_meta_info = NULL;
352 if (video_crop_meta_info == NULL) {
353 video_crop_meta_info =
354 gst_meta_register (GST_VIDEO_CROP_META_API_TYPE, "GstVideoCropMeta",
355 sizeof (GstVideoCropMeta), (GstMetaInitFunction) NULL,
356 (GstMetaFreeFunction) NULL, gst_video_crop_meta_transform);
358 return video_crop_meta_info;
362 * gst_video_meta_transform_scale_get_quark:
364 * Get the #GQuark for the "gst-video-scale" metadata transform operation.
369 gst_video_meta_transform_scale_get_quark (void)
371 static GQuark _value = 0;
374 _value = g_quark_from_static_string ("gst-video-scale");