After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 563828 - [decodebin2] Complains about loops in the graph when demuxer output requires another demuxer
[decodebin2] Complains about loops in the graph when demuxer output requires ...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
git master
Other Linux
: Normal major
: 0.10.26
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on: 596183
Blocks: 303975
 
 
Reported: 2008-12-09 10:15 UTC by Sebastian Dröge (slomo)
Modified: 2009-10-07 15:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
decodebin2-demuxer-demuxer.diff (2.96 KB, patch)
2009-04-05 09:57 UTC, Sebastian Dröge (slomo)
rejected Details | Review

Description Sebastian Dröge (slomo) 2008-12-09 10:15:31 UTC
Hi,
decodebin2 complains about loops in the graph when playing MXF files which contain DV. Other files work fine so it's probably caused by the demuxer after the demuxer (mxfdemux ! dvdemux).

Output below, full debug log attached ;)


Setting pipeline to PAUSED ...
/GstPipeline:pipeline0/GstDecodeBin2:d/GstTypeFindElement:typefind.GstPad:src: caps = application/mxf
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMXFDemux:mxfdemux0.GstPad:sink: caps = application/mxf
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink0: caps = video/x-dv, systemstream=(boolean)true
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src0: caps = video/x-dv, systemstream=(boolean)true
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src0: caps = video/x-dv, systemstream=(boolean)true
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink2: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink2: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
# no audio
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0: max-size-buffers = 5
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0: max-size-time = 2000000000
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0: max-size-bytes = 2097152
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src1: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:src: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:sink: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src1: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src1.GstProxyPad:proxypad3: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstAlsaSink:alsasink0.GstPad:sink: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstAlsaSink:alsasink0.GstPad:sink: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstAlsaSink:alsasink0.GstPad:sink: caps = audio/x-raw-int, rate=(int)48000, channels=(int)1, signed=(boolean)true, endianness=(int)1234, depth=(int)16, width=(int)16
/GstPipeline:pipeline0/GstDecodeBin2:d/GstDVDemux:dvdemux0.GstPad:video: caps = video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int)576, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink3: caps = video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int)576, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src3: caps = video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int)576, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstDecodeBin2:d/ffdec_dvvideo:ffdec_dvvideo0.GstPad:sink: caps = video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int)576, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstDecodeBin2:d/ffdec_dvvideo:ffdec_dvvideo0.GstPad:src: caps = video/x-raw-yuv, width=(int)720, height=(int)576, framerate=(fraction)25/1, format=(fourcc)I420, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstFFMpegCsp:ffmpegcsp0.GstPad:src: caps = video/x-raw-yuv, width=(int)720, height=(int)576, framerate=(fraction)25/1, format=(fourcc)I420, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstFFMpegCsp:ffmpegcsp0.GstPad:sink: caps = video/x-raw-yuv, width=(int)720, height=(int)576, framerate=(fraction)25/1, format=(fourcc)I420, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src0: caps = video/x-raw-yuv, width=(int)720, height=(int)576, framerate=(fraction)25/1, format=(fourcc)I420, pixel-aspect-ratio=(fraction)59/54
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src0.GstProxyPad:proxypad6: caps = video/x-raw-yuv, width=(int)720, height=(int)576, framerate=(fraction)25/1, format=(fourcc)I420, pixel-aspect-ratio=(fraction)59/54
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
# no audio
/GstPipeline:pipeline0/GstXvImageSink:xvimagesink0.GstPad:sink: caps = video/x-raw-yuv, width=(int)720, height=(int)576, framerate=(fraction)25/1, format=(fourcc)I420, pixel-aspect-ratio=(fraction)59/54
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...

(gst-launch-0.10:11118): GStreamer-WARNING **: loop detected in the graph of bin d!!
New clock: GstAudioSinkClock
# no audio
# no audio
Got EOS from element "pipeline0".
Execution ended after 2163142172 ns.
Setting pipeline to PAUSED ...

(gst-launch-0.10:11118): GStreamer-WARNING **: loop detected in the graph of bin d!!
Setting pipeline to READY ...
/GstPipeline:pipeline0/GstAlsaSink:alsasink0.GstPad:sink: caps = NULL
/GstPipeline:pipeline0/GstXvImageSink:xvimagesink0.GstPad:sink: caps = NULL
/GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:src: caps = NULL
/GstPipeline:pipeline0/GstAudioConvert:audioconvert0.GstPad:sink: caps = NULL
/GstPipeline:pipeline0/GstFFMpegCsp:ffmpegcsp0.GstPad:src: caps = NULL
/GstPipeline:pipeline0/GstFFMpegCsp:ffmpegcsp0.GstPad:sink: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src2: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src1: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d.GstDecodePad:src0: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/ffdec_dvvideo:ffdec_dvvideo0.GstPad:src: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/ffdec_dvvideo:ffdec_dvvideo0.GstPad:sink: caps = NULL

