From 14738704ede6dfa6ac79f362a9c1f7f40f470cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Eduardo?= Date: Mon, 11 Sep 2017 17:47:17 -0500 Subject: rename mvc at lvc --- mvc/qtfaststart/processor.py | 215 ------------------------------------------- 1 file changed, 215 deletions(-) delete mode 100755 mvc/qtfaststart/processor.py (limited to 'mvc/qtfaststart/processor.py') diff --git a/mvc/qtfaststart/processor.py b/mvc/qtfaststart/processor.py deleted file mode 100755 index df2a900..0000000 --- a/mvc/qtfaststart/processor.py +++ /dev/null @@ -1,215 +0,0 @@ -""" - The guts that actually do the work. This is available here for the - 'qtfaststart' script and for your application's direct use. -""" - -import logging -import os -import struct - -#from StringIO import StringIO -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - -from mvc.qtfaststart.exceptions import FastStartException - -CHUNK_SIZE = 8192 - -log = logging.getLogger("qtfaststart") - -# Older versions of Python require this to be defined -if not hasattr(os, 'SEEK_CUR'): - os.SEEK_CUR = 1 - -def read_atom(datastream): - """ - Read an atom and return a tuple of (size, type) where size is the size - in bytes (including the 8 bytes already read) and type is a "fourcc" - like "ftyp" or "moov". - """ - return struct.unpack(">L4s", datastream.read(8)) - - -def get_index(datastream): - """ - Return an index of top level atoms, their absolute byte-position in the - file and their size in a list: - - index = [ - ("ftyp", 0, 24), - ("moov", 25, 2658), - ("free", 2683, 8), - ... - ] - - The tuple elements will be in the order that they appear in the file. - """ - index = [] - - log.debug("Getting index of top level atoms...") - - # Read atoms until we catch an error - while(datastream): - try: - skip = 8 - atom_size, atom_type = read_atom(datastream) - if atom_size == 1: - atom_size = struct.unpack(">Q", datastream.read(8))[0] - skip = 16 - log.debug("%s: %s" % (atom_type, atom_size)) - except: - break - - index.append((atom_type, datastream.tell() - skip, atom_size)) - - if atom_size == 0: - # Some files may end in mdat with no size set, which generally - # means to seek to the end of the file. We can just stop indexing - # as no more entries will be found! - break - - datastream.seek(atom_size - skip, os.SEEK_CUR) - - # Make sure the atoms we need exist - top_level_atoms = set([item[0] for item in index]) - for key in ["moov", "mdat"]: - if key not in top_level_atoms: - log.error("%s atom not found, is this a valid MOV/MP4 file?" % key) - raise FastStartException() - - return index - - -def find_atoms(size, datastream): - """ - This function is a generator that will yield either "stco" or "co64" - when either atom is found. datastream can be assumed to be 8 bytes - into the stco or co64 atom when the value is yielded. - - It is assumed that datastream will be at the end of the atom after - the value has been yielded and processed. - - size is the number of bytes to the end of the atom in the datastream. - """ - stop = datastream.tell() + size - - while datastream.tell() < stop: - try: - atom_size, atom_type = read_atom(datastream) - except: - log.exception("Error reading next atom!") - raise FastStartException() - - if atom_type in ["trak", "mdia", "minf", "stbl"]: - # Known ancestor atom of stco or co64, search within it! - for atype in find_atoms(atom_size - 8, datastream): - yield atype - elif atom_type in ["stco", "co64"]: - yield atom_type - else: - # Ignore this atom, seek to the end of it. - datastream.seek(atom_size - 8, os.SEEK_CUR) - - -def process(infilename, outfilename, limit=0): - """ - Convert a Quicktime/MP4 file for streaming by moving the metadata to - the front of the file. This method writes a new file. - - If limit is set to something other than zero it will be used as the - number of bytes to write of the atoms following the moov atom. This - is very useful to create a small sample of a file with full headers, - which can then be used in bug reports and such. - """ - datastream = open(infilename, "rb") - - # Get the top level atom index - index = get_index(datastream) - - mdat_pos = 999999 - free_size = 0 - - # Make sure moov occurs AFTER mdat, otherwise no need to run! - for atom, pos, size in index: - # The atoms are guaranteed to exist from get_index above! - if atom == "moov": - moov_pos = pos - moov_size = size - elif atom == "mdat": - mdat_pos = pos - elif atom == "free" and pos < mdat_pos: - # This free atom is before the mdat! - free_size += size - log.info("Removing free atom at %d (%d bytes)" % (pos, size)) - - # Offset to shift positions - offset = moov_size - free_size - - if moov_pos < mdat_pos: - # moov appears to be in the proper place, don't shift by moov size - offset -= moov_size - if not free_size: - # No free atoms and moov is correct, we are done! - log.error("This file appears to already be setup for streaming!") - raise FastStartException() - - # Read and fix moov - datastream.seek(moov_pos) - moov = StringIO(datastream.read(moov_size)) - - # Ignore moov identifier and size, start reading children - moov.seek(8) - - for atom_type in find_atoms(moov_size - 8, moov): - # Read either 32-bit or 64-bit offsets - ctype, csize = atom_type == "stco" and ("L", 4) or ("Q", 8) - - # Get number of entries - version, entry_count = struct.unpack(">2L", moov.read(8)) - - log.info("Patching %s with %d entries" % (atom_type, entry_count)) - - # Read entries - entries = struct.unpack(">" + ctype * entry_count, - moov.read(csize * entry_count)) - - # Patch and write entries - moov.seek(-csize * entry_count, os.SEEK_CUR) - moov.write(struct.pack(">" + ctype * entry_count, - *[entry + offset for entry in entries])) - - log.info("Writing output...") - outfile = open(outfilename, "wb") - - # Write ftype - for atom, pos, size in index: - if atom == "ftyp": - datastream.seek(pos) - outfile.write(datastream.read(size)) - - # Write moov - moov.seek(0) - outfile.write(moov.read()) - - # Write the rest - written = 0 - atoms = [item for item in index if item[0] not in ["ftyp", "moov", "free"]] - for atom, pos, size in atoms: - datastream.seek(pos) - - # Write in chunks to not use too much memory - for x in range(size / CHUNK_SIZE): - outfile.write(datastream.read(CHUNK_SIZE)) - written += CHUNK_SIZE - if limit and written >= limit: - # A limit was set and we've just passed it, stop writing! - break - - if size % CHUNK_SIZE: - outfile.write(datastream.read(size % CHUNK_SIZE)) - written += (size % CHUNK_SIZE) - if limit and written >= limit: - # A limit was set and we've just passed it, stop writing! - break -- cgit v1.2.3