| /* |
| * Copyright (C) 2010 Ole André Vadla Ravnås <oleavr@soundrop.com> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "corevideobuffer.h" |
| |
| static void |
| gst_core_video_meta_free (GstCoreVideoMeta * meta, GstBuffer * buf) |
| { |
| if (meta->pixbuf != NULL) { |
| CVPixelBufferUnlockBaseAddress (meta->pixbuf, 0); |
| } |
| |
| CVBufferRelease (meta->cvbuf); |
| } |
| |
| GType |
| gst_core_video_meta_api_get_type (void) |
| { |
| static volatile GType type; |
| static const gchar *tags[] = { "memory", NULL }; |
| |
| if (g_once_init_enter (&type)) { |
| GType _type = gst_meta_api_type_register ("GstCoreVideoMetaAPI", tags); |
| g_once_init_leave (&type, _type); |
| } |
| return type; |
| } |
| |
| static const GstMetaInfo * |
| gst_core_video_meta_get_info (void) |
| { |
| static const GstMetaInfo *core_video_meta_info = NULL; |
| |
| if (g_once_init_enter (&core_video_meta_info)) { |
| const GstMetaInfo *meta = gst_meta_register (GST_CORE_VIDEO_META_API_TYPE, |
| "GstCoreVideoMeta", sizeof (GstCoreVideoMeta), |
| (GstMetaInitFunction) NULL, |
| (GstMetaFreeFunction) gst_core_video_meta_free, |
| (GstMetaTransformFunction) NULL); |
| g_once_init_leave (&core_video_meta_info, meta); |
| } |
| return core_video_meta_info; |
| } |
| |
| GstBuffer * |
| gst_core_video_buffer_new (CVBufferRef cvbuf, GstVideoInfo * vinfo, |
| gboolean map) |
| { |
| CVPixelBufferRef pixbuf = NULL; |
| GstBuffer *buf; |
| GstCoreVideoMeta *meta; |
| guint n_planes; |
| gsize offset[GST_VIDEO_MAX_PLANES]; |
| gint stride[GST_VIDEO_MAX_PLANES]; |
| |
| if (CFGetTypeID (cvbuf) != CVPixelBufferGetTypeID ()) |
| /* TODO: Do we need to handle other buffer types? */ |
| goto error; |
| |
| pixbuf = (CVPixelBufferRef) cvbuf; |
| |
| if (map && CVPixelBufferLockBaseAddress (pixbuf, 0) != kCVReturnSuccess) { |
| goto error; |
| } |
| |
| buf = gst_buffer_new (); |
| |
| /* add the corevideo meta to free the underlying corevideo buffer */ |
| meta = (GstCoreVideoMeta *) gst_buffer_add_meta (buf, |
| gst_core_video_meta_get_info (), NULL); |
| meta->cvbuf = CVBufferRetain (cvbuf); |
| meta->pixbuf = pixbuf; |
| |
| /* set stride, offset and size */ |
| memset (&offset, 0, sizeof (offset)); |
| memset (&stride, 0, sizeof (stride)); |
| |
| if (CVPixelBufferIsPlanar (pixbuf)) { |
| int i, size, off; |
| |
| n_planes = CVPixelBufferGetPlaneCount (pixbuf); |
| off = 0; |
| for (i = 0; i < n_planes; ++i) { |
| stride[i] = CVPixelBufferGetBytesPerRowOfPlane (pixbuf, i); |
| size = stride[i] * CVPixelBufferGetHeightOfPlane (pixbuf, i); |
| offset[i] = off; |
| off += size; |
| |
| if (map) { |
| gst_buffer_append_memory (buf, |
| gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, |
| CVPixelBufferGetBaseAddressOfPlane (pixbuf, i), size, 0, size, |
| NULL, NULL)); |
| } |
| } |
| } else { |
| int size; |
| |
| n_planes = 1; |
| stride[0] = CVPixelBufferGetBytesPerRow (pixbuf); |
| offset[0] = 0; |
| size = stride[0] * CVPixelBufferGetHeight (pixbuf); |
| |
| if (map) { |
| gst_buffer_append_memory (buf, |
| gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, |
| CVPixelBufferGetBaseAddress (pixbuf), size, 0, size, NULL, NULL)); |
| } |
| } |
| |
| if (vinfo) { |
| GstVideoMeta *video_meta; |
| |
| video_meta = |
| gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, |
| vinfo->finfo->format, CVPixelBufferGetWidth (pixbuf), |
| CVPixelBufferGetHeight (pixbuf), n_planes, offset, stride); |
| } |
| |
| return buf; |
| |
| error: |
| return NULL; |
| } |