寻求python gstreamer的大原始视频文件

时间:2016-05-14 18:04:36

标签: linux python-3.x gstreamer python-gstreamer

我正在制作节目,应该显示大型原始视频,在其中搜索我能够设置从中切割时间,设置黑色边框大小以隐藏图像的抖动边框。该项目的关键部分是寻求。我已经尝试了5分钟的文件截止时间,当我在视频开始时寻找时,它可以,但是在中间出现问题之后。由于似乎没有太多的例子和文档,我使用它:

self.pipe.seek_simple(
        Gst.Format.TIME,
        Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
        destSeek
    )

我的实际(非成熟)代码:

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

GObject.threads_init()
Gst.init(None)

testGrab = "testRAW.mkv"

class VideoDec(Gst.Bin):
    def __init__(self):
        super().__init__()

        # elements
        q1 = Gst.ElementFactory.make('queue', None)
        videoparse = Gst.ElementFactory.make('videoparse', None)
        q2 = Gst.ElementFactory.make('queue', None)

        self.add(q1)
        self.add(videoparse)
        self.add(q2)

        videoparse.set_property('width', 720)
        videoparse.set_property('height', 576)
        videoparse.set_property('format', 4)

        # link
        q1.link(videoparse)
        videoparse.link(q2)

        # Add Ghost Pads
        self.add_pad(
            Gst.GhostPad.new('sink', q1.get_static_pad('sink'))
        )
        self.add_pad(
            Gst.GhostPad.new('src', q2.get_static_pad('src'))
        )

class AudioDec(Gst.Bin):
    def __init__(self):
        super().__init__()

        # elements
        q1 = Gst.ElementFactory.make('queue', None)
        audioparse = Gst.ElementFactory.make('audioparse', None)
        q2 = Gst.ElementFactory.make('queue', None)
        #sink = Gst.ElementFactory.make('autoaudiosink', None)

        self.add(q1)
        self.add(audioparse)
        self.add(q2)
        #self.add(sink)

        # link
        q1.link(audioparse)
        audioparse.link(q2)
        #audioparse.link(sink)

        # Add Ghost Pads
        self.add_pad(
            Gst.GhostPad.new('sink', q1.get_static_pad('sink'))
        )
        self.add_pad(
            Gst.GhostPad.new('src', q2.get_static_pad('src'))
        )

