Skip to content
Open
File renamed without changes.
8 changes: 8 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

EBML (Extensible Binary Meta Language) library for Python

TODO


82 changes: 82 additions & 0 deletions ebml/utils/ebml_data.py
Original file line number Diff line number Diff line change
@@ -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

34 changes: 34 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -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,
)
13 changes: 13 additions & 0 deletions tools/get_first_cluster_timecode.py
Original file line number Diff line number Diff line change
@@ -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()





53 changes: 53 additions & 0 deletions tools/get_info.py
Original file line number Diff line number Diff line change
@@ -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)