Enigma2 plugin to to play various online streams (mostly Latvian).

basic-tutorial-4.py 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. # GStreamer SDK Tutorials in Python
  4. #
  5. # basic-tutorial-4
  6. #
  7. """
  8. basic-tutorial-4: Time management
  9. http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+4%3A+Time+management
  10. """
  11. import sys
  12. from gi.repository import Gst
  13. Gst.init(None)
  14. # Python version of GST_TIME_ARGS
  15. def convert_ns(t):
  16. s, ns = divmod(t, 1000000000)
  17. m, s = divmod(s, 60)
  18. if m < 60:
  19. return "0:%02i:%02i.%i" % (m, s, ns)
  20. else:
  21. h, m = divmod(m, 60)
  22. return "%i:%02i:%02i.%i" % (h, m, s, ns)
  23. def handle_message(data, msg):
  24. if message.type == Gst.MessageType.ERROR:
  25. err, debug = message.parse_error()
  26. print("Error received from element %s: %s" % (message.src.get_name(), err), file=sys.stderr)
  27. print("Debugging information: %s" % debug, file=sys.stderr)
  28. data["terminate"] = True
  29. elif message.type == Gst.MessageType.EOS:
  30. print("End-Of-Stream reached.")
  31. data["terminate"] = True
  32. elif message.type == Gst.MessageType.DURATION_CHANGED:
  33. # The duration has changed, mark the current one as invalid
  34. data["duration"] = Gst.CLOCK_TIME_NONE
  35. elif message.type == Gst.MessageType.STATE_CHANGED:
  36. if message.src == data["playbin"]:
  37. old_state, new_state, pending_state = message.parse_state_changed()
  38. print("Pipeline state changed from %s to %s." % (old_state.value_nick, new_state.value_nick))
  39. data["playing"] = (new_state == Gst.State.PLAYING)
  40. if data["playing"]:
  41. query = Gst.Query.new_seeking(Gst.Format.TIME)
  42. if data["playbin"].query(query):
  43. (aux, data["seek_enabled"], start, end) = query.parse_seeking()
  44. if data["seek_enabled"]:
  45. print("Seeking is ENABLED from %s to %s" % (convert_ns(start), convert_ns(end)))
  46. else:
  47. print("Seeking is DISABLED for this stream.")
  48. else:
  49. print("Seeking query failed.", file=sys.stderr)
  50. else:
  51. print("Unexpected message received.", file=sys.stderr)
  52. data = dict()
  53. data["playing"] = False
  54. data["terminate"] = False
  55. data["seek_enabled"] = False
  56. data["seek_done"] = False
  57. data["duration"] = Gst.CLOCK_TIME_NONE
  58. # Create the elements
  59. data["playbin"] = Gst.ElementFactory.make("playbin", "playbin")
  60. if not data["playbin"]:
  61. print("Not all elements could be created.", file=sys.stderr)
  62. exit(-1)
  63. # Set the URI to play
  64. data["playbin"].set_property(
  65. "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm")
  66. # Start playing
  67. ret = data["playbin"].set_state(Gst.State.PLAYING)
  68. if ret == Gst.StateChangeReturn.FAILURE:
  69. print("Unable to set the pipeline to the playing state.", file=sys.stderr)
  70. exit(-1)
  71. # Listen to the bus
  72. bus = data["playbin"].get_bus()
  73. while not data["terminate"]:
  74. message = bus.timed_pop_filtered(100 * Gst.MSECOND,
  75. Gst.MessageType.STATE_CHANGED |
  76. Gst.MessageType.ERROR |
  77. Gst.MessageType.EOS |
  78. Gst.MessageType.DURATION_CHANGED)
  79. # Parse message
  80. if message:
  81. handle_message(data, message)
  82. else:
  83. if data["playing"]:
  84. fmt = Gst.Format.TIME
  85. current = -1
  86. # Query the current position of the stream
  87. _, current = data['playbin'].query_position(fmt)
  88. if not current:
  89. print("Could not query current position", file=sys.stderr)
  90. # If we didn't know it yet, query the stream duration
  91. if data["duration"] == Gst.CLOCK_TIME_NONE:
  92. _, data["duration"] = data['playbin'].query_duration(fmt)
  93. if not data["duration"]:
  94. print("Could not query current duration", file=sys.stderr)
  95. print("Position %s / %s\r" % (
  96. convert_ns(current), convert_ns(data["duration"])), end=' ')
  97. sys.stdout.flush()
  98. # If seeking is enabled, we have not done it yet, and the time is
  99. # right, seek
  100. if data["seek_enabled"] and not data["seek_done"] and current > 10 * Gst.SECOND:
  101. print("\nReached 10s, performing seek...")
  102. data['playbin'].seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 30 * Gst.SECOND)
  103. data["seek_done"] = True
  104. # Free resources
  105. data["playbin"].set_state(Gst.State.NULL)