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.
		
		
		
		
		
			
		
			
				
					
					
						
							87 lines
						
					
					
						
							2.5 KiB
						
					
					
				
			
		
		
	
	
							87 lines
						
					
					
						
							2.5 KiB
						
					
					
				| #!/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)
 | |
| 
 | |
| 
 |