transport stream pipeline doesn't play

316 views Asked by At

I am attempting to playback a transport stream with gstreamer. I am able to build the pipeline and it claims to be playing, but no audio or video is produced. The demo app which uses playbin works in this limited case but isn't really an option. Using gst-launch to build the exact same graph also works, but isn't an option. This is the (simplified) code I am using using to build the pipeline:

class composer:
  def __init__(self,pipeline,upstream = None):
    self.pipeline = pipeline
    self.upstream = upstream
  def link(self,filter,src_pad_name = None):
    x = Gst.ElementFactory.make(filter)
    self.pipeline.add(x)
    if self.upstream:
      if src_pad_name:
        src_pad = self.upstream.get_static_pad(src_pad_name)
      else:
        src_pad = self.upstream.srcpads[0]
      src_pad.link(x.sinkpads[0])
    self.upstream = x
    return self
  def props(self,pd):
    for k in pd:
      self.upstream.set_property(k,pd[k])
    return self
def connect(self,message,handler):
  self.upstream.connect(message,handler)
  return self

class graph(object):
  def render_streams(self,unused):
    c = composer(self.pipeline,self.mux) \
     .link('queue','video_0031') \
     .link('mpegvideoparse') \
     .link('mpeg2dec') \
     .link('queue') \
     .link('videoconvert') \
     .link('videoscale') \
     .link('xvimagesink')
    c = composer(self.pipeline,self.mux) \
     .link('queue','audio_0032') \
     .link('ac3parse') \
     .link('a52dec') \
     .link('queue') \
     .link('audioconvert') \
     .link('audioresample') \
     .link('pulsesink')
    self.rendered = True
  def __init__(self,file):
    self.pipeline = Gst.Pipeline('pipeline for ' + file)
    self.demo_copy_pasta() #from http://bazaar.launchpad.net/~jderose/+junk/gst-examples/view/head:/video-player-1.0
    self.rendered = False

    c = composer(self.pipeline) \
      .link('filesrc') \
        .props({'location':file}) \
      .link('tsdemux') \
        .connect('no-more-pads',self.render_streams)
    self.mux = c.upstream

    self.pipeline.set_state(Gst.State.PAUSED)
    while not self.rendered: # not spinning in real app
      time.sleep(0.5)
  def run(self):
    self.window.show_all()
    self.xid = self.drawingarea.get_property('window').get_xid()
    self.pipeline.set_state(Gst.State.PLAYING)
    Gtk.main()

graph('bbb.ts').run() #run has the same implementation as the (working) demo code

One thing that I noticed about the graph is that formats don't look like they are fully negotiated. For example the format between the demux and the queue is mpeg2 on the working version. On the broken version it is mpeg2 on the demux side, but any on the queue side.

What else do I need to do to get this to play back?

2

There are 2 answers

0
Yaur On BEST ANSWER

The problem is that when new elements are connected to the tsdemux it is already in the paused state and this doesn't appear to propogate properly. Adding the code:

  state = self.upstream.get_state(1)
  x.set_state(state[1])

to composer.link allows the graph to play back normally.

1
theamk On

I see two problems with this implementation:

(1) You never set the state to State.PLAYING

(2) You never pump the message loop: You cannot do 'time.sleep' in the main gstreamer thread. You need to run the message loop, for example by calling Gtk.main().

The example URL that you mention in the code does both of these things properly.