Advertisement
Guest User

Untitled

a guest
Feb 29th, 2016
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.83 KB | None | 0 0
  1. from __future__ import (
  2.     absolute_import, division, print_function, unicode_literals)
  3.  
  4. import collections
  5. import time
  6. import sys
  7.  
  8. import gi
  9. gi.require_version('Gst', '1.0')
  10. gi.require_version('GstPbutils', '1.0')
  11. from gi.repository import Gst, GLib, GstPbutils
  12.  
  13. _Result = collections.namedtuple(
  14.     'Result', ('uri', 'tags', 'duration', 'seekable', 'mime'))
  15.  
  16. class Signals(object):
  17.  
  18.     """Helper for tracking gobject signal registrations"""
  19.  
  20.     def __init__(self):
  21.         self._ids = {}
  22.  
  23.     def connect(self, element, event, func, *args):
  24.         """Connect a function + args to signal event on an element.
  25.        Each event may only be handled by one callback in this implementation.
  26.        """
  27.         assert (element, event) not in self._ids
  28.         self._ids[(element, event)] = element.connect(event, func, *args)
  29.  
  30.     def disconnect(self, element, event):
  31.         """Disconnect whatever handler we have for an element+event pair.
  32.        Does nothing it the handler has already been removed.
  33.        """
  34.         signal_id = self._ids.pop((element, event), None)
  35.         if signal_id is not None:
  36.             element.disconnect(signal_id)
  37.  
  38.     def clear(self):
  39.         """Clear all registered signal handlers."""
  40.         for element, event in self._ids.keys():
  41.             element.disconnect(self._ids.pop((element, event)))
  42.  
  43. class Scanner(object):
  44.     def __init__(self, timeout=1000, proxy_config=None):
  45.         self._timeout_ms = int(timeout)
  46.         self._proxy_config = proxy_config or {}
  47.  
  48.     def scan(self, uri, timeout=None):
  49.         timeout = int(timeout or self._timeout_ms)
  50.         tags, duration, seekable, mime = None, None, None, None
  51.         pipeline = _setup_pipeline(uri, self._proxy_config)
  52.  
  53.         _start_pipeline(pipeline)
  54.         tags, mime = _process(pipeline, timeout)
  55.  
  56.         return _Result(uri, tags, duration, seekable, mime)
  57.  
  58. def _setup_pipeline(uri, proxy_config=None):
  59.     Gst.init([])
  60.     print ("version: " + Gst.version_string())
  61.  
  62.     src = Gst.Element.make_from_uri(Gst.URIType.SRC, uri)
  63.     if not src:
  64.         print ("can't open file: " + uri)
  65.         exit(0)
  66.  
  67.     typefind = Gst.ElementFactory.make('typefind')
  68.     decodebin = Gst.ElementFactory.make('decodebin')
  69.  
  70.     pipeline = Gst.ElementFactory.make('pipeline')
  71.     for e in (src, typefind, decodebin):
  72.         pipeline.add(e)
  73.     src.link(typefind)
  74.     typefind.link(decodebin)
  75.  
  76.     signals = Signals()
  77.     signals.connect(decodebin, 'pad-added', _pad_added, pipeline)
  78.  
  79.     return pipeline
  80.  
  81. def _pad_added(element, pad, pipeline):
  82.     sink = Gst.ElementFactory.make('fakesink')
  83.     sink.set_property('sync', False)
  84.  
  85.     pipeline.add(sink)
  86.     sink.sync_state_with_parent()
  87.     pad.link(sink.get_static_pad('sink'))
  88.  
  89. def _start_pipeline(pipeline):
  90.     result = pipeline.set_state(Gst.State.PAUSED)
  91.     if result == Gst.StateChangeReturn.NO_PREROLL:
  92.         pipeline.set_state(Gst.State.PLAYING)
  93.  
  94. def convert_taglist(taglist):
  95.     result = collections.defaultdict(list)
  96.  
  97.     for n in range(taglist.n_tags()):
  98.         tag = taglist.nth_tag_name(n)
  99.  
  100.         for i in range(taglist.get_tag_size(tag)):
  101.             value = taglist.get_value_index(tag, i)
  102.  
  103.             if isinstance(value, GLib.Date):
  104.                 date = datetime.date(
  105.                     value.get_year(), value.get_month(), value.get_day())
  106.                 result[tag].append(date.isoformat().decode('utf-8'))
  107.             if isinstance(value, Gst.DateTime):
  108.                 result[tag].append(value.to_iso8601_string().decode('utf-8'))
  109.             elif isinstance(value, bytes):
  110.                 result[tag].append(value.decode('utf-8', 'replace'))
  111.             else:
  112.                 pass
  113.  
  114.     return result
  115.  
  116. def _process(pipeline, timeout_ms):
  117.     bus = pipeline.get_bus()
  118.     tags = {}
  119.     mime = None
  120.     missing_message = None
  121.  
  122.     types = (
  123.         Gst.MessageType.ELEMENT |
  124.         Gst.MessageType.APPLICATION |
  125.         Gst.MessageType.ERROR |
  126.         Gst.MessageType.EOS |
  127.         Gst.MessageType.ASYNC_DONE |
  128.         Gst.MessageType.TAG
  129.     )
  130.  
  131.     timeout = timeout_ms
  132.     previous = int(time.time() * 1000)
  133.     while timeout > 0:
  134.         message = bus.timed_pop_filtered(timeout * Gst.MSECOND, types)
  135.  
  136.         if message is None:
  137.             break
  138.  
  139.         print (message.type)
  140.         if message.type == Gst.MessageType.APPLICATION:
  141.             if message.get_structure().get_name() == 'have-type':
  142.                 mime = message.get_structure().get_value('caps').get_name()
  143.                 if mime and (
  144.                         mime.startswith('text/') or mime == 'application/xml'):
  145.                     return tags, mime, have_audio
  146.         elif message.type == Gst.MessageType.ERROR:
  147.             if missing_message and not mime:
  148.                 caps = missing_message.get_structure().get_value('detail')
  149.                 mime = caps.get_structure(0).get_name()
  150.             err, debug = message.parse_error()
  151.             print("Error received from element %s: %s" % (
  152.                 message.src.get_name(), err))
  153.             print("Debugging information: %s" % debug)
  154.             return tags, mime
  155.         elif message.type == Gst.MessageType.EOS:
  156.             return tags, mime
  157.         elif message.type == Gst.MessageType.ASYNC_DONE:
  158.             return tags, mime
  159.         elif message.type == Gst.MessageType.TAG:
  160.             taglist = message.parse_tag()
  161.             # Note that this will only keep the last tag.
  162.             tags.update(convert_taglist(taglist))
  163.  
  164.         now = int(time.time() * 1000)
  165.         timeout -= now - previous
  166.         previous = now
  167.  
  168. s = Scanner()
  169. result = s.scan("file://" + sys.argv[1])
  170.  
  171. for key in ('uri', 'mime', 'duration', 'seekable'):
  172.     print('%-20s   %s' % (key, getattr(result, key)))
  173. print('tags')
  174. for tag, value in result.tags.items():
  175.     print('%-20s   %s' % (tag, value))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement