applemedia: don't use the dynamic API for public frameworks

Public frameworks don't need to build the API dynamically, we instead
use the framework directly.
The exception is for VideoToolbox which went public in the 10.8 SDK,
but it's still private in older version of the SDK and iOS. This allow
building the plugin against SDK's where it's not a public framework.
This commit is contained in:
Andoni Morales Alastruey 2013-04-24 22:15:01 +02:00 committed by Sebastian Dröge
parent 57b97beb6d
commit 97bb1edf6c
14 changed files with 77 additions and 653 deletions

View file

@ -7,8 +7,6 @@ libgstapplemedia_la_SOURCES = \
corevideobuffer.c \
coremediabuffer.c \
coremediactx.c \
cvapi.c \
cmapi.c \
vtapi.c \
dynapi.c
@ -38,6 +36,7 @@ libgstapplemedia_la_LDFLAGS = \
$(GST_BASE_LDFLAGS) \
$(GST_PLUGINS_BASE_LDFLAGS) \
-Wl,-framework -Wl,CoreFoundation \
-Wl,-framework -Wl,CoreMedia \
-Wl,-framework -Wl,CoreVideo
noinst_HEADERS = \
@ -52,8 +51,6 @@ noinst_HEADERS = \
corevideobuffer.h \
coremediabuffer.h \
coremediactx.h \
cvapi.h \
cmapi.h \
vtapi.h \
dynapi.h \
dynapi-internal.h

View file

@ -1,137 +0,0 @@
/*
* 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 "cmapi.h"
#include "dynapi-internal.h"
#include <gmodule.h>
#define CM_FRAMEWORK_PATH "/System/Library/Frameworks/" \
"CoreMedia.framework/CoreMedia"
#define CM_FRAMEWORK_PATH_OLD "/System/Library/PrivateFrameworks/" \
"CoreMedia.framework/CoreMedia"
G_DEFINE_TYPE (GstCMApi, gst_cm_api, GST_TYPE_DYN_API);
static void
gst_cm_api_init (GstCMApi * self)
{
}
static void
gst_cm_api_class_init (GstCMApiClass * klass)
{
}
#define SYM_SPEC(name) GST_DYN_SYM_SPEC (GstCMApi, name)
GstCMApi *
gst_cm_api_obtain (GError ** error)
{
static const GstDynSymSpec symbols[] = {
SYM_SPEC (FigBaseObjectGetVTable),
SYM_SPEC (CMGetAttachment),
SYM_SPEC (FigFormatDescriptionRelease),
SYM_SPEC (FigFormatDescriptionRetain),
SYM_SPEC (CMFormatDescriptionEqual),
SYM_SPEC (CMFormatDescriptionGetExtension),
SYM_SPEC (CMFormatDescriptionGetMediaType),
SYM_SPEC (CMFormatDescriptionGetMediaSubType),
SYM_SPEC (CMVideoFormatDescriptionCreate),
SYM_SPEC
(FigVideoFormatDescriptionCreateWithSampleDescriptionExtensionAtom),
SYM_SPEC (CMVideoFormatDescriptionGetDimensions),
SYM_SPEC (CMTimeMake),
SYM_SPEC (CMSampleBufferCreate),
SYM_SPEC (CMSampleBufferDataIsReady),
SYM_SPEC (CMSampleBufferGetDataBuffer),
SYM_SPEC (CMSampleBufferGetFormatDescription),
SYM_SPEC (CMSampleBufferGetImageBuffer),
SYM_SPEC (CMSampleBufferGetNumSamples),
SYM_SPEC (CMSampleBufferGetSampleAttachmentsArray),
SYM_SPEC (CMSampleBufferGetSampleSize),
SYM_SPEC (FigSampleBufferRelease),
SYM_SPEC (FigSampleBufferRetain),
SYM_SPEC (CMBlockBufferCreateWithMemoryBlock),
SYM_SPEC (CMBlockBufferGetDataLength),
SYM_SPEC (CMBlockBufferGetDataPointer),
SYM_SPEC (FigBlockBufferRelease),
SYM_SPEC (FigBlockBufferRetain),
SYM_SPEC (CMBufferQueueDequeueAndRetain),
SYM_SPEC (CMBufferQueueGetBufferCount),
SYM_SPEC (CMBufferQueueInstallTrigger),
SYM_SPEC (CMBufferQueueIsEmpty),
SYM_SPEC (FigBufferQueueRelease),
SYM_SPEC (CMBufferQueueRemoveTrigger),
SYM_SPEC (CMBufferQueueSetValidationCallback),
SYM_SPEC (kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms),
SYM_SPEC (kCMSampleAttachmentKey_DependsOnOthers),
SYM_SPEC (kCMTimeInvalid),
{NULL, 0},
};
GstCMApi *result;
GModule *module;
/* We cannot stat() the library as it may not be present on the filesystem.
* This is the case on newer versions of iOS where system libraries are all
* part of dyld_shared_cache... */
module = g_module_open (CM_FRAMEWORK_PATH, 0);
if (module != NULL) {
result = _gst_dyn_api_new (gst_cm_api_get_type (), CM_FRAMEWORK_PATH,
symbols, error);
g_module_close (module);
} else {
GstDynSymSpec *old_symbols;
guint i;
old_symbols = g_memdup (symbols, sizeof (symbols));
for (i = 0; old_symbols[i].name != NULL; i++) {
const gchar *name = old_symbols[i].name;
const gchar *translated_name;
if (g_str_has_prefix (name, "CM"))
translated_name = g_strconcat ("Fig", name + 2, NULL);
else if (g_str_has_prefix (name, "kCM"))
translated_name = g_strconcat ("kFig", name + 3, NULL);
else
translated_name = g_strdup (name);
old_symbols[i].name = translated_name;
}
result = _gst_dyn_api_new (gst_cm_api_get_type (), CM_FRAMEWORK_PATH_OLD,
old_symbols, error);
for (i = 0; old_symbols[i].name != NULL; i++)
g_free ((gpointer) old_symbols[i].name);
g_free (old_symbols);
}
return result;
}

