From: Andoni Morales Alastruey Date: Thu, 26 Sep 2013 11:21:59 +0000 (+0200) Subject: iosassetsrc: Add new element from the GStreamer SDK project X-Git-Tag: 1.19.3~507^2~13060 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e5d5faa67eb69a457b3addf6113b09a068bbacf5;p=platform%2Fupstream%2Fgstreamer.git iosassetsrc: Add new element from the GStreamer SDK project --- diff --git a/sys/applemedia/Makefile.am b/sys/applemedia/Makefile.am index f8cdd19..27872b4 100644 --- a/sys/applemedia/Makefile.am +++ b/sys/applemedia/Makefile.am @@ -67,11 +67,13 @@ noinst_HEADERS = \ vtapi.h \ atdec.h \ dynapi.h \ - dynapi-internal.h + dynapi-internal.h \ + iosassetsrc.h if HAVE_IOS -#libgstapplemedia_la_SOURCES += \ +libgstapplemedia_la_SOURCES += \ + iosassetsrc.m # avfvideosrc.m #libgstapplemedia_la_LDFLAGS += \ diff --git a/sys/applemedia/iosassetsrc.h b/sys/applemedia/iosassetsrc.h new file mode 100644 index 0000000..d874938 --- /dev/null +++ b/sys/applemedia/iosassetsrc.h @@ -0,0 +1,83 @@ +/* GStreamer + * Copyright (C) 2013 Fluendo S.L. + * Authors: 2013 Andoni Morales Alastruey + * + * gstios_assetsrc.h: + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_IOS_ASSET_SRC_H__ +#define __GST_IOS_ASSET_SRC_H__ + +#include + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_IOS_ASSET_SRC \ + (gst_ios_asset_src_get_type()) +#define GST_IOS_ASSET_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IOS_ASSET_SRC,GstIOSAssetSrc)) +#define GST_IOS_ASSET_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IOS_ASSET_SRC,GstIOSAssetSrcClass)) +#define GST_IS_IOS_ASSET_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IOS_ASSET_SRC)) +#define GST_IS_IOS_ASSET_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IOS_ASSET_SRC)) +#define GST_IOS_ASSET_SRC_CAST(obj) ((GstIOSAssetSrc*) obj) + +typedef struct _GstIOSAssetSrc GstIOSAssetSrc; +typedef struct _GstIOSAssetSrcClass GstIOSAssetSrcClass; + +@interface GstAssetsLibrary : ALAssetsLibrary +{ +} + +@property (retain) ALAsset *asset; +@property (retain) ALAssetRepresentation *result; + +- (ALAssetRepresentation *) assetForURLSync:(NSURL*) uri; +@end + +/** + * GstIOSAssetSrc: + * + * Opaque #GstIOSAssetSrc structure. + */ +struct _GstIOSAssetSrc { + GstBaseSrc element; + + /*< private >*/ + gchar * uri; /* asset uri */ + NSURL * url; /* asset url */ + ALAssetRepresentation * asset; /* asset representation */ + GstAssetsLibrary * library; /* assets library */ +}; + +struct _GstIOSAssetSrcClass { + GstBaseSrcClass parent_class; +}; + +GType gst_ios_asset_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_IOS_ASSET_SRC_H__ */ diff --git a/sys/applemedia/iosassetsrc.m b/sys/applemedia/iosassetsrc.m new file mode 100644 index 0000000..4464316 --- /dev/null +++ b/sys/applemedia/iosassetsrc.m @@ -0,0 +1,504 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gstios_assetsrc.c: + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-ios_assetsrc + * @see_also: #GstIOSAssetSrc + * + * Read data from an iOS asset from the media library. + * + * + * Example launch line + * |[ + * gst-launch iosassetsrc uri=assets-library://asset/asset.M4V?id=11&ext=M4V ! decodebin2 ! autoaudiosink + * ]| Plays asset with id a song.ogg from local dir. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "iosassetsrc.h" + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_ios_asset_src_debug); +#define GST_CAT_DEFAULT gst_ios_asset_src_debug + + +#define DEFAULT_BLOCKSIZE 4*1024 +#define OBJC_CALLOUT_BEGIN() \ + NSAutoreleasePool *pool; \ + \ + pool = [[NSAutoreleasePool alloc] init] +#define OBJC_CALLOUT_END() \ + [pool release] + +enum +{ + ARG_0, + ARG_URI, +}; + +static void gst_ios_asset_src_finalize (GObject * object); + +static void gst_ios_asset_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_ios_asset_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_ios_asset_src_start (GstBaseSrc * basesrc); +static gboolean gst_ios_asset_src_stop (GstBaseSrc * basesrc); + +static gboolean gst_ios_asset_src_is_seekable (GstBaseSrc * src); +static gboolean gst_ios_asset_src_get_size (GstBaseSrc * src, guint64 * size); +static GstFlowReturn gst_ios_asset_src_create (GstBaseSrc * src, guint64 offset, + guint length, GstBuffer ** buffer); +static gboolean gst_ios_asset_src_query (GstBaseSrc * src, GstQuery * query); + +static void gst_ios_asset_src_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +static void +_do_init (GType ios_assetsrc_type) +{ + static const GInterfaceInfo urihandler_info = { + gst_ios_asset_src_uri_handler_init, + NULL, + NULL + }; + + g_type_add_interface_static (ios_assetsrc_type, GST_TYPE_URI_HANDLER, + &urihandler_info); + GST_DEBUG_CATEGORY_INIT (gst_ios_asset_src_debug, "iosassetsrc", 0, "iosassetsrc element"); +} + +GST_BOILERPLATE_FULL (GstIOSAssetSrc, gst_ios_asset_src, GstBaseSrc, GST_TYPE_BASE_SRC, + _do_init); + +static void +gst_ios_asset_src_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "IOSAsset Source", + "Source/File", + "Read from arbitrary point in a iOS asset", + "Andoni Morales Alastruey "); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); +} + +static void +gst_ios_asset_src_class_init (GstIOSAssetSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasesrc_class = GST_BASE_SRC_CLASS (klass); + + gobject_class->set_property = gst_ios_asset_src_set_property; + gobject_class->get_property = gst_ios_asset_src_get_property; + + g_object_class_install_property (gobject_class, ARG_URI, + g_param_spec_string ("uri", "Asset URI", + "URI of the asset to read", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); + + gobject_class->finalize = gst_ios_asset_src_finalize; + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_ios_asset_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_ios_asset_src_stop); + gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_ios_asset_src_is_seekable); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_ios_asset_src_get_size); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_ios_asset_src_create); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_ios_asset_src_query); +} + +static void +gst_ios_asset_src_init (GstIOSAssetSrc * src, GstIOSAssetSrcClass * g_class) +{ + OBJC_CALLOUT_BEGIN (); + src->uri = NULL; + src->asset = NULL; + src->library = [[[GstAssetsLibrary alloc] init] retain]; + gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE); + OBJC_CALLOUT_END (); +} + +static void +gst_ios_asset_src_free_resources (GstIOSAssetSrc *src) +{ + OBJC_CALLOUT_BEGIN (); + if (src->asset != NULL) { + [src->asset release]; + src->asset = NULL; + } + + if (src->url != NULL) { + [src->url release]; + src->url = NULL; + } + + if (src->uri != NULL) { + g_free (src->uri); + src->uri = NULL; + } + OBJC_CALLOUT_END (); +} + +static void +gst_ios_asset_src_finalize (GObject * object) +{ + GstIOSAssetSrc *src; + + OBJC_CALLOUT_BEGIN (); + src = GST_IOS_ASSET_SRC (object); + gst_ios_asset_src_free_resources (src); + [src->library release]; + + OBJC_CALLOUT_END (); + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_ios_asset_src_set_uri (GstIOSAssetSrc * src, const gchar * uri) +{ + GstState state; + NSString *nsuristr; + NSURL *url; + + OBJC_CALLOUT_BEGIN (); + /* the element must be stopped in order to do this */ + GST_OBJECT_LOCK (src); + state = GST_STATE (src); + if (state != GST_STATE_READY && state != GST_STATE_NULL) + goto wrong_state; + GST_OBJECT_UNLOCK (src); + + gst_ios_asset_src_free_resources (src); + + nsuristr = [[NSString alloc] initWithUTF8String:uri]; + url = [[NSURL alloc] initWithString:nsuristr]; + + if (url == NULL) { + GST_ERROR_OBJECT (src, "Invalid URI : %s", src->uri); + return FALSE; + } + + GST_INFO_OBJECT (src, "URI : %s", src->uri); + src->url = url; + src->uri = g_strdup (uri); + g_object_notify (G_OBJECT (src), "uri"); + gst_uri_handler_new_uri (GST_URI_HANDLER (src), src->uri); + + OBJC_CALLOUT_END (); + return TRUE; + + /* ERROR */ +wrong_state: + { + g_warning ("Changing the 'uri' property on iosassetsrc when an asset is " + "open is not supported."); + GST_OBJECT_UNLOCK (src); + OBJC_CALLOUT_END (); + return FALSE; + } +} + +static void +gst_ios_asset_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstIOSAssetSrc *src; + + g_return_if_fail (GST_IS_IOS_ASSET_SRC (object)); + + src = GST_IOS_ASSET_SRC (object); + + switch (prop_id) { + case ARG_URI: + gst_ios_asset_src_set_uri (src, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ios_asset_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstIOSAssetSrc *src; + + g_return_if_fail (GST_IS_IOS_ASSET_SRC (object)); + + src = GST_IOS_ASSET_SRC (object); + + switch (prop_id) { + case ARG_URI: + g_value_set_string (value, src->uri); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +gst_ios_asset_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, + GstBuffer ** buffer) +{ + GstBuffer *buf; + NSError *err = nil; + guint bytes_read; + GstFlowReturn ret; + GstIOSAssetSrc *src = GST_IOS_ASSET_SRC (basesrc); + + OBJC_CALLOUT_BEGIN (); + buf = gst_buffer_try_new_and_alloc (length); + if (G_UNLIKELY (buf == NULL && length > 0)) { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length); + ret = GST_FLOW_ERROR; + goto exit; + } + + /* No need to read anything if length is 0 */ + GST_BUFFER_SIZE (buf) = 0; + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset; + bytes_read = [src->asset getBytes: GST_BUFFER_DATA (buf) + fromOffset:offset + length:length + error:&err]; + if (G_UNLIKELY (err != NULL)) { + goto could_not_read; + } + + /* we should eos if we read less than what was requested */ + if (G_UNLIKELY (bytes_read < length)) { + goto eos; + } + + GST_BUFFER_SIZE (buf) = bytes_read; + GST_BUFFER_OFFSET_END (buf) = offset + bytes_read; + + *buffer = buf; + + ret = GST_FLOW_OK; + goto exit; + + /* ERROR */ +could_not_read: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + gst_buffer_unref (buf); + ret = GST_FLOW_ERROR; + goto exit; + } +eos: + { + GST_DEBUG ("EOS"); + gst_buffer_unref (buf); + ret = GST_FLOW_UNEXPECTED; + goto exit; + } +exit: + { + OBJC_CALLOUT_END (); + return ret; + } + +} + +static gboolean +gst_ios_asset_src_query (GstBaseSrc * basesrc, GstQuery * query) +{ + gboolean ret = FALSE; + GstIOSAssetSrc *src = GST_IOS_ASSET_SRC (basesrc); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_URI: + gst_query_set_uri (query, src->uri); + ret = TRUE; + break; + default: + ret = FALSE; + break; + } + + if (!ret) + ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); + + return ret; +} + +static gboolean +gst_ios_asset_src_is_seekable (GstBaseSrc * basesrc) +{ + return TRUE; +} + +static gboolean +gst_ios_asset_src_get_size (GstBaseSrc * basesrc, guint64 * size) +{ + GstIOSAssetSrc *src; + + src = GST_IOS_ASSET_SRC (basesrc); + + OBJC_CALLOUT_BEGIN (); + *size = (guint64) [src->asset size]; + OBJC_CALLOUT_END (); + return TRUE; +} + +static gboolean +gst_ios_asset_src_start (GstBaseSrc * basesrc) +{ + GstIOSAssetSrc *src = GST_IOS_ASSET_SRC (basesrc); + gboolean ret = TRUE; + + OBJC_CALLOUT_BEGIN (); + src->asset = [[src->library assetForURLSync: src->url] retain]; + + if (src->asset == NULL) { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + ("Could not open asset \"%s\" for reading.", src->uri), + GST_ERROR_SYSTEM); + ret = FALSE; + }; + + OBJC_CALLOUT_END (); + return ret; +} + +/* unmap and close the ios_asset */ +static gboolean +gst_ios_asset_src_stop (GstBaseSrc * basesrc) +{ + GstIOSAssetSrc *src = GST_IOS_ASSET_SRC (basesrc); + + OBJC_CALLOUT_BEGIN (); + [src->asset release]; + OBJC_CALLOUT_END (); + return TRUE; +} + +static GstURIType +gst_ios_asset_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_ios_asset_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "assets-library", NULL }; + + return protocols; +} + +static const gchar * +gst_ios_asset_src_uri_get_uri (GstURIHandler * handler) +{ + GstIOSAssetSrc *src = GST_IOS_ASSET_SRC (handler); + + return src->uri; +} + +static gboolean +gst_ios_asset_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstIOSAssetSrc *src = GST_IOS_ASSET_SRC (handler); + GError *error = NULL; + + if (! g_str_has_prefix (uri, "assets-library://")) { + GST_WARNING_OBJECT (src, "Invalid URI '%s' for ios_assetsrc: %s", uri, + error->message); + return FALSE; + } + + return gst_ios_asset_src_set_uri (src, uri); +} + +static void +gst_ios_asset_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_ios_asset_src_uri_get_type; + iface->get_protocols = gst_ios_asset_src_uri_get_protocols; + iface->get_uri = gst_ios_asset_src_uri_get_uri; + iface->set_uri = gst_ios_asset_src_uri_set_uri; +} + + +@implementation GstAssetsLibrary + +@synthesize asset; +@synthesize result; + +- (id) init +{ + self = [super init]; + + return self; +} + +- (ALAssetRepresentation *) assetForURLSync:(NSURL*) uri +{ + dispatch_semaphore_t sema = dispatch_semaphore_create(0); + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); + + dispatch_async(queue, ^{ + [self assetForURL:uri resultBlock: + ^(ALAsset *myasset) + { + self.asset = myasset; + self.result = [myasset defaultRepresentation]; + + dispatch_semaphore_signal(sema); + } + failureBlock: + ^(NSError *myerror) + { + self.result = nil; + dispatch_semaphore_signal(sema); + } + ]; + }); + + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + dispatch_release(sema); + + return self.result; +} +@end diff --git a/sys/applemedia/plugin.m b/sys/applemedia/plugin.m index de7f3a6..d32bf47 100644 --- a/sys/applemedia/plugin.m +++ b/sys/applemedia/plugin.m @@ -23,6 +23,7 @@ #ifdef HAVE_IOS #include "avfvideosrc.h" +#include "iosassetsrc.h" #else #include "qtkitvideosrc.h" #include @@ -50,6 +51,8 @@ plugin_init (GstPlugin * plugin) gboolean res = TRUE; #ifdef HAVE_IOS + res &= gst_element_register (plugin, "iosassetsrc", GST_RANK_SECONDARY, + GST_TYPE_IOS_ASSET_SRC); #if 0 res = gst_element_register (plugin, "avfvideosrc", GST_RANK_NONE, GST_TYPE_AVF_VIDEO_SRC);