class Player(object):
    def __init__(self):
        self.fps = 25
        self.window = Gtk.Window()
        self.window.connect('destroy', self.quit)
        self.window.set_default_size(800, 600)

        self.drawingarea = Gtk.DrawingArea()

        #hbox
        self.hbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

        self.window.add(self.hbox)
        Gtk.Box.pack_start(self.hbox, self.drawingarea, True, True, 0)

        self.setPipeline()

        self.setGUI()
        self.setShortcuts()

        self.playing = False

    def setPipeline(self):
        self.pipe = Gst.Pipeline.new('player')

        # Create bus to get events from GStreamer pipeline
        self.bus = self.pipe.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect('message::eos', self.on_eos)
        self.bus.connect('message::error', self.on_error)

        # This is needed to make the video output in our DrawingArea:
        self.bus.enable_sync_message_emission()
        self.bus.connect('sync-message::element', self.on_sync_message)

        self.src = Gst.ElementFactory.make('filesrc', None)
        self.src.set_property("location", testGrab)
        self.dec = Gst.ElementFactory.make('decodebin', None)
        self.video = VideoDec()
        self.audio = AudioDec()
        self.glimagesink = Gst.ElementFactory.make('glimagesink', None)
        self.audiosink = Gst.ElementFactory.make('autoaudiosink', None)

        self.pipe.add(self.src)
        self.pipe.add(self.dec)
        self.pipe.add(self.video)
        self.pipe.add(self.audio)
        self.pipe.add(self.glimagesink)
        self.pipe.add(self.audiosink)
        #self.pipe.add(self.autovideosink)

        # Connect signal handlers
        self.dec.connect('pad-added', self.on_pad_added)

        # link
        self.src.link(self.dec)
        self.video.link(self.glimagesink)
        self.audio.link(self.audiosink)

    def on_pad_added(self, element, pad):
        string = pad.query_caps(None).to_string()
        print('on_pad_added():', string)
        if string.startswith('audio/'):
            pad.link(self.audio.get_static_pad('sink'))
        elif string.startswith('video/'):
            pad.link(self.video.get_static_pad('sink'))

    def setGUI(self):
        vbox = Gtk.Box(Gtk.Orientation.HORIZONTAL, 0)
        vbox.set_margin_top(3)
        vbox.set_margin_bottom(3)
        Gtk.Box.pack_start(self.hbox, vbox, False, False, 0)

        self.playButtonImage = Gtk.Image()
        self.playButtonImage.set_from_stock("gtk-media-play", Gtk.IconSize.BUTTON)
        self.playButton = Gtk.Button.new()
        self.playButton.add(self.playButtonImage)
        self.playButton.connect("clicked", self.playToggled)
        Gtk.Box.pack_start(vbox, self.playButton, False, False, 0)

        self.slider = Gtk.HScale()
        self.slider.set_margin_left(6)
        self.slider.set_margin_right(6)
        self.slider.set_draw_value(False)
        self.slider.set_range(0, 100)
        self.slider.set_increments(1, 10)

        Gtk.Box.pack_start(vbox, self.slider, True, True, 0)


        self.label = Gtk.Label(label='0:00')
        self.label.set_margin_left(6)
        self.label.set_margin_right(6)
        Gtk.Box.pack_start(vbox, self.label, False, False, 0)

    def setShortcuts(self):
        accel = Gtk.AccelGroup()
        accel.connect(Gdk.KEY_space, Gdk.ModifierType.CONTROL_MASK, 0, self.playToggled)
        accel.connect(Gdk.KEY_Right, Gdk.ModifierType.CONTROL_MASK, 0, self.seekFW0)
        accel.connect(Gdk.KEY_Right, Gdk.ModifierType.CONTROL_MASK|Gdk.ModifierType.SHIFT_MASK, 0, self.seekFW10s)
        accel.connect(Gdk.KEY_Right, Gdk.ModifierType.SHIFT_MASK, 0, self.seekFW2)
        accel.connect(Gdk.KEY_Right, Gdk.ModifierType.MOD1_MASK, 0, self.seekFW10) # alt key
        self.window.add_accel_group(accel)

    def seekFW0(self, *args):
        self.seekTime = 2 * Gst.SECOND // self.fps
        self.seekFW()

    def seekFW10s(self, *args):
        self.seekTime = Gst.SECOND * 10
        self.seekFW()

    def seekFW2(self, *args):
        self.seekTime = Gst.SECOND * 60 * 2
        self.seekFW()

    def seekFW10(self, *args):
        self.seekTime = Gst.SECOND * 60 * 10
        self.seekFW()

    def seekFW(self, *args):
        nanosecs = self.pipe.query_position(Gst.Format.TIME)[1]
        destSeek = nanosecs + self.seekTime
        self.pipe.seek_simple(
            Gst.Format.TIME,
            Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
            destSeek
        )

    def play(self):
        self.pipe.set_state(Gst.State.PLAYING)
        GObject.timeout_add(1000, self.updateSlider)


    def stop(self):
        self.pipe.set_state(Gst.State.PAUSED)


    def playToggled(self, *w):

        if(self.playing == False):
            self.play()
        else:
            self.stop()


        self.playing=not(self.playing)
        self.updateButtons()

    def updateSlider(self):
        try:
            nanosecs = self.pipe.query_position(Gst.Format.TIME)[1]
            duration_nanosecs = self.pipe.query_duration(Gst.Format.TIME)[1]


            # block seek handler so we don't seek when we set_value()
            # self.slider.handler_block_by_func(self.on_slider_change)


            duration = float(duration_nanosecs) / Gst.SECOND
            position = float(nanosecs) / Gst.SECOND
            self.slider.set_range(0, duration)
            self.slider.set_value(position)
            self.label.set_text ("%d" % (position / 60) + ":%02d" % (position % 60))


            #self.slider.handler_unblock_by_func(self.on_slider_change)


        except Exception as e:
            # pipeline must not be ready and does not know position
            print(e)
            pass


        return True

    def updateButtons(self):
        if(self.playing == False):
            self.playButtonImage.set_from_stock("gtk-media-play", Gtk.IconSize.BUTTON)
        else:
            self.playButtonImage.set_from_stock("gtk-media-pause", Gtk.IconSize.BUTTON)

    def run(self):
        self.window.show_all()
        # You need to get the XID after window.show_all().  You shouldn't get it
        # in the on_sync_message() handler because threading issues will cause
        # segfaults there.
        self.xid = self.drawingarea.get_property('window').get_xid()
        #self.pipeline.set_state(Gst.State.PLAYING)
        Gtk.main()

    def quit(self, window):
        self.pipe.set_state(Gst.State.NULL)
        Gtk.main_quit()

    def on_sync_message(self, bus, msg):
        if msg.get_structure().get_name() == 'prepare-window-handle':
            print('prepare-window-handle')
            msg.src.set_window_handle(self.xid)

    def on_eos(self, bus, msg):
        #print('on_eos(): seeking to start of video')
        print('on_eos(): pausing video')
        self.stop()
        #self.pipeline.seek_simple(
        #    Gst.Format.TIME,        
        #    Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
        #    0
        #)
        #self.playing = False
        #self.slider.set_value(0)
        #self.label.set_text("0:00")
        #self.updateButtons()

    def on_error(self, bus, msg):
        print('on_error():', msg.parse_error())


p = Player()
p.run()

如果有人可以分享智慧或文档/示例链接,我会感到高兴。

1 个答案:

答案 0 :(得分:0)

我不再记得为什么我放弃使用seek_simple,但我确实记得它让我无法忍受悲伤。
而是使用标准搜索:

Gplayer.seek(self.rate, Gst.Format.TIME, 
    (Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE),
    Gst.SeekType.SET, seek_time , Gst.SeekType.NONE, -1)

Gstreamer1.0 seek