213 "unlocking from thread %p", \ |
218 "unlocking from thread %p", \ |
214 g_thread_self ()); \ |
219 g_thread_self ()); \ |
215 g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->lock); \ |
220 g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->lock); \ |
216 } G_STMT_END |
221 } G_STMT_END |
217 |
222 |
|
223 #define DECODE_BIN_DYN_LOCK(dbin) G_STMT_START { \ |
|
224 GST_LOG_OBJECT (dbin, \ |
|
225 "dynlocking from thread %p", \ |
|
226 g_thread_self ()); \ |
|
227 g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->dyn_lock); \ |
|
228 GST_LOG_OBJECT (dbin, \ |
|
229 "dynlocked from thread %p", \ |
|
230 g_thread_self ()); \ |
|
231 } G_STMT_END |
|
232 |
|
233 #define DECODE_BIN_DYN_UNLOCK(dbin) G_STMT_START { \ |
|
234 GST_LOG_OBJECT (dbin, \ |
|
235 "dynunlocking from thread %p", \ |
|
236 g_thread_self ()); \ |
|
237 g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->dyn_lock); \ |
|
238 } G_STMT_END |
|
239 |
218 /* GstDecodeGroup |
240 /* GstDecodeGroup |
219 * |
241 * |
220 * Streams belonging to the same group/chain of a media file |
242 * Streams belonging to the same group/chain of a media file |
221 * |
243 * |
222 */ |
244 */ |
223 struct _GstDecodeGroup |
245 struct _GstDecodeGroup |
224 { |
246 { |
225 GstDecodeBin *dbin; |
247 GstDecodeBin *dbin; |
226 GMutex *lock; |
248 GMutex *lock; |
227 GstElement *multiqueue; |
249 GstElement *multiqueue; |
|
250 |
228 gboolean exposed; /* TRUE if this group is exposed */ |
251 gboolean exposed; /* TRUE if this group is exposed */ |
229 gboolean drained; /* TRUE if EOS went throug all endpads */ |
252 gboolean drained; /* TRUE if EOS went through all endpads */ |
230 gboolean blocked; /* TRUE if all endpads are blocked */ |
253 gboolean blocked; /* TRUE if all endpads are blocked */ |
231 gboolean complete; /* TRUE if we are not expecting anymore streams |
254 gboolean complete; /* TRUE if we are not expecting anymore streams |
232 * on this group */ |
255 * on this group */ |
233 gulong overrunsig; |
256 gulong overrunsig; /* the overrun signal for multiqueue */ |
234 gulong underrunsig; |
|
235 guint nbdynamic; /* number of dynamic pads in the group. */ |
257 guint nbdynamic; /* number of dynamic pads in the group. */ |
236 |
258 |
237 GList *endpads; /* List of GstDecodePad of source pads to be exposed */ |
259 GList *endpads; /* List of GstDecodePad of source pads to be exposed */ |
238 GList *ghosts; /* List of GstGhostPad for the endpads */ |
|
239 GList *reqpads; /* List of RequestPads for multiqueue. */ |
260 GList *reqpads; /* List of RequestPads for multiqueue. */ |
240 }; |
261 }; |
241 |
262 |
242 #define GROUP_MUTEX_LOCK(group) G_STMT_START { \ |
263 #define GROUP_MUTEX_LOCK(group) G_STMT_START { \ |
243 GST_LOG_OBJECT (group->dbin, \ |
264 GST_LOG_OBJECT (group->dbin, \ |
260 static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * decode_bin, |
281 static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * decode_bin, |
261 gboolean use_queue); |
282 gboolean use_queue); |
262 static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, |
283 static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, |
263 GstPad * pad); |
284 GstPad * pad); |
264 static gboolean gst_decode_group_control_source_pad (GstDecodeGroup * group, |
285 static gboolean gst_decode_group_control_source_pad (GstDecodeGroup * group, |
265 GstPad * pad); |
286 GstDecodePad * pad); |
266 static gboolean gst_decode_group_expose (GstDecodeGroup * group); |
287 static gboolean gst_decode_group_expose (GstDecodeGroup * group); |
267 static void gst_decode_group_check_if_blocked (GstDecodeGroup * group); |
288 static gboolean gst_decode_group_check_if_blocked (GstDecodeGroup * group); |
268 static void gst_decode_group_set_complete (GstDecodeGroup * group); |
289 static void gst_decode_group_set_complete (GstDecodeGroup * group); |
269 static void gst_decode_group_hide (GstDecodeGroup * group); |
290 static void gst_decode_group_hide (GstDecodeGroup * group); |
270 static void gst_decode_group_free (GstDecodeGroup * group); |
291 static void gst_decode_group_free (GstDecodeGroup * group); |
271 |
292 |
272 /* GstDecodePad |
293 /* GstDecodePad |
273 * |
294 * |
274 * GstPad private used for source pads of groups |
295 * GstPad private used for source pads of groups |
275 */ |
296 */ |
276 |
|
277 struct _GstDecodePad |
297 struct _GstDecodePad |
278 { |
298 { |
279 GstPad *pad; |
299 GstGhostPad parent; |
280 GstDecodeGroup *group; |
|
281 gboolean blocked; |
|
282 gboolean drained; |
|
283 }; |
|
284 |
|
285 static GstDecodePad *gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, |
|
286 gboolean block); |
|
287 static void source_pad_blocked_cb (GstPad * pad, gboolean blocked, |
|
288 GstDecodePad * dpad); |
|
289 |
|
290 /* TempPadStruct |
|
291 * Internal structure used for pads which have more than one structure. |
|
292 */ |
|
293 typedef struct _TempPadStruct |
|
294 { |
|
295 GstDecodeBin *dbin; |
300 GstDecodeBin *dbin; |
296 GstDecodeGroup *group; |
301 GstDecodeGroup *group; |
297 } TempPadStruct; |
302 |
|
303 gboolean blocked; /* the pad is blocked */ |
|
304 gboolean drained; /* an EOS has been seen on the pad */ |
|
305 gboolean added; /* the pad is added to decodebin */ |
|
306 }; |
|
307 |
|
308 G_DEFINE_TYPE (GstDecodePad, gst_decode_pad, GST_TYPE_GHOST_PAD); |
|
309 #define GST_TYPE_DECODE_PAD (gst_decode_pad_get_type ()) |
|
310 #define GST_DECODE_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_PAD,GstDecodePad)) |
|
311 |
|
312 static GstDecodePad *gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad, |
|
313 GstDecodeGroup * group); |
|
314 static void gst_decode_pad_activate (GstDecodePad * dpad, |
|
315 GstDecodeGroup * group); |
|
316 static void gst_decode_pad_unblock (GstDecodePad * dpad); |
298 |
317 |
299 /******************************** |
318 /******************************** |
300 * Standard GObject boilerplate * |
319 * Standard GObject boilerplate * |
301 ********************************/ |
320 ********************************/ |
302 |
321 |
418 G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, |
439 G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, |
419 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
440 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
420 |
441 |
421 /** |
442 /** |
422 * GstDecodeBin2::unknown-type: |
443 * GstDecodeBin2::unknown-type: |
423 * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type. |
444 * @bin: The decodebin |
424 * @caps: the #GstCaps of the pad that cannot be resolved. |
445 * @pad: The new pad containing caps that cannot be resolved to a 'final' |
|
446 * stream type. |
|
447 * @caps: The #GstCaps of the pad that cannot be resolved. |
425 * |
448 * |
426 * This signal is emitted when a pad for which there is no further possible |
449 * This signal is emitted when a pad for which there is no further possible |
427 * decoding is added to the decodebin. |
450 * decoding is added to the decodebin. |
428 */ |
451 */ |
429 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = |
452 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = |
430 g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), |
453 g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), |
431 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), |
454 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), |
432 NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, |
455 NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, |
433 GST_TYPE_PAD, GST_TYPE_CAPS); |
456 GST_TYPE_PAD, GST_TYPE_CAPS); |
434 |
457 |
435 /** |
458 /** |
436 * GstDecodeBin2::autoplug-continue: |
459 * GstDecodeBin2::autoplug-continue: |
|
460 * @bin: The decodebin |
437 * @pad: The #GstPad. |
461 * @pad: The #GstPad. |
438 * @caps: The #GstCaps found. |
462 * @caps: The #GstCaps found. |
439 * |
463 * |
440 * This signal is emitted whenever decodebin2 finds a new stream. It is |
464 * This signal is emitted whenever decodebin2 finds a new stream. It is |
441 * emitted before looking for any elements that can handle that stream. |
465 * emitted before looking for any elements that can handle that stream. |
492 * Returns: A new sorted array of #GstElementFactory objects. |
518 * Returns: A new sorted array of #GstElementFactory objects. |
493 */ |
519 */ |
494 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] = |
520 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] = |
495 g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass), |
521 g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass), |
496 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort), |
522 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort), |
497 NULL, NULL, gst_play_marshal_BOXED__OBJECT_OBJECT_BOXED, |
523 NULL, NULL, gst_play_marshal_BOXED__OBJECT_BOXED_BOXED, |
498 G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY); |
524 G_TYPE_VALUE_ARRAY, 3, GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY); |
499 |
525 |
500 /** |
526 /** |
501 * GstDecodeBin2::autoplug-select: |
527 * GstDecodeBin2::autoplug-select: |
|
528 * @bin: The decodebin |
502 * @pad: The #GstPad. |
529 * @pad: The #GstPad. |
503 * @caps: The #GstCaps. |
530 * @caps: The #GstCaps. |
504 * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by |
531 * @factory: A #GstElementFactory to use |
505 * rank (higher ranks come first). |
|
506 * |
532 * |
507 * This signal is emitted once decodebin2 has found all the possible |
533 * This signal is emitted once decodebin2 has found all the possible |
508 * #GstElementFactory that can be used to handle the given @caps. |
534 * #GstElementFactory that can be used to handle the given @caps. For each of |
|
535 * those factories, this signal is emited. |
509 * |
536 * |
510 * Returns: A #gint indicating what factory index from the @factories array |
537 * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum |
511 * that you wish decodebin2 to use for trying to decode the given @caps. |
538 * value indicating what decodebin2 should do next. |
512 * Return -1 to stop selection of a factory and expose the pad as a raw type. |
539 * |
513 * The default handler always returns the first possible factory (index 0). |
540 * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from |
|
541 * @factory. |
|
542 * |
|
543 * A value of #GST_AUTOPLUG_SELECT_EXPOSE will expose @pad without plugging |
|
544 * any element to it. |
|
545 * |
|
546 * A value of #GST_AUTOPLUG_SELECT_SKIP will skip @factory and move to the |
|
547 * next factory. |
|
548 * |
|
549 * Returns: a #GST_TYPE_AUTOPLUG_SELECT_RESULT that indicates the required |
|
550 * operation. the default handler will always return |
|
551 * #GST_AUTOPLUG_SELECT_TRY. |
514 */ |
552 */ |
515 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] = |
553 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] = |
516 g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass), |
554 g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass), |
517 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select), |
555 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select), |
518 _gst_select_accumulator, NULL, |
556 _gst_select_accumulator, NULL, |
519 gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT, |
557 gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT, |
520 GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, |
558 GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, |
521 GST_TYPE_ELEMENT_FACTORY); |
559 GST_TYPE_ELEMENT_FACTORY); |
522 |
560 |
523 /** |
561 /** |
524 * GstDecodeBin2::drained |
562 * GstDecodeBin2::drained |
|
563 * @bin: The decodebin |
525 * |
564 * |
526 * This signal is emitted once decodebin2 has finished decoding all the data. |
565 * This signal is emitted once decodebin2 has finished decoding all the data. |
527 * |
566 * |
528 * Since: 0.10.16 |
567 * Since: 0.10.16 |
529 */ |
568 */ |
532 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, drained), |
571 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, drained), |
533 NULL, NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); |
572 NULL, NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); |
534 |
573 |
535 g_object_class_install_property (gobject_klass, PROP_CAPS, |
574 g_object_class_install_property (gobject_klass, PROP_CAPS, |
536 g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.", |
575 g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.", |
537 GST_TYPE_CAPS, G_PARAM_READWRITE)); |
576 GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
538 |
577 |
539 g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, |
578 g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, |
540 g_param_spec_string ("subtitle-encoding", "subtitle encoding", |
579 g_param_spec_string ("subtitle-encoding", "subtitle encoding", |
541 "Encoding to assume if input subtitles are not in UTF-8 encoding. " |
580 "Encoding to assume if input subtitles are not in UTF-8 encoding. " |
542 "If not set, the GST_SUBTITLE_ENCODING environment variable will " |
581 "If not set, the GST_SUBTITLE_ENCODING environment variable will " |
543 "be checked for an encoding to use. If that is not set either, " |
582 "be checked for an encoding to use. If that is not set either, " |
544 "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE)); |
583 "ISO-8859-15 will be assumed.", NULL, |
|
584 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
585 |
|
586 g_object_class_install_property (gobject_klass, PROP_SINK_CAPS, |
|
587 g_param_spec_boxed ("sink-caps", "Sink Caps", |
|
588 "The caps of the input data. (NULL = use typefind element)", |
|
589 GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
545 |
590 |
546 klass->autoplug_continue = |
591 klass->autoplug_continue = |
547 GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue); |
592 GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue); |
548 klass->autoplug_factories = |
593 klass->autoplug_factories = |
549 GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories); |
594 GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories); |
602 |
647 |
603 decode_bin->lock = g_mutex_new (); |
648 decode_bin->lock = g_mutex_new (); |
604 decode_bin->activegroup = NULL; |
649 decode_bin->activegroup = NULL; |
605 decode_bin->groups = NULL; |
650 decode_bin->groups = NULL; |
606 |
651 |
|
652 decode_bin->dyn_lock = g_mutex_new (); |
|
653 decode_bin->shutdown = FALSE; |
|
654 decode_bin->blocked_pads = NULL; |
|
655 |
607 decode_bin->caps = |
656 decode_bin->caps = |
608 gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;" |
657 gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;" |
609 "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup"); |
658 "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup;" |
610 |
659 "video/x-dvd-subpicture; subpicture/x-pgs"); |
611 add_fakesink (decode_bin); |
660 } |
612 |
661 |
613 /* FILLME */ |
662 static void |
|
663 gst_decode_bin_remove_groups (GstDecodeBin * dbin) |
|
664 { |
|
665 GList *tmp; |
|
666 GstIterator *it; |
|
667 gpointer point; |
|
668 gboolean done; |
|
669 GstIteratorResult res; |
|
670 |
|
671 GST_DEBUG_OBJECT (dbin, "cleaning up"); |
|
672 |
|
673 if (dbin->activegroup) { |
|
674 GST_DEBUG_OBJECT (dbin, "free active group %p", dbin->activegroup); |
|
675 gst_decode_group_free (dbin->activegroup); |
|
676 dbin->activegroup = NULL; |
|
677 } |
|
678 |
|
679 /* remove groups */ |
|
680 for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) { |
|
681 GstDecodeGroup *group = (GstDecodeGroup *) tmp->data; |
|
682 |
|
683 GST_DEBUG_OBJECT (dbin, "free group %p", group); |
|
684 gst_decode_group_free (group); |
|
685 } |
|
686 g_list_free (dbin->groups); |
|
687 dbin->groups = NULL; |
|
688 |
|
689 for (tmp = dbin->oldgroups; tmp; tmp = g_list_next (tmp)) { |
|
690 GstDecodeGroup *group = (GstDecodeGroup *) tmp->data; |
|
691 |
|
692 GST_DEBUG_OBJECT (dbin, "free old group %p", group); |
|
693 gst_decode_group_free (group); |
|
694 } |
|
695 g_list_free (dbin->oldgroups); |
|
696 dbin->oldgroups = NULL; |
|
697 |
|
698 GST_DEBUG_OBJECT (dbin, "removing last elements"); |
|
699 |
|
700 /* remove all remaining elements */ |
|
701 it = gst_bin_iterate_elements (GST_BIN_CAST (dbin)); |
|
702 restart: |
|
703 done = FALSE; |
|
704 while (!done) { |
|
705 res = gst_iterator_next (it, &point); |
|
706 switch (res) { |
|
707 case GST_ITERATOR_DONE: |
|
708 done = TRUE; |
|
709 break; |
|
710 case GST_ITERATOR_RESYNC: |
|
711 gst_iterator_resync (it); |
|
712 goto restart; |
|
713 case GST_ITERATOR_ERROR: |
|
714 GST_WARNING_OBJECT (dbin, |
|
715 "Had an error while iterating bin %s", GST_ELEMENT_NAME (dbin)); |
|
716 done = TRUE; |
|
717 break; |
|
718 case GST_ITERATOR_OK: |
|
719 { |
|
720 GstElement *elem = GST_ELEMENT_CAST (point); |
|
721 |
|
722 /* don't remove the typefind element */ |
|
723 if (elem != dbin->typefind) { |
|
724 GST_DEBUG_OBJECT (dbin, "remove element %s", GST_ELEMENT_NAME (elem)); |
|
725 gst_bin_remove (GST_BIN_CAST (dbin), elem); |
|
726 gst_element_set_state (elem, GST_STATE_NULL); |
|
727 } |
|
728 gst_object_unref (elem); |
|
729 break; |
|
730 } |
|
731 default: |
|
732 break; |
|
733 } |
|
734 } |
|
735 gst_iterator_free (it); |
614 } |
736 } |
615 |
737 |
616 static void |
738 static void |
617 gst_decode_bin_dispose (GObject * object) |
739 gst_decode_bin_dispose (GObject * object) |
618 { |
740 { |
619 GstDecodeBin *decode_bin; |
741 GstDecodeBin *decode_bin; |
620 GList *tmp; |
|
621 |
742 |
622 decode_bin = GST_DECODE_BIN (object); |
743 decode_bin = GST_DECODE_BIN (object); |
623 |
744 |
624 if (decode_bin->factories) |
745 if (decode_bin->factories) |
625 g_value_array_free (decode_bin->factories); |
746 g_value_array_free (decode_bin->factories); |
626 decode_bin->factories = NULL; |
747 decode_bin->factories = NULL; |
627 |
748 |
628 if (decode_bin->activegroup) { |
749 gst_decode_bin_remove_groups (decode_bin); |
629 gst_decode_group_free (decode_bin->activegroup); |
|
630 decode_bin->activegroup = NULL; |
|
631 } |
|
632 |
|
633 /* remove groups */ |
|
634 for (tmp = decode_bin->groups; tmp; tmp = g_list_next (tmp)) { |
|
635 GstDecodeGroup *group = (GstDecodeGroup *) tmp->data; |
|
636 |
|
637 gst_decode_group_free (group); |
|
638 } |
|
639 g_list_free (decode_bin->groups); |
|
640 decode_bin->groups = NULL; |
|
641 |
|
642 for (tmp = decode_bin->oldgroups; tmp; tmp = g_list_next (tmp)) { |
|
643 GstDecodeGroup *group = (GstDecodeGroup *) tmp->data; |
|
644 |
|
645 gst_decode_group_free (group); |
|
646 } |
|
647 g_list_free (decode_bin->oldgroups); |
|
648 decode_bin->oldgroups = NULL; |
|
649 |
750 |
650 if (decode_bin->caps) |
751 if (decode_bin->caps) |
651 gst_caps_unref (decode_bin->caps); |
752 gst_caps_unref (decode_bin->caps); |
652 decode_bin->caps = NULL; |
753 decode_bin->caps = NULL; |
653 |
754 |
654 g_free (decode_bin->encoding); |
755 g_free (decode_bin->encoding); |
655 decode_bin->encoding = NULL; |
756 decode_bin->encoding = NULL; |
656 |
757 |
657 remove_fakesink (decode_bin); |
758 g_list_free (decode_bin->subtitles); |
|
759 decode_bin->subtitles = NULL; |
658 |
760 |
659 G_OBJECT_CLASS (parent_class)->dispose (object); |
761 G_OBJECT_CLASS (parent_class)->dispose (object); |
660 } |
762 } |
661 |
763 |
662 static void |
764 static void |
683 * MT-safe |
790 * MT-safe |
684 */ |
791 */ |
685 static void |
792 static void |
686 gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps) |
793 gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps) |
687 { |
794 { |
|
795 GstCaps *old; |
|
796 |
688 GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); |
797 GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); |
689 |
798 |
690 DECODE_BIN_LOCK (dbin); |
799 GST_OBJECT_LOCK (dbin); |
691 if (dbin->caps) |
800 old = dbin->caps; |
692 gst_caps_unref (dbin->caps); |
801 if (old != caps) { |
693 if (caps) |
802 if (caps) |
694 gst_caps_ref (caps); |
803 gst_caps_ref (caps); |
695 dbin->caps = caps; |
804 |
696 DECODE_BIN_UNLOCK (dbin); |
805 dbin->caps = caps; |
|
806 |
|
807 if (old) |
|
808 gst_caps_unref (old); |
|
809 } |
|
810 GST_OBJECT_UNLOCK (dbin); |
697 } |
811 } |
698 |
812 |
699 /* _get_caps |
813 /* _get_caps |
700 * Returns the currently configured caps on which decodebin will stop decoding. |
814 * Returns the currently configured caps on which decodebin will stop decoding. |
701 * The returned caps (if not NULL), will have its refcount incremented. |
815 * The returned caps (if not NULL), will have its refcount incremented. |
702 * |
816 * |
703 * MT-safe |
817 * MT-safe |
704 */ |
818 */ |
705 |
|
706 static GstCaps * |
819 static GstCaps * |
707 gst_decode_bin_get_caps (GstDecodeBin * dbin) |
820 gst_decode_bin_get_caps (GstDecodeBin * dbin) |
708 { |
821 { |
709 GstCaps *caps; |
822 GstCaps *caps; |
710 |
823 |
711 GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); |
824 GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); |
712 |
825 |
713 DECODE_BIN_LOCK (dbin); |
826 GST_OBJECT_LOCK (dbin); |
714 caps = dbin->caps; |
827 caps = dbin->caps; |
715 if (caps) |
828 if (caps) |
716 gst_caps_ref (caps); |
829 gst_caps_ref (caps); |
717 DECODE_BIN_UNLOCK (dbin); |
830 GST_OBJECT_UNLOCK (dbin); |
718 |
831 |
719 return caps; |
832 return caps; |
720 } |
833 } |
721 |
834 |
722 static void |
835 static void |
|
836 gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps) |
|
837 { |
|
838 GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); |
|
839 |
|
840 g_object_set (dbin->typefind, "force-caps", caps, NULL); |
|
841 } |
|
842 |
|
843 static GstCaps * |
|
844 gst_decode_bin_get_sink_caps (GstDecodeBin * dbin) |
|
845 { |
|
846 GstCaps *caps; |
|
847 |
|
848 GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); |
|
849 |
|
850 g_object_get (dbin->typefind, "force-caps", &caps, NULL); |
|
851 |
|
852 return caps; |
|
853 } |
|
854 |
|
855 static void |
723 gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding) |
856 gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding) |
724 { |
857 { |
|
858 GList *walk; |
|
859 |
725 GST_DEBUG_OBJECT (dbin, "Setting new encoding: %s", GST_STR_NULL (encoding)); |
860 GST_DEBUG_OBJECT (dbin, "Setting new encoding: %s", GST_STR_NULL (encoding)); |
726 |
861 |
727 DECODE_BIN_LOCK (dbin); |
862 DECODE_BIN_LOCK (dbin); |
|
863 GST_OBJECT_LOCK (dbin); |
728 g_free (dbin->encoding); |
864 g_free (dbin->encoding); |
729 dbin->encoding = g_strdup (encoding); |
865 dbin->encoding = g_strdup (encoding); |
|
866 GST_OBJECT_UNLOCK (dbin); |
|
867 |
|
868 /* set the subtitle encoding on all added elements */ |
|
869 for (walk = dbin->subtitles; walk; walk = g_list_next (walk)) { |
|
870 g_object_set (G_OBJECT (walk->data), "subtitle-encoding", dbin->encoding, |
|
871 NULL); |
|
872 } |
730 DECODE_BIN_UNLOCK (dbin); |
873 DECODE_BIN_UNLOCK (dbin); |
731 } |
874 } |
732 |
875 |
733 static gchar * |
876 static gchar * |
734 gst_decode_bin_get_subs_encoding (GstDecodeBin * dbin) |
877 gst_decode_bin_get_subs_encoding (GstDecodeBin * dbin) |
735 { |
878 { |
736 gchar *encoding; |
879 gchar *encoding; |
737 |
880 |
738 GST_DEBUG_OBJECT (dbin, "Getting currently set encoding"); |
881 GST_DEBUG_OBJECT (dbin, "Getting currently set encoding"); |
739 |
882 |
740 DECODE_BIN_LOCK (dbin); |
883 GST_OBJECT_LOCK (dbin); |
741 encoding = g_strdup (dbin->encoding); |
884 encoding = g_strdup (dbin->encoding); |
742 DECODE_BIN_UNLOCK (dbin); |
885 GST_OBJECT_UNLOCK (dbin); |
743 |
886 |
744 return encoding; |
887 return encoding; |
745 } |
888 } |
746 |
889 |
747 static void |
890 static void |
846 |
995 |
847 static gboolean are_raw_caps (GstDecodeBin * dbin, GstCaps * caps); |
996 static gboolean are_raw_caps (GstDecodeBin * dbin, GstCaps * caps); |
848 static gboolean is_demuxer_element (GstElement * srcelement); |
997 static gboolean is_demuxer_element (GstElement * srcelement); |
849 |
998 |
850 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src, |
999 static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src, |
851 GstPad * pad, GstCaps * caps, GValueArray * factories, |
1000 GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GValueArray * factories, |
852 GstDecodeGroup * group); |
1001 GstDecodeGroup * group); |
853 static gboolean connect_element (GstDecodeBin * dbin, GstElement * element, |
1002 static gboolean connect_element (GstDecodeBin * dbin, GstElement * element, |
854 GstDecodeGroup * group); |
1003 GstDecodeGroup * group); |
855 static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
1004 static void expose_pad (GstDecodeBin * dbin, GstElement * src, |
856 GstDecodeGroup * group); |
1005 GstDecodePad * dpad, GstPad * pad, GstDecodeGroup * group); |
857 |
1006 |
858 static void pad_added_group_cb (GstElement * element, GstPad * pad, |
1007 static void pad_added_group_cb (GstElement * element, GstPad * pad, |
859 GstDecodeGroup * group); |
1008 GstDecodeGroup * group); |
860 static void pad_removed_group_cb (GstElement * element, GstPad * pad, |
1009 static void pad_removed_group_cb (GstElement * element, GstPad * pad, |
861 GstDecodeGroup * group); |
1010 GstDecodeGroup * group); |
885 analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
1035 analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, |
886 GstCaps * caps, GstDecodeGroup * group) |
1036 GstCaps * caps, GstDecodeGroup * group) |
887 { |
1037 { |
888 gboolean apcontinue = TRUE; |
1038 gboolean apcontinue = TRUE; |
889 GValueArray *factories = NULL, *result = NULL; |
1039 GValueArray *factories = NULL, *result = NULL; |
|
1040 GstDecodePad *dpad; |
890 |
1041 |
891 GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT, |
1042 GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT, |
892 GST_DEBUG_PAD_NAME (pad), caps); |
1043 GST_DEBUG_PAD_NAME (pad), caps); |
893 |
1044 |
894 if ((caps == NULL) || gst_caps_is_empty (caps)) |
1045 if ((caps == NULL) || gst_caps_is_empty (caps)) |
895 goto unknown_type; |
1046 goto unknown_type; |
896 |
1047 |
897 if (gst_caps_is_any (caps)) |
1048 if (gst_caps_is_any (caps)) |
898 goto any_caps; |
1049 goto any_caps; |
|
1050 |
|
1051 dpad = gst_decode_pad_new (dbin, pad, group); |
899 |
1052 |
900 /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs |
1053 /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs |
901 * further autoplugging. */ |
1054 * further autoplugging. */ |
902 g_signal_emit (G_OBJECT (dbin), |
1055 g_signal_emit (G_OBJECT (dbin), |
903 gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, pad, caps, |
1056 gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, dpad, caps, |
904 &apcontinue); |
1057 &apcontinue); |
905 |
1058 |
906 /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */ |
1059 /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */ |
907 if ((!apcontinue) || are_raw_caps (dbin, caps)) |
1060 if ((!apcontinue) || are_raw_caps (dbin, caps)) |
908 goto expose_pad; |
1061 goto expose_pad; |
913 goto non_fixed; |
1066 goto non_fixed; |
914 |
1067 |
915 /* 1.c else get the factories and if there's no compatible factory goto |
1068 /* 1.c else get the factories and if there's no compatible factory goto |
916 * unknown_type */ |
1069 * unknown_type */ |
917 g_signal_emit (G_OBJECT (dbin), |
1070 g_signal_emit (G_OBJECT (dbin), |
918 gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps, |
1071 gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, dpad, caps, |
919 &factories); |
1072 &factories); |
920 |
1073 |
921 /* NULL means that we can expose the pad */ |
1074 /* NULL means that we can expose the pad */ |
922 if (factories == NULL) |
1075 if (factories == NULL) |
923 goto expose_pad; |
1076 goto expose_pad; |
924 |
1077 |
925 /* if the array is empty, we have an unknown type */ |
1078 /* if the array is empty, we have an unknown type */ |
926 if (factories->n_values == 0) { |
1079 if (factories->n_values == 0) { |
927 /* no compatible factories */ |
1080 /* no compatible factories */ |
928 g_value_array_free (factories); |
1081 g_value_array_free (factories); |
|
1082 gst_object_unref (dpad); |
929 goto unknown_type; |
1083 goto unknown_type; |
930 } |
1084 } |
931 |
1085 |
932 /* 1.d sort some more. */ |
1086 /* 1.d sort some more. */ |
933 g_signal_emit (G_OBJECT (dbin), |
1087 g_signal_emit (G_OBJECT (dbin), |
934 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps, factories, |
1088 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, dpad, caps, factories, |
935 &result); |
1089 &result); |
936 g_value_array_free (factories); |
1090 g_value_array_free (factories); |
937 factories = result; |
1091 factories = result; |
938 |
1092 |
939 /* 1.e else continue autoplugging something from the list. */ |
1093 /* 1.e else continue autoplugging something from the list. */ |
940 GST_LOG_OBJECT (pad, "Let's continue discovery on this pad"); |
1094 GST_LOG_OBJECT (pad, "Let's continue discovery on this pad"); |
941 connect_pad (dbin, src, pad, caps, factories, group); |
1095 connect_pad (dbin, src, dpad, pad, caps, factories, group); |
942 |
1096 |
|
1097 gst_object_unref (dpad); |
943 g_value_array_free (factories); |
1098 g_value_array_free (factories); |
944 |
1099 |
945 return; |
1100 return; |
946 |
1101 |
947 expose_pad: |
1102 expose_pad: |
948 { |
1103 { |
949 GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue); |
1104 GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue); |
950 expose_pad (dbin, src, pad, group); |
1105 expose_pad (dbin, src, dpad, pad, group); |
|
1106 gst_object_unref (dpad); |
951 return; |
1107 return; |
952 } |
1108 } |
953 unknown_type: |
1109 unknown_type: |
954 { |
1110 { |
955 GST_LOG_OBJECT (pad, "Unknown type, firing signal"); |
1111 GST_LOG_OBJECT (pad, "Unknown type, firing signal"); |
956 g_signal_emit (G_OBJECT (dbin), |
1112 g_signal_emit (G_OBJECT (dbin), |
957 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); |
1113 gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); |
958 |
1114 |
959 /* Check if there are no pending groups, if so, remove fakesink */ |
1115 /* Check if there are no pending groups, if so, commit our state */ |
960 if (dbin->groups == NULL) |
1116 if (dbin->groups == NULL) { |
961 remove_fakesink (dbin); |
1117 do_async_done (dbin); |
|
1118 } |
962 |
1119 |
963 if (src == dbin->typefind) { |
1120 if (src == dbin->typefind) { |
964 gchar *desc; |
1121 gchar *desc; |
965 |
1122 |
966 desc = gst_pb_utils_get_decoder_description (caps); |
1123 desc = gst_pb_utils_get_decoder_description (caps); |
1028 /* 1. is element demuxer or parser */ |
1191 /* 1. is element demuxer or parser */ |
1029 if (is_demuxer_element (src)) { |
1192 if (is_demuxer_element (src)) { |
1030 GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue"); |
1193 GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue"); |
1031 |
1194 |
1032 if (!group) |
1195 if (!group) |
1033 if (!(group = get_current_group (dbin))) { |
1196 group = get_current_group (dbin, TRUE, TRUE, NULL); |
1034 group = gst_decode_group_new (dbin, TRUE); |
1197 |
1035 DECODE_BIN_LOCK (dbin); |
1198 gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL); |
1036 dbin->groups = g_list_append (dbin->groups, group); |
|
1037 DECODE_BIN_UNLOCK (dbin); |
|
1038 } |
|
1039 |
|
1040 if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad))) |
1199 if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad))) |
1041 goto beach; |
1200 goto beach; |
1042 src = group->multiqueue; |
1201 src = group->multiqueue; |
1043 pad = mqpad; |
1202 pad = mqpad; |
|
1203 gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad); |
1044 } |
1204 } |
1045 |
1205 |
1046 /* 2. Try to create an element and link to it */ |
1206 /* 2. Try to create an element and link to it */ |
1047 while (factories->n_values > 0) { |
1207 while (factories->n_values > 0) { |
1048 GstAutoplugSelectResult ret; |
1208 GstAutoplugSelectResult ret; |
1049 GstElementFactory *factory; |
1209 GstElementFactory *factory; |
1050 GstElement *element; |
1210 GstElement *element; |
1051 GstPad *sinkpad; |
1211 GstPad *sinkpad; |
|
1212 gboolean subtitle; |
1052 |
1213 |
1053 /* take first factory */ |
1214 /* take first factory */ |
1054 factory = g_value_get_object (g_value_array_get_nth (factories, 0)); |
1215 factory = g_value_get_object (g_value_array_get_nth (factories, 0)); |
1055 /* Remove selected factory from the list. */ |
1216 /* Remove selected factory from the list. */ |
1056 g_value_array_remove (factories, 0); |
1217 g_value_array_remove (factories, 0); |
1057 |
1218 |
1058 /* emit autoplug-select to see what we should do with it. */ |
1219 /* emit autoplug-select to see what we should do with it. */ |
1059 g_signal_emit (G_OBJECT (dbin), |
1220 g_signal_emit (G_OBJECT (dbin), |
1060 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], |
1221 gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], |
1061 0, pad, caps, factory, &ret); |
1222 0, dpad, caps, factory, &ret); |
1062 |
1223 |
1063 switch (ret) { |
1224 switch (ret) { |
1064 case GST_AUTOPLUG_SELECT_TRY: |
1225 case GST_AUTOPLUG_SELECT_TRY: |
1065 GST_DEBUG_OBJECT (dbin, "autoplug select requested try"); |
1226 GST_DEBUG_OBJECT (dbin, "autoplug select requested try"); |
1066 break; |
1227 break; |
1067 case GST_AUTOPLUG_SELECT_EXPOSE: |
1228 case GST_AUTOPLUG_SELECT_EXPOSE: |
1068 GST_DEBUG_OBJECT (dbin, "autoplug select requested expose"); |
1229 GST_DEBUG_OBJECT (dbin, "autoplug select requested expose"); |
1069 /* expose the pad, we don't have the source element */ |
1230 /* expose the pad, we don't have the source element */ |
1070 expose_pad (dbin, src, pad, group); |
1231 expose_pad (dbin, src, dpad, pad, group); |
1071 res = TRUE; |
1232 res = TRUE; |
1072 goto beach; |
1233 goto beach; |
1073 case GST_AUTOPLUG_SELECT_SKIP: |
1234 case GST_AUTOPLUG_SELECT_SKIP: |
1074 GST_DEBUG_OBJECT (dbin, "autoplug select requested skip"); |
1235 GST_DEBUG_OBJECT (dbin, "autoplug select requested skip"); |
1075 continue; |
1236 continue; |
1076 default: |
1237 default: |
1077 GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret); |
1238 GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret); |
1078 break; |
1239 break; |
1079 } |
1240 } |
|
1241 |
|
1242 /* 2.0. Unlink pad */ |
|
1243 gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL); |
1080 |
1244 |
1081 /* 2.1. Try to create an element */ |
1245 /* 2.1. Try to create an element */ |
1082 if ((element = gst_element_factory_create (factory, NULL)) == NULL) { |
1246 if ((element = gst_element_factory_create (factory, NULL)) == NULL) { |
1083 GST_WARNING_OBJECT (dbin, "Could not create an element from %s", |
1247 GST_WARNING_OBJECT (dbin, "Could not create an element from %s", |
1084 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); |
1248 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); |
1341 static void |
1532 static void |
1342 pad_added_group_cb (GstElement * element, GstPad * pad, GstDecodeGroup * group) |
1533 pad_added_group_cb (GstElement * element, GstPad * pad, GstDecodeGroup * group) |
1343 { |
1534 { |
1344 GstCaps *caps; |
1535 GstCaps *caps; |
1345 gboolean expose = FALSE; |
1536 gboolean expose = FALSE; |
|
1537 GstDecodeBin *dbin; |
|
1538 |
|
1539 dbin = group->dbin; |
1346 |
1540 |
1347 GST_DEBUG_OBJECT (pad, "pad added, group:%p", group); |
1541 GST_DEBUG_OBJECT (pad, "pad added, group:%p", group); |
1348 |
1542 |
1349 caps = gst_pad_get_caps (pad); |
1543 caps = gst_pad_get_caps (pad); |
1350 analyze_new_pad (group->dbin, element, pad, caps, group); |
1544 analyze_new_pad (dbin, element, pad, caps, group); |
1351 if (caps) |
1545 if (caps) |
1352 gst_caps_unref (caps); |
1546 gst_caps_unref (caps); |
1353 |
1547 |
1354 GROUP_MUTEX_LOCK (group); |
1548 GROUP_MUTEX_LOCK (group); |
1355 group->nbdynamic--; |
1549 if (group->nbdynamic > 0) |
1356 GST_LOG ("Group %p has now %d dynamic objects", group, group->nbdynamic); |
1550 group->nbdynamic--; |
|
1551 GST_LOG_OBJECT (dbin, "Group %p has now %d dynamic objects", group, |
|
1552 group->nbdynamic); |
1357 if (group->nbdynamic == 0) |
1553 if (group->nbdynamic == 0) |
1358 expose = TRUE; |
1554 expose = TRUE; |
1359 GROUP_MUTEX_UNLOCK (group); |
1555 GROUP_MUTEX_UNLOCK (group); |
1360 |
1556 |
1361 if (expose) { |
1557 if (expose) { |
1362 GST_LOG |
1558 GST_LOG_OBJECT (dbin, |
1363 ("That was the last dynamic object, now attempting to expose the group"); |
1559 "That was the last dynamic object, now attempting to expose the group"); |
1364 DECODE_BIN_LOCK (group->dbin); |
1560 DECODE_BIN_LOCK (dbin); |
1365 gst_decode_group_expose (group); |
1561 if (!gst_decode_group_expose (group)) |
1366 DECODE_BIN_UNLOCK (group->dbin); |
1562 GST_WARNING_OBJECT (dbin, "Couldn't expose group"); |
|
1563 DECODE_BIN_UNLOCK (dbin); |
1367 } |
1564 } |
1368 } |
1565 } |
1369 |
1566 |
1370 static void |
1567 static void |
1371 pad_removed_group_cb (GstElement * element, GstPad * pad, |
1568 pad_removed_group_cb (GstElement * element, GstPad * pad, |
1547 |
1741 |
1548 /**** |
1742 /**** |
1549 * GstDecodeGroup functions |
1743 * GstDecodeGroup functions |
1550 ****/ |
1744 ****/ |
1551 |
1745 |
|
1746 /* The overrun callback is used to expose groups that have not yet had their |
|
1747 * no_more_pads called while the (large) multiqueue overflowed. When this |
|
1748 * happens we must assume that the no_more_pads will not arrive anymore and we |
|
1749 * must expose the pads that we have. |
|
1750 */ |
1552 static void |
1751 static void |
1553 multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group) |
1752 multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group) |
1554 { |
1753 { |
1555 GST_LOG_OBJECT (group->dbin, "multiqueue is full"); |
1754 GstDecodeBin *dbin; |
1556 |
1755 gboolean expose; |
1557 /* if we haven't exposed the group, do it */ |
1756 |
1558 DECODE_BIN_LOCK (group->dbin); |
1757 dbin = group->dbin; |
1559 gst_decode_group_expose (group); |
1758 |
1560 DECODE_BIN_UNLOCK (group->dbin); |
1759 GST_LOG_OBJECT (dbin, "multiqueue %p is full", queue); |
1561 } |
1760 |
1562 |
1761 GROUP_MUTEX_LOCK (group); |
1563 static void |
1762 if (group->complete) { |
1564 multi_queue_underrun_cb (GstElement * queue, GstDecodeGroup * group) |
1763 /* the group was already complete (had the no_more_pads called), we |
1565 { |
1764 * can ignore the overrun signal, the last remaining dynamic element |
1566 GstDecodeBin *dbin = group->dbin; |
1765 * will expose the group eventually. */ |
1567 |
1766 GST_LOG_OBJECT (dbin, "group %p was already complete", group); |
1568 GST_LOG_OBJECT (dbin, "multiqueue is empty for group %p", group); |
1767 expose = FALSE; |
1569 |
1768 } else { |
1570 /* Check if we need to activate another group */ |
1769 /* set number of dynamic element to 0, we don't expect anything anymore |
1571 DECODE_BIN_LOCK (dbin); |
1770 * and we need the groups to be 0 for the expose to work */ |
1572 if ((group == dbin->activegroup) && dbin->groups) { |
1771 group->nbdynamic = 0; |
1573 GST_DEBUG_OBJECT (dbin, "Switching to new group"); |
1772 expose = TRUE; |
1574 /* unexpose current active */ |
1773 } |
1575 gst_decode_group_hide (group); |
1774 GROUP_MUTEX_UNLOCK (group); |
1576 |
1775 |
1577 /* expose first group of groups */ |
1776 if (expose) { |
1578 gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data); |
1777 DECODE_BIN_LOCK (dbin); |
1579 } |
1778 if (!gst_decode_group_expose (group)) |
1580 DECODE_BIN_UNLOCK (dbin); |
1779 GST_WARNING_OBJECT (dbin, "Couldn't expose group"); |
1581 } |
1780 DECODE_BIN_UNLOCK (group->dbin); |
1582 |
1781 } |
1583 /* gst_decode_group_new |
1782 } |
|
1783 |
|
1784 /* gst_decode_group_new: |
1584 * |
1785 * |
1585 * Creates a new GstDecodeGroup. It is up to the caller to add it to the list |
1786 * Creates a new GstDecodeGroup. It is up to the caller to add it to the list |
1586 * of groups. |
1787 * of groups. |
1587 */ |
1788 */ |
1588 static GstDecodeGroup * |
1789 static GstDecodeGroup * |
1617 /* we first configure the multiqueue to buffer an unlimited number of |
1818 /* we first configure the multiqueue to buffer an unlimited number of |
1618 * buffers up to 5 seconds or, when no timestamps are present, up to 2 MB of |
1819 * buffers up to 5 seconds or, when no timestamps are present, up to 2 MB of |
1619 * memory. When this queue overruns, we assume the group is complete and can |
1820 * memory. When this queue overruns, we assume the group is complete and can |
1620 * be exposed. */ |
1821 * be exposed. */ |
1621 g_object_set (G_OBJECT (mq), |
1822 g_object_set (G_OBJECT (mq), |
1622 "max-size-bytes", 2 * 1024 * 1024, |
1823 "max-size-bytes", (guint) 2 * 1024 * 1024, |
1623 "max-size-time", 5 * GST_SECOND, "max-size-buffers", 0, NULL); |
1824 "max-size-time", (guint64) 0, "max-size-buffers", (guint) 0, NULL); |
1624 /* will expose the group */ |
1825 /* will expose the group */ |
1625 group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun", |
1826 group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun", |
1626 G_CALLBACK (multi_queue_overrun_cb), group); |
1827 G_CALLBACK (multi_queue_overrun_cb), group); |
1627 /* will hide the group again, this is usually called when the multiqueue is |
|
1628 * drained because of EOS. */ |
|
1629 group->underrunsig = g_signal_connect (G_OBJECT (mq), "underrun", |
|
1630 G_CALLBACK (multi_queue_underrun_cb), group); |
|
1631 |
1828 |
1632 gst_bin_add (GST_BIN (dbin), mq); |
1829 gst_bin_add (GST_BIN (dbin), mq); |
1633 gst_element_set_state (mq, GST_STATE_PAUSED); |
1830 gst_element_set_state (mq, GST_STATE_PAUSED); |
1634 } |
1831 } |
1635 |
1832 |
1636 GST_LOG_OBJECT (dbin, "Returning new group %p", group); |
1833 GST_LOG_OBJECT (dbin, "Returning new group %p", group); |
1637 |
1834 |
1638 return group; |
1835 return group; |
1639 } |
1836 } |
1640 |
1837 |
1641 /** get_current_group: |
1838 /* get_current_group: |
1642 * |
1839 * @dbin: the decodebin |
1643 * Returns the current non-completed group. |
1840 * @create: create the group when not present |
1644 * |
1841 * @as_demux: create the group as a demuxer |
1645 * Returns NULL if no groups are available, or all groups are completed. |
1842 * @created: result when the group was created |
|
1843 * |
|
1844 * Returns the current non-completed group. The dynamic refcount of the group is |
|
1845 * increased when dealing with a demuxer. |
|
1846 * |
|
1847 * Returns: %NULL if no groups are available, or all groups are completed. |
1646 */ |
1848 */ |
1647 static GstDecodeGroup * |
1849 static GstDecodeGroup * |
1648 get_current_group (GstDecodeBin * dbin) |
1850 get_current_group (GstDecodeBin * dbin, gboolean create, gboolean as_demux, |
|
1851 gboolean * created) |
1649 { |
1852 { |
1650 GList *tmp; |
1853 GList *tmp; |
1651 GstDecodeGroup *group = NULL; |
1854 GstDecodeGroup *group = NULL; |
1652 |
1855 |
1653 DECODE_BIN_LOCK (dbin); |
1856 DECODE_BIN_LOCK (dbin); |
1654 for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) { |
1857 for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) { |
1655 GstDecodeGroup *this = (GstDecodeGroup *) tmp->data; |
1858 GstDecodeGroup *this = (GstDecodeGroup *) tmp->data; |
1656 |
1859 |
|
1860 GROUP_MUTEX_LOCK (this); |
1657 GST_LOG_OBJECT (dbin, "group %p, complete:%d", this, this->complete); |
1861 GST_LOG_OBJECT (dbin, "group %p, complete:%d", this, this->complete); |
1658 |
1862 |
1659 if (!this->complete) { |
1863 if (!this->complete) { |
1660 group = this; |
1864 group = this; |
|
1865 GROUP_MUTEX_UNLOCK (this); |
1661 break; |
1866 break; |
|
1867 } else { |
|
1868 GROUP_MUTEX_UNLOCK (this); |
1662 } |
1869 } |
1663 } |
1870 } |
|
1871 if (group == NULL && create) { |
|
1872 group = gst_decode_group_new (dbin, as_demux); |
|
1873 GST_LOG_OBJECT (dbin, "added group %p, demux %d", group, as_demux); |
|
1874 dbin->groups = g_list_prepend (dbin->groups, group); |
|
1875 if (created) |
|
1876 *created = TRUE; |
|
1877 /* demuxers are dynamic, we need no-more-pads or overrun now */ |
|
1878 if (as_demux) |
|
1879 group->nbdynamic++; |
|
1880 } |
1664 DECODE_BIN_UNLOCK (dbin); |
1881 DECODE_BIN_UNLOCK (dbin); |
1665 |
1882 |
1666 GST_LOG_OBJECT (dbin, "Returning group %p", group); |
1883 GST_LOG_OBJECT (dbin, "Returning group %p", group); |
1667 |
1884 |
1668 return group; |
1885 return group; |
1669 } |
|
1670 |
|
1671 static gboolean |
|
1672 group_demuxer_event_probe (GstPad * pad, GstEvent * event, |
|
1673 GstDecodeGroup * group) |
|
1674 { |
|
1675 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { |
|
1676 GST_DEBUG_OBJECT (group->dbin, |
|
1677 "Got EOS on group input pads, exposing group if it wasn't before"); |
|
1678 DECODE_BIN_LOCK (group->dbin); |
|
1679 gst_decode_group_expose (group); |
|
1680 DECODE_BIN_UNLOCK (group->dbin); |
|
1681 } |
|
1682 return TRUE; |
|
1683 } |
1886 } |
1684 |
1887 |
1685 /* gst_decode_group_control_demuxer_pad |
1888 /* gst_decode_group_control_demuxer_pad |
1686 * |
1889 * |
1687 * Adds a new demuxer srcpad to the given group. |
1890 * Adds a new demuxer srcpad to the given group. |
1690 * Returns NULL if there was an error. |
1893 * Returns NULL if there was an error. |
1691 */ |
1894 */ |
1692 static GstPad * |
1895 static GstPad * |
1693 gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad) |
1896 gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad) |
1694 { |
1897 { |
|
1898 GstDecodeBin *dbin; |
1695 GstPad *srcpad, *sinkpad; |
1899 GstPad *srcpad, *sinkpad; |
1696 gchar *nb, *sinkname, *srcname; |
1900 gchar *nb, *sinkname, *srcname; |
1697 |
1901 |
1698 GST_LOG ("group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad)); |
1902 dbin = group->dbin; |
|
1903 |
|
1904 GST_LOG_OBJECT (dbin, "group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad)); |
1699 |
1905 |
1700 srcpad = NULL; |
1906 srcpad = NULL; |
1701 |
1907 |
1702 if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink%d"))) { |
1908 if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink%d"))) { |
1703 GST_ERROR ("Couldn't get sinkpad from multiqueue"); |
1909 GST_ERROR_OBJECT (dbin, "Couldn't get sinkpad from multiqueue"); |
1704 return NULL; |
1910 return NULL; |
1705 } |
1911 } |
1706 |
1912 |
1707 if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) { |
1913 if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) { |
1708 GST_ERROR ("Couldn't link demuxer and multiqueue"); |
1914 GST_ERROR_OBJECT (dbin, "Couldn't link demuxer and multiqueue"); |
1709 goto beach; |
1915 goto beach; |
1710 } |
1916 } |
1711 |
1917 |
1712 group->reqpads = g_list_append (group->reqpads, sinkpad); |
1918 group->reqpads = g_list_prepend (group->reqpads, sinkpad); |
1713 |
1919 |
1714 sinkname = gst_pad_get_name (sinkpad); |
1920 sinkname = gst_pad_get_name (sinkpad); |
1715 nb = sinkname + 4; |
1921 nb = sinkname + 4; |
1716 srcname = g_strdup_printf ("src%s", nb); |
1922 srcname = g_strdup_printf ("src%s", nb); |
1717 g_free (sinkname); |
1923 g_free (sinkname); |
1718 |
1924 |
1719 GROUP_MUTEX_LOCK (group); |
1925 GROUP_MUTEX_LOCK (group); |
1720 |
1926 |
1721 if (!(srcpad = gst_element_get_pad (group->multiqueue, srcname))) { |
1927 if (!(srcpad = gst_element_get_static_pad (group->multiqueue, srcname))) { |
1722 GST_ERROR ("Couldn't get srcpad %s from multiqueue", srcname); |
1928 GST_ERROR_OBJECT (dbin, "Couldn't get srcpad %s from multiqueue", srcname); |
1723 goto chiringuito; |
1929 goto chiringuito; |
1724 } |
1930 } |
1725 |
|
1726 /* connect event handler on pad to intercept EOS events */ |
|
1727 gst_pad_add_event_probe (pad, G_CALLBACK (group_demuxer_event_probe), group); |
|
1728 |
1931 |
1729 chiringuito: |
1932 chiringuito: |
1730 g_free (srcname); |
1933 g_free (srcname); |
1731 GROUP_MUTEX_UNLOCK (group); |
1934 GROUP_MUTEX_UNLOCK (group); |
1732 |
1935 |
1788 blocked = FALSE; |
1991 blocked = FALSE; |
1789 break; |
1992 break; |
1790 } |
1993 } |
1791 } |
1994 } |
1792 |
1995 |
1793 /* 2. Update status of group */ |
1996 /* Update status of group */ |
1794 group->blocked = blocked; |
1997 group->blocked = blocked; |
1795 GST_LOG ("group is blocked:%d", blocked); |
1998 GST_LOG_OBJECT (dbin, "group is blocked:%d", blocked); |
1796 |
1999 |
1797 /* 3. don't do anything if not blocked completely */ |
2000 return blocked; |
1798 if (!blocked) |
2001 } |
1799 return; |
2002 |
1800 |
2003 /* activate the next group when there is one |
1801 /* 4. if we're the current group, expose pads */ |
2004 * |
1802 DECODE_BIN_LOCK (group->dbin); |
2005 * Returns: TRUE when group was the active group and there was a |
1803 if (!gst_decode_group_expose (group)) |
2006 * next group to activate. |
1804 GST_WARNING_OBJECT (group->dbin, "Couldn't expose group"); |
2007 */ |
1805 DECODE_BIN_UNLOCK (group->dbin); |
2008 static gboolean |
1806 } |
2009 gst_decode_bin_activate_next_group (GstDecodeBin * dbin, GstDecodeGroup * group) |
1807 |
2010 { |
1808 static void |
2011 gboolean have_next = FALSE; |
1809 gst_decode_group_check_if_drained (GstDecodeGroup * group) |
2012 |
|
2013 DECODE_BIN_LOCK (dbin); |
|
2014 /* Check if there is a next group to activate */ |
|
2015 if ((group == dbin->activegroup) && dbin->groups) { |
|
2016 GstDecodeGroup *newgroup; |
|
2017 |
|
2018 /* get the next group */ |
|
2019 newgroup = (GstDecodeGroup *) dbin->groups->data; |
|
2020 |
|
2021 GST_DEBUG_OBJECT (dbin, "Switching to new group"); |
|
2022 |
|
2023 /* hide current group */ |
|
2024 gst_decode_group_hide (group); |
|
2025 /* expose next group */ |
|
2026 gst_decode_group_expose (newgroup); |
|
2027 |
|
2028 /* we have a next group */ |
|
2029 have_next = TRUE; |
|
2030 } |
|
2031 DECODE_BIN_UNLOCK (dbin); |
|
2032 |
|
2033 return have_next; |
|
2034 } |
|
2035 |
|
2036 /* check if the group is drained, meaning all pads have seen an EOS |
|
2037 * event. */ |
|
2038 static void |
|
2039 gst_decode_pad_handle_eos (GstDecodePad * pad) |
1810 { |
2040 { |
1811 GList *tmp; |
2041 GList *tmp; |
1812 GstDecodeBin *dbin = group->dbin; |
2042 GstDecodeBin *dbin; |
|
2043 GstDecodeGroup *group; |
1813 gboolean drained = TRUE; |
2044 gboolean drained = TRUE; |
1814 |
2045 |
1815 GST_LOG ("group : %p", group); |
2046 group = pad->group; |
|
2047 dbin = group->dbin; |
|
2048 |
|
2049 GST_LOG_OBJECT (dbin, "group : %p, pad %p", group, pad); |
|
2050 |
|
2051 GROUP_MUTEX_LOCK (group); |
|
2052 /* mark pad as drained */ |
|
2053 pad->drained = TRUE; |
|
2054 |
|
2055 /* Ensure we only emit the drained signal once, for this group */ |
|
2056 if (group->drained) |
|
2057 goto was_drained; |
1816 |
2058 |
1817 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
2059 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
1818 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2060 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
1819 |
2061 |
1820 GST_LOG ("testing dpad %p", dpad); |
2062 GST_LOG_OBJECT (dbin, "testing dpad %p %d", dpad, dpad->drained); |
1821 |
2063 |
1822 if (!dpad->drained) { |
2064 if (!dpad->drained) { |
1823 drained = FALSE; |
2065 drained = FALSE; |
1824 break; |
2066 break; |
1825 } |
2067 } |
1826 } |
2068 } |
1827 |
|
1828 group->drained = drained; |
2069 group->drained = drained; |
1829 if (!drained) |
2070 GROUP_MUTEX_UNLOCK (group); |
|
2071 |
|
2072 if (drained) { |
|
2073 /* the current group is completely drained, try to activate the next |
|
2074 * group. this function returns FALSE if there was no next group activated |
|
2075 * and so we are really drained. */ |
|
2076 if (!gst_decode_bin_activate_next_group (dbin, group)) { |
|
2077 /* no more groups to activate, we're completely drained now */ |
|
2078 GST_LOG_OBJECT (dbin, "all groups drained, fire signal"); |
|
2079 g_signal_emit (G_OBJECT (dbin), gst_decode_bin_signals[SIGNAL_DRAINED], 0, |
|
2080 NULL); |
|
2081 } |
|
2082 } |
|
2083 return; |
|
2084 |
|
2085 was_drained: |
|
2086 { |
|
2087 GST_LOG_OBJECT (dbin, "group was already drained"); |
|
2088 GROUP_MUTEX_UNLOCK (group); |
1830 return; |
2089 return; |
1831 |
|
1832 /* we are drained. Check if there is a next group to activate */ |
|
1833 DECODE_BIN_LOCK (dbin); |
|
1834 if ((group == dbin->activegroup) && dbin->groups) { |
|
1835 GST_DEBUG_OBJECT (dbin, "Switching to new group"); |
|
1836 |
|
1837 /* hide current group */ |
|
1838 gst_decode_group_hide (group); |
|
1839 /* expose next group */ |
|
1840 gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data); |
|
1841 /* we're not yet drained now */ |
|
1842 drained = FALSE; |
|
1843 } |
|
1844 DECODE_BIN_UNLOCK (dbin); |
|
1845 |
|
1846 if (drained) { |
|
1847 /* no more groups to activate, we're completely drained now */ |
|
1848 GST_LOG ("all groups drained, fire signal"); |
|
1849 g_signal_emit (G_OBJECT (dbin), gst_decode_bin_signals[SIGNAL_DRAINED], 0, |
|
1850 NULL); |
|
1851 } |
2090 } |
1852 } |
2091 } |
1853 |
2092 |
1854 /* sort_end_pads: |
2093 /* sort_end_pads: |
1855 * GCompareFunc to use with lists of GstPad. |
2094 * GCompareFunc to use with lists of GstPad. |
1911 |
2146 |
1912 /* gst_decode_group_expose: |
2147 /* gst_decode_group_expose: |
1913 * |
2148 * |
1914 * Expose this group's pads. |
2149 * Expose this group's pads. |
1915 * |
2150 * |
1916 * Not MT safe, please take the group lock |
2151 * Not MT safe, please take the decodebin lock |
1917 */ |
2152 */ |
1918 static gboolean |
2153 static gboolean |
1919 gst_decode_group_expose (GstDecodeGroup * group) |
2154 gst_decode_group_expose (GstDecodeGroup * group) |
1920 { |
2155 { |
1921 GList *tmp; |
2156 GList *tmp; |
1922 GList *next = NULL; |
2157 GList *next = NULL; |
1923 |
2158 GstDecodeBin *dbin; |
1924 if (group->dbin->activegroup) { |
2159 |
1925 GST_DEBUG_OBJECT (group->dbin, "A group is already active and exposed"); |
2160 dbin = group->dbin; |
|
2161 |
|
2162 GST_DEBUG_OBJECT (dbin, "going to expose group %p", group); |
|
2163 |
|
2164 if (group->nbdynamic) { |
|
2165 GST_DEBUG_OBJECT (dbin, |
|
2166 "Group %p still has %d dynamic objects, not exposing yet", group, |
|
2167 group->nbdynamic); |
|
2168 return FALSE; |
|
2169 } |
|
2170 |
|
2171 if (dbin->activegroup == group) { |
|
2172 GST_DEBUG_OBJECT (dbin, "Group %p is already exposed, all is fine", group); |
1926 return TRUE; |
2173 return TRUE; |
1927 } |
2174 } |
1928 |
|
1929 if (group->dbin->activegroup == group) { |
|
1930 GST_WARNING ("Group %p is already exposed", group); |
|
1931 return TRUE; |
|
1932 } |
|
1933 |
|
1934 if (!group->dbin->groups |
|
1935 || (group != (GstDecodeGroup *) group->dbin->groups->data)) { |
|
1936 GST_WARNING ("Group %p is not the first group to expose", group); |
|
1937 return FALSE; |
|
1938 } |
|
1939 |
|
1940 if (group->nbdynamic) { |
|
1941 GST_WARNING ("Group %p still has %d dynamic objects, not exposing yet", |
|
1942 group, group->nbdynamic); |
|
1943 return FALSE; |
|
1944 } |
|
1945 |
|
1946 GST_LOG ("Exposing group %p", group); |
|
1947 |
2175 |
1948 if (group->multiqueue) { |
2176 if (group->multiqueue) { |
1949 /* update runtime limits. At runtime, we try to keep the amount of buffers |
2177 /* update runtime limits. At runtime, we try to keep the amount of buffers |
1950 * in the queues as low as possible (but at least 5 buffers). */ |
2178 * in the queues as low as possible (but at least 5 buffers). */ |
1951 g_object_set (G_OBJECT (group->multiqueue), |
2179 g_object_set (G_OBJECT (group->multiqueue), |
1952 "max-size-bytes", 2 * 1024 * 1024, |
2180 "max-size-bytes", 2 * 1024 * 1024, "max-size-buffers", 5, NULL); |
1953 "max-size-time", 2 * GST_SECOND, "max-size-buffers", 5, NULL); |
|
1954 /* we can now disconnect any overrun signal, which is used to expose the |
2181 /* we can now disconnect any overrun signal, which is used to expose the |
1955 * group. */ |
2182 * group. */ |
1956 if (group->overrunsig) { |
2183 if (group->overrunsig) { |
1957 GST_LOG ("Disconnecting overrun"); |
2184 GST_LOG_OBJECT (dbin, "Disconnecting overrun"); |
1958 g_signal_handler_disconnect (group->multiqueue, group->overrunsig); |
2185 g_signal_handler_disconnect (group->multiqueue, group->overrunsig); |
1959 group->overrunsig = 0; |
2186 group->overrunsig = 0; |
1960 } |
2187 } |
1961 } |
2188 } |
1962 |
2189 |
|
2190 if (dbin->activegroup) { |
|
2191 GST_DEBUG_OBJECT (dbin, |
|
2192 "another group %p is already exposed, waiting for EOS", |
|
2193 dbin->activegroup); |
|
2194 return TRUE; |
|
2195 } |
|
2196 |
|
2197 if (!dbin->groups || (group != (GstDecodeGroup *) dbin->groups->data)) { |
|
2198 GST_WARNING_OBJECT (dbin, "Group %p is not the first group to expose", |
|
2199 group); |
|
2200 return FALSE; |
|
2201 } |
|
2202 |
|
2203 GST_LOG_OBJECT (dbin, "Exposing group %p", group); |
|
2204 |
1963 /* re-order pads : video, then audio, then others */ |
2205 /* re-order pads : video, then audio, then others */ |
1964 group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads); |
2206 group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads); |
1965 |
2207 |
1966 /* Expose pads */ |
2208 /* Expose pads */ |
1967 |
|
1968 for (tmp = group->endpads; tmp; tmp = next) { |
2209 for (tmp = group->endpads; tmp; tmp = next) { |
1969 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2210 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
1970 gchar *padname; |
2211 gchar *padname; |
1971 GstPad *ghost; |
|
1972 |
2212 |
1973 next = g_list_next (tmp); |
2213 next = g_list_next (tmp); |
1974 |
2214 |
1975 /* 1. ghost pad */ |
2215 /* 1. rewrite name */ |
1976 padname = g_strdup_printf ("src%d", group->dbin->nbpads); |
2216 padname = g_strdup_printf ("src%d", dbin->nbpads); |
1977 group->dbin->nbpads++; |
2217 dbin->nbpads++; |
1978 |
2218 GST_DEBUG_OBJECT (dbin, "About to expose dpad %s as %s", |
1979 GST_LOG_OBJECT (group->dbin, "About to expose pad %s:%s", |
2219 GST_OBJECT_NAME (dpad), padname); |
1980 GST_DEBUG_PAD_NAME (dpad->pad)); |
2220 gst_object_set_name (GST_OBJECT (dpad), padname); |
1981 |
|
1982 ghost = gst_ghost_pad_new (padname, dpad->pad); |
|
1983 gst_pad_set_active (ghost, TRUE); |
|
1984 gst_element_add_pad (GST_ELEMENT (group->dbin), ghost); |
|
1985 group->ghosts = g_list_append (group->ghosts, ghost); |
|
1986 |
|
1987 g_free (padname); |
2221 g_free (padname); |
1988 |
2222 |
1989 /* 2. emit signal */ |
2223 /* 2. activate and add */ |
1990 GST_DEBUG_OBJECT (group->dbin, "emitting new-decoded-pad"); |
2224 if (!gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD (dpad))) { |
1991 g_signal_emit (G_OBJECT (group->dbin), |
2225 /* not really fatal, we can try to add the other pads */ |
1992 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost, |
2226 g_warning ("error adding pad to decodebin2"); |
|
2227 continue; |
|
2228 } |
|
2229 dpad->added = TRUE; |
|
2230 |
|
2231 /* 3. emit signal */ |
|
2232 GST_DEBUG_OBJECT (dbin, "emitting new-decoded-pad"); |
|
2233 g_signal_emit (G_OBJECT (dbin), |
|
2234 gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, dpad, |
1993 (next == NULL)); |
2235 (next == NULL)); |
1994 GST_DEBUG_OBJECT (group->dbin, "emitted new-decoded-pad"); |
2236 GST_DEBUG_OBJECT (dbin, "emitted new-decoded-pad"); |
1995 } |
2237 } |
1996 |
2238 |
1997 /* signal no-more-pads. This allows the application to hook stuff to the |
2239 /* signal no-more-pads. This allows the application to hook stuff to the |
1998 * exposed pads */ |
2240 * exposed pads */ |
1999 GST_LOG_OBJECT (group->dbin, "signalling no-more-pads"); |
2241 GST_LOG_OBJECT (dbin, "signalling no-more-pads"); |
2000 gst_element_no_more_pads (GST_ELEMENT (group->dbin)); |
2242 gst_element_no_more_pads (GST_ELEMENT (dbin)); |
2001 |
2243 |
2002 /* 3. Unblock internal pads. The application should have connected stuff now |
2244 /* 4. Unblock internal pads. The application should have connected stuff now |
2003 * so that streaming can continue. */ |
2245 * so that streaming can continue. */ |
2004 for (tmp = group->endpads; tmp; tmp = next) { |
2246 for (tmp = group->endpads; tmp; tmp = next) { |
2005 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2247 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2006 |
2248 |
2007 next = g_list_next (tmp); |
2249 next = g_list_next (tmp); |
2008 |
2250 |
2009 GST_DEBUG_OBJECT (dpad->pad, "unblocking"); |
2251 GST_DEBUG_OBJECT (dpad, "unblocking"); |
2010 gst_pad_set_blocked_async (dpad->pad, FALSE, |
2252 gst_decode_pad_unblock (dpad); |
2011 (GstPadBlockCallback) source_pad_blocked_cb, dpad); |
2253 GST_DEBUG_OBJECT (dpad, "unblocked"); |
2012 GST_DEBUG_OBJECT (dpad->pad, "unblocked"); |
2254 } |
2013 } |
2255 |
2014 |
2256 dbin->activegroup = group; |
2015 group->dbin->activegroup = group; |
|
2016 |
2257 |
2017 /* pop off the first group */ |
2258 /* pop off the first group */ |
2018 group->dbin->groups = |
2259 if (dbin->groups && dbin->groups->data) { |
2019 g_list_delete_link (group->dbin->groups, group->dbin->groups); |
2260 GST_LOG_OBJECT (dbin, "removed group %p", dbin->groups->data); |
2020 |
2261 dbin->groups = g_list_delete_link (dbin->groups, dbin->groups); |
2021 remove_fakesink (group->dbin); |
2262 } else { |
|
2263 GST_LOG_OBJECT (dbin, "no more groups"); |
|
2264 } |
|
2265 |
|
2266 do_async_done (dbin); |
2022 |
2267 |
2023 group->exposed = TRUE; |
2268 group->exposed = TRUE; |
2024 |
2269 |
2025 GST_LOG_OBJECT (group->dbin, "Group %p exposed", group); |
2270 GST_LOG_OBJECT (dbin, "Group %p exposed", group); |
2026 return TRUE; |
2271 return TRUE; |
2027 } |
2272 } |
2028 |
2273 |
|
2274 /* must be called with the decodebin lock */ |
2029 static void |
2275 static void |
2030 gst_decode_group_hide (GstDecodeGroup * group) |
2276 gst_decode_group_hide (GstDecodeGroup * group) |
2031 { |
2277 { |
2032 GList *tmp; |
2278 GList *tmp; |
2033 |
2279 GstDecodeBin *dbin; |
2034 GST_LOG ("Hiding group %p", group); |
2280 |
2035 |
2281 dbin = group->dbin; |
2036 if (group != group->dbin->activegroup) { |
2282 |
2037 GST_WARNING ("This group is not the active one, aborting"); |
2283 GST_LOG_OBJECT (dbin, "Hiding group %p", group); |
|
2284 |
|
2285 if (group != dbin->activegroup) { |
|
2286 GST_WARNING_OBJECT (dbin, "This group is not the active one, ignoring"); |
2038 return; |
2287 return; |
2039 } |
2288 } |
2040 |
2289 |
2041 GROUP_MUTEX_LOCK (group); |
2290 GROUP_MUTEX_LOCK (group); |
2042 |
|
2043 /* Remove ghost pads */ |
2291 /* Remove ghost pads */ |
2044 for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp)) |
2292 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
2045 gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data); |
2293 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2046 |
2294 |
2047 g_list_free (group->ghosts); |
2295 if (dpad->added) |
2048 group->ghosts = NULL; |
2296 gst_element_remove_pad (GST_ELEMENT (group->dbin), GST_PAD (dpad)); |
2049 |
2297 dpad->added = FALSE; |
|
2298 } |
2050 group->exposed = FALSE; |
2299 group->exposed = FALSE; |
2051 |
|
2052 GROUP_MUTEX_UNLOCK (group); |
2300 GROUP_MUTEX_UNLOCK (group); |
2053 |
2301 |
2054 group->dbin->activegroup = NULL; |
2302 group->dbin->activegroup = NULL; |
2055 group->dbin->oldgroups = g_list_append (group->dbin->oldgroups, group); |
2303 group->dbin->oldgroups = g_list_prepend (group->dbin->oldgroups, group); |
2056 } |
2304 } |
2057 |
2305 |
2058 static void |
2306 static void |
2059 deactivate_free_recursive (GstDecodeGroup * group, GstElement * element) |
2307 deactivate_free_recursive (GstDecodeGroup * group, GstElement * element) |
2060 { |
2308 { |
2061 GstIterator *it; |
2309 GstIterator *it; |
2062 GstIteratorResult res; |
2310 GstIteratorResult res; |
2063 gpointer point; |
2311 gpointer point; |
2064 |
2312 GstDecodeBin *dbin; |
2065 GST_LOG ("element:%s", GST_ELEMENT_NAME (element)); |
2313 |
|
2314 dbin = group->dbin; |
|
2315 |
|
2316 GST_LOG_OBJECT (dbin, "element:%s", GST_ELEMENT_NAME (element)); |
2066 |
2317 |
2067 /* call on downstream elements */ |
2318 /* call on downstream elements */ |
2068 it = gst_element_iterate_src_pads (element); |
2319 it = gst_element_iterate_src_pads (element); |
2069 |
2320 |
2070 restart: |
2321 restart: |
2106 } |
2358 } |
2107 } |
2359 } |
2108 |
2360 |
2109 done: |
2361 done: |
2110 gst_element_set_state (element, GST_STATE_NULL); |
2362 gst_element_set_state (element, GST_STATE_NULL); |
2111 gst_bin_remove (GST_BIN (group->dbin), element); |
2363 DECODE_BIN_LOCK (dbin); |
|
2364 /* remove possible subtitle element */ |
|
2365 dbin->subtitles = g_list_remove (dbin->subtitles, element); |
|
2366 DECODE_BIN_UNLOCK (dbin); |
|
2367 gst_bin_remove (GST_BIN (dbin), element); |
2112 |
2368 |
2113 beach: |
2369 beach: |
2114 gst_iterator_free (it); |
2370 gst_iterator_free (it); |
2115 |
2371 |
2116 return; |
2372 return; |
2117 } |
2373 } |
2118 |
2374 |
2119 static void |
2375 static void |
2120 gst_decode_group_free (GstDecodeGroup * group) |
2376 gst_decode_group_free (GstDecodeGroup * group) |
2121 { |
2377 { |
|
2378 GstDecodeBin *dbin; |
2122 GList *tmp; |
2379 GList *tmp; |
2123 |
2380 |
2124 GST_LOG ("group %p", group); |
2381 dbin = group->dbin; |
|
2382 |
|
2383 GST_LOG_OBJECT (dbin, "group %p", group); |
2125 |
2384 |
2126 GROUP_MUTEX_LOCK (group); |
2385 GROUP_MUTEX_LOCK (group); |
2127 |
2386 |
2128 /* free ghost pads */ |
2387 /* remove exposed pads */ |
2129 if (group == group->dbin->activegroup) { |
2388 if (group == dbin->activegroup) { |
2130 for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp)) |
2389 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
2131 gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data); |
2390 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2132 |
2391 |
2133 g_list_free (group->ghosts); |
2392 if (dpad->added) |
2134 group->ghosts = NULL; |
2393 gst_element_remove_pad (GST_ELEMENT (dbin), GST_PAD (dpad)); |
|
2394 dpad->added = FALSE; |
|
2395 } |
2135 } |
2396 } |
2136 |
2397 |
2137 /* Clear all GstDecodePad */ |
2398 /* Clear all GstDecodePad */ |
2138 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) { |
2399 for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) |
2139 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
2400 gst_object_unref (tmp->data); |
2140 |
|
2141 g_free (dpad); |
|
2142 } |
|
2143 g_list_free (group->endpads); |
2401 g_list_free (group->endpads); |
2144 group->endpads = NULL; |
2402 group->endpads = NULL; |
2145 |
2403 |
2146 /* release request pads */ |
2404 /* release request pads */ |
2147 for (tmp = group->reqpads; tmp; tmp = g_list_next (tmp)) { |
2405 for (tmp = group->reqpads; tmp; tmp = g_list_next (tmp)) { |
2168 } |
2424 } |
2169 |
2425 |
2170 /* gst_decode_group_set_complete: |
2426 /* gst_decode_group_set_complete: |
2171 * |
2427 * |
2172 * Mark the group as complete. This means no more streams will be controlled |
2428 * Mark the group as complete. This means no more streams will be controlled |
2173 * through this group. |
2429 * through this group. This method is usually called when we got no_more_pads or |
|
2430 * when we added the last pad not from a demuxer. |
|
2431 * |
|
2432 * When this method is called, it is possible that some dynamic plugging is |
|
2433 * going on in streaming threads. We decrement the dynamic counter and when it |
|
2434 * reaches zero, we check if all of our pads are blocked before we finally |
|
2435 * expose the group. |
2174 * |
2436 * |
2175 * MT safe |
2437 * MT safe |
2176 */ |
2438 */ |
2177 static void |
2439 static void |
2178 gst_decode_group_set_complete (GstDecodeGroup * group) |
2440 gst_decode_group_set_complete (GstDecodeGroup * group) |
2179 { |
2441 { |
2180 GST_LOG_OBJECT (group->dbin, "Setting group %p to COMPLETE", group); |
2442 gboolean expose = FALSE; |
|
2443 GstDecodeBin *dbin; |
|
2444 |
|
2445 dbin = group->dbin; |
|
2446 |
|
2447 GST_LOG_OBJECT (dbin, "Setting group %p to COMPLETE", group); |
2181 |
2448 |
2182 GROUP_MUTEX_LOCK (group); |
2449 GROUP_MUTEX_LOCK (group); |
2183 group->complete = TRUE; |
2450 group->complete = TRUE; |
2184 gst_decode_group_check_if_blocked (group); |
2451 if (group->nbdynamic > 0) |
|
2452 group->nbdynamic--; |
|
2453 expose = gst_decode_group_check_if_blocked (group); |
2185 GROUP_MUTEX_UNLOCK (group); |
2454 GROUP_MUTEX_UNLOCK (group); |
2186 } |
2455 |
2187 |
2456 /* don't do anything if not blocked completely */ |
2188 |
2457 if (expose) { |
|
2458 DECODE_BIN_LOCK (dbin); |
|
2459 if (!gst_decode_group_expose (group)) |
|
2460 GST_WARNING_OBJECT (dbin, "Couldn't expose group"); |
|
2461 DECODE_BIN_UNLOCK (dbin); |
|
2462 } |
|
2463 } |
2189 |
2464 |
2190 /************************* |
2465 /************************* |
2191 * GstDecodePad functions |
2466 * GstDecodePad functions |
2192 *************************/ |
2467 *************************/ |
2193 |
2468 |
2194 static void |
2469 static void |
2195 source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad) |
2470 gst_decode_pad_class_init (GstDecodePadClass * klass) |
2196 { |
2471 { |
2197 GST_LOG_OBJECT (pad, "blocked:%d , dpad:%p, dpad->group:%p", |
2472 } |
2198 blocked, dpad, dpad->group); |
2473 |
2199 |
2474 static void |
|
2475 gst_decode_pad_init (GstDecodePad * pad) |
|
2476 { |
|
2477 pad->group = NULL; |
|
2478 pad->blocked = FALSE; |
|
2479 pad->drained = FALSE; |
|
2480 gst_object_ref (pad); |
|
2481 gst_object_sink (pad); |
|
2482 } |
|
2483 |
|
2484 static void |
|
2485 source_pad_blocked_cb (GstDecodePad * dpad, gboolean blocked, gpointer unused) |
|
2486 { |
|
2487 GstDecodeGroup *group; |
|
2488 GstDecodeBin *dbin; |
|
2489 gboolean expose = FALSE; |
|
2490 |
|
2491 group = dpad->group; |
|
2492 dbin = group->dbin; |
|
2493 |
|
2494 GST_LOG_OBJECT (dpad, "blocked:%d, dpad->group:%p", blocked, group); |
|
2495 |
|
2496 GROUP_MUTEX_LOCK (group); |
2200 /* Update this GstDecodePad status */ |
2497 /* Update this GstDecodePad status */ |
2201 dpad->blocked = blocked; |
2498 dpad->blocked = blocked; |
2202 |
2499 if (blocked) |
2203 if (blocked) { |
2500 expose = gst_decode_group_check_if_blocked (group); |
2204 GROUP_MUTEX_LOCK (dpad->group); |
2501 GROUP_MUTEX_UNLOCK (group); |
2205 gst_decode_group_check_if_blocked (dpad->group); |
2502 |
2206 GROUP_MUTEX_UNLOCK (dpad->group); |
2503 if (expose) { |
|
2504 DECODE_BIN_LOCK (dbin); |
|
2505 if (!gst_decode_group_expose (group)) |
|
2506 GST_WARNING_OBJECT (dbin, "Couldn't expose group"); |
|
2507 DECODE_BIN_UNLOCK (dbin); |
2207 } |
2508 } |
2208 } |
2509 } |
2209 |
2510 |
2210 static gboolean |
2511 static gboolean |
2211 source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad) |
2512 source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad) |
2212 { |
2513 { |
2213 GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad); |
2514 GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad); |
2214 |
2515 |
2215 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { |
2516 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { |
2216 /* Set our pad as drained */ |
|
2217 dpad->drained = TRUE; |
|
2218 |
|
2219 GST_DEBUG_OBJECT (pad, "we received EOS"); |
2517 GST_DEBUG_OBJECT (pad, "we received EOS"); |
2220 |
2518 |
2221 /* Check if all pads are drained. If there is a next group to expose, we |
2519 /* Check if all pads are drained. If there is a next group to expose, we |
2222 * will remove the ghostpad of the current group first, which unlinks the |
2520 * will remove the ghostpad of the current group first, which unlinks the |
2223 * peer and so drops the EOS. */ |
2521 * peer and so drops the EOS. */ |
2224 gst_decode_group_check_if_drained (dpad->group); |
2522 gst_decode_pad_handle_eos (dpad); |
2225 } |
2523 } |
2226 /* never drop events */ |
2524 /* never drop events */ |
2227 return TRUE; |
2525 return TRUE; |
2228 } |
2526 } |
2229 |
2527 |
|
2528 static void |
|
2529 gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked) |
|
2530 { |
|
2531 GstDecodeBin *dbin = dpad->dbin; |
|
2532 |
|
2533 DECODE_BIN_DYN_LOCK (dbin); |
|
2534 gst_pad_set_blocked_async (GST_PAD (dpad), blocked, |
|
2535 (GstPadBlockCallback) source_pad_blocked_cb, NULL); |
|
2536 if (blocked) { |
|
2537 if (dbin->shutdown) { |
|
2538 /* deactivate to force flushing state to prevent NOT_LINKED errors */ |
|
2539 gst_pad_set_active (GST_PAD (dpad), FALSE); |
|
2540 } else { |
|
2541 gst_object_ref (dpad); |
|
2542 dbin->blocked_pads = g_list_prepend (dbin->blocked_pads, dpad); |
|
2543 } |
|
2544 } else { |
|
2545 if (g_list_find (dbin->blocked_pads, dpad)) |
|
2546 gst_object_unref (dpad); |
|
2547 dbin->blocked_pads = g_list_remove (dbin->blocked_pads, dpad); |
|
2548 } |
|
2549 DECODE_BIN_DYN_UNLOCK (dbin); |
|
2550 } |
|
2551 |
|
2552 static void |
|
2553 gst_decode_pad_add_drained_check (GstDecodePad * dpad) |
|
2554 { |
|
2555 gst_pad_add_event_probe (GST_PAD (dpad), |
|
2556 G_CALLBACK (source_pad_event_probe), dpad); |
|
2557 } |
|
2558 |
|
2559 static void |
|
2560 gst_decode_pad_activate (GstDecodePad * dpad, GstDecodeGroup * group) |
|
2561 { |
|
2562 g_return_if_fail (group != NULL); |
|
2563 |
|
2564 dpad->group = group; |
|
2565 gst_pad_set_active (GST_PAD (dpad), TRUE); |
|
2566 gst_decode_pad_set_blocked (dpad, TRUE); |
|
2567 gst_decode_pad_add_drained_check (dpad); |
|
2568 } |
|
2569 |
|
2570 static void |
|
2571 gst_decode_pad_unblock (GstDecodePad * dpad) |
|
2572 { |
|
2573 gst_decode_pad_set_blocked (dpad, FALSE); |
|
2574 } |
|
2575 |
2230 /*gst_decode_pad_new: |
2576 /*gst_decode_pad_new: |
2231 * |
2577 * |
2232 * Creates a new GstDecodePad for the given pad. |
2578 * Creates a new GstDecodePad for the given pad. |
2233 * If block is TRUE, Sets the pad blocking asynchronously |
|
2234 */ |
2579 */ |
2235 static GstDecodePad * |
2580 static GstDecodePad * |
2236 gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, gboolean block) |
2581 gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad, GstDecodeGroup * group) |
2237 { |
2582 { |
2238 GstDecodePad *dpad; |
2583 GstDecodePad *dpad; |
2239 |
2584 |
2240 dpad = g_new0 (GstDecodePad, 1); |
2585 dpad = |
2241 dpad->pad = pad; |
2586 g_object_new (GST_TYPE_DECODE_PAD, "direction", GST_PAD_DIRECTION (pad), |
|
2587 NULL); |
|
2588 gst_ghost_pad_construct (GST_GHOST_PAD (dpad)); |
|
2589 gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad); |
2242 dpad->group = group; |
2590 dpad->group = group; |
2243 dpad->blocked = FALSE; |
2591 dpad->dbin = dbin; |
2244 dpad->drained = TRUE; |
2592 |
2245 |
|
2246 if (block) |
|
2247 gst_pad_set_blocked_async (pad, TRUE, |
|
2248 (GstPadBlockCallback) source_pad_blocked_cb, dpad); |
|
2249 gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), dpad); |
|
2250 return dpad; |
2593 return dpad; |
2251 } |
2594 } |
2252 |
2595 |
2253 |
2596 |
2254 /***** |
2597 /***** |
2255 * Element add/remove |
2598 * Element add/remove |
2256 *****/ |
2599 *****/ |
2257 |
2600 |
2258 /* |
2601 static void |
2259 * add_fakesink / remove_fakesink |
2602 do_async_start (GstDecodeBin * dbin) |
2260 * |
2603 { |
2261 * We use a sink so that the parent ::change_state returns GST_STATE_CHANGE_ASYNC |
2604 GstMessage *message; |
2262 * when that sink is present (since it's not connected to anything it will |
2605 |
2263 * always return GST_STATE_CHANGE_ASYNC). |
2606 dbin->async_pending = TRUE; |
2264 * |
2607 |
2265 * But this is an ugly way of achieving this goal. |
2608 message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE); |
2266 * Ideally, we shouldn't use a sink and just return GST_STATE_CHANGE_ASYNC in |
2609 parent_class->handle_message (GST_BIN_CAST (dbin), message); |
2267 * our ::change_state if we have not exposed the active group. |
2610 } |
2268 * We also need to override ::get_state to fake the asynchronous behaviour. |
2611 |
2269 * Once the active group is exposed, we would then post a |
2612 static void |
2270 * GST_MESSAGE_STATE_DIRTY and return GST_STATE_CHANGE_SUCCESS (which will call |
2613 do_async_done (GstDecodeBin * dbin) |
2271 * ::get_state . |
2614 { |
2272 */ |
2615 GstMessage *message; |
2273 |
2616 |
2274 static gboolean |
2617 if (dbin->async_pending) { |
2275 add_fakesink (GstDecodeBin * decode_bin) |
2618 message = gst_message_new_async_done (GST_OBJECT_CAST (dbin)); |
2276 { |
2619 parent_class->handle_message (GST_BIN_CAST (dbin), message); |
2277 GST_DEBUG_OBJECT (decode_bin, "Adding the fakesink"); |
2620 |
2278 |
2621 dbin->async_pending = FALSE; |
2279 if (decode_bin->fakesink) |
2622 } |
2280 return TRUE; |
|
2281 |
|
2282 decode_bin->fakesink = |
|
2283 gst_element_factory_make ("fakesink", "async-fakesink"); |
|
2284 if (!decode_bin->fakesink) |
|
2285 goto no_fakesink; |
|
2286 |
|
2287 /* enable sync so that we force ASYNC preroll */ |
|
2288 g_object_set (G_OBJECT (decode_bin->fakesink), "sync", TRUE, NULL); |
|
2289 |
|
2290 /* hacky, remove sink flag, we don't want our decodebin to become a sink |
|
2291 * just because we add a fakesink element to make us ASYNC */ |
|
2292 GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK); |
|
2293 |
|
2294 if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink)) |
|
2295 goto could_not_add; |
|
2296 |
|
2297 return TRUE; |
|
2298 |
|
2299 /* ERRORS */ |
|
2300 no_fakesink: |
|
2301 { |
|
2302 g_warning ("can't find fakesink element, decodebin will not work"); |
|
2303 return FALSE; |
|
2304 } |
|
2305 could_not_add: |
|
2306 { |
|
2307 g_warning ("Could not add fakesink to decodebin, decodebin will not work"); |
|
2308 gst_object_unref (decode_bin->fakesink); |
|
2309 decode_bin->fakesink = NULL; |
|
2310 return FALSE; |
|
2311 } |
|
2312 } |
|
2313 |
|
2314 static void |
|
2315 remove_fakesink (GstDecodeBin * decode_bin) |
|
2316 { |
|
2317 if (decode_bin->fakesink == NULL) |
|
2318 return; |
|
2319 |
|
2320 GST_DEBUG_OBJECT (decode_bin, "Removing the fakesink"); |
|
2321 |
|
2322 gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL); |
|
2323 gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink); |
|
2324 decode_bin->fakesink = NULL; |
|
2325 } |
2623 } |
2326 |
2624 |
2327 /***** |
2625 /***** |
2328 * convenience functions |
2626 * convenience functions |
2329 *****/ |
2627 *****/ |
2349 gst_iterator_free (it); |
2647 gst_iterator_free (it); |
2350 |
2648 |
2351 return pad; |
2649 return pad; |
2352 } |
2650 } |
2353 |
2651 |
|
2652 /* call with dyn_lock held */ |
|
2653 static void |
|
2654 unblock_pads (GstDecodeBin * dbin) |
|
2655 { |
|
2656 GList *tmp, *next; |
|
2657 |
|
2658 for (tmp = dbin->blocked_pads; tmp; tmp = next) { |
|
2659 GstDecodePad *dpad = (GstDecodePad *) tmp->data; |
|
2660 |
|
2661 next = g_list_next (tmp); |
|
2662 |
|
2663 GST_DEBUG_OBJECT (dpad, "unblocking"); |
|
2664 gst_pad_set_blocked_async (GST_PAD (dpad), FALSE, |
|
2665 (GstPadBlockCallback) source_pad_blocked_cb, NULL); |
|
2666 /* make flushing, prevent NOT_LINKED */ |
|
2667 GST_PAD_SET_FLUSHING (GST_PAD (dpad)); |
|
2668 gst_object_unref (dpad); |
|
2669 GST_DEBUG_OBJECT (dpad, "unblocked"); |
|
2670 } |
|
2671 |
|
2672 /* clear, no more blocked pads */ |
|
2673 g_list_free (dbin->blocked_pads); |
|
2674 dbin->blocked_pads = NULL; |
|
2675 } |
|
2676 |
2354 static GstStateChangeReturn |
2677 static GstStateChangeReturn |
2355 gst_decode_bin_change_state (GstElement * element, GstStateChange transition) |
2678 gst_decode_bin_change_state (GstElement * element, GstStateChange transition) |
2356 { |
2679 { |
2357 GstStateChangeReturn ret; |
2680 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; |
2358 GstDecodeBin *dbin = GST_DECODE_BIN (element); |
2681 GstDecodeBin *dbin = GST_DECODE_BIN (element); |
2359 |
2682 |
2360 switch (transition) { |
2683 switch (transition) { |
2361 case GST_STATE_CHANGE_NULL_TO_READY: |
2684 case GST_STATE_CHANGE_NULL_TO_READY: |
2362 if (dbin->typefind == NULL) |
2685 if (dbin->typefind == NULL) |
2363 goto missing_typefind; |
2686 goto missing_typefind; |
2364 break; |
2687 break; |
2365 case GST_STATE_CHANGE_READY_TO_PAUSED:{ |
2688 case GST_STATE_CHANGE_READY_TO_PAUSED: |
|
2689 DECODE_BIN_DYN_LOCK (dbin); |
|
2690 GST_LOG_OBJECT (dbin, "clearing shutdown flag"); |
|
2691 dbin->shutdown = FALSE; |
|
2692 DECODE_BIN_DYN_UNLOCK (dbin); |
2366 dbin->have_type = FALSE; |
2693 dbin->have_type = FALSE; |
2367 if (!add_fakesink (dbin)) |
2694 ret = GST_STATE_CHANGE_ASYNC; |
2368 goto missing_fakesink; |
2695 do_async_start (dbin); |
2369 break; |
2696 break; |
2370 } |
2697 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
2698 DECODE_BIN_DYN_LOCK (dbin); |
|
2699 GST_LOG_OBJECT (dbin, "setting shutdown flag"); |
|
2700 dbin->shutdown = TRUE; |
|
2701 unblock_pads (dbin); |
|
2702 DECODE_BIN_DYN_UNLOCK (dbin); |
2371 default: |
2703 default: |
2372 break; |
2704 break; |
2373 } |
2705 } |
2374 |
2706 |
2375 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
2707 { |
2376 |
2708 GstStateChangeReturn bret; |
2377 /* FIXME : put some cleanup functions here.. if needed */ |
2709 |
|
2710 bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
|
2711 if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE)) |
|
2712 goto activate_failed; |
|
2713 else if (G_UNLIKELY (bret == GST_STATE_CHANGE_NO_PREROLL)) { |
|
2714 do_async_done (dbin); |
|
2715 ret = bret; |
|
2716 } |
|
2717 } |
|
2718 switch (transition) { |
|
2719 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
2720 do_async_done (dbin); |
|
2721 gst_decode_bin_remove_groups (dbin); |
|
2722 break; |
|
2723 case GST_STATE_CHANGE_READY_TO_NULL: |
|
2724 gst_decode_bin_remove_groups (dbin); |
|
2725 break; |
|
2726 default: |
|
2727 break; |
|
2728 } |
2378 |
2729 |
2379 return ret; |
2730 return ret; |
2380 |
2731 |
2381 /* ERRORS */ |
2732 /* ERRORS */ |
2382 missing_typefind: |
2733 missing_typefind: |
2384 gst_element_post_message (element, |
2735 gst_element_post_message (element, |
2385 gst_missing_element_message_new (element, "typefind")); |
2736 gst_missing_element_message_new (element, "typefind")); |
2386 GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!")); |
2737 GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!")); |
2387 return GST_STATE_CHANGE_FAILURE; |
2738 return GST_STATE_CHANGE_FAILURE; |
2388 } |
2739 } |
2389 missing_fakesink: |
2740 activate_failed: |
2390 { |
2741 { |
2391 gst_element_post_message (element, |
2742 GST_DEBUG_OBJECT (element, |
2392 gst_missing_element_message_new (element, "fakesink")); |
2743 "element failed to change states -- activation problem?"); |
2393 GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!")); |
|
2394 return GST_STATE_CHANGE_FAILURE; |
2744 return GST_STATE_CHANGE_FAILURE; |
2395 } |
2745 } |
2396 } |
2746 } |
2397 |
2747 #ifdef __SYMBIAN32__ |
2398 static gboolean |
2748 EXPORT_C |
|
2749 #endif |
|
2750 |
|
2751 |
|
2752 gboolean |
2399 gst_decode_bin_plugin_init (GstPlugin * plugin) |
2753 gst_decode_bin_plugin_init (GstPlugin * plugin) |
2400 { |
2754 { |
2401 GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0, |
2755 GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0, |
2402 "decoder bin"); |
2756 "decoder bin"); |
2403 |
2757 |
2404 #ifdef ENABLE_NLS |
2758 #ifdef ENABLE_NLS |
2405 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
2759 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, |
2406 LOCALEDIR); |
2760 LOCALEDIR); |
2407 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
2761 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); |
|
2762 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
2408 #endif /* ENABLE_NLS */ |
2763 #endif /* ENABLE_NLS */ |
2409 |
2764 |
2410 return gst_element_register (plugin, "decodebin2", GST_RANK_NONE, |
2765 return gst_element_register (plugin, "decodebin2", GST_RANK_NONE, |
2411 GST_TYPE_DECODE_BIN); |
2766 GST_TYPE_DECODE_BIN); |
2412 } |
2767 } |