gst/base/gstbasesrc.c (gst_basesrc_set_property)
[platform/upstream/gstreamer.git] / libs / gst / base / gstbasesrc.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *               2000,2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstbasesrc.c: 
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #ifdef HAVE_CONFIG_H
28 #  include "config.h"
29 #endif
30
31 #include "gstbasesrc.h"
32 #include "gsttypefindhelper.h"
33 #include <gst/gstmarshal.h>
34
35 #define DEFAULT_BLOCKSIZE       4096
36
37 GST_DEBUG_CATEGORY_STATIC (gst_basesrc_debug);
38 #define GST_CAT_DEFAULT gst_basesrc_debug
39
40 /* BaseSrc signals and args */
41 enum
42 {
43   /* FILL ME */
44   LAST_SIGNAL
45 };
46
47 enum
48 {
49   PROP_0,
50   PROP_BLOCKSIZE,
51 };
52
53 static GstElementClass *parent_class = NULL;
54
55 static void gst_basesrc_base_init (gpointer g_class);
56 static void gst_basesrc_class_init (GstBaseSrcClass * klass);
57 static void gst_basesrc_init (GstBaseSrc * src, gpointer g_class);
58
59 GType
60 gst_basesrc_get_type (void)
61 {
62   static GType basesrc_type = 0;
63
64   if (!basesrc_type) {
65     static const GTypeInfo basesrc_info = {
66       sizeof (GstBaseSrcClass),
67       (GBaseInitFunc) gst_basesrc_base_init,
68       NULL,
69       (GClassInitFunc) gst_basesrc_class_init,
70       NULL,
71       NULL,
72       sizeof (GstBaseSrc),
73       0,
74       (GInstanceInitFunc) gst_basesrc_init,
75     };
76
77     basesrc_type = g_type_register_static (GST_TYPE_ELEMENT,
78         "GstBaseSrc", &basesrc_info, G_TYPE_FLAG_ABSTRACT);
79   }
80   return basesrc_type;
81 }
82
83 static gboolean gst_basesrc_activate (GstPad * pad, GstActivateMode mode);
84 static void gst_basesrc_set_property (GObject * object, guint prop_id,
85     const GValue * value, GParamSpec * pspec);
86 static void gst_basesrc_get_property (GObject * object, guint prop_id,
87     GValue * value, GParamSpec * pspec);
88 static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event);
89 static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad);
90 static const GstQueryType *gst_basesrc_get_query_types (GstPad * pad);
91 static gboolean gst_basesrc_query (GstPad * pad, GstQueryType type,
92     GstFormat * format, gint64 * value);
93 static const GstFormat *gst_basesrc_get_formats (GstPad * pad);
94
95 static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc);
96 static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size);
97 static gboolean gst_basesrc_start (GstBaseSrc * basesrc);
98 static gboolean gst_basesrc_stop (GstBaseSrc * basesrc);
99
100 static GstElementStateReturn gst_basesrc_change_state (GstElement * element);
101
102 static void gst_basesrc_loop (GstPad * pad);
103 static gboolean gst_basesrc_check_get_range (GstPad * pad);
104 static GstFlowReturn gst_basesrc_get_range (GstPad * pad, guint64 offset,
105     guint length, GstBuffer ** buf);
106
107 static void
108 gst_basesrc_base_init (gpointer g_class)
109 {
110   GST_DEBUG_CATEGORY_INIT (gst_basesrc_debug, "basesrc", 0, "basesrc element");
111 }
112
113 static void
114 gst_basesrc_class_init (GstBaseSrcClass * klass)
115 {
116   GObjectClass *gobject_class;
117   GstElementClass *gstelement_class;
118
119   gobject_class = (GObjectClass *) klass;
120   gstelement_class = (GstElementClass *) klass;
121
122   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
123
124   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_basesrc_set_property);
125   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_basesrc_get_property);
126
127   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BLOCKSIZE,
128       g_param_spec_ulong ("blocksize", "Block size",
129           "Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
130           G_PARAM_READWRITE));
131
132   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_basesrc_change_state);
133 }
134
135 static void
136 gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class)
137 {
138   GstPad *pad;
139   GstPadTemplate *pad_template;
140
141   pad_template =
142       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
143   g_return_if_fail (pad_template != NULL);
144
145   pad = gst_pad_new_from_template (pad_template, "src");
146
147   gst_pad_set_activate_function (pad, gst_basesrc_activate);
148   gst_pad_set_event_function (pad, gst_basesrc_event_handler);
149   gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask);
150   gst_pad_set_query_function (pad, gst_basesrc_query);
151   gst_pad_set_query_type_function (pad, gst_basesrc_get_query_types);
152   gst_pad_set_formats_function (pad, gst_basesrc_get_formats);
153   gst_pad_set_loop_function (pad, gst_basesrc_loop);
154   gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range);
155   gst_pad_set_getrange_function (pad, gst_basesrc_get_range);
156   /* hold ref to pad */
157   basesrc->srcpad = pad;
158   gst_element_add_pad (GST_ELEMENT (basesrc), pad);
159
160   basesrc->segment_start = -1;
161   basesrc->segment_end = -1;
162   basesrc->blocksize = DEFAULT_BLOCKSIZE;
163
164   GST_FLAG_UNSET (basesrc, GST_BASESRC_STARTED);
165 }
166
167 static const GstFormat *
168 gst_basesrc_get_formats (GstPad * pad)
169 {
170   static const GstFormat formats[] = {
171     GST_FORMAT_DEFAULT,
172     GST_FORMAT_BYTES,
173     0,
174   };
175
176   return formats;
177 }
178
179 static const GstQueryType *
180 gst_basesrc_get_query_types (GstPad * pad)
181 {
182   static const GstQueryType types[] = {
183     GST_QUERY_TOTAL,
184     GST_QUERY_POSITION,
185     GST_QUERY_START,
186     GST_QUERY_SEGMENT_END,
187     0,
188   };
189
190   return types;
191 }
192
193 static gboolean
194 gst_basesrc_query (GstPad * pad, GstQueryType type,
195     GstFormat * format, gint64 * value)
196 {
197   GstBaseSrc *src = GST_BASESRC (GST_PAD_PARENT (pad));
198
199   if (*format == GST_FORMAT_DEFAULT)
200     *format = GST_FORMAT_BYTES;
201
202   switch (type) {
203     case GST_QUERY_TOTAL:
204       switch (*format) {
205         case GST_FORMAT_BYTES:
206         {
207           gboolean ret;
208
209           ret = gst_basesrc_get_size (src, value);
210           GST_DEBUG ("getting length %d %lld", ret, *value);
211           return ret;
212         }
213         case GST_FORMAT_PERCENT:
214           *value = GST_FORMAT_PERCENT_MAX;
215           return TRUE;
216         default:
217           return FALSE;
218       }
219       break;
220     case GST_QUERY_POSITION:
221       switch (*format) {
222         case GST_FORMAT_BYTES:
223           *value = src->offset;
224           break;
225         case GST_FORMAT_PERCENT:
226           if (!gst_basesrc_get_size (src, value))
227             return FALSE;
228           *value = src->offset * GST_FORMAT_PERCENT_MAX / *value;
229           return TRUE;
230         default:
231           return FALSE;
232       }
233       break;
234     case GST_QUERY_START:
235       *value = src->segment_start;
236       return TRUE;
237     case GST_QUERY_SEGMENT_END:
238       *value = src->segment_end;
239       return TRUE;
240     default:
241       return FALSE;
242   }
243   return FALSE;
244 }
245
246 static const GstEventMask *
247 gst_basesrc_get_event_mask (GstPad * pad)
248 {
249   static const GstEventMask masks[] = {
250     {GST_EVENT_SEEK, GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_SET |
251           GST_SEEK_METHOD_END | GST_SEEK_FLAG_FLUSH |
252           GST_SEEK_FLAG_SEGMENT_LOOP},
253     {GST_EVENT_FLUSH, 0},
254     {GST_EVENT_SIZE, 0},
255     {0, 0},
256   };
257   return masks;
258 }
259
260 static gboolean
261 gst_basesrc_do_seek (GstBaseSrc * src, GstEvent * event)
262 {
263   GstFormat format;
264   gint64 offset;
265
266   format = GST_EVENT_SEEK_FORMAT (event);
267
268   /* get seek format */
269   if (format == GST_FORMAT_DEFAULT)
270     format = GST_FORMAT_BYTES;
271   /* we can only seek bytes */
272   if (format != GST_FORMAT_BYTES)
273     return FALSE;
274
275   /* get seek positions */
276   offset = GST_EVENT_SEEK_OFFSET (event);
277   src->segment_start = offset;
278   src->segment_end = GST_EVENT_SEEK_ENDOFFSET (event);
279   src->segment_loop = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_SEGMENT_LOOP;
280
281   /* send flush start */
282   gst_pad_push_event (src->srcpad, gst_event_new_flush (FALSE));
283
284   /* unblock streaming thread */
285   gst_basesrc_unlock (src);
286
287   /* grab streaming lock */
288   GST_STREAM_LOCK (src->srcpad);
289
290   switch (GST_EVENT_SEEK_METHOD (event)) {
291     case GST_SEEK_METHOD_SET:
292       if (offset < 0)
293         goto error;
294       src->offset = MIN (offset, src->size);
295       GST_DEBUG_OBJECT (src, "seek set pending to %" G_GINT64_FORMAT,
296           src->offset);
297       break;
298     case GST_SEEK_METHOD_CUR:
299       offset += src->offset;
300       src->offset = CLAMP (offset, 0, src->size);
301       GST_DEBUG_OBJECT (src, "seek cur pending to %" G_GINT64_FORMAT,
302           src->offset);
303       break;
304     case GST_SEEK_METHOD_END:
305       if (offset > 0)
306         goto error;
307       offset = src->size + offset;
308       src->offset = MAX (0, offset);
309       GST_DEBUG_OBJECT (src, "seek end pending to %" G_GINT64_FORMAT,
310           src->offset);
311       break;
312     default:
313       goto error;
314   }
315   /* send flush end */
316   gst_pad_push_event (src->srcpad, gst_event_new_flush (TRUE));
317
318   /* now send discont */
319   {
320     GstEvent *event;
321
322     event = gst_event_new_discontinuous (1.0,
323         GST_FORMAT_TIME,
324         (gint64) src->segment_start, (gint64) src->segment_end, NULL);
325
326     gst_pad_push_event (src->srcpad, event);
327   }
328
329   /* and restart the task */
330   if (GST_RPAD_TASK (src->srcpad)) {
331     gst_task_start (GST_RPAD_TASK (src->srcpad));
332   }
333   GST_STREAM_UNLOCK (src->srcpad);
334
335   gst_event_unref (event);
336
337   return TRUE;
338
339   /* ERROR */
340 error:
341   {
342     GST_DEBUG_OBJECT (src, "seek error");
343     GST_STREAM_UNLOCK (src->srcpad);
344     gst_event_unref (event);
345     return FALSE;
346   }
347 }
348
349 static gboolean
350 gst_basesrc_event_handler (GstPad * pad, GstEvent * event)
351 {
352   GstBaseSrc *src;
353   GstBaseSrcClass *bclass;
354   gboolean result;
355
356   src = GST_BASESRC (GST_PAD_PARENT (pad));
357   bclass = GST_BASESRC_GET_CLASS (src);
358
359   if (bclass->event)
360     result = bclass->event (src, event);
361
362   switch (GST_EVENT_TYPE (event)) {
363     case GST_EVENT_SEEK:
364       return gst_basesrc_do_seek (src, event);
365     case GST_EVENT_SIZE:
366     {
367       GstFormat format;
368
369       format = GST_EVENT_SIZE_FORMAT (event);
370       if (format == GST_FORMAT_DEFAULT)
371         format = GST_FORMAT_BYTES;
372       /* we can only accept bytes */
373       if (format != GST_FORMAT_BYTES)
374         return FALSE;
375
376       src->blocksize = GST_EVENT_SIZE_VALUE (event);
377       g_object_notify (G_OBJECT (src), "blocksize");
378       break;
379     }
380     case GST_EVENT_FLUSH:
381       /* cancel any blocking getrange */
382       if (!GST_EVENT_FLUSH_DONE (event))
383         gst_basesrc_unlock (src);
384       break;
385     default:
386       break;
387   }
388   gst_event_unref (event);
389
390   return TRUE;
391 }
392
393 static void
394 gst_basesrc_set_property (GObject * object, guint prop_id, const GValue * value,
395     GParamSpec * pspec)
396 {
397   GstBaseSrc *src;
398
399   src = GST_BASESRC (object);
400
401   switch (prop_id) {
402     case PROP_BLOCKSIZE:
403       src->blocksize = g_value_get_ulong (value);
404       break;
405     default:
406       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
407       break;
408   }
409 }
410
411 static void
412 gst_basesrc_get_property (GObject * object, guint prop_id, GValue * value,
413     GParamSpec * pspec)
414 {
415   GstBaseSrc *src;
416
417   src = GST_BASESRC (object);
418
419   switch (prop_id) {
420     case PROP_BLOCKSIZE:
421       g_value_set_ulong (value, src->blocksize);
422       break;
423     default:
424       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
425       break;
426   }
427 }
428
429 static GstFlowReturn
430 gst_basesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length,
431     GstBuffer ** buf)
432 {
433   GstFlowReturn ret;
434   GstBaseSrc *src;
435   GstBaseSrcClass *bclass;
436
437   src = GST_BASESRC (GST_OBJECT_PARENT (pad));
438   bclass = GST_BASESRC_GET_CLASS (src);
439
440   if (!GST_FLAG_IS_SET (src, GST_BASESRC_STARTED))
441     goto not_started;
442
443   if (!bclass->create)
444     goto no_function;
445
446   /* check size */
447   if (src->size != -1) {
448     if (offset + length > src->size) {
449       if (bclass->get_size)
450         bclass->get_size (src, &src->size);
451
452       if (offset + length > src->size) {
453         length = src->size - offset;
454       }
455     }
456   }
457   if (length == 0)
458     return GST_FLOW_UNEXPECTED;
459
460   ret = bclass->create (src, offset, length, buf);
461
462   return ret;
463
464   /* ERROR */
465 not_started:
466   {
467     GST_DEBUG_OBJECT (src, "getrange but not started");
468     return GST_FLOW_WRONG_STATE;
469   }
470 no_function:
471   {
472     GST_DEBUG_OBJECT (src, "no create function");
473     return GST_FLOW_ERROR;
474   }
475 }
476
477 static GstFlowReturn
478 gst_basesrc_get_range (GstPad * pad, guint64 offset, guint length,
479     GstBuffer ** ret)
480 {
481   GstFlowReturn fret;
482
483   GST_STREAM_LOCK (pad);
484
485   fret = gst_basesrc_get_range_unlocked (pad, offset, length, ret);
486
487   GST_STREAM_UNLOCK (pad);
488
489   return fret;
490 }
491
492 static gboolean
493 gst_basesrc_check_get_range (GstPad * pad)
494 {
495   GstBaseSrc *src;
496
497   src = GST_BASESRC (GST_OBJECT_PARENT (pad));
498
499   if (!GST_FLAG_IS_SET (src, GST_BASESRC_STARTED)) {
500     gst_basesrc_start (src);
501     gst_basesrc_stop (src);
502   }
503
504   return src->seekable;
505 }
506
507 static void
508 gst_basesrc_loop (GstPad * pad)
509 {
510   GstBaseSrc *src;
511   GstBuffer *buf = NULL;
512   GstFlowReturn ret;
513
514   src = GST_BASESRC (GST_OBJECT_PARENT (pad));
515
516   GST_STREAM_LOCK (pad);
517
518   ret = gst_basesrc_get_range_unlocked (pad, src->offset, src->blocksize, &buf);
519   if (ret != GST_FLOW_OK)
520     goto eos;
521
522   src->offset += GST_BUFFER_SIZE (buf);
523
524   ret = gst_pad_push (pad, buf);
525   if (ret != GST_FLOW_OK)
526     goto pause;
527
528   GST_STREAM_UNLOCK (pad);
529   return;
530
531 eos:
532   {
533     GST_DEBUG_OBJECT (src, "going to EOS");
534     gst_task_pause (GST_RPAD_TASK (pad));
535     gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
536     GST_STREAM_UNLOCK (pad);
537     return;
538   }
539 pause:
540   {
541     GST_DEBUG_OBJECT (src, "pausing task");
542     gst_task_pause (GST_RPAD_TASK (pad));
543     GST_STREAM_UNLOCK (pad);
544     return;
545   }
546 }
547
548 static gboolean
549 gst_basesrc_unlock (GstBaseSrc * basesrc)
550 {
551   GstBaseSrcClass *bclass;
552   gboolean result = FALSE;
553
554   bclass = GST_BASESRC_GET_CLASS (basesrc);
555   if (bclass->unlock)
556     result = bclass->unlock (basesrc);
557
558   return result;
559 }
560
561 static gboolean
562 gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size)
563 {
564   GstBaseSrcClass *bclass;
565   gboolean result = FALSE;
566
567   bclass = GST_BASESRC_GET_CLASS (basesrc);
568   if (bclass->get_size)
569     result = bclass->get_size (basesrc, size);
570
571   if (result)
572     basesrc->size = *size;
573
574   return result;
575 }
576
577 static gboolean
578 gst_basesrc_start (GstBaseSrc * basesrc)
579 {
580   GstBaseSrcClass *bclass;
581   gboolean result;
582
583   if (GST_FLAG_IS_SET (basesrc, GST_BASESRC_STARTED))
584     return TRUE;
585
586   bclass = GST_BASESRC_GET_CLASS (basesrc);
587   if (bclass->start)
588     result = bclass->start (basesrc);
589   else
590     result = TRUE;
591
592   if (!result)
593     goto could_not_start;
594
595   GST_FLAG_SET (basesrc, GST_BASESRC_STARTED);
596
597   /* start in the beginning */
598   basesrc->offset = 0;
599   basesrc->segment_start = 0;
600
601   /* figure out the size */
602   if (bclass->get_size) {
603     result = bclass->get_size (basesrc, &basesrc->size);
604   } else {
605     result = FALSE;
606     basesrc->size = -1;
607   }
608
609   GST_DEBUG ("size %d %lld", result, basesrc->size);
610
611   /* we always run to the end */
612   basesrc->segment_end = -1;
613
614   /* check if we can seek */
615   if (bclass->is_seekable)
616     basesrc->seekable = bclass->is_seekable (basesrc);
617   else
618     basesrc->seekable = FALSE;
619
620   /* run typefind */
621 #if 0
622   if (basesrc->seekable) {
623     GstCaps *caps;
624
625     caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
626     gst_pad_set_caps (basesrc->srcpad, caps);
627   }
628 #endif
629
630   return TRUE;
631
632   /* ERROR */
633 could_not_start:
634   {
635     GST_DEBUG_OBJECT (basesrc, "could not start");
636     return FALSE;
637   }
638 }
639
640 static gboolean
641 gst_basesrc_stop (GstBaseSrc * basesrc)
642 {
643   GstBaseSrcClass *bclass;
644   gboolean result = TRUE;
645
646   if (!GST_FLAG_IS_SET (basesrc, GST_BASESRC_STARTED))
647     return TRUE;
648
649   bclass = GST_BASESRC_GET_CLASS (basesrc);
650   if (bclass->stop)
651     result = bclass->stop (basesrc);
652
653   if (result)
654     GST_FLAG_UNSET (basesrc, GST_BASESRC_STARTED);
655
656   return result;
657 }
658
659 static gboolean
660 gst_basesrc_activate (GstPad * pad, GstActivateMode mode)
661 {
662   gboolean result;
663   GstBaseSrc *basesrc;
664
665   basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad));
666
667   /* prepare subclass first */
668   switch (mode) {
669     case GST_ACTIVATE_PUSH:
670     case GST_ACTIVATE_PULL:
671       result = gst_basesrc_start (basesrc);
672       break;
673     default:
674       result = TRUE;
675       break;
676   }
677   /* if that failed we can stop here */
678   if (!result)
679     goto error_start;
680
681   result = FALSE;
682   switch (mode) {
683     case GST_ACTIVATE_PUSH:
684       /* if we have a scheduler we can start the task */
685       if (GST_ELEMENT_SCHEDULER (basesrc)) {
686         GST_STREAM_LOCK (pad);
687         GST_RPAD_TASK (pad) =
688             gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (basesrc),
689             (GstTaskFunction) gst_basesrc_loop, pad);
690
691         gst_task_start (GST_RPAD_TASK (pad));
692         GST_STREAM_UNLOCK (pad);
693         result = TRUE;
694       }
695       break;
696     case GST_ACTIVATE_PULL:
697       result = TRUE;
698       break;
699     case GST_ACTIVATE_NONE:
700       /* step 1, unblock clock sync (if any) */
701
702       /* step 2, make sure streaming finishes */
703       GST_STREAM_LOCK (pad);
704       /* step 3, stop the task */
705       if (GST_RPAD_TASK (pad)) {
706         gst_task_stop (GST_RPAD_TASK (pad));
707         gst_object_unref (GST_OBJECT (GST_RPAD_TASK (pad)));
708         GST_RPAD_TASK (pad) = NULL;
709       }
710       GST_STREAM_UNLOCK (pad);
711
712       result = TRUE;
713       break;
714   }
715   return result;
716
717   /* ERROR */
718 error_start:
719   {
720     GST_DEBUG_OBJECT (basesrc, "failed to start");
721     return FALSE;
722   }
723 }
724
725 static GstElementStateReturn
726 gst_basesrc_change_state (GstElement * element)
727 {
728   GstBaseSrc *basesrc;
729   GstElementStateReturn result = GST_STATE_FAILURE;
730   GstElementState transition;
731
732   basesrc = GST_BASESRC (element);
733
734   transition = GST_STATE_TRANSITION (element);
735
736   switch (transition) {
737     case GST_STATE_NULL_TO_READY:
738       break;
739     case GST_STATE_READY_TO_PAUSED:
740       break;
741     case GST_STATE_PAUSED_TO_PLAYING:
742       break;
743     default:
744       break;
745   }
746
747   result = GST_ELEMENT_CLASS (parent_class)->change_state (element);
748
749   switch (transition) {
750     case GST_STATE_PLAYING_TO_PAUSED:
751       break;
752     case GST_STATE_PAUSED_TO_READY:
753       result = gst_basesrc_stop (basesrc);
754       break;
755     case GST_STATE_READY_TO_NULL:
756       break;
757     default:
758       break;
759   }
760
761   return result;
762 }