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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, 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 (g_once_init_enter (&video_meta_info)) {
80 const GstMetaInfo *meta =
81 gst_meta_register (GST_VIDEO_META_API_TYPE, "GstVideoMeta",
82 sizeof (GstVideoMeta), (GstMetaInitFunction) NULL,
83 (GstMetaFreeFunction) NULL, gst_video_meta_transform);
84 g_once_init_leave (&video_meta_info, meta);
86 return video_meta_info;
90 * gst_buffer_get_video_meta_id:
91 * @buffer: a #GstBuffer
94 * Find the #GstVideoMeta on @buffer with the given @id.
96 * Buffers can contain multiple #GstVideoMeta metadata items when dealing with
99 * Returns: the #GstVideoMeta with @id or %NULL when there is no such metadata
103 gst_buffer_get_video_meta_id (GstBuffer * buffer, gint id)
105 gpointer state = NULL;
107 const GstMetaInfo *info = GST_VIDEO_META_INFO;
109 while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
110 if (meta->info->api == info->api) {
111 GstVideoMeta *vmeta = (GstVideoMeta *) meta;
120 default_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
121 gpointer * data, gint * stride, GstMapFlags flags)
125 GstBuffer *buffer = meta->buffer;
127 offset = meta->offset[plane];
129 /* find the memory block for this plane, this is the memory block containing
130 * the plane offset. FIXME use plane size */
131 if (!gst_buffer_find_memory (buffer, offset, 1, &idx, &length, &skip))
134 if (!gst_buffer_map_range (buffer, idx, length, info, flags))
137 *stride = meta->stride[plane];
138 *data = (guint8 *) info->data + skip;
145 GST_DEBUG ("plane %u, no memory at offset %" G_GSIZE_FORMAT, plane, offset);
150 GST_DEBUG ("cannot map memory range %u-%u", idx, length);
156 default_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
158 GstBuffer *buffer = meta->buffer;
160 gst_buffer_unmap (buffer, info);
166 * gst_buffer_add_video_meta:
167 * @buffer: a #GstBuffer
168 * @flags: #GstVideoFrameFlags
169 * @format: a #GstVideoFormat
171 * @height: the height
173 * Attaches GstVideoMeta metadata to @buffer with the given parameters and the
174 * default offsets and strides for @format and @width x @height.
176 * This function calculates the default offsets and strides and then calls
177 * gst_buffer_add_video_meta_full() with them.
179 * Returns: the #GstVideoMeta on @buffer.
182 gst_buffer_add_video_meta (GstBuffer * buffer,
183 GstVideoFrameFlags flags, GstVideoFormat format, guint width, guint height)
188 gst_video_info_set_format (&info, format, width, height);
191 gst_buffer_add_video_meta_full (buffer, flags, format, width,
192 height, info.finfo->n_planes, info.offset, info.stride);
198 * gst_buffer_add_video_meta_full:
199 * @buffer: a #GstBuffer
200 * @flags: #GstVideoFrameFlags
201 * @format: a #GstVideoFormat
203 * @height: the height
204 * @n_planes: number of planes
205 * @offset: offset of each plane
206 * @stride: stride of each plane
208 * Attaches GstVideoMeta metadata to @buffer with the given parameters.
210 * Returns: the #GstVideoMeta on @buffer.
213 gst_buffer_add_video_meta_full (GstBuffer * buffer,
214 GstVideoFrameFlags flags, GstVideoFormat format, guint width,
215 guint height, guint n_planes, gsize offset[GST_VIDEO_MAX_PLANES],
216 gint stride[GST_VIDEO_MAX_PLANES])
222 (GstVideoMeta *) gst_buffer_add_meta (buffer, GST_VIDEO_META_INFO, NULL);
225 meta->format = format;
228 meta->height = height;
229 meta->buffer = buffer;
231 meta->n_planes = n_planes;
232 for (i = 0; i < n_planes; i++) {
233 meta->offset[i] = offset[i];
234 meta->stride[i] = stride[i];
235 GST_LOG ("plane %d, offset %" G_GSIZE_FORMAT ", stride %d", i, offset[i],
238 meta->map = default_map;
239 meta->unmap = default_unmap;
245 * gst_video_meta_map:
246 * @meta: a #GstVideoMeta
248 * @info: a #GstMapInfo
249 * @data: the data of @plane
250 * @stride: the stride of @plane
251 * @flags: @GstMapFlags
253 * Map the video plane with index @plane in @meta and return a pointer to the
254 * first byte of the plane and the stride of the plane.
256 * Returns: TRUE if the map operation was successful.
259 gst_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
260 gpointer * data, gint * stride, GstMapFlags flags)
262 g_return_val_if_fail (meta != NULL, FALSE);
263 g_return_val_if_fail (meta->map != NULL, FALSE);
264 g_return_val_if_fail (plane < meta->n_planes, FALSE);
265 g_return_val_if_fail (info != NULL, FALSE);
266 g_return_val_if_fail (data != NULL, FALSE);
267 g_return_val_if_fail (stride != NULL, FALSE);
268 g_return_val_if_fail (meta->buffer != NULL, FALSE);
269 g_return_val_if_fail (!(flags & GST_MAP_WRITE)
270 || gst_buffer_is_writable (meta->buffer), FALSE);
272 return meta->map (meta, plane, info, data, stride, flags);
276 * gst_video_meta_unmap:
277 * @meta: a #GstVideoMeta
279 * @info: a #GstMapInfo
281 * Unmap a previously mapped plane with gst_video_meta_map().
283 * Returns: TRUE if the memory was successfully unmapped.
286 gst_video_meta_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
288 g_return_val_if_fail (meta != NULL, FALSE);
289 g_return_val_if_fail (meta->unmap != NULL, FALSE);
290 g_return_val_if_fail (plane < meta->n_planes, FALSE);
291 g_return_val_if_fail (info != NULL, FALSE);
293 return meta->unmap (meta, plane, info);
297 gst_video_crop_meta_transform (GstBuffer * dest, GstMeta * meta,
298 GstBuffer * buffer, GQuark type, gpointer data)
300 GstVideoCropMeta *dmeta, *smeta;
302 if (GST_META_TRANSFORM_IS_COPY (type)) {
303 smeta = (GstVideoCropMeta *) meta;
304 dmeta = gst_buffer_add_video_crop_meta (dest);
306 GST_DEBUG ("copy crop metadata");
309 dmeta->width = smeta->width;
310 dmeta->height = smeta->height;
311 } else if (GST_VIDEO_META_TRANSFORM_IS_SCALE (type)) {
312 GstVideoMetaTransform *trans = data;
315 smeta = (GstVideoCropMeta *) meta;
316 dmeta = gst_buffer_add_video_crop_meta (dest);
318 ow = GST_VIDEO_INFO_WIDTH (trans->in_info);
319 nw = GST_VIDEO_INFO_WIDTH (trans->out_info);
320 oh = GST_VIDEO_INFO_HEIGHT (trans->in_info);
321 nh = GST_VIDEO_INFO_HEIGHT (trans->out_info);
323 GST_DEBUG ("scaling crop metadata %dx%d -> %dx%d", ow, oh, nw, nh);
324 dmeta->x = (smeta->x * nw) / ow;
325 dmeta->y = (smeta->y * nh) / oh;
326 dmeta->width = (smeta->width * nw) / ow;
327 dmeta->height = (smeta->height * nh) / oh;
328 GST_DEBUG ("crop offset %dx%d -> %dx%d", smeta->x, smeta->y, dmeta->x,
330 GST_DEBUG ("crop size %dx%d -> %dx%d", smeta->width, smeta->height,
331 dmeta->width, dmeta->height);
337 gst_video_crop_meta_api_get_type (void)
339 static volatile GType type = 0;
340 static const gchar *tags[] = { "size", "orientation", NULL };
342 if (g_once_init_enter (&type)) {
343 GType _type = gst_meta_api_type_register ("GstVideoCropMetaAPI", tags);
344 g_once_init_leave (&type, _type);
350 gst_video_crop_meta_get_info (void)
352 static const GstMetaInfo *video_crop_meta_info = NULL;
354 if (g_once_init_enter (&video_crop_meta_info)) {
355 const GstMetaInfo *meta =
356 gst_meta_register (GST_VIDEO_CROP_META_API_TYPE, "GstVideoCropMeta",
357 sizeof (GstVideoCropMeta), (GstMetaInitFunction) NULL,
358 (GstMetaFreeFunction) NULL, gst_video_crop_meta_transform);
359 g_once_init_leave (&video_crop_meta_info, meta);
361 return video_crop_meta_info;
365 * gst_video_meta_transform_scale_get_quark:
367 * Get the #GQuark for the "gst-video-scale" metadata transform operation.
372 gst_video_meta_transform_scale_get_quark (void)
374 static GQuark _value = 0;
377 _value = g_quark_from_static_string ("gst-video-scale");
384 gst_video_gl_texture_upload_meta_api_get_type (void)
386 static volatile GType type = 0;
387 static const gchar *tags[] = { "memory", NULL };
389 if (g_once_init_enter (&type)) {
391 gst_meta_api_type_register ("GstVideoGLTextureUploadMetaAPI", tags);
392 g_once_init_leave (&type, _type);
398 gst_video_gl_texture_upload_meta_free (GstMeta * meta, GstBuffer * buffer)
400 GstVideoGLTextureUploadMeta *vmeta = (GstVideoGLTextureUploadMeta *) meta;
402 if (vmeta->user_data_free)
403 vmeta->user_data_free (vmeta->user_data);
407 gst_video_gl_texture_upload_meta_transform (GstBuffer * dest, GstMeta * meta,
408 GstBuffer * buffer, GQuark type, gpointer data)
410 GstVideoGLTextureUploadMeta *dmeta, *smeta;
412 smeta = (GstVideoGLTextureUploadMeta *) meta;
414 if (GST_META_TRANSFORM_IS_COPY (type)) {
415 GstMetaTransformCopy *copy = data;
418 /* only copy if the complete data is copied as well */
420 (GstVideoGLTextureUploadMeta *) gst_buffer_add_meta (dest,
421 GST_VIDEO_GL_TEXTURE_UPLOAD_META_INFO, NULL);
422 dmeta->buffer = dest;
423 dmeta->upload = smeta->upload;
424 dmeta->user_data = smeta->user_data;
425 dmeta->user_data_copy = smeta->user_data_copy;
426 dmeta->user_data_free = smeta->user_data_free;
427 if (dmeta->user_data_copy)
428 dmeta->user_data = dmeta->user_data_copy (dmeta->user_data);
435 gst_video_gl_texture_upload_meta_get_info (void)
437 static const GstMetaInfo *info = NULL;
439 if (g_once_init_enter (&info)) {
440 const GstMetaInfo *meta =
441 gst_meta_register (GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE,
442 "GstVideoGLTextureUploadMeta",
443 sizeof (GstVideoGLTextureUploadMeta),
445 gst_video_gl_texture_upload_meta_free,
446 gst_video_gl_texture_upload_meta_transform);
447 g_once_init_leave (&info, meta);
453 * gst_buffer_add_video_meta:
454 * @buffer: a #GstBuffer
455 * @flags: #GstVideoFrameFlags
456 * @format: a #GstVideoFormat
458 * @height: the height
460 * Attaches GstVideoMeta metadata to @buffer with the given parameters and the
461 * default offsets and strides for @format and @width x @height.
463 * This function calculates the default offsets and strides and then calls
464 * gst_buffer_add_video_meta_full() with them.
466 * Returns: the #GstVideoMeta on @buffer.
468 GstVideoGLTextureUploadMeta *
469 gst_buffer_add_video_gl_texture_upload_meta (GstBuffer * buffer,
470 GstVideoGLTextureUpload upload, gpointer user_data,
471 GBoxedCopyFunc user_data_copy, GBoxedFreeFunc user_data_free)
473 GstVideoGLTextureUploadMeta *meta;
475 g_return_val_if_fail (buffer != NULL, NULL);
476 g_return_val_if_fail (upload != NULL, NULL);
479 (GstVideoGLTextureUploadMeta *) gst_buffer_add_meta (buffer,
480 GST_VIDEO_GL_TEXTURE_UPLOAD_META_INFO, NULL);
482 meta->buffer = buffer;
483 meta->upload = upload;
484 meta->user_data = user_data;
485 meta->user_data_copy = user_data_copy;
486 meta->user_data_free = user_data_free;
492 gst_video_gl_texture_upload_meta_upload (GstVideoGLTextureUploadMeta * meta,
493 guint format, guint texture_id)
495 g_return_val_if_fail (meta != NULL, FALSE);
497 return meta->upload (meta, format, texture_id);