View file

@ -1,212 +0,0 @@
/*
* 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.
*/
#ifndef __GST_CM_API_H__
#define __GST_CM_API_H__
#include "dynapi.h"
#include <CoreFoundation/CoreFoundation.h>
#include "cvapi.h"
G_BEGIN_DECLS
typedef struct _GstCMApi GstCMApi;
typedef struct _GstCMApiClass GstCMApiClass;
typedef CFTypeRef FigBaseObjectRef;
typedef struct _FigBaseVTable FigBaseVTable;
typedef struct _FigBaseIface FigBaseIface;
typedef CFTypeRef CMFormatDescriptionRef;
typedef struct _CMVideoDimensions CMVideoDimensions;
typedef struct _CMTime CMTime;
typedef CFTypeRef CMBufferQueueRef;
typedef SInt32 CMBufferQueueTriggerCondition;
typedef struct _CMBufferQueueTriggerToken *CMBufferQueueTriggerToken;
typedef CFTypeRef CMSampleBufferRef;
typedef CFTypeRef CMBlockBufferRef;
typedef void (* CMBufferQueueTriggerCallback) (void *triggerRefcon,
CMBufferQueueTriggerToken triggerToken);
typedef Boolean (* CMBufferQueueValidationCallback) (CMBufferQueueRef queue,
CMSampleBufferRef buf, void *refCon);
enum _FigMediaType
{
kFigMediaTypeVideo = 'vide'
};
enum _FigCodecType
{
kComponentVideoUnsigned = 'yuvs',
kFigVideoCodecType_JPEG_OpenDML = 'dmb1',
kYUV420vCodecType = '420v'
};
enum _CMBufferQueueTriggerCondition
{
kCMBufferQueueTrigger_WhenDurationBecomesLessThan = 1,
kCMBufferQueueTrigger_WhenDurationBecomesLessThanOrEqualTo = 2,
kCMBufferQueueTrigger_WhenDurationBecomesGreaterThan = 3,
kCMBufferQueueTrigger_WhenDurationBecomesGreaterThanOrEqualTo = 4,
kCMBufferQueueTrigger_WhenMinPresentationTimeStampChanges = 5,
kCMBufferQueueTrigger_WhenMaxPresentationTimeStampChanges = 6,
kCMBufferQueueTrigger_WhenDataBecomesReady = 7,
kCMBufferQueueTrigger_WhenEndOfDataReached = 8,
kCMBufferQueueTrigger_WhenReset = 9,
kCMBufferQueueTrigger_WhenBufferCountBecomesLessThan = 10,
kCMBufferQueueTrigger_WhenBufferCountBecomesGreaterThan = 11
};
struct _FigBaseVTable
{
gsize unk;
FigBaseIface * base;
void * derived;
};
struct _FigBaseIface
{
gsize unk1;
gsize unk2;
gsize unk3;
OSStatus (* Invalidate) (FigBaseObjectRef obj);
OSStatus (* Finalize) (FigBaseObjectRef obj);
gpointer unk4;
OSStatus (* CopyProperty) (FigBaseObjectRef obj, CFTypeRef key, void *unk,
CFTypeRef * value);
OSStatus (* SetProperty) (FigBaseObjectRef obj, CFTypeRef key,
CFTypeRef value);
};
struct _CMVideoDimensions
{
UInt32 width;
UInt32 height;
};
struct _CMTime
{
UInt8 data[24];
};
struct _GstCMApi
{
GstDynApi parent;
FigBaseVTable * (* FigBaseObjectGetVTable) (FigBaseObjectRef obj);
void * (* CMGetAttachment) (CFTypeRef obj, CFStringRef attachmentKey,
UInt32 * foundWherePtr);
void (* FigFormatDescriptionRelease) (CMFormatDescriptionRef desc);
CMFormatDescriptionRef (* FigFormatDescriptionRetain) (
CMFormatDescriptionRef desc);
Boolean (* CMFormatDescriptionEqual) (CMFormatDescriptionRef desc1,
CMFormatDescriptionRef desc2);
CFTypeRef (* CMFormatDescriptionGetExtension) (
const CMFormatDescriptionRef desc, CFStringRef extensionKey);
UInt32 (* CMFormatDescriptionGetMediaType) (
const CMFormatDescriptionRef desc);
UInt32 (* CMFormatDescriptionGetMediaSubType) (
const CMFormatDescriptionRef desc);
OSStatus (* CMVideoFormatDescriptionCreate) (
CFAllocatorRef allocator, UInt32 formatId, UInt32 width, UInt32 height,
CFDictionaryRef extensions, CMFormatDescriptionRef * desc);
OSStatus (* FigVideoFormatDescriptionCreateWithSampleDescriptionExtensionAtom)
(CFAllocatorRef allocator, UInt32 formatId, UInt32 width, UInt32 height,
UInt32 atomId, const UInt8 * data, CFIndex len, void *unk1,
CMFormatDescriptionRef * formatDesc);
CMVideoDimensions (* CMVideoFormatDescriptionGetDimensions) (
const CMFormatDescriptionRef desc);
CMTime (* CMTimeMake) (int64_t value, int32_t timescale);
OSStatus (* CMSampleBufferCreate) (CFAllocatorRef allocator,
CMBlockBufferRef blockBuf, Boolean dataReady,
void *makeDataReadyCallback,
void *makeDataReadyRefcon,
CMFormatDescriptionRef fmtDesc, size_t numSamples,
size_t numSampleTimingEntries,
const void *sampleTimingArray,
size_t numSampleSizeEntries, const size_t *sampleSizeArray,
CMSampleBufferRef * sampleBuffer);
Boolean (* CMSampleBufferDataIsReady) (
const CMSampleBufferRef buf);
CMBlockBufferRef (* CMSampleBufferGetDataBuffer) (
const CMSampleBufferRef buf);
CMFormatDescriptionRef (* CMSampleBufferGetFormatDescription) (
const CMSampleBufferRef buf);
CVImageBufferRef (* CMSampleBufferGetImageBuffer) (
const CMSampleBufferRef buf);
SInt32 (* CMSampleBufferGetNumSamples) (
const CMSampleBufferRef buf);
CFArrayRef (* CMSampleBufferGetSampleAttachmentsArray) (
const CMSampleBufferRef buf, SInt32 sampleIndex);
SInt32 (* CMSampleBufferGetSampleSize) (
const CMSampleBufferRef buf, SInt32 sampleIndex);
void (* FigSampleBufferRelease) (CMSampleBufferRef buf);
CMSampleBufferRef (* FigSampleBufferRetain) (CMSampleBufferRef buf);
OSStatus (* CMBlockBufferCreateWithMemoryBlock)
(CFAllocatorRef allocator, void * memoryBlock, size_t blockLength,
CFAllocatorRef dataAllocator, void *customBlockSource,
size_t offsetToData, size_t dataLength,
int flags, CMBlockBufferRef * blockBuffer);
SInt32 (* CMBlockBufferGetDataLength) (const CMBlockBufferRef buf);
OSStatus (* CMBlockBufferGetDataPointer) (
const CMBlockBufferRef buf, UInt32 unk1, UInt32 unk2, UInt32 unk3,
Byte ** dataPtr);
void (* FigBlockBufferRelease) (CMBlockBufferRef buf);
CMBlockBufferRef (* FigBlockBufferRetain) (CMBlockBufferRef buf);
CMSampleBufferRef (* CMBufferQueueDequeueAndRetain)
(CMBufferQueueRef queue);
CFIndex (* CMBufferQueueGetBufferCount) (CMBufferQueueRef queue);
OSStatus (* CMBufferQueueInstallTrigger) (CMBufferQueueRef queue,
CMBufferQueueTriggerCallback triggerCallback, void * triggerRefCon,
CMBufferQueueTriggerCondition triggerCondition, CMTime triggerTime,
CMBufferQueueTriggerToken * triggerTokenOut);
Boolean (* CMBufferQueueIsEmpty) (CMBufferQueueRef queue);
void (* FigBufferQueueRelease) (CMBufferQueueRef queue);
OSStatus (* CMBufferQueueRemoveTrigger) (CMBufferQueueRef queue,
CMBufferQueueTriggerToken triggerToken);
OSStatus (* CMBufferQueueSetValidationCallback) (CMBufferQueueRef queue,
CMBufferQueueValidationCallback func, void *refCon);
CFStringRef * kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms;
CFStringRef * kCMSampleAttachmentKey_DependsOnOthers;
CMTime * kCMTimeInvalid;
};
struct _GstCMApiClass
{
GstDynApiClass parent_class;
};
GType gst_cm_api_get_type (void);
GstCMApi * gst_cm_api_obtain (GError ** error);
G_END_DECLS
#endif

