Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / wearable / dashdemux / src / gstfragment.c
1 /* GStreamer
2  * Copyright (C) 2011 Andoni Morales Alastruey <ylatuya@gmail.com>
3  *
4  * gstfragment.c:
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <glib.h>
23 #include <gst/base/gsttypefindhelper.h>
24 #include "glibcompat.h"
25 #include "gstfragmented.h"
26 #include "gstfragment.h"
27
28 #define GST_CAT_DEFAULT fragmented_debug
29
30 #define GST_FRAGMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_FRAGMENT, GstFragmentPrivate))
31
32 enum
33 {
34   PROP_0,
35   PROP_INDEX,
36   PROP_NAME,
37   PROP_DURATION,
38   PROP_DISCONTINOUS,
39   PROP_BUFFER_LIST,
40   PROP_CAPS,
41   PROP_LAST
42 };
43
44 struct _GstFragmentPrivate
45 {
46   GstBufferList *buffer_list;
47   guint64 size;
48   GstBufferListIterator *buffer_iterator;
49   GstCaps *caps;
50   G_MUTEX lock;
51 };
52
53 G_DEFINE_TYPE (GstFragment, gst_fragment, G_TYPE_OBJECT);
54
55 static void gst_fragment_dispose (GObject * object);
56 static void gst_fragment_finalize (GObject * object);
57
58 static void
59 gst_fragment_set_property (GObject * object,
60     guint property_id, const GValue * value, GParamSpec * pspec)
61 {
62   GstFragment *fragment = GST_FRAGMENT (object);
63
64   switch (property_id) {
65     case PROP_CAPS:
66       gst_fragment_set_caps (fragment, g_value_get_boxed (value));
67       break;
68
69     default:
70       /* We don't have any other property... */
71       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
72       break;
73   }
74 }
75
76 static void
77 gst_fragment_get_property (GObject * object,
78     guint property_id, GValue * value, GParamSpec * pspec)
79 {
80   GstFragment *fragment = GST_FRAGMENT (object);
81
82   switch (property_id) {
83     case PROP_INDEX:
84       g_value_set_uint (value, fragment->index);
85       break;
86
87     case PROP_NAME:
88       g_value_set_string (value, fragment->name);
89       break;
90
91     case PROP_DURATION:
92       g_value_set_uint64 (value, fragment->stop_time - fragment->start_time);
93       break;
94
95     case PROP_DISCONTINOUS:
96       g_value_set_boolean (value, fragment->discontinuous);
97       break;
98
99     case PROP_BUFFER_LIST:
100       g_value_set_object (value, gst_fragment_get_buffer_list (fragment));
101       break;
102
103     case PROP_CAPS:
104       g_value_set_boxed (value, gst_fragment_get_caps (fragment));
105       break;
106
107     default:
108       /* We don't have any other property... */
109       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
110       break;
111   }
112 }
113
114
115
116 static void
117 gst_fragment_class_init (GstFragmentClass * klass)
118 {
119   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
120
121   g_type_class_add_private (klass, sizeof (GstFragmentPrivate));
122
123   gobject_class->set_property = gst_fragment_set_property;
124   gobject_class->get_property = gst_fragment_get_property;
125   gobject_class->dispose = gst_fragment_dispose;
126   gobject_class->finalize = gst_fragment_finalize;
127
128   g_object_class_install_property (gobject_class, PROP_INDEX,
129       g_param_spec_uint ("index", "Index", "Index of the fragment", 0,
130           G_MAXUINT, 0, G_PARAM_READABLE));
131
132   g_object_class_install_property (gobject_class, PROP_NAME,
133       g_param_spec_string ("name", "Name",
134           "Name of the fragment (eg:fragment-12.ts)", NULL, G_PARAM_READABLE));
135
136   g_object_class_install_property (gobject_class, PROP_DISCONTINOUS,
137       g_param_spec_boolean ("discontinuous", "Discontinous",
138           "Whether this fragment has a discontinuity or not",
139           FALSE, G_PARAM_READABLE));
140
141   g_object_class_install_property (gobject_class, PROP_DURATION,
142       g_param_spec_uint64 ("duration", "Fragment duration",
143           "Duration of the fragment", 0, G_MAXUINT64, 0, G_PARAM_READABLE));
144
145   g_object_class_install_property (gobject_class, PROP_BUFFER_LIST,
146       g_param_spec_object ("buffer-list", "Buffer List",
147           "A list with the fragment's buffers", GST_TYPE_FRAGMENT,
148           G_PARAM_READABLE));
149
150   g_object_class_install_property (gobject_class, PROP_CAPS,
151       g_param_spec_boxed ("caps", "Fragment caps",
152           "The caps of the fragment's buffer. (NULL = detect)", GST_TYPE_CAPS,
153           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
154 }
155
156 static void
157 gst_fragment_init (GstFragment * fragment)
158 {
159   GstFragmentPrivate *priv;
160
161   fragment->priv = priv = GST_FRAGMENT_GET_PRIVATE (fragment);
162
163   G_MUTEX_INIT (fragment->priv->lock);
164   priv->buffer_list = gst_buffer_list_new ();
165   priv->size = 0;
166   priv->buffer_iterator = gst_buffer_list_iterate (priv->buffer_list);
167   gst_buffer_list_iterator_add_group (priv->buffer_iterator);
168   fragment->download_start_time = g_get_real_time ();
169   fragment->start_time = 0;
170   fragment->stop_time = 0;
171   fragment->index = 0;
172   fragment->name = g_strdup ("");
173   fragment->completed = FALSE;
174   fragment->discontinuous = FALSE;
175 }
176
177 GstFragment *
178 gst_fragment_new (void)
179 {
180   return GST_FRAGMENT (g_object_new (GST_TYPE_FRAGMENT, NULL));
181 }
182
183 static void
184 gst_fragment_finalize (GObject * gobject)
185 {
186   GstFragment *fragment = GST_FRAGMENT (gobject);
187
188   g_free (fragment->name);
189   G_MUTEX_CLEAR (fragment->priv->lock);
190
191   G_OBJECT_CLASS (gst_fragment_parent_class)->finalize (gobject);
192 }
193
194 void
195 gst_fragment_dispose (GObject * object)
196 {
197   GstFragmentPrivate *priv = GST_FRAGMENT (object)->priv;
198
199   if (priv->buffer_list != NULL) {
200     gst_buffer_list_iterator_free (priv->buffer_iterator);
201     gst_buffer_list_unref (priv->buffer_list);
202     priv->buffer_list = NULL;
203     priv->size = 0;
204   }
205
206   if (priv->caps != NULL) {
207     gst_caps_unref (priv->caps);
208     priv->caps = NULL;
209   }
210
211   G_OBJECT_CLASS (gst_fragment_parent_class)->dispose (object);
212 }
213
214 GstBufferList *
215 gst_fragment_get_buffer_list (GstFragment * fragment)
216 {
217   g_return_val_if_fail (fragment != NULL, NULL);
218
219   if (!fragment->completed)
220     return NULL;
221
222   gst_buffer_list_ref (fragment->priv->buffer_list);
223   return fragment->priv->buffer_list;
224 }
225
226 void
227 gst_fragment_set_caps (GstFragment * fragment, GstCaps * caps)
228 {
229   g_return_if_fail (fragment != NULL);
230
231   G_MUTEX_LOCK (fragment->priv->lock);
232   gst_caps_replace (&fragment->priv->caps, caps);
233   G_MUTEX_UNLOCK (fragment->priv->lock);
234 }
235
236 GstCaps *
237 gst_fragment_get_caps (GstFragment * fragment)
238 {
239   g_return_val_if_fail (fragment != NULL, NULL);
240
241   if (!fragment->completed)
242     return NULL;
243
244   G_MUTEX_LOCK (fragment->priv->lock);
245   if (fragment->priv->caps == NULL) {
246     GstBuffer *buf = gst_buffer_list_get (fragment->priv->buffer_list, 0, 0);
247     fragment->priv->caps = gst_type_find_helper_for_buffer (NULL, buf, NULL);
248   }
249   gst_caps_ref (fragment->priv->caps);
250   G_MUTEX_UNLOCK (fragment->priv->lock);
251
252   return fragment->priv->caps;
253 }
254
255 guint64
256 gst_fragment_get_buffer_size (GstFragment * fragment)
257 {
258   g_return_val_if_fail (fragment != NULL, 0);
259
260   if (!fragment->completed)
261     return 0;
262   return fragment->priv->size;
263 }
264
265
266
267 gboolean
268 gst_fragment_add_buffer (GstFragment * fragment, GstBuffer * buffer)
269 {
270   g_return_val_if_fail (fragment != NULL, FALSE);
271   g_return_val_if_fail (buffer != NULL, FALSE);
272
273   if (fragment->completed) {
274     GST_WARNING ("Fragment is completed, could not add more buffers");
275     return FALSE;
276   }
277
278   gst_buffer_list_iterator_add (fragment->priv->buffer_iterator, buffer);
279   fragment->priv->size = fragment->priv->size + GST_BUFFER_SIZE (buffer);
280   return TRUE;
281 }