mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	
		
			
	
	
		
			231 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			231 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | # VFile -- two classes for Video Files. | ||
|  | # VinFile -- for video input. | ||
|  | # VoutFile -- for video output. | ||
|  | 
 | ||
|  | import sys | ||
|  | import gl | ||
|  | import GL | ||
|  | 
 | ||
|  | Error = 'VFile.Error' # Exception | ||
|  | 
 | ||
|  | 
 | ||
|  | # Class VinFile represents a video file used for input. | ||
|  | # | ||
|  | # It has the following methods: | ||
|  | # init(filename) | ||
|  | # initfp(fp, filename) | ||
|  | # rewind() | ||
|  | # getframe() | ||
|  | # skipframe() | ||
|  | # | ||
|  | # The following read-only data members provide public information: | ||
|  | # version | ||
|  | # filename | ||
|  | # width, height | ||
|  | # packfactor | ||
|  | # ybits, ibits, qbits, chrompack | ||
|  | # | ||
|  | # These writable data members provide additional parametrization: | ||
|  | # xorigin, yorigin | ||
|  | 
 | ||
|  | class VinFile(): | ||
|  | 
 | ||
|  | 	# init() and initfp() raise Error if the header is bad. | ||
|  | 	# init() raises whatever open() raises if the file can't be opened. | ||
|  | 
 | ||
|  | 	def init(self, filename): | ||
|  | 		if filename = '-': | ||
|  | 			return self.initfp(sys.stdin, filename) | ||
|  | 		return self.initfp(open(filename, 'r'), filename) | ||
|  | 
 | ||
|  | 	def initfp(self, (fp, filename)): | ||
|  | 		self.colormapinited = 0 | ||
|  | 		self.magnify = 1.0 | ||
|  | 		self.xorigin = self.yorigin = 0 | ||
|  | 		self.fp = fp | ||
|  | 		self.filename = filename | ||
|  | 		# | ||
|  | 		line = self.fp.readline() | ||
|  | 		if line = 'CMIF video 1.0\n': | ||
|  | 			self.version = 1.0 | ||
|  | 		elif line = 'CMIF video 2.0\n': | ||
|  | 			self.version = 2.0 | ||
|  | 		else: | ||
|  | 			raise Error, self.filename + ': bad video format' | ||
|  | 		# | ||
|  | 		if self.version < 2.0: | ||
|  | 			self.ybits, self.ibits, self.qbits = 8, 0, 0 | ||
|  | 			self.chrompack = 0 | ||
|  | 		else: | ||
|  | 			line = self.fp.readline() | ||
|  | 			try: | ||
|  | 				self.ybits, self.ibits, self.qbits, \ | ||
|  | 					self.chrompack = eval(line[:-1]) | ||
|  | 			except: | ||
|  | 				raise Error, self.filename + ': bad color info' | ||
|  | 		# | ||
|  | 		line = self.fp.readline() | ||
|  | 		try: | ||
|  | 			x = eval(line[:-1]) | ||
|  | 			if self.version > 1.0 or len(x) = 3: | ||
|  | 				self.width, self.height, self.packfactor = x | ||
|  | 			else: | ||
|  | 				sef.width, self.height = x | ||
|  | 				self.packfactor = 2 | ||
|  | 		except: | ||
|  | 			raise Error, self.filename + ': bad (w,h,pf) info' | ||
|  | 		# | ||
|  | 		return self | ||
|  | 
 | ||
|  | 	# rewind() raises Error if the header is bad (which can only | ||
|  | 	# happen if the file was written to since opened). | ||
|  | 
 | ||
|  | 	def rewind(self): | ||
|  | 		self.fp.seek(0) | ||
|  | 		x = self.initfp(self.fp, self.filename) | ||
|  | 
 | ||
|  | 	# getnextframe() raises EOFError (built-in) if there is no next frame, | ||
|  | 	# or if the next frame is broken. | ||
|  | 	# So to getnextframeheader(), getnextframedata() and skipnextframe(). | ||
|  | 
 | ||
|  | 	def getnextframe(self): | ||
|  | 		time, size, chromsize = self.getnextframeheader() | ||
|  | 		data, chromdata = self.getnextframedata(size, chromsize) | ||
|  | 		return time, data, chromdata | ||
|  | 
 | ||
|  | 	def getnextframedata(self, (size, chromsize)): | ||
|  | 		data = self.fp.read(size) | ||
|  | 		if len(data) <> size: raise EOFError | ||
|  | 		if chromsize: | ||
|  | 			chromdata = self.fp.read(chromsize) | ||
|  | 			if len(chromdata) <> chromsize: raise EOFError | ||
|  | 		else: | ||
|  | 			chromdata = None | ||
|  | 		# | ||
|  | 		return data, chromdata | ||
|  | 
 | ||
|  | 	def skipnextframe(self): | ||
|  | 		time, size, chromsize = self.getnextframeheader() | ||
|  | 		self.skipnextframedata(size, chromsize) | ||
|  | 		return time | ||
|  | 
 | ||
|  | 	def skipnextframedata(self, (size, chromsize)): | ||
|  | 		# Note that this won't raise EOFError for a partial frame. | ||
|  | 		try: | ||
|  | 			self.fp.seek(size + chromsize, 1) # Relative seek | ||
|  | 		except: | ||
|  | 			# Assume it's a pipe -- read the data to discard it | ||
|  | 			dummy = self.fp.read(size) | ||
|  | 			dummy = self.fp.read(chromsize) | ||
|  | 
 | ||
