diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index 66589c20ac..bb3e104260 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -230,7 +230,10 @@ gst_base_parse_convert_default gst_base_parse_add_index_entry GstBaseParseFrameFlags +gst_base_parse_frame_new gst_base_parse_frame_init +gst_base_parse_frame_free + gst_base_parse_push_frame GST_BASE_PARSE_SRC_PAD @@ -245,6 +248,7 @@ GST_IS_BASE_PARSE_CLASS GST_BASE_PARSE_GET_CLASS gst_base_parse_get_type +gst_base_parse_frame_get_type
diff --git a/gst/gstpluginloader.c b/gst/gstpluginloader.c index 6ac9b600b7..8bb2df8539 100644 --- a/gst/gstpluginloader.c +++ b/gst/gstpluginloader.c @@ -37,6 +37,10 @@ #include #endif +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + #include #include @@ -350,38 +354,74 @@ plugin_loader_create_blacklist_plugin (GstPluginLoader * l, gst_registry_add_plugin (l->registry, plugin); } +#ifdef __APPLE__ +#if defined(__x86_64__) +#define USR_BIN_ARCH_SWITCH "-x86_64" +#elif defined(__i386__) +#define USR_BIN_ARCH_SWITCH "-i386" +#elif defined(__ppc__) +#define USR_BIN_ARCH_SWITCH "-ppc" +#elif defined(__ppc64__) +#define USR_BIN_ARCH_SWITCH "-ppc64" +#endif +#endif + +#define YES_MULTIARCH 1 +#define NO_MULTIARCH 2 + +#if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH) +static gboolean +gst_plugin_loader_use_usr_bin_arch (void) +{ + static volatile gsize multiarch = 0; + + if (g_once_init_enter (&multiarch)) { + gsize res = NO_MULTIARCH; + +#ifdef HAVE_SYS_UTSNAME_H + { + struct utsname uname_data; + + if (uname (&uname_data) == 0) { + /* Check for OS X >= 10.5 (darwin kernel 9.0) */ + GST_LOG ("%s %s", uname_data.sysname, uname_data.release); + if (g_ascii_strcasecmp (uname_data.sysname, "Darwin") == 0 && + g_strtod (uname_data.release, NULL) >= 9.0) { + res = YES_MULTIARCH; + } + } + } +#endif + + GST_INFO ("multiarch: %s", (res == YES_MULTIARCH) ? "yes" : "no"); + g_once_init_leave (&multiarch, res); + } + return (multiarch == YES_MULTIARCH); +} +#endif /* __APPLE__ && USR_BIN_ARCH_SWITCH */ + static gboolean gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location) { -#ifdef __APPLE__ -#if defined(__x86_64__) - char *argv[] = { (char *) "/usr/bin/arch", (char *) "-x86_64", - location, (char *) "-l", NULL - }; -#elif defined(__i386__) - char *argv[] = { (char *) "/usr/bin/arch", (char *) "-i386", - location, (char *) "-l", NULL - }; -#elif defined(__ppc__) - char *argv[] = { (char *) "/usr/bin/arch", (char *) "-ppc", - location, (char *) "-l", NULL - }; -#elif defined(__ppc64__) - char *argv[] = { (char *) "/usr/bin/arch", (char *) "-ppc64", - location, (char *) "-l", NULL - }; -#endif -#else /* ! __APPLE__ */ - char *argv[] = { location, (char *) "-l", NULL }; -#endif + char *argv[5] = { NULL, }; + int c = 0; - -#ifdef __APPLE__ - GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s", - location, argv[1]); -#else - GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location); +#if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH) + if (gst_plugin_loader_use_usr_bin_arch ()) { + argv[c++] = (char *) "/usr/bin/arch"; + argv[c++] = (char *) USR_BIN_ARCH_SWITCH; + } #endif + argv[c++] = location; + argv[c++] = (char *) "-l"; + argv[c++] = NULL; + + if (c > 3) { + GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s", + location, argv[1]); + } else { + GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s", location); + } if (!g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD /* | G_SPAWN_STDERR_TO_DEV_NULL */ , diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c index a8371fdb55..1b609381ce 100644 --- a/libs/gst/base/gstbaseparse.c +++ b/libs/gst/base/gstbaseparse.c @@ -199,6 +199,8 @@ #include "gstbaseparse.h" +#define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC (1 << 0) + #define MIN_FRAMES_TO_POST_BITRATE 10 #define TARGET_DIFFERENCE (20 * GST_SECOND) @@ -397,10 +399,6 @@ static GstFlowReturn gst_base_parse_process_fragment (GstBaseParse * parse, static gboolean gst_base_parse_is_seekable (GstBaseParse * parse); -static void gst_base_parse_frame_free (GstBaseParseFrame * frame); -static GstBaseParseFrame *gst_base_parse_frame_copy_and_clear (GstBaseParseFrame - * frame); - static void gst_base_parse_clear_queues (GstBaseParse * parse) { @@ -538,52 +536,101 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) GST_DEBUG_OBJECT (parse, "init ok"); } -/** - * gst_base_parse_frame_init: - * @parse: #GstBaseParse. - * @frame: #GstBaseParseFrame. - * - * Sets a #GstBaseParseFrame to initial state. Currently this means - * all fields are zero-ed. - * - * Since: 0.10.33 - */ -void -gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - memset (frame, 0, sizeof (*frame)); -} - -/* clear == frame no longer to be used following this */ -static void -gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - /* limited for now */ - if (frame->buffer) { - gst_buffer_unref (frame->buffer); - frame->buffer = NULL; - } -} - -/* free frame allocated with copy_and_clear (and not on the stack) */ -static void -gst_base_parse_frame_free (GstBaseParseFrame * frame) -{ - gst_base_parse_frame_clear (NULL, frame); - g_slice_free (GstBaseParseFrame, frame); -} - -/* copy frame (taking ownership of contents of passed frame) */ static GstBaseParseFrame * -gst_base_parse_frame_copy_and_clear (GstBaseParseFrame * frame) +gst_base_parse_frame_copy (GstBaseParseFrame * frame) { GstBaseParseFrame *copy; copy = g_slice_dup (GstBaseParseFrame, frame); - memset (frame, 0, sizeof (GstBaseParseFrame)); + copy->buffer = gst_buffer_ref (frame->buffer); + copy->_private_flags &= ~GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC; + + GST_TRACE ("copied frame %p -> %p", frame, copy); + return copy; } +void +gst_base_parse_frame_free (GstBaseParseFrame * frame) +{ + GST_TRACE ("freeing frame %p", frame); + + if (frame->buffer) { + gst_buffer_unref (frame->buffer); + frame->buffer = NULL; + } + + if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) + g_slice_free (GstBaseParseFrame, frame); +} + +GType +gst_base_parse_frame_get_type (void) +{ + static volatile gsize frame_type = 0; + + if (g_once_init_enter (&frame_type)) { + GType _type; + + _type = g_boxed_type_register_static ("GstBaseParseFrame", + (GBoxedCopyFunc) gst_base_parse_frame_copy, + (GBoxedFreeFunc) gst_base_parse_frame_free); + g_once_init_leave (&frame_type, _type); + } + return (GType) frame_type; +} + +/** + * gst_base_parse_frame_init: + * @frame: #GstBaseParseFrame. + * + * Sets a #GstBaseParseFrame to initial state. Currently this means + * all public fields are zero-ed and a private flag is set to make + * sure gst_base_parse_frame_free() only frees the contents but not + * the actual frame. Use this function to initialise a #GstBaseParseFrame + * allocated on the stack. + * + * Since: 0.10.33 + */ +void +gst_base_parse_frame_init (GstBaseParseFrame * frame) +{ + memset (frame, 0, sizeof (GstBaseParseFrame)); + frame->_private_flags = GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC; + GST_TRACE ("inited frame %p", frame); +} + +/** + * gst_base_parse_frame_new: + * @buffer: (transfer none): a #GstBuffer + * @flags: the flags + * @overhead: number of bytes in this frame which should be counted as + * metadata overhead, ie. not used to calculate the average bitrate. + * Set to -1 to mark the entire frame as metadata. If in doubt, set to 0. + * + * Allocates a new #GstBaseParseFrame. This function is mainly for bindings, + * elements written in C should usually allocate the frame on the stack and + * then use gst_base_parse_frame_init() to initialise it. + * + * Returns: a newly-allocated #GstBaseParseFrame. Free with + * gst_base_parse_frame_free() when no longer needed, unless you gave + * away ownership to gst_base_parse_push_frame(). + * + * Since: 0.10.33 + */ +GstBaseParseFrame * +gst_base_parse_frame_new (GstBuffer * buffer, GstBaseParseFrameFlags flags, + gint overhead) +{ + GstBaseParseFrame *frame; + + frame = g_slice_new0 (GstBaseParseFrame); + frame->buffer = gst_buffer_ref (buffer); + + GST_TRACE ("created frame %p", frame); + return frame; +} + static inline void gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame, GstBuffer * buf) @@ -1478,10 +1525,29 @@ gst_base_parse_check_media (GstBaseParse * parse) GST_DEBUG_OBJECT (parse, "media is video == %d", parse->priv->is_video); } +/* takes ownership of frame */ +static void +gst_base_parse_queue_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) { + /* frame allocated on the heap, we can just take ownership */ + g_queue_push_tail (&parse->priv->queued_frames, frame); + GST_TRACE ("queued frame %p", frame); + } else { + GstBaseParseFrame *copy; + + /* probably allocated on the stack, must make a proper copy */ + copy = gst_base_parse_frame_copy (frame); + g_queue_push_tail (&parse->priv->queued_frames, copy); + GST_TRACE ("queued frame %p (copy of %p)", copy, frame); + gst_base_parse_frame_free (frame); + } +} + /* gst_base_parse_handle_and_push_buffer: * @parse: #GstBaseParse. * @klass: #GstBaseParseClass. - * @buffer: #GstBuffer. + * @frame: (transfer full): a #GstBaseParseFrame * * Parses the frame from given buffer and pushes it forward. Also performs * timestamp handling and checks the segment limits. @@ -1581,11 +1647,10 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse, * frames to decide on the format and queues them internally */ /* convert internal flow to OK and mark discont for the next buffer. */ if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - gst_base_parse_frame_clear (parse, frame); + gst_base_parse_frame_free (frame); return GST_FLOW_OK; } else if (ret == GST_BASE_PARSE_FLOW_QUEUED) { - g_queue_push_tail (&parse->priv->queued_frames, - gst_base_parse_frame_copy_and_clear (frame)); + gst_base_parse_queue_frame (parse, frame); return GST_FLOW_OK; } else if (ret != GST_FLOW_OK) { return ret; @@ -1610,10 +1675,12 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse, /** * gst_base_parse_push_frame: * @parse: #GstBaseParse. - * @frame: #GstBaseParseFrame. + * @frame: (transfer full): a #GstBaseParseFrame * * Pushes the frame downstream, sends any pending events and - * does some timestamp and segment handling. + * does some timestamp and segment handling. Takes ownership + * of @frame and will clear it (if it was initialised with + * gst_base_parse_frame_init()) or free it. * * This must be called with sinkpad STREAM_LOCK held. * @@ -1634,6 +1701,8 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); + GST_TRACE_OBJECT (parse, "pushing frame %p", frame); + buffer = frame->buffer; GST_LOG_OBJECT (parse, @@ -1845,7 +1914,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) parse->segment.last_stop < last_stop) gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); - gst_base_parse_frame_clear (parse, frame); + gst_base_parse_frame_free (frame); return ret; } @@ -2069,13 +2138,15 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) const guint8 *data; guint old_min_size = 0, min_size, av; GstClockTime timestamp; - GstBaseParseFrame _frame = { 0, }; + GstBaseParseFrame _frame; GstBaseParseFrame *frame; parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_PARSE_GET_CLASS (parse); frame = &_frame; + gst_base_parse_frame_init (frame); + if (G_LIKELY (buffer)) { GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer)); @@ -2519,7 +2590,7 @@ gst_base_parse_loop (GstPad * pad) GstBaseParse *parse; GstBaseParseClass *klass; GstFlowReturn ret = GST_FLOW_OK; - GstBaseParseFrame frame = { 0, }; + GstBaseParseFrame frame; parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); klass = GST_BASE_PARSE_GET_CLASS (parse); @@ -2536,6 +2607,7 @@ gst_base_parse_loop (GstPad * pad) } } + gst_base_parse_frame_init (&frame); ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE); if (ret != GST_FLOW_OK) goto done; @@ -3109,7 +3181,7 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, gboolean orig_drain, orig_discont; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf = NULL; - GstBaseParseFrame frame = { 0, }; + GstBaseParseFrame frame; g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL); g_return_val_if_fail (GST_FLOW_ERROR, time != NULL); @@ -3128,6 +3200,8 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT " (%#" G_GINT64_MODIFIER "x)", *pos, *pos); + gst_base_parse_frame_init (&frame); + /* jump elsewhere and locate next frame */ parse->priv->offset = *pos; ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE); @@ -3149,7 +3223,8 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* but it should provide proper time */ *time = GST_BUFFER_TIMESTAMP (buf); *duration = GST_BUFFER_DURATION (buf); - gst_base_parse_frame_clear (parse, &frame); + + gst_base_parse_frame_free (&frame); GST_LOG_OBJECT (parse, "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h index ca42feef71..74eaa97b84 100644 --- a/libs/gst/base/gstbaseparse.h +++ b/libs/gst/base/gstbaseparse.h @@ -148,8 +148,9 @@ typedef struct { guint flags; gint overhead; /*< private >*/ - gint _gst_reserved_i[2]; + guint _gst_reserved_i[2]; gpointer _gst_reserved_p[2]; + guint _private_flags; } GstBaseParseFrame; typedef struct _GstBaseParse GstBaseParse; @@ -257,8 +258,15 @@ struct _GstBaseParseClass { GType gst_base_parse_get_type (void); -void gst_base_parse_frame_init (GstBaseParse * parse, - GstBaseParseFrame * frame); +GType gst_base_parse_frame_get_type (void); + +GstBaseParseFrame * gst_base_parse_frame_new (GstBuffer * buffer, + GstBaseParseFrameFlags flags, + gint overhead); + +void gst_base_parse_frame_init (GstBaseParseFrame * frame); + +void gst_base_parse_frame_free (GstBaseParseFrame * frame); GstFlowReturn gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 95e9f23b90..1ca7894a3a 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -733,6 +733,7 @@ EXPORTS gst_parse_bin_from_description_full gst_parse_context_free gst_parse_context_get_missing_elements + gst_parse_context_get_type gst_parse_context_new gst_parse_error_get_type gst_parse_error_quark