diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..32f41e4 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,8 @@ +include *.xml +include *.rst +include *.txt +global-exclude *.pyc +prune dist +prune build +prune python_ebml.egg-info +recursive-include tools \ No newline at end of file diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..67b3b17 --- /dev/null +++ b/README.rst @@ -0,0 +1,6 @@ + +EBML (Extensible Binary Meta Language) library for Python + +TODO + + diff --git a/ebml/utils/ebml_data.py b/ebml/utils/ebml_data.py new file mode 100644 index 0000000..a9d1faf --- /dev/null +++ b/ebml/utils/ebml_data.py @@ -0,0 +1,82 @@ + +from ebml.schema import EBMLDocument, UnknownElement, CONTAINER, BINARY + +import json +import os +import datetime + +class EBMLData(object): + + def __init__(self, filename): + self.mod_name, _, self.cls_name = 'ebml.schema.matroska.MatroskaDocument'.rpartition('.') + try: + self.doc_mod = __import__(self.mod_name, fromlist=[self.cls_name]) + self.doc_cls = getattr(self.doc_mod, self.cls_name) + except ImportError: + parser.error('unable to import module %s' % self.mod_name) + except AttributeError: + parser.error('unable to import class %s from %s' % (self.cls_name, self.mod_name)) + + + + self.video_info = {} + self.video_info['filename'] = filename + self.video_info['total_size'] = os.stat(filename).st_size + self.video_info['clusters'] = [] + + self.doc = self.doc_cls(open(filename, 'rb')) + + def get_data(self): + offset = 0 + for el in self.doc.roots: + self.fill_video_info(el, offset, self.video_info) + offset += el.size + return self.video_info + + def get_full_info(self): + self.max_count = -1 + return self.get_data() + + def get_first_cluster_timedelta(self): + self.max_count = 4 + data = self.get_data() + ms = data['clusters'][0]['timecode'] + return datetime.timedelta(microseconds=ms*1000) + + def get_first_cluster_timecode(self): + td = self.get_first_cluster_timedelta() + hours = td.days * 24 + td.seconds / 3600 + minutes = (td.seconds % 3600) / 60 + seconds = td.seconds % 60 + microseconds = td.microseconds + return "%.2d:%.2d:%.2d.%.2d" % (hours, minutes, seconds, microseconds) + + def get_first_cluster_seconds(self): + td = self.get_first_cluster_timedelta() + return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.0**6 + + def fill_video_info(self, element, offset, video_info): + if element.name == 'Duration': + video_info['duration'] = element.value + + if element.name == 'DisplayWidth': + video_info['width'] = element.value + + if element.name == 'DisplayHeight': + video_info['height'] = element.value + + if element.name == 'Cluster': + video_info['clusters'].append({'offset': offset}) + + if element.name == 'Timecode': + video_info['clusters'][-1]['timecode'] = element.value + + if element.type == CONTAINER: + i = 0 + for sub_el in element.value: + self.fill_video_info(sub_el, offset + element.head_size, video_info) + offset += sub_el.size + if i == self.max_count: + break + i += 1 + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..99355c9 --- /dev/null +++ b/setup.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +'''The setup and build script for the library.''' + +from setuptools import setup, find_packages + +CLASSIFIERS = ['Programming Language :: Python', + 'Development Status :: 3 - Alpha', + 'Operating System :: OS Independent', + 'Topic :: Multimedia :: Video', + 'Topic :: Software Development :: Libraries :: Python Modules', + ] + +setup( + name = "python-ebml", + url = "https://github.com/yomguy/python-ebml.git", + description = "EBML (Extensible Binary Meta Language) library for Python", + long_description = open('README.rst').read(), + author = "Joseph Spiros", + author_email = "joseph@josephspiros.com", + version = '0.2', + install_requires = [ + 'setuptools', + ], + platforms=['OS Independent'], + license='BSD', + packages = find_packages(), + namespace_packages=['ebml'], + package_data={'': ['*.xml']}, + include_package_data = True, + zip_safe = False, + classifiers = CLASSIFIERS, +) diff --git a/tools/get_first_cluster_timecode.py b/tools/get_first_cluster_timecode.py new file mode 100644 index 0000000..b5ca570 --- /dev/null +++ b/tools/get_first_cluster_timecode.py @@ -0,0 +1,13 @@ + +from ebml.utils.ebml_data import * + +import sys + +if __name__ == '__main__': + ebml_obj = EBMLData(sys.argv[-1]) + print ebml_obj.get_first_cluster_timecode() + + + + + diff --git a/tools/get_info.py b/tools/get_info.py new file mode 100644 index 0000000..68ec7eb --- /dev/null +++ b/tools/get_info.py @@ -0,0 +1,53 @@ + +from ebml.schema import EBMLDocument, UnknownElement, CONTAINER, BINARY + + +def fill_video_info(element, offset, video_info): + if element.name == 'Duration': + video_info['duration'] = element.value + + if element.name == 'DisplayWidth': + video_info['width'] = element.value + + if element.name == 'DisplayHeight': + video_info['height'] = element.value + + if element.name == 'Cluster': + video_info['clusters'].append({'offset': offset}) + + if element.name == 'Timecode': + video_info['clusters'][-1]['timecode'] = element.value + + if element.type == CONTAINER: + for sub_el in element.value: + fill_video_info(sub_el, offset + element.head_size, video_info) + offset += sub_el.size + + +if __name__ == '__main__': + import sys + import json + import os + + mod_name, _, cls_name = 'ebml.schema.matroska.MatroskaDocument'.rpartition('.') + try: + doc_mod = __import__(mod_name, fromlist=[cls_name]) + doc_cls = getattr(doc_mod, cls_name) + except ImportError: + parser.error('unable to import module %s' % mod_name) + except AttributeError: + parser.error('unable to import class %s from %s' % (cls_name, mod_name)) + + video_info = {} + video_info['filename'] = sys.argv[1] + video_info['total_size'] = os.stat(sys.argv[1]).st_size + video_info['clusters'] = [] + + with open(sys.argv[1], 'rb') as stream: + doc = doc_cls(stream) + offset = 0 + for el in doc.roots: + fill_video_info(el, offset, video_info) + offset += el.size + + print json.dumps(video_info)