|  | 	def getnextframeheader(self): | ||
|  | 		line = self.fp.readline() | ||
|  | 		if not line: | ||
|  | 			raise EOFError | ||
|  | 		# | ||
|  | 		w, h, pf = self.width, self.height, self.packfactor | ||
|  | 		try: | ||
|  | 			x = eval(line[:-1]) | ||
|  | 			if type(x) in (type(0), type(0.0)): | ||
|  | 				time = x | ||
|  | 				if pf = 0: | ||
|  | 					size = w * h * 4 | ||
|  | 				else: | ||
|  | 					size = (w/pf) * (h/pf) | ||
|  | 			elif len(x) = 2: | ||
|  | 				time, size = x | ||
|  | 				cp = self.chrompack | ||
|  | 				if cp: | ||
|  | 					cw = (w + cp - 1) / cp | ||
|  | 					ch = (h + cp - 1) / cp | ||
|  | 					chromsize = 2 * cw * ch | ||
|  | 				else: | ||
|  | 					chromsize = 0 | ||
|  | 			else: | ||
|  | 				time, size, chromsize = x | ||
|  | 		except: | ||
|  | 			raise Error, self.filename + ': bad frame header' | ||
|  | 		return time, size, chromsize | ||
|  | 
 | ||
|  | 	def shownextframe(self): | ||
|  | 		time, data, chromdata = self.getnextframe() | ||
|  | 		self.showframe(data, chromdata) | ||
|  | 		return time | ||
|  | 
 | ||
|  | 	def showframe(self, (data, chromdata)): | ||
|  | 		w, h, pf = self.width, self.height, self.packfactor | ||
|  | 		factor = self.magnify | ||
|  | 		if pf: factor = factor * pf | ||
|  | 		if chromdata: | ||
|  | 			cp = self.chrompack | ||
|  | 			cw = (w+cp-1)/cp | ||
|  | 			ch = (h+cp-1)/cp | ||
|  | 			gl.rectzoom(factor*cp, factor*cp) | ||
|  | 			gl.pixmode(GL.PM_SIZE, 16) | ||
|  | 			gl.writemask(0x7ff - ((1 << self.ybits) - 1)) | ||
|  | 			gl.lrectwrite(self.xorigin, self.yorigin, \ | ||
|  | 				self.xorigin + cw - 1, self.yorigin + ch - 1, \ | ||
|  | 				chromdata) | ||
|  | 		# | ||
|  | 		if pf: | ||
|  | 			if not self.colormapinited: | ||
|  | 				self.initcolormap() | ||
|  | 			gl.writemask((1 << self.ybits) - 1) | ||
|  | 			gl.pixmode(GL.PM_SIZE, 8) | ||
|  | 			gl.rectzoom(factor, factor) | ||
|  | 			w = w/pf | ||
|  | 			h = h/pf | ||
|  | 		gl.lrectwrite(self.xorigin, self.yorigin, \ | ||
|  | 			self.xorigin + w - 1, self.yorigin + h - 1, data) | ||
|  | 
 | ||
|  | 	def initcolormap(self): | ||
|  | 		initcmap(self.ybits, self.ibits, self.qbits, self.chrompack) | ||
|  | 		gl.color(0x800) | ||
|  | 		gl.clear() | ||
|  | 		self.colormapinited = 1 | ||
|  | 
 | ||
|  | 
 | ||
|  | def initcmap(ybits, ibits, qbits, chrompack): | ||
|  | 	if ybits+ibits+qbits > 11: | ||
|  | 		raise Error, 'Sorry, 11 bits max' | ||
|  | 	import colorsys | ||
|  | 	maxy = 1 << ybits | ||
|  | 	maxi = 1 << ibits | ||
|  | 	maxq = 1 << qbits | ||
|  | 	for i in range(2048, 4096-256): | ||
|  | 		gl.mapcolor(i, 0, 255, 0) | ||
|  | 	for y in range(maxy): | ||
|  | 		yv = y/float(maxy-1) | ||
|  | 		for i in range(maxi): | ||
|  | 			if maxi = 1: | ||
|  | 				iv = 0 | ||
|  | 			else: | ||
|  | 				iv = (i/float(maxi-1))-0.5 | ||
|  | 			for q in range(maxq): | ||
|  | 				if maxq = 1: | ||
|  | 					qv = 0 | ||
|  | 				else: | ||
|  | 					qv = (q/float(maxq-1))-0.5 | ||
|  | 				index = 2048 + y + \ | ||
|  | 					(i << ybits) + (q << (ybits+ibits)) | ||
|  | 				rv, gv, bv = colorsys.yiq_to_rgb(yv, iv, qv) | ||
|  | 				r, g, b = \ | ||
|  | 				    int(rv*255.0), int(gv*255.0), int(bv*255.0) | ||
|  | 				if index < 4096 - 256: | ||
|  | 					gl.mapcolor(index, r, g, b) | ||
|  | 
 | ||
|  | 
 | ||
|  | def test(): | ||
|  | 	import sys | ||
|  | 	filename = 'film.video' | ||
|  | 	if sys.argv[1:]: filename = sys.argv[1] | ||
|  | 	vin = VinFile().init(filename) | ||
|  | 	gl.foreground() | ||
|  | 	gl.prefsize(vin.width, vin.height) | ||
|  | 	wid = gl.winopen('VFile.test: ' + filename) | ||
|  | 	try: | ||
|  | 		while 1: | ||
|  | 			t = vin.shownextframe() | ||
|  | 	except EOFError: | ||
|  | 		pass |