qq_27949759 2016-06-13 06:53 采纳率: 0%
浏览 1931
已结题

python-gst程序黑屏,求指教

python-gst想要写一个解码h264并分屏显示的应用,可是测试发现无显示,是不是管道设置错了>

 #!/usr/bin/env python

import sys

input_path = 'wifibroadcast'
oculus_width = 1920
oculus_height = 1200

if len(sys.argv) > 1:
    input_path = sys.argv[1]

# Set output_port to an output name recognized by xrandr to override where
# we output the video - if output_port is None we'll look for
# the first monitor that is 1920x1080.  If not None, we'll ignore
# oculus_width and oculus_height and assume the resolution reported by
# xrandr with half of the screen area for each eye.
#output_port = 'HDMI1'
output_port = None

if input_path == 'wifibroadcast':
    input_pipeline = 'filesrc location="/home/milkrong/test.264" ! h264parse ! avdec_h264'
else:
    input_pipeline = 'v4l2src device=' + input_path + ' ! deinterlace'

# Don't write the stream to disk by default
#dump_pipeline = ''
dump_pipeline = 'orig. ! queue ! filesink location=capture.raw'

import subprocess, re, gi
gi.require_version('Gst', '1.0')
gi.require_version('Gtk', '3.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst, GObject, Gtk, Gdk

# Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:
from gi.repository import GdkX11, GstVideo

class GTK_Main(object):
    def __init__(self, w, h, x, y):
        window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
        window.set_decorated(False)
        window.set_size_request(1280, 800)
        window.move(x, y)

        #window.resize(w/2, h/2)
        #window.fullscreen()

        window.connect("destroy", Gtk.main_quit, "WM destroy")
        window.connect("key_press_event", self.on_key_press)
        self.gst_window = Gtk.DrawingArea()
        #self.gst_window.set_size_request(1060, 397)
        window.add(self.gst_window)
        window.show_all()

        # TODO: disable screen saver (gsettings?)

        self.per_eye_w = 1280 / 2
        self.left_x = 0
        self.right_x = 1280 / 2
        self.offset_x = 0

        # Set up the gstreamer pipeline
        self.player = Gst.parse_launch(input_pipeline + ' ! ' +
                'tee name=orig ! ' +
                'videoscale add-borders=1 ! ' +
                'video/x-raw,width=' + str(self.per_eye_w) + ',height=' +
                str(h) + ' !  ' +
                'tee name=tee ! ' +
                'queue ! ' +
                'videomixer name=mixer ! ' +
                'xvimagesink double-buffer=false sync=false ' +
                'tee. ! ' +
                'queue ! ' +
                'mixer. ' +
                dump_pipeline)
        self.mixer = self.player.get_by_name('mixer')
        bus = self.player.get_bus()
        bus.add_signal_watch()
        bus.enable_sync_message_emission()
        bus.connect("message", self.on_message)
        bus.connect("sync-message::element", self.on_sync_message)

        self.xpos_update()

        self.player.set_state(Gst.State.PLAYING)
        sys.stderr.write('Gstreamer pipeline created and started\n')

    def xpos_update(self):
        # TODO: reimplement x offset in a way that one eye's video never
        # shows in the other eye's half of the screen

        sink0 = self.mixer.get_static_pad('sink_0')
        sink1 = self.mixer.get_static_pad('sink_1')

        sink0.set_property('xpos', self.left_x + self.offset_x)
        sink1.set_property('xpos', self.right_x + self.offset_x)

    def on_message(self, bus, message):
        t = message.type
        if t == Gst.MessageType.EOS:
            sys.stderr.write('Stream ended\n')
            Gtk.main_quit()
        elif t == Gst.MessageType.ERROR:
            err, debug = message.parse_error()
            sys.stderr.write('Error: ' + str(err) + '\n' + str(debug))
            Gtk.main_quit()

    def on_sync_message(self, bus, message):
        if message.get_structure().get_name() == 'prepare-window-handle':
            imagesink = message.src

            Gdk.threads_enter()
            imagesink.set_window_handle(
                    self.gst_window.get_property('window').get_xid())
            Gdk.threads_leave()
            sys.stderr.write('Gstreamer synced\n')

    def on_key_press(self, widget, event):
        keyname = Gdk.keyval_name(event.keyval)

        if keyname in [ 'q', 'Q', 'Escape' ]:
            Gtk.main_quit()
        elif keyname == 'Left':
            self.offset_x -= 4
            self.xpos_update()
        elif keyname == 'Right':
            self.offset_x += 4
            self.xpos_update()
        elif keyname == 'Up':
            self.left_x -= 1
            self.right_x += 1
            self.xpos_update()
        elif keyname == 'Down':
            self.left_x += 1
            self.right_x -= 1
            self.xpos_update()

# Find the selected screen using xrandr directly
#
# Should either use one of the libxrandr bindings libraries but none is popular
# enough to be packaged by distributions, or use gtk.gdk:
# scr = gtk.gdk.screen_get_default()
# n = scr.get_n_monitors()
# [ scr.get_monitor_plug_name(i) for i in range(0, n) ]
# [ scr.get_monitor_geometry(i) for i in range(0, n) ]
# also subscribe to scr signal "monitor-changed"
#
# We'd still need to use xrandr to actually rotate the screen, it seems.

#p = subprocess.Popen([ 'xrandr', '-q' ], stdout=subprocess.PIPE)
#output = p.communicate()[0]
#monitor_line = None
#resolution_str1 = ' ' + str(oculus_width) + 'x' + str(oculus_height) + '+'
#resolution_str2 = ' ' + str(oculus_height) + 'x' + str(oculus_width) + '+'

#for line in output.split('\n'):
#    if output_port and line.startswith(output_port):
#        monitor_line = line
#        break
#    if not output_port and (resolution_str1 in line or resolution_str2 in line):
#        monitor_line = line
#        break

#if not monitor_line:
#    if output_port:
#        sys.stderr.write(outout_port + ' not found\n')
#    else:
#        sys.stderr.write('No screen found with the right resolution\n')
#    sys.exit(-1)

#if not output_port:
#    output_port = monitor_line.split()[0]
#if 'disconnected' in monitor_line:
#    sys.stderr.write(output_port + ' seems to be disconnected\n')
#    sys.exit(-1)

#match = re.search(r'\b([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+)\b', monitor_line)
#w, h, x, y = [ int(n) for n in match.groups() ]

#sys.stderr.write('Using ' + output_port + ' for output\n')

# If screen seems to be in vertical/portrait mode (height > width), rotate it
#if h > w:
#    sys.stderr.write('Setting --rotate left\n')
#    subprocess.check_call([ 'xrandr',
#            '--output', output_port,
#            '--rotate', 'left' ])
#    w, h = h, w
#
GObject.threads_init()
Gst.init(None)
GTK_Main(1280, 800, 0, 0)
Gtk.main()

  • 写回答

1条回答

  • qq_27949759 2016-06-13 06:59
    关注

    #!/usr/bin/env python

    import sys

    input_path = 'wifibroadcast'
    oculus_width = 1920
    oculus_height = 1200

    if len(sys.argv) > 1:
    input_path = sys.argv[1]

    Set output_port to an output name recognized by xrandr to override where

    we output the video - if output_port is None we'll look for

    the first monitor that is 1920x1080. If not None, we'll ignore

    oculus_width and oculus_height and assume the resolution reported by

    xrandr with half of the screen area for each eye.

    #output_port = 'HDMI1'
    output_port = None

    if input_path == 'wifibroadcast':
    input_pipeline = 'filesrc location="/home/milkrong/test.264" ! h264parse ! avdec_h264'
    else:
    input_pipeline = 'v4l2src device=' + input_path + ' ! deinterlace'

    Don't write the stream to disk by default

    #dump_pipeline = ''
    dump_pipeline = 'orig. ! queue ! filesink location=capture.raw'

    import subprocess, re, gi
    gi.require_version('Gst', '1.0')
    gi.require_version('Gtk', '3.0')
    gi.require_version('GstVideo', '1.0')
    from gi.repository import Gst, GObject, Gtk, Gdk

    Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:

    from gi.repository import GdkX11, GstVideo

    class GTK_Main(object):
    def init(self, w, h, x, y):
    window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
    window.set_decorated(False)
    window.set_size_request(1280, 800)
    window.move(x, y)

        #window.resize(w/2, h/2)
        #window.fullscreen()
    
        window.connect("destroy", Gtk.main_quit, "WM destroy")
        window.connect("key_press_event", self.on_key_press)
        self.gst_window = Gtk.DrawingArea()
        #self.gst_window.set_size_request(1060, 397)
        window.add(self.gst_window)
        window.show_all()
    
        # TODO: disable screen saver (gsettings?)
    
        self.per_eye_w = 1280 / 2
        self.left_x = 0
        self.right_x = 1280 / 2
        self.offset_x = 0
    
        # Set up the gstreamer pipeline
        self.player = Gst.parse_launch(input_pipeline + ' ! ' +
                'tee name=orig ! ' +
                'videoscale add-borders=1 ! ' +
                'video/x-raw,width=' + str(self.per_eye_w) + ',height=' +
                str(h) + ' !  ' +
                'tee name=tee ! ' +
                'queue ! ' +
                'videomixer name=mixer ! ' +
                'xvimagesink double-buffer=false sync=false ' +
                'tee. ! ' +
                'queue ! ' +
                'mixer. ' +
                dump_pipeline)
        self.mixer = self.player.get_by_name('mixer')
        bus = self.player.get_bus()
        bus.add_signal_watch()
        bus.enable_sync_message_emission()
        bus.connect("message", self.on_message)
        bus.connect("sync-message::element", self.on_sync_message)
    
        self.xpos_update()
    
        self.player.set_state(Gst.State.PLAYING)
        sys.stderr.write('Gstreamer pipeline created and started\n')
    
    def xpos_update(self):
        # TODO: reimplement x offset in a way that one eye's video never
        # shows in the other eye's half of the screen
    
        sink0 = self.mixer.get_static_pad('sink_0')
        sink1 = self.mixer.get_static_pad('sink_1')
    
        sink0.set_property('xpos', self.left_x + self.offset_x)
        sink1.set_property('xpos', self.right_x + self.offset_x)
    
    def on_message(self, bus, message):
        t = message.type
        if t == Gst.MessageType.EOS:
            sys.stderr.write('Stream ended\n')
            Gtk.main_quit()
        elif t == Gst.MessageType.ERROR:
            err, debug = message.parse_error()
            sys.stderr.write('Error: ' + str(err) + '\n' + str(debug))
            Gtk.main_quit()
    
    def on_sync_message(self, bus, message):
        if message.get_structure().get_name() == 'prepare-window-handle':
            imagesink = message.src
    
            Gdk.threads_enter()
            imagesink.set_window_handle(
                    self.gst_window.get_property('window').get_xid())
            Gdk.threads_leave()
            sys.stderr.write('Gstreamer synced\n')
    
    def on_key_press(self, widget, event):
        keyname = Gdk.keyval_name(event.keyval)
    
        if keyname in [ 'q', 'Q', 'Escape' ]:
            Gtk.main_quit()
        elif keyname == 'Left':
            self.offset_x -= 4
            self.xpos_update()
        elif keyname == 'Right':
            self.offset_x += 4
            self.xpos_update()
        elif keyname == 'Up':
            self.left_x -= 1
            self.right_x += 1
            self.xpos_update()
        elif keyname == 'Down':
            self.left_x += 1
            self.right_x -= 1
            self.xpos_update()
    

    Find the selected screen using xrandr directly

    #

    Should either use one of the libxrandr bindings libraries but none is popular

    enough to be packaged by distributions, or use gtk.gdk:

    scr = gtk.gdk.screen_get_default()

    n = scr.get_n_monitors()

    [ scr.get_monitor_plug_name(i) for i in range(0, n) ]

    [ scr.get_monitor_geometry(i) for i in range(0, n) ]

    also subscribe to scr signal "monitor-changed"

    #

    We'd still need to use xrandr to actually rotate the screen, it seems.

    #p = subprocess.Popen([ 'xrandr', '-q' ], stdout=subprocess.PIPE)
    #output = p.communicate()[0]
    #monitor_line = None
    #resolution_str1 = ' ' + str(oculus_width) + 'x' + str(oculus_height) + '+'
    #resolution_str2 = ' ' + str(oculus_height) + 'x' + str(oculus_width) + '+'

    #for line in output.split('\n'):

    if output_port and line.startswith(output_port):

    monitor_line = line

    break

    if not output_port and (resolution_str1 in line or resolution_str2 in line):

    monitor_line = line

    break

    #if not monitor_line:

    if output_port:

    sys.stderr.write(outout_port + ' not found\n')

    else:

    sys.stderr.write('No screen found with the right resolution\n')

    sys.exit(-1)

    #if not output_port:

    output_port = monitor_line.split()[0]

    #if 'disconnected' in monitor_line:

    sys.stderr.write(output_port + ' seems to be disconnected\n')

    sys.exit(-1)

    #match = re.search(r'\b([0-9]+)x([0-9]+)+([0-9]+)+([0-9]+)\b', monitor_line)
    #w, h, x, y = [ int(n) for n in match.groups() ]

    #sys.stderr.write('Using ' + output_port + ' for output\n')

    If screen seems to be in vertical/portrait mode (height > width), rotate it

    #if h > w:

    sys.stderr.write('Setting --rotate left\n')

    subprocess.check_call([ 'xrandr',

    '--output', output_port,

    '--rotate', 'left' ])

    w, h = h, w

    #
    GObject.threads_init()
    Gst.init(None)
    GTK_Main(1280, 800, 0, 0)
    Gtk.main()

    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料