/* GStreamer * Copyright (C) 2011 Andoni Morales Alastruey * * gstfragment.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. */ #include #include #include "gstfragmented.h" #include "gstfragment.h" #define GST_CAT_DEFAULT fragmented_debug #define GST_FRAGMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_FRAGMENT, GstFragmentPrivate)) enum { PROP_0, PROP_INDEX, PROP_NAME, PROP_DURATION, PROP_DISCONTINOUS, PROP_BUFFER, PROP_CAPS, PROP_LAST }; struct _GstFragmentPrivate { GstBuffer *buffer; GstCaps *caps; GMutex lock; }; G_DEFINE_TYPE (GstFragment, gst_fragment, G_TYPE_OBJECT); static void gst_fragment_dispose (GObject * object); static void gst_fragment_finalize (GObject * object); static void gst_fragment_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { GstFragment *fragment = GST_FRAGMENT (object); switch (property_id) { case PROP_CAPS: gst_fragment_set_caps (fragment, g_value_get_boxed (value)); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gst_fragment_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { GstFragment *fragment = GST_FRAGMENT (object); switch (property_id) { case PROP_INDEX: g_value_set_uint (value, fragment->index); break; case PROP_NAME: g_value_set_string (value, fragment->name); break; case PROP_DURATION: g_value_set_uint64 (value, fragment->stop_time - fragment->start_time); break; case PROP_DISCONTINOUS: g_value_set_boolean (value, fragment->discontinuous); break; case PROP_BUFFER: g_value_set_boxed (value, gst_fragment_get_buffer (fragment)); break; case PROP_CAPS: g_value_set_boxed (value, gst_fragment_get_caps (fragment)); break; default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gst_fragment_class_init (GstFragmentClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GstFragmentPrivate)); gobject_class->set_property = gst_fragment_set_property; gobject_class->get_property = gst_fragment_get_property; gobject_class->dispose = gst_fragment_dispose; gobject_class->finalize = gst_fragment_finalize; g_object_class_install_property (gobject_class, PROP_INDEX, g_param_spec_uint ("index", "Index", "Index of the fragment", 0, G_MAXUINT, 0, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_NAME, g_param_spec_string ("name", "Name", "Name of the fragment (eg:fragment-12.ts)", NULL, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_DISCONTINOUS, g_param_spec_boolean ("discontinuous", "Discontinous", "Whether this fragment has a discontinuity or not", FALSE, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_DURATION, g_param_spec_uint64 ("duration", "Fragment duration", "Duration of the fragment", 0, G_MAXUINT64, 0, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_BUFFER, g_param_spec_boxed ("buffer", "Buffer", "The fragment's buffer", GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_CAPS, g_param_spec_boxed ("caps", "Fragment caps", "The caps of the fragment's buffer. (NULL = detect)", GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void gst_fragment_init (GstFragment * fragment) { GstFragmentPrivate *priv; fragment->priv = priv = GST_FRAGMENT_GET_PRIVATE (fragment); g_mutex_init (&fragment->priv->lock); priv->buffer = NULL; fragment->download_start_time = g_get_real_time (); fragment->start_time = 0; fragment->stop_time = 0; fragment->index = 0; fragment->name = g_strdup (""); fragment->completed = FALSE; fragment->discontinuous = FALSE; } GstFragment * gst_fragment_new (void) { return GST_FRAGMENT (g_object_new (GST_TYPE_FRAGMENT, NULL)); } static void gst_fragment_finalize (GObject * gobject) { GstFragment *fragment = GST_FRAGMENT (gobject); g_free (fragment->name); g_mutex_clear (&fragment->priv->lock); G_OBJECT_CLASS (gst_fragment_parent_class)->finalize (gobject); } void gst_fragment_dispose (GObject * object) { GstFragmentPrivate *priv = GST_FRAGMENT (object)->priv; if (priv->buffer != NULL) { gst_buffer_unref (priv->buffer); priv->buffer = NULL; } if (priv->caps != NULL) { gst_caps_unref (priv->caps); priv->caps = NULL; } G_OBJECT_CLASS (gst_fragment_parent_class)->dispose (object); } GstBuffer * gst_fragment_get_buffer (GstFragment * fragment) { g_return_val_if_fail (fragment != NULL, NULL); if (!fragment->completed) return NULL; gst_buffer_ref (fragment->priv->buffer); return fragment->priv->buffer; } void gst_fragment_set_caps (GstFragment * fragment, GstCaps * caps) { g_return_if_fail (fragment != NULL); g_mutex_lock (&fragment->priv->lock); gst_caps_replace (&fragment->priv->caps, caps); g_mutex_unlock (&fragment->priv->lock); } GstCaps * gst_fragment_get_caps (GstFragment * fragment) { g_return_val_if_fail (fragment != NULL, NULL); if (!fragment->completed) return NULL; g_mutex_lock (&fragment->priv->lock); if (fragment->priv->caps == NULL) fragment->priv->caps = gst_type_find_helper_for_buffer (NULL, fragment->priv->buffer, NULL); gst_caps_ref (fragment->priv->caps); g_mutex_unlock (&fragment->priv->lock); return fragment->priv->caps; } gboolean gst_fragment_add_buffer (GstFragment * fragment, GstBuffer * buffer) { g_return_val_if_fail (fragment != NULL, FALSE); g_return_val_if_fail (buffer != NULL, FALSE); if (fragment->completed) { GST_WARNING ("Fragment is completed, could not add more buffers"); return FALSE; } GST_DEBUG ("Adding new buffer to the fragment"); /* We steal the buffers you pass in */ if (fragment->priv->buffer == NULL) fragment->priv->buffer = buffer; else fragment->priv->buffer = gst_buffer_append (fragment->priv->buffer, buffer); return TRUE; }