简体   繁体   English

使用GStreamer 1.0和Python播放.avi视频

[英]Play .avi video using GStreamer 1.0 and Python

I've been searching a lot of examples for using GStreamer's python library on Windows but the only ones that work well are like this: 我一直在搜索许多在Windows上使用GStreamer的python库的示例,但唯一运行良好的示例如下:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# GStreamer SDK Tutorials in Python
#
#     basic-tutorial-2
#
"""
basic-tutorial-2: GStreamer concepts
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+2%3A+GStreamer+concepts
"""

import sys
from gi.repository import Gst
Gst.init(None)

# Create the elements
source = Gst.ElementFactory.make("videotestsrc", "source")
sink = Gst.ElementFactory.make("autovideosink", "sink")

# Create the empty pipeline
pipeline = Gst.Pipeline.new("test-pipeline")


if not source or not sink or not pipeline:
    print("Not all elements could be created.", file=sys.stderr)
    exit(-1)

# Build the pipeline
pipeline.add(source)
pipeline.add(sink)
if not Gst.Element.link(source, sink):
    print("Elements could not be linked.", file=sys.stderr)
    exit(-1)

# Modify the source's properties
source.set_property("pattern", 0)

# Start playing
ret = pipeline.set_state(Gst.State.PLAYING)
if ret == Gst.StateChangeReturn.FAILURE:
    print("Unable to set the pipeline to the playing state.", file=sys.stderr)
    exit(-1)

# Wait until error or EOS
bus = pipeline.get_bus()
msg = bus.timed_pop_filtered(
    Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)

# Parse message
if (msg):
    if msg.type == Gst.MessageType.ERROR:
        err, debug = msg.parse_error()
        print("Error received from element %s: %s" % (
            msg.src.get_name(), err), file=sys.stderr)
        print("Debugging information: %s" % debug, file=sys.stderr)
    elif msg.type == Gst.MessageType.EOS:
        print("End-Of-Stream reached.")
    else:
        print("Unexpected message received.", file=sys.stderr)

# Free resources
pipeline.set_state(Gst.State.NULL)

that is a simple test and uses just a "sink object", or the ones that stream the GStreamer example file (Sintel Movie Trailer), like this one: 这是一个简单的测试,仅使用一个“接收器对象”,或使用流GStreamer示例文件(Sintel Movie Trailer)的测试器,如下所示:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# GStreamer SDK Tutorials in Python
#
#     basic-tutorial-4
#
"""
basic-tutorial-4: Time management
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+4%3A+Time+management
"""

import sys
from gi.repository import Gst
Gst.init(None)

# Python version of GST_TIME_ARGS


def convert_ns(t):
    s, ns = divmod(t, 1000000000)
    m, s = divmod(s, 60)

    if m < 60:
        return "0:%02i:%02i.%i" % (m, s, ns)
    else:
        h, m = divmod(m, 60)
        return "%i:%02i:%02i.%i" % (h, m, s, ns)


def handle_message(data, msg):
    if message.type == Gst.MessageType.ERROR:
        err, debug = message.parse_error()
        print("Error received from element %s: %s" % (message.src.get_name(), err), file=sys.stderr)
        print("Debugging information: %s" % debug, file=sys.stderr)
        data["terminate"] = True
    elif message.type == Gst.MessageType.EOS:
        print("End-Of-Stream reached.")
        data["terminate"] = True
    elif message.type == Gst.MessageType.DURATION_CHANGED:
        # The duration has changed, mark the current one as invalid
        data["duration"] = Gst.CLOCK_TIME_NONE
    elif message.type == Gst.MessageType.STATE_CHANGED:
        if message.src == data["playbin"]:
            old_state, new_state, pending_state = message.parse_state_changed()
            print("Pipeline state changed from %s to %s." % (old_state.value_nick, new_state.value_nick))
            data["playing"] = (new_state == Gst.State.PLAYING)
            if data["playing"]:
                query = Gst.Query.new_seeking(Gst.Format.TIME)
                if data["playbin"].query(query):
                    (aux, data["seek_enabled"], start, end) = query.parse_seeking()
                    if data["seek_enabled"]:
                        print("Seeking is ENABLED from %s to %s" % (convert_ns(start), convert_ns(end)))
                    else:
                        print("Seeking is DISABLED for this stream.")
                else:
                    print("Seeking query failed.", file=sys.stderr)
    else:
        print("Unexpected message received.", file=sys.stderr)