View file

@ -23,12 +23,10 @@ static void
gst_core_media_meta_free (GstCoreMediaMeta * meta, GstBuffer * buf)
{
if (meta->image_buf != NULL) {
GstCVApi *cv = meta->ctx->cv;
cv->CVPixelBufferUnlockBaseAddress (meta->image_buf,
CVPixelBufferUnlockBaseAddress (meta->image_buf,
kCVPixelBufferLock_ReadOnly);
}
meta->ctx->cm->FigSampleBufferRelease (meta->sample_buf);
g_object_unref (meta->ctx);
CVBufferRelease ((CVBufferRef)meta->sample_buf);
}
GType
@ -61,53 +59,51 @@ gst_core_media_meta_get_info (void)
}
GstBuffer *
gst_core_media_buffer_new (GstCoreMediaCtx * ctx, CMSampleBufferRef sample_buf)
gst_core_media_buffer_new (CMSampleBufferRef sample_buf)
{
GstCVApi *cv = ctx->cv;
GstCMApi *cm = ctx->cm;
CVImageBufferRef image_buf;
CVPixelBufferRef pixel_buf;
CMBlockBufferRef block_buf;
Byte *data = NULL;
gchar *data = NULL;
UInt32 size;
OSStatus status;
GstBuffer *buf;
GstCoreMediaMeta *meta;
image_buf = cm->CMSampleBufferGetImageBuffer (sample_buf);
image_buf = CMSampleBufferGetImageBuffer (sample_buf);
pixel_buf = NULL;
block_buf = cm->CMSampleBufferGetDataBuffer (sample_buf);
block_buf = CMSampleBufferGetDataBuffer (sample_buf);
if (image_buf != NULL &&
CFGetTypeID (image_buf) == cv->CVPixelBufferGetTypeID ()) {
CFGetTypeID (image_buf) == CVPixelBufferGetTypeID ()) {
pixel_buf = (CVPixelBufferRef) image_buf;
if (cv->CVPixelBufferLockBaseAddress (pixel_buf,
if (CVPixelBufferLockBaseAddress (pixel_buf,
kCVPixelBufferLock_ReadOnly) != kCVReturnSuccess) {
goto error;
}
if (cv->CVPixelBufferIsPlanar (pixel_buf)) {
if (CVPixelBufferIsPlanar (pixel_buf)) {
gint plane_count, plane_idx;
data = cv->CVPixelBufferGetBaseAddressOfPlane (pixel_buf, 0);
data = CVPixelBufferGetBaseAddressOfPlane (pixel_buf, 0);
size = 0;
plane_count = cv->CVPixelBufferGetPlaneCount (pixel_buf);
plane_count = CVPixelBufferGetPlaneCount (pixel_buf);
for (plane_idx = 0; plane_idx != plane_count; plane_idx++) {
size += cv->CVPixelBufferGetBytesPerRowOfPlane (pixel_buf, plane_idx) *
cv->CVPixelBufferGetHeightOfPlane (pixel_buf, plane_idx);
size += CVPixelBufferGetBytesPerRowOfPlane (pixel_buf, plane_idx) *
CVPixelBufferGetHeightOfPlane (pixel_buf, plane_idx);
}
} else {
data = cv->CVPixelBufferGetBaseAddress (pixel_buf);
size = cv->CVPixelBufferGetBytesPerRow (pixel_buf) *
cv->CVPixelBufferGetHeight (pixel_buf);
data = CVPixelBufferGetBaseAddress (pixel_buf);
size = CVPixelBufferGetBytesPerRow (pixel_buf) *
CVPixelBufferGetHeight (pixel_buf);
}
} else if (block_buf != NULL) {
status = cm->CMBlockBufferGetDataPointer (block_buf, 0, 0, 0, &data);
status = CMBlockBufferGetDataPointer (block_buf, 0, 0, 0, &data);
if (status != noErr)
goto error;
size = cm->CMBlockBufferGetDataLength (block_buf);
size = CMBlockBufferGetDataLength (block_buf);
} else {
goto error;
}
@ -116,8 +112,8 @@ gst_core_media_buffer_new (GstCoreMediaCtx * ctx, CMSampleBufferRef sample_buf)
meta = (GstCoreMediaMeta *) gst_buffer_add_meta (buf,
gst_core_media_meta_get_info (), NULL);
meta->ctx = g_object_ref (ctx);
meta->sample_buf = cm->FigSampleBufferRetain (sample_buf);
CVBufferRetain ((CVBufferRef)sample_buf);
meta->sample_buf = sample_buf;
meta->image_buf = image_buf;
meta->pixel_buf = pixel_buf;
meta->block_buf = block_buf;
@ -139,5 +135,5 @@ gst_core_media_buffer_get_pixel_buffer (GstBuffer * buf)
GST_CORE_MEDIA_META_API_TYPE);
g_return_val_if_fail (meta != NULL, NULL);
return meta->ctx->cv->CVPixelBufferRetain (meta->pixel_buf);
return CVPixelBufferRetain (meta->pixel_buf);
}

View file

@ -22,7 +22,7 @@
#include <gst/gst.h>
#include "coremediactx.h"
#include "CoreMedia/CoreMedia.h"
G_BEGIN_DECLS
@ -34,7 +34,6 @@ typedef struct _GstCoreMediaMeta
{
GstMeta meta;
GstCoreMediaCtx * ctx;
CMSampleBufferRef sample_buf;
CVImageBufferRef image_buf;
CVPixelBufferRef pixel_buf;
@ -42,8 +41,7 @@ typedef struct _GstCoreMediaMeta
} GstCoreMediaMeta;
GstBuffer * gst_core_media_buffer_new (GstCoreMediaCtx * ctx,
CMSampleBufferRef sample_buf);
GstBuffer * gst_core_media_buffer_new (CMSampleBufferRef sample_buf);
CVPixelBufferRef gst_core_media_buffer_get_pixel_buffer
(GstBuffer * buf);
GType gst_core_media_meta_api_get_type (void);

View file

@ -41,8 +41,6 @@ struct _GstApiProvider
G_STRUCT_OFFSET (GstCoreMediaCtx, a_n) }
static const GstApiProvider api_provider[] = {
API_PROVIDER (CORE_VIDEO, cv),
API_PROVIDER (CORE_MEDIA, cm),
API_PROVIDER (VIDEO_TOOLBOX, vt),
};

View file

@ -20,8 +20,6 @@
#ifndef __GST_CORE_MEDIA_CTX_H__
#define __GST_CORE_MEDIA_CTX_H__
#include "cvapi.h"
#include "cmapi.h"
#include "vtapi.h"
#include <glib.h>
@ -51,8 +49,6 @@ struct _GstCoreMediaCtx
GObject parent;
/* Common */
GstCVApi *cv;
GstCMApi *cm;
GstVTApi *vt;
};
@ -63,9 +59,7 @@ struct _GstCoreMediaCtxClass
enum _GstCoreMediaApi
{
GST_API_CORE_VIDEO = (1 << 0),
GST_API_CORE_MEDIA = (1 << 1),
GST_API_VIDEO_TOOLBOX = (1 << 2),
GST_API_VIDEO_TOOLBOX = (1 << 0),
};
GType gst_core_media_ctx_get_type (void);

View file

@ -22,15 +22,12 @@
static void
gst_core_video_meta_free (GstCoreVideoMeta * meta, GstBuffer * buf)
{
GstCVApi *cv = meta->ctx->cv;
if (meta->pixbuf != NULL) {
cv->CVPixelBufferUnlockBaseAddress (meta->pixbuf,
CVPixelBufferUnlockBaseAddress (meta->pixbuf,
kCVPixelBufferLock_ReadOnly);
}
cv->CVBufferRelease (meta->cvbuf);
g_object_unref (meta->ctx);
CVBufferRelease (meta->cvbuf);
}
GType
@ -63,10 +60,9 @@ gst_core_video_meta_get_info (void)
}
GstBuffer *
gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf,
gst_core_video_buffer_new (CVBufferRef cvbuf,
GstVideoInfo * vinfo)
{
GstCVApi *cv = ctx->cv;
void *data;
size_t size;
CVPixelBufferRef pixbuf = NULL;
@ -76,13 +72,13 @@ gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf,
gsize offset[GST_VIDEO_MAX_PLANES];
gint stride[GST_VIDEO_MAX_PLANES];
if (CFGetTypeID (cvbuf) != cv->CVPixelBufferGetTypeID ())
if (CFGetTypeID (cvbuf) != CVPixelBufferGetTypeID ())
/* TODO: Do we need to handle other buffer types? */
goto error;
pixbuf = (CVPixelBufferRef) cvbuf;
if (cv->CVPixelBufferLockBaseAddress (pixbuf,
if (CVPixelBufferLockBaseAddress (pixbuf,
kCVPixelBufferLock_ReadOnly) != kCVReturnSuccess) {
goto error;
}
@ -92,22 +88,21 @@ gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf,
/* 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->ctx = g_object_ref (ctx);
meta->cvbuf = cv->CVBufferRetain (cvbuf);
meta->cvbuf = CVBufferRetain (cvbuf);
meta->pixbuf = pixbuf;
/* set stride, offset and size */
memset (&offset, 0, sizeof (offset));
memset (&stride, 0, sizeof (stride));
data = cv->CVPixelBufferGetBaseAddress (pixbuf);
height = cv->CVPixelBufferGetHeight (pixbuf);
if (cv->CVPixelBufferIsPlanar (pixbuf)) {
data = CVPixelBufferGetBaseAddress (pixbuf);
height = CVPixelBufferGetHeight (pixbuf);
if (CVPixelBufferIsPlanar (pixbuf)) {
GstVideoInfo tmp_vinfo;
n_planes = cv->CVPixelBufferGetPlaneCount (pixbuf);
n_planes = CVPixelBufferGetPlaneCount (pixbuf);
for (i = 0; i < n_planes; ++i)
stride[i] = cv->CVPixelBufferGetBytesPerRowOfPlane (pixbuf, i);
stride[i] = CVPixelBufferGetBytesPerRowOfPlane (pixbuf, i);
/* FIXME: don't hardcode NV12 */
gst_video_info_init (&tmp_vinfo);
@ -117,7 +112,7 @@ gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf,
size = tmp_vinfo.size;
} else {
n_planes = 1;
size = cv->CVPixelBufferGetBytesPerRow (pixbuf) * height;
size = CVPixelBufferGetBytesPerRow (pixbuf) * height;
}
gst_buffer_append_memory (buf,

View file

@ -24,7 +24,7 @@
#include <gst/video/video.h>
#include <gst/video/gstvideometa.h>
#include "coremediactx.h"
#include "CoreVideo/CoreVideo.h"
G_BEGIN_DECLS
@ -36,13 +36,11 @@ typedef struct _GstCoreVideoMeta
{
GstMeta meta;
GstCoreMediaCtx *ctx;
CVBufferRef cvbuf;
CVPixelBufferRef pixbuf;
} GstCoreVideoMeta;
GstBuffer * gst_core_video_buffer_new (GstCoreMediaCtx * ctx,
CVBufferRef cvbuf,
GstBuffer * gst_core_video_buffer_new (CVBufferRef cvbuf,
GstVideoInfo *info);
GType gst_core_video_meta_api_get_type (void);

View file

@ -1,77 +0,0 @@
/*
* 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 "cvapi.h"
#include "dynapi-internal.h"
#define CV_FRAMEWORK_PATH "/System/Library/Frameworks/CoreVideo.framework/" \
"CoreVideo"
G_DEFINE_TYPE (GstCVApi, gst_cv_api, GST_TYPE_DYN_API);
static void
gst_cv_api_init (GstCVApi * self)
{
}
static void
gst_cv_api_class_init (GstCVApiClass * klass)
{
}
#define SYM_SPEC(name) GST_DYN_SYM_SPEC (GstCVApi, name)
#define SYM_SPEC_OPTIONAL(name) GST_DYN_SYM_SPEC_OPTIONAL (GstCVApi, name)
GstCVApi *
gst_cv_api_obtain (GError ** error)
{
static const GstDynSymSpec symbols[] = {
SYM_SPEC (CVBufferRelease),
SYM_SPEC (CVBufferRetain),
SYM_SPEC (CVPixelBufferCreateWithBytes),
SYM_SPEC (CVPixelBufferCreateWithPlanarBytes),
SYM_SPEC (CVPixelBufferGetBaseAddress),
SYM_SPEC (CVPixelBufferGetBaseAddressOfPlane),
SYM_SPEC (CVPixelBufferGetBytesPerRow),
SYM_SPEC (CVPixelBufferGetBytesPerRowOfPlane),
SYM_SPEC (CVPixelBufferGetHeight),
SYM_SPEC (CVPixelBufferGetHeightOfPlane),
SYM_SPEC_OPTIONAL (CVPixelBufferGetIOSurface),
SYM_SPEC (CVPixelBufferGetPlaneCount),
SYM_SPEC (CVPixelBufferGetTypeID),
SYM_SPEC (CVPixelBufferIsPlanar),
SYM_SPEC (CVPixelBufferLockBaseAddress),
SYM_SPEC (CVPixelBufferRelease),
SYM_SPEC (CVPixelBufferRetain),
SYM_SPEC (CVPixelBufferUnlockBaseAddress),
SYM_SPEC (kCVPixelBufferPixelFormatTypeKey),
SYM_SPEC (kCVPixelBufferWidthKey),
SYM_SPEC (kCVPixelBufferHeightKey),
SYM_SPEC (kCVPixelBufferBytesPerRowAlignmentKey),
SYM_SPEC (kCVPixelBufferPlaneAlignmentKey),
{NULL, 0},
};
return _gst_dyn_api_new (gst_cv_api_get_type (), CV_FRAMEWORK_PATH, symbols,
error);
}

View file

@ -1,126 +0,0 @@
/*
* 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.
*/
#ifndef __GST_CV_API_H__
#define __GST_CV_API_H__
#include "dynapi.h"
#include <CoreFoundation/CoreFoundation.h>
G_BEGIN_DECLS
typedef struct _GstCVApi GstCVApi;
typedef struct _GstCVApiClass GstCVApiClass;
typedef int32_t CVReturn;
typedef uint64_t CVOptionFlags;
typedef struct _CVBuffer * CVBufferRef;
typedef CVBufferRef CVImageBufferRef;
typedef CVImageBufferRef CVPixelBufferRef;
typedef void (* CVPixelBufferReleaseBytesCallback) (void * releaseRefCon,
const void * baseAddress);
enum _CVReturn
{
kCVReturnSuccess = 0
};
enum _CVPixelFormatType
{
kCVPixelFormatType_420YpCbCr8Planar = 'y420',
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v',
kCVPixelFormatType_422YpCbCr8Deprecated = 'yuvs',
kCVPixelFormatType_422YpCbCr8 = '2vuy'
};
enum _CVPixelBufferLockFlags
{
kCVPixelBufferLock_ReadOnly = 0x00000001
};
struct _GstCVApi
{
GstDynApi parent;
void (* CVBufferRelease) (CVBufferRef buffer);
CVBufferRef (* CVBufferRetain) (CVBufferRef buffer);
CVReturn (* CVPixelBufferCreateWithBytes)
(CFAllocatorRef allocator, size_t width, size_t height,
OSType pixelFormatType, void * baseAddress, size_t bytesPerRow,
CVPixelBufferReleaseBytesCallback releaseCallback,
void * releaseRefCon, CFDictionaryRef pixelBufferAttributes,
CVPixelBufferRef * pixelBufferOut);
CVReturn (* CVPixelBufferCreateWithPlanarBytes)
(CFAllocatorRef allocator, size_t width, size_t height,
OSType pixelFormatType, void * dataPtr, size_t dataSize,
size_t numberOfPlanes, void *planeBaseAddress[],
size_t planeWidth[], size_t planeHeight[],
size_t planeBytesPerRow[],
CVPixelBufferReleaseBytesCallback releaseCallback,
void * releaseRefCon, CFDictionaryRef pixelBufferAttributes,
CVPixelBufferRef * pixelBufferOut);
void * (* CVPixelBufferGetBaseAddress)
(CVPixelBufferRef pixelBuffer);
void * (* CVPixelBufferGetBaseAddressOfPlane)
(CVPixelBufferRef pixelBuffer, size_t planeIndex);
size_t (* CVPixelBufferGetBytesPerRow)
(CVPixelBufferRef pixelBuffer);
size_t (* CVPixelBufferGetBytesPerRowOfPlane)
(CVPixelBufferRef pixelBuffer, size_t planeIndex);
size_t (* CVPixelBufferGetHeight) (CVPixelBufferRef pixelBuffer);
size_t (* CVPixelBufferGetHeightOfPlane)
(CVPixelBufferRef pixelBuffer, size_t planeIndex);
void * (* CVPixelBufferGetIOSurface)
(CVPixelBufferRef pixelBuffer);
size_t (* CVPixelBufferGetPlaneCount)
(CVPixelBufferRef pixelBuffer);
CFTypeID (* CVPixelBufferGetTypeID) (void);
Boolean (* CVPixelBufferIsPlanar) (CVPixelBufferRef pixelBuffer);
CVReturn (* CVPixelBufferLockBaseAddress)
(CVPixelBufferRef pixelBuffer, CVOptionFlags lockFlags);
void (* CVPixelBufferRelease) (CVPixelBufferRef pixelBuffer);
CVPixelBufferRef (* CVPixelBufferRetain)
(CVPixelBufferRef pixelBuffer);
CVReturn (* CVPixelBufferUnlockBaseAddress)
(CVPixelBufferRef pixelBuffer, CVOptionFlags unlockFlags);
CFStringRef * kCVPixelBufferPixelFormatTypeKey;
CFStringRef * kCVPixelBufferWidthKey;
CFStringRef * kCVPixelBufferHeightKey;
CFStringRef * kCVPixelBufferBytesPerRowAlignmentKey;
CFStringRef * kCVPixelBufferPlaneAlignmentKey;
};
struct _GstCVApiClass
{
GstDynApiClass parent_class;
};
GType gst_cv_api_get_type (void);
GstCVApi * gst_cv_api_obtain (GError ** error);
G_END_DECLS
#endif

View file

@ -20,7 +20,8 @@
#ifndef __GST_VT_API_H__
#define __GST_VT_API_H__
#include "cmapi.h"
#include "dynapi.h"
#include "CoreMedia/CoreMedia.h"
G_BEGIN_DECLS

View file

@ -54,6 +54,11 @@ static gboolean gst_vtdec_sink_event (GstPad * pad, GstObject * parent,
static CMSampleBufferRef gst_vtdec_sample_buffer_from (GstVTDec * self,
GstBuffer * buf);
extern OSStatus FigVideoFormatDescriptionCreateWithSampleDescriptionExtensionAtom
(CFAllocatorRef allocator, UInt32 formatId, UInt32 width, UInt32 height,
UInt32 atomId, const UInt8 * data, CFIndex len, void *unk1,
CMFormatDescriptionRef * formatDesc);
static void
gst_vtdec_base_init (GstVTDecClass * klass)
{
@ -143,8 +148,7 @@ gst_vtdec_change_state (GstElement * element, GstStateChange transition)
GstStateChangeReturn ret;
if (transition == GST_STATE_CHANGE_NULL_TO_READY) {
self->ctx = gst_core_media_ctx_new (GST_API_CORE_VIDEO | GST_API_CORE_MEDIA
| GST_API_VIDEO_TOOLBOX, &error);
self->ctx = gst_core_media_ctx_new (GST_API_VIDEO_TOOLBOX, &error);
if (error != NULL)
goto api_error;
@ -156,7 +160,7 @@ gst_vtdec_change_state (GstElement * element, GstStateChange transition)
if (transition == GST_STATE_CHANGE_READY_TO_NULL) {
gst_vtdec_destroy_session (self, &self->session);
self->ctx->cm->FigFormatDescriptionRelease (self->fmt_desc);
CFRelease (self->fmt_desc);
self->fmt_desc = NULL;
gst_video_info_init (&self->vinfo);
@ -261,7 +265,9 @@ gst_vtdec_sink_setcaps (GstVTDec * self, GstCaps * caps)
if (fmt_desc != NULL) {
gst_vtdec_destroy_session (self, &self->session);
self->ctx->cm->FigFormatDescriptionRelease (self->fmt_desc);
if (self->fmt_desc != NULL) {
CFRelease (self->fmt_desc);
}
self->fmt_desc = fmt_desc;
self->session = gst_vtdec_create_session (self, fmt_desc);
@ -339,7 +345,7 @@ gst_vtdec_create_format_description (GstVTDec * self)
CMFormatDescriptionRef fmt_desc;
OSStatus status;
status = self->ctx->cm->CMVideoFormatDescriptionCreate (NULL,
status = CMVideoFormatDescriptionCreate (NULL,
self->details->format_id, self->vinfo.width, self->vinfo.height,
NULL, &fmt_desc);
if (status == noErr)
@ -359,7 +365,6 @@ gst_vtdec_create_format_description_from_codec_data (GstVTDec * self,
gst_buffer_map (codec_data, &map, GST_MAP_READ);
status =
self->ctx->cm->
FigVideoFormatDescriptionCreateWithSampleDescriptionExtensionAtom (NULL,
self->details->format_id, self->vinfo.width, self->vinfo.height, 'avcC',
map.data, map.size, NULL, &fmt_desc);
@ -376,21 +381,20 @@ static VTDecompressionSessionRef
gst_vtdec_create_session (GstVTDec * self, CMFormatDescriptionRef fmt_desc)
{
VTDecompressionSessionRef session = NULL;
GstCVApi *cv = self->ctx->cv;
CFMutableDictionaryRef pb_attrs;
VTDecompressionOutputCallback callback;
VTStatus status;
pb_attrs = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferPixelFormatTypeKey),
gst_vtutil_dict_set_i32 (pb_attrs, kCVPixelBufferPixelFormatTypeKey,
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange);
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferWidthKey),
gst_vtutil_dict_set_i32 (pb_attrs, kCVPixelBufferWidthKey,
self->vinfo.width);
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey),
gst_vtutil_dict_set_i32 (pb_attrs, kCVPixelBufferHeightKey,
self->vinfo.height);
gst_vtutil_dict_set_i32 (pb_attrs,
*(cv->kCVPixelBufferBytesPerRowAlignmentKey), 2 * self->vinfo.width);
kCVPixelBufferBytesPerRowAlignmentKey, 2 * self->vinfo.width);
callback.func = gst_vtdec_enqueue_frame;
callback.data = self;
@ -439,7 +443,7 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf)
"VTDecompressionSessionWaitForAsynchronousFrames returned %d", status);
}
self->ctx->cm->FigSampleBufferRelease (sbuf);
CFRelease (sbuf);
self->cur_inbuf = NULL;
gst_buffer_unref (buf);
@ -472,7 +476,7 @@ gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2,
if (result != kVTSuccess)
goto beach;
buf = gst_core_video_buffer_new (self->ctx, cvbuf, &self->vinfo);
buf = gst_core_video_buffer_new (cvbuf, &self->vinfo);
gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_METADATA, 0, -1);
g_ptr_array_add (self->cur_outbufs, buf);
@ -484,7 +488,6 @@ beach:
static CMSampleBufferRef
gst_vtdec_sample_buffer_from (GstVTDec * self, GstBuffer * buf)
{
GstCMApi *cm = self->ctx->cm;
OSStatus status;
CMBlockBufferRef bbuf = NULL;
CMSampleBufferRef sbuf = NULL;
@ -494,7 +497,7 @@ gst_vtdec_sample_buffer_from (GstVTDec * self, GstBuffer * buf)
gst_buffer_map (buf, &map, GST_MAP_READ);
status = cm->CMBlockBufferCreateWithMemoryBlock (NULL,
status = CMBlockBufferCreateWithMemoryBlock (NULL,
map.data, (gint64) map.size, kCFAllocatorNull, NULL, 0, (gint64) map.size,
FALSE, &bbuf);
@ -503,13 +506,13 @@ gst_vtdec_sample_buffer_from (GstVTDec * self, GstBuffer * buf)
if (status != noErr)
goto error;
status = cm->CMSampleBufferCreate (NULL, bbuf, TRUE, 0, 0, self->fmt_desc,
status = CMSampleBufferCreate (NULL, bbuf, TRUE, 0, 0, self->fmt_desc,
1, 0, NULL, 0, NULL, &sbuf);
if (status != noErr)
goto error;
beach:
cm->FigBlockBufferRelease (bbuf);
CFRelease (bbuf);
return sbuf;
error:

View file

@ -295,8 +295,7 @@ gst_vtenc_change_state (GstElement * element, GstStateChange transition)
GstStateChangeReturn ret;
if (transition == GST_STATE_CHANGE_NULL_TO_READY) {
self->ctx = gst_core_media_ctx_new (GST_API_CORE_VIDEO | GST_API_CORE_MEDIA
| GST_API_VIDEO_TOOLBOX, &error);
self->ctx = gst_core_media_ctx_new (GST_API_VIDEO_TOOLBOX, &error);
if (error != NULL)
goto api_error;
@ -409,7 +408,6 @@ static gboolean
gst_vtenc_negotiate_downstream (GstVTEnc * self, CMSampleBufferRef sbuf)
{
gboolean result;
GstCMApi *cm = self->ctx->cm;
GstCaps *caps;
GstStructure *s;
@ -437,9 +435,9 @@ gst_vtenc_negotiate_downstream (GstVTEnc * self, CMSampleBufferRef sbuf)
gsize codec_data_size;
GstBuffer *codec_data_buf;
fmt = cm->CMSampleBufferGetFormatDescription (sbuf);
atoms = cm->CMFormatDescriptionGetExtension (fmt,
*(cm->kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms));
fmt = CMSampleBufferGetFormatDescription (sbuf);
atoms = CMFormatDescriptionGetExtension (fmt,
kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms);
avccKey = CFStringCreateWithCString (NULL, "avcC", kCFStringEncodingUTF8);
avcc = CFDictionaryGetValue (atoms, avccKey);
CFRelease (avccKey);
@ -525,7 +523,6 @@ static VTCompressionSessionRef
gst_vtenc_create_session (GstVTEnc * self)
{
VTCompressionSessionRef session = NULL;
GstCVApi *cv = self->ctx->cv;
GstVTApi *vt = self->ctx->vt;
CFMutableDictionaryRef pb_attrs;
VTCompressionOutputCallback callback;
@ -533,11 +530,11 @@ gst_vtenc_create_session (GstVTEnc * self)
pb_attrs = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferPixelFormatTypeKey),
gst_vtutil_dict_set_i32 (pb_attrs, kCVPixelBufferPixelFormatTypeKey,
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange);
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferWidthKey),
gst_vtutil_dict_set_i32 (pb_attrs, kCVPixelBufferWidthKey,
self->negotiated_width);
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey),
gst_vtutil_dict_set_i32 (pb_attrs, kCVPixelBufferHeightKey,
self->negotiated_height);
callback.func = gst_vtenc_enqueue_buffer;
@ -753,7 +750,6 @@ gst_vtenc_session_configure_property_double (GstVTEnc * self,
static GstFlowReturn
gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf)
{
GstCVApi *cv = self->ctx->cv;
GstVTApi *vt = self->ctx->vt;
CMTime ts, duration;
GstCoreMediaMeta *meta;
@ -764,9 +760,9 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf)
self->cur_inbuf = buf;
ts = self->ctx->cm->CMTimeMake
ts = CMTimeMake
(GST_TIME_AS_MSECONDS (GST_BUFFER_TIMESTAMP (buf)), 1000);
duration = self->ctx->cm->CMTimeMake
duration = CMTimeMake
(GST_TIME_AS_MSECONDS (GST_BUFFER_DURATION (buf)), 1000);
meta = gst_buffer_get_core_media_meta (buf);
@ -779,9 +775,9 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf)
CVReturn cv_ret;
frame = gst_vtenc_frame_new (buf);
cv_ret = cv->CVPixelBufferCreateWithBytes (NULL,
cv_ret = CVPixelBufferCreateWithBytes (NULL,
self->negotiated_width, self->negotiated_height,
kCVPixelFormatType_422YpCbCr8Deprecated, frame->map.data,
kCVPixelFormatType_422YpCbCr8, frame->map.data,
self->negotiated_width * 2,
(CVPixelBufferReleaseBytesCallback) gst_vtenc_frame_free, frame,
NULL, &pbuf);
@ -807,11 +803,11 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf)
}
self->ctx->vt->VTCompressionSessionCompleteFrames (self->session,
*(self->ctx->cm->kCMTimeInvalid));
kCMTimeInvalid);
GST_OBJECT_UNLOCK (self);
cv->CVPixelBufferRelease (pbuf);
CVPixelBufferRelease (pbuf);
self->cur_inbuf = NULL;
gst_buffer_unref (buf);
@ -866,7 +862,7 @@ gst_vtenc_enqueue_buffer (void *data, int a2, int a3, int a4,
}
self->expect_keyframe = FALSE;
buf = gst_core_media_buffer_new (self->ctx, sbuf);
buf = gst_core_media_buffer_new (sbuf);
gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_TIMESTAMPS,
0, -1);
if (is_keyframe) {
@ -889,14 +885,14 @@ gst_vtenc_buffer_is_keyframe (GstVTEnc * self, CMSampleBufferRef sbuf)
CFArrayRef attachments_for_sample;
attachments_for_sample =
self->ctx->cm->CMSampleBufferGetSampleAttachmentsArray (sbuf, 0);
CMSampleBufferGetSampleAttachmentsArray (sbuf, 0);
if (attachments_for_sample != NULL) {
CFDictionaryRef attachments;
CFBooleanRef depends_on_others;
attachments = CFArrayGetValueAtIndex (attachments_for_sample, 0);
depends_on_others = CFDictionaryGetValue (attachments,
*(self->ctx->cm->kCMSampleAttachmentKey_DependsOnOthers));
kCMSampleAttachmentKey_DependsOnOthers);
result = (depends_on_others == kCFBooleanFalse);
}