applemedia: implement copying of meta

Before this, buffers would lose their Core Video / Core Media meta
over intervideo* boundary.

https://bugzilla.gnome.org/show_bug.cgi?id=747216
This commit is contained in:
Ilya Konstantinov 2015-04-19 00:30:48 +03:00 committed by Alessandro Decina
parent 936b2fdfbc
commit 8577224c74
2 changed files with 77 additions and 19 deletions

View file

@ -23,12 +23,38 @@
#include "coremediabuffer.h"
#include "corevideomemory.h"
static const GstMetaInfo *gst_core_media_meta_get_info (void);
static void
gst_core_media_meta_add (GstBuffer * buffer, CMSampleBufferRef sample_buf,
CVImageBufferRef image_buf, CMBlockBufferRef block_buf)
{
GstCoreMediaMeta *meta;
meta =
(GstCoreMediaMeta *) gst_buffer_add_meta (buffer,
gst_core_media_meta_get_info (), NULL);
CFRetain (sample_buf);
if (image_buf)
CVBufferRetain (image_buf);
if (block_buf)
CFRetain (block_buf);
meta->sample_buf = sample_buf;
meta->image_buf = image_buf;
meta->block_buf = block_buf;
if (image_buf != NULL && CFGetTypeID (image_buf) == CVPixelBufferGetTypeID ())
meta->pixel_buf = (CVPixelBufferRef) image_buf;
else
meta->pixel_buf = NULL;
}
static void
gst_core_media_meta_free (GstCoreMediaMeta * meta, GstBuffer * buf)
{
if (meta->image_buf != NULL) {
CVBufferRelease (meta->image_buf);
}
if (meta->block_buf != NULL) {
CFRelease (meta->block_buf);
}
@ -36,6 +62,22 @@ gst_core_media_meta_free (GstCoreMediaMeta * meta, GstBuffer * buf)
CFRelease (meta->sample_buf);
}
static gboolean
gst_core_media_meta_transform (GstBuffer * transbuf, GstCoreMediaMeta * meta,
GstBuffer * buffer, GQuark type, GstMetaTransformCopy * data)
{
if (!data->region) {
/* only copy if the complete data is copied as well */
gst_core_media_meta_add (transbuf, meta->sample_buf, meta->image_buf,
meta->block_buf);
} else {
GST_WARNING_OBJECT (transbuf,
"dropping Core Media metadata due to partial buffer");
}
return TRUE; /* retval unused */
}
GType
gst_core_media_meta_api_get_type (void)
{
@ -59,7 +101,7 @@ gst_core_media_meta_get_info (void)
"GstCoreMediaMeta", sizeof (GstCoreMediaMeta),
(GstMetaInitFunction) NULL,
(GstMetaFreeFunction) gst_core_media_meta_free,
(GstMetaTransformFunction) NULL);
(GstMetaTransformFunction) gst_core_media_meta_transform);
g_once_init_leave (&core_media_meta_info, meta);
}
return core_media_meta_info;
@ -190,7 +232,6 @@ gst_core_media_buffer_new (CMSampleBufferRef sample_buf,
{
CVImageBufferRef image_buf;
CMBlockBufferRef block_buf;
GstCoreMediaMeta *meta;
GstBuffer *buf;
image_buf = CMSampleBufferGetImageBuffer (sample_buf);
@ -198,29 +239,18 @@ gst_core_media_buffer_new (CMSampleBufferRef sample_buf,
buf = gst_buffer_new ();
meta = (GstCoreMediaMeta *) gst_buffer_add_meta (buf,
gst_core_media_meta_get_info (), NULL);
CFRetain (sample_buf);
if (image_buf)
CVBufferRetain (image_buf);
if (block_buf)
CFRetain (block_buf);
meta->sample_buf = sample_buf;
meta->image_buf = image_buf;
meta->pixel_buf = NULL;
meta->block_buf = block_buf;
gst_core_media_meta_add (buf, sample_buf, image_buf, block_buf);
if (image_buf != NULL && CFGetTypeID (image_buf) == CVPixelBufferGetTypeID ()) {
GstVideoInfo info;
gboolean has_padding = FALSE;
CVPixelBufferRef pixel_buf = (CVPixelBufferRef) image_buf;
meta->pixel_buf = (CVPixelBufferRef) image_buf;
if (!gst_video_info_init_from_pixel_buffer (&info, meta->pixel_buf)) {
if (!gst_video_info_init_from_pixel_buffer (&info, pixel_buf)) {
goto error;
}
gst_core_video_wrap_pixel_buffer (buf, &info, meta->pixel_buf, &has_padding,
map);
gst_core_video_wrap_pixel_buffer (buf, &info, pixel_buf, &has_padding, map);
/* If the video meta API is not supported, remove padding by
* copying the core media buffer to a system memory buffer */

View file

@ -20,12 +20,40 @@
#include "corevideobuffer.h"
#include "corevideomemory.h"
static const GstMetaInfo *gst_core_video_meta_get_info (void);
static void
gst_core_video_meta_add (GstBuffer * buffer, CVBufferRef cvbuf)
{
GstCoreVideoMeta *meta;
meta = (GstCoreVideoMeta *) gst_buffer_add_meta (buffer,
gst_core_video_meta_get_info (), NULL);
meta->cvbuf = CVBufferRetain (cvbuf);
meta->pixbuf = (CVPixelBufferRef) cvbuf;
}
static void
gst_core_video_meta_free (GstCoreVideoMeta * meta, GstBuffer * buf)
{
CVBufferRelease (meta->cvbuf);
}
static gboolean
gst_core_video_meta_transform (GstBuffer * transbuf, GstCoreVideoMeta * meta,
GstBuffer * buffer, GQuark type, GstMetaTransformCopy * data)
{
if (!data->region) {
/* only copy if the complete data is copied as well */
gst_core_video_meta_add (transbuf, meta->cvbuf);
} else {
GST_WARNING_OBJECT (transbuf,
"dropping Core Video metadata due to partial buffer");
}
return TRUE; /* retval unused */
}
GType
gst_core_video_meta_api_get_type (void)
{
@ -49,7 +77,7 @@ gst_core_video_meta_get_info (void)
"GstCoreVideoMeta", sizeof (GstCoreVideoMeta),
(GstMetaInitFunction) NULL,
(GstMetaFreeFunction) gst_core_video_meta_free,
(GstMetaTransformFunction) NULL);
(GstMetaTransformFunction) gst_core_video_meta_transform);
g_once_init_leave (&core_video_meta_info, meta);
}
return core_video_meta_info;
@ -140,7 +168,7 @@ gst_core_video_buffer_new (CVBufferRef cvbuf, GstVideoInfo * vinfo,
buf = gst_buffer_new ();
/* add the corevideo meta to free the underlying corevideo buffer */
/* add the corevideo meta to pass the underlying corevideo buffer */
meta = (GstCoreVideoMeta *) gst_buffer_add_meta (buf,
gst_core_video_meta_get_info (), NULL);
meta->cvbuf = CVBufferRetain (cvbuf);