(gst-launch-0.10:11118): GStreamer-WARNING **: loop detected in the graph of bin d!!
/GstPipeline:pipeline0/GstDecodeBin2:d/GstDVDemux:dvdemux0.GstPad:video: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstDVDemux:dvdemux0.GstPad:sink: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink3: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src3: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink2: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src2: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink1: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src1: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:sink0: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMultiQueue:multiqueue0.GstPad:src0: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMXFDemux:mxfdemux0.GstMXFDemuxPad:track_4: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMXFDemux:mxfdemux0.GstMXFDemuxPad:track_3: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMXFDemux:mxfdemux0.GstMXFDemuxPad:track_2: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstMXFDemux:mxfdemux0.GstPad:sink: caps = NULL
/GstPipeline:pipeline0/GstDecodeBin2:d/GstTypeFindElement:typefind.GstPad:src: caps = NULL
Setting pipeline to NULL ...
FREEING pipeline ...
Comment 1 Sebastian Dröge (slomo) 2008-12-09 10:16:02 UTC
Ah, an example file would be http://gstreamer.freedesktop.org/media/incoming/mxf/opencubetech.com/op1a-pal-dv25-dms1.mxf
Comment 2 Sebastian Dröge (slomo) 2008-12-09 10:19:02 UTC
...and I can't attach the debug log because it's too large (even when bz2 compressed). Fortunately this can be easily reproduced ;)
Comment 3 Sebastian Dröge (slomo) 2008-12-11 13:22:01 UTC
Not only does it complain about loops in the graph, it also stops playback very soon while playbin(1) plays it correctly.
Comment 4 Sebastian Dröge (slomo) 2008-12-18 17:56:05 UTC
The problem is, that both, mxfdemux and dvdemux, go through the same multiqueue which then of course creates a loop in the pipeline.

According to Edward decodebin2 should be changed to put everything that needs further demuxing/parsing before the multiqueue and only connect the final demuxer/parser to the multiqueue.
Comment 5 Edward Hervey 2008-12-18 18:10:06 UTC
Having had another look at the code, this should be possible to implement in connect_pad (gstdecodebin2.c:1080).

The idea would be to add a first step check to see if the pad caps can be connected to a parser/muxer and not pass the pad to gst_decode_group_control_demuxer_pad() until we get something different from a parser or muxer.
Comment 6 Sebastian Dröge (slomo) 2008-12-19 09:55:42 UTC
How would you detect that "we get something different from a parser or demuxer"? Checking the caps for equality won't work because an intermediate parser might add some caps fields... just checking the caps's structure name doesn't work (just think about video/x-dv,systemstream=true and video/x-dv,systemstream=false).
Comment 7 Edward Hervey 2008-12-19 10:35:13 UTC
I never said the check should be done on the caps, but on the compatible factory(ies) you get passed as arguments. That might require adding a is_demuxer_parser_element_factory() function that checks whether the factory is a demuxer or parser. And that check would be similar to is_demuxer_element().

You don't check the caps, but the klass and padtemplate types.
Comment 8 Sebastian Dröge (slomo) 2008-12-19 12:30:40 UTC
Ah, makes sense and shouldn't be too hard to implement :)
Comment 9 Sebastian Dröge (slomo) 2008-12-20 18:02:11 UTC
Hm, there's still a problem.

We can't just check on the factories as the factories only contain the static pad templates and we probably don't want to instanciate all elements.

The other solution would be to move the "is_demuxer_element (src)" check and gst_decode_group_control_demuxer_pad() call between 2.4 and 2.5. The check should be extended to "is_demuxer_element (src) && !is_demuxer_element (element)" and then it works just fine for my testcase.
mxfd10.c
Now there's only the problem, what to do if linking or set_state() on the element fails later. We might need to destroy a decode group (as it was created just for the current element that didn't work) and we have to remove the created requestpad on the multiqueue. And of course reset pad/src to the old values.

Currently I don't see an easy way to accomplish that :)
Comment 10 Sebastian Dröge (slomo) 2009-01-03 09:58:08 UTC
Edward, any idea how to do this as clean as possible? :)
Comment 11 Sebastian Dröge (slomo) 2009-03-24 12:10:57 UTC
ping
Comment 12 Sebastian Dröge (slomo) 2009-04-05 09:57:37 UTC
Created attachment 132111 [details] [review]
decodebin2-demuxer-demuxer.diff

Potential patch, unfortunately it doesn't work correctly for some reason and all threads are hanging...
Comment 13 Edward Hervey 2009-04-15 15:45:25 UTC
will be reviewing the patch in the plane.
Comment 14 Sebastian Dröge (slomo) 2009-07-30 12:59:16 UTC
Edward, did you take a look at the patch already?
Comment 15 Edward Hervey 2009-07-30 14:38:06 UTC
... alas no :(
Comment 16 Sebastian Dröge (slomo) 2009-10-07 15:47:51 UTC
Fixed now:

commit cf9c6a2271ad35e422c8fba6af842e3ea309d82d
Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
Date:   Sat Sep 26 12:17:49 2009 +0200

    decodebin2: Rewrite autoplugging and how groups of pads are exposed
    
    This now keeps track of everything that is going on, creates
    a tree of chains and groups to allow "demuxer after demuxer" scenarios
    and allows chained Oggs with multiple streams (needs oggdemux or playbin2 fi
    
    Also document everything in detail and give a general overview of what
    decodebin2 is doing at the top of the sources.
    
    Fixes bug #596183, #563828 and #591677.