You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					88 lines
				
				2.5 KiB
			
		
		
			
		
	
	
					88 lines
				
				2.5 KiB
			| 
								 
											6 years ago
										 
									 | 
							
								#!/usr/bin/env python
							 | 
						||
| 
								 | 
							
								# Copyright (c) 2016, Comma.ai, Inc.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import re
							 | 
						||
| 
								 | 
							
								import binascii
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from tools.lib.mkvparse import mkvparse
							 | 
						||
| 
								 | 
							
								from tools.lib.mkvparse import mkvgen
							 | 
						||
| 
								 | 
							
								from tools.lib.mkvparse.mkvgen import ben, ebml_element, ebml_encode_number
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class MatroskaIndex(mkvparse.MatroskaHandler):
							 | 
						||
| 
								 | 
							
								  # def __init__(self, banlist, nocluster_mode):
							 | 
						||
| 
								 | 
							
								  #   pass
							 | 
						||
| 
								 | 
							
								  def __init__(self):
							 | 
						||
| 
								 | 
							
								    self.frameindex = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def tracks_available(self):
							 | 
						||
| 
								 | 
							
								    _, self.config_record = self.tracks[1]['CodecPrivate']
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def frame(self, track_id, timestamp, pos, length, more_laced_frames, duration,
							 | 
						||
| 
								 | 
							
								        keyframe, invisible, discardable):
							 | 
						||
| 
								 | 
							
								    self.frameindex.append((pos, length, keyframe))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def mkvindex(f):
							 | 
						||
| 
								 | 
							
								  handler = MatroskaIndex()
							 | 
						||
| 
								 | 
							
								  mkvparse.mkvparse(f, handler)
							 | 
						||
| 
								 | 
							
								  return handler.config_record, handler.frameindex
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def simple_gen(of, config_record, w, h, framedata):
							 | 
						||
| 
								 | 
							
								  mkvgen.write_ebml_header(of, "matroska", 2, 2)
							 | 
						||
| 
								 | 
							
								  mkvgen.write_infinite_segment_header(of)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  of.write(ebml_element(0x1654AE6B, "" # Tracks
							 | 
						||
| 
								 | 
							
								    + ebml_element(0xAE, "" # TrackEntry
							 | 
						||
| 
								 | 
							
								      + ebml_element(0xD7, ben(1)) # TrackNumber
							 | 
						||
| 
								 | 
							
								      + ebml_element(0x73C5, ben(1)) # TrackUID
							 | 
						||
| 
								 | 
							
								      + ebml_element(0x83, ben(1)) # TrackType = video track
							 | 
						||
| 
								 | 
							
								      + ebml_element(0x86, "V_MS/VFW/FOURCC") # CodecID
							 | 
						||
| 
								 | 
							
								      + ebml_element(0xE0, "" # Video
							 | 
						||
| 
								 | 
							
								        + ebml_element(0xB0, ben(w)) # PixelWidth
							 | 
						||
| 
								 | 
							
								        + ebml_element(0xBA, ben(h)) # PixelHeight
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      + ebml_element(0x63A2, config_record) # CodecPrivate (ffv1 configuration record)
							 | 
						||
| 
								 | 
							
								      )
							 | 
						||
| 
								 | 
							
								    ))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  blocks = []
							 | 
						||
| 
								 | 
							
								  for fd in framedata:
							 | 
						||
| 
								 | 
							
								    blocks.append(
							 | 
						||
| 
								 | 
							
								      ebml_element(0xA3, "" # SimpleBlock
							 | 
						||
| 
								 | 
							
								        + ebml_encode_number(1) # track number
							 | 
						||
| 
								 | 
							
								        + chr(0x00) + chr(0x00) # timecode, relative to Cluster timecode, sint16, in milliseconds
							 | 
						||
| 
								 | 
							
								        + chr(0x80) # flags (keyframe)
							 | 
						||
| 
								 | 
							
								        + fd
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  of.write(ebml_element(0x1F43B675, "" # Cluster
							 | 
						||
| 
								 | 
							
								    + ebml_element(0xE7, ben(0)) # TimeCode, uint, milliseconds
							 | 
						||
| 
								 | 
							
								    # + ebml_element(0xA7, ben(0)) # Position, uint
							 | 
						||
| 
								 | 
							
								    + ''.join(blocks)))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if __name__ == "__main__":
							 | 
						||
| 
								 | 
							
								  import random
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if len(sys.argv) != 2:
							 | 
						||
| 
								 | 
							
								    print("usage: %s mkvpath" % sys.argv[0])
							 | 
						||
| 
								 | 
							
								  with open(sys.argv[1], "rb") as f:
							 | 
						||
| 
								 | 
							
								    cr, index = mkvindex(f)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  # cr = "280000003002000030010000010018004646563100cb070000000000000000000000000000000000".decode("hex")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def geti(i):
							 | 
						||
| 
								 | 
							
								    pos, length = index[i]
							 | 
						||
| 
								 | 
							
								    with open(sys.argv[1], "rb") as f:
							 | 
						||
| 
								 | 
							
								      f.seek(pos)
							 | 
						||
| 
								 | 
							
								      return f.read(length)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  dats = [geti(random.randrange(200)) for _ in xrange(30)]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  with open("tmpout.mkv", "wb") as of:
							 | 
						||
| 
								 | 
							
								    simple_gen(of, cr, dats)
							 | 
						||
| 
								 | 
							
								
							 |