data = dict()

data["playing"] = False
data["terminate"] = False
data["seek_enabled"] = False
data["seek_done"] = False
data["duration"] = Gst.CLOCK_TIME_NONE

# Create the elements
data["playbin"] = Gst.ElementFactory.make("playbin", "playbin")

if not data["playbin"]:
    print("Not all elements could be created.", file=sys.stderr)
    exit(-1)

# Set the URI to play
data["playbin"].set_property(
    "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm")

# Start playing
ret = data["playbin"].set_state(Gst.State.PLAYING)
if ret == Gst.StateChangeReturn.FAILURE:
    print("Unable to set the pipeline to the playing state.", file=sys.stderr)
    exit(-1)

# Listen to the bus
bus = data["playbin"].get_bus()
while not data["terminate"]:
    message = bus.timed_pop_filtered(100 * Gst.MSECOND,
                                     Gst.MessageType.STATE_CHANGED | 
                                     Gst.MessageType.ERROR | 
                                     Gst.MessageType.EOS | 
                                     Gst.MessageType.DURATION_CHANGED)

    # Parse message
    if message:
        handle_message(data, message)
    else:
        if data["playing"]:
            fmt = Gst.Format.TIME
            current = -1
            # Query the current position of the stream
            _, current = data['playbin'].query_position(fmt)
            if not current:
                print("Could not query current position", file=sys.stderr)

            # If we didn't know it yet, query the stream duration
            if data["duration"] == Gst.CLOCK_TIME_NONE:
                _, data["duration"] = data['playbin'].query_duration(fmt)
                if not data["duration"]:
                    print("Could not query current duration", file=sys.stderr)

            print("Position %s / %s\r" % (
                convert_ns(current), convert_ns(data["duration"])), end=' ')
            sys.stdout.flush()

            # If seeking is enabled, we have not done it yet, and the time is
            # right, seek
            if data["seek_enabled"] and not data["seek_done"] and current > 10 * Gst.SECOND:
                print("\nReached 10s, performing seek...")
                data['playbin'].seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 30 * Gst.SECOND)
                data["seek_done"] = True


# Free resources
data["playbin"].set_state(Gst.State.NULL)

So, after trying to change the code I've got some questions: 因此,在尝试更改代码后,我遇到了一些问题:

  1. Is this "file:///C:/folder/video.avi" the correct path format for GStreamer? 这个“ file:/// C:/folder/video.avi”是否是GStreamer的正确路径格式?
  2. I know that I have to use a "playerbin" object and set its uri property but I don't know where exactly I should put that lines and how to use it properly. 我知道我必须使用“ playerbin”对象并设置其uri属性,但是我不知道我应该在哪一行以及如何正确使用它。
  3. Is there any problem caused by the video format? 视频格式有问题吗?

Thank you so much for your help! 非常感谢你的帮助!

  1. Looks right but I can't test it as I use Linux 看起来不错,但是在使用Linux时无法测试
  2. Change the line: 更改行:
    data["playbin"].set_property( "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm")
    to
    data["playbin"].set_property("uri", "file:///C:/folder/video.avi")
  3. No, it should be fine, playbin will run with just about anything that you throw at it. 不,应该没问题,playbin几乎可以与您扔给它的任何东西一起运行。
  4. http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-playbin.html http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-playbin.html
    to see the playbin properties that can be modified 查看可以修改的playbin属性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM