| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | #! /ufs/guido/bin/sgi/python | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Universal (non-interactive) CMIF video file copier. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Possibilities: | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # - Manipulate the time base: | 
					
						
							|  |  |  | #   = resample at a fixed rate | 
					
						
							|  |  |  | #   = divide the time codes by a speed factor (to make it go faster/slower) | 
					
						
							|  |  |  | #   = drop frames that are less than n msec apart (to accomodate slow players) | 
					
						
							|  |  |  | # - Convert to a different format | 
					
						
							|  |  |  | # - Magnify (scale) the image | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Usage function (keep this up-to-date if you change the program!) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def usage(): | 
					
						
							|  |  |  | 	print 'Usage: Vcopy [options] [infile [outfile]]' | 
					
						
							|  |  |  | 	print | 
					
						
							|  |  |  | 	print 'Options:' | 
					
						
							|  |  |  | 	print | 
					
						
							|  |  |  | 	print '-t type    : new image type (default unchanged)' | 
					
						
							|  |  |  | 	print | 
					
						
							|  |  |  | 	print '-M magnify : image magnification factor (default unchanged)' | 
					
						
							|  |  |  | 	print '-w width   : output image width (default height*4/3 if -h used)' | 
					
						
							|  |  |  | 	print '-h height  : output image height (default width*3/4 if -w used)' | 
					
						
							|  |  |  | 	print | 
					
						
							|  |  |  | 	print '-p pf      : new x and y packfactor (default unchanged)' | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 	print '-x xpf     : new x packfactor (default unchanged)' | 
					
						
							|  |  |  | 	print '-y ypf     : new y packfactor (default unchanged)' | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	print | 
					
						
							|  |  |  | 	print '-m delta   : drop frames closer than delta msec (default 0)' | 
					
						
							|  |  |  | 	print '-r delta   : regenerate input time base delta msec apart' | 
					
						
							|  |  |  | 	print '-s speed   : speed change factor (default unchanged)' | 
					
						
							|  |  |  | 	print | 
					
						
							|  |  |  | 	print 'infile     : input file (default film.video)' | 
					
						
							|  |  |  | 	print 'outfile    : output file (default out.video)' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | sys.path.append('/ufs/guido/src/video') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | import VFile | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | import imgconv | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | import imageop | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | import getopt | 
					
						
							|  |  |  | import string | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | # Global options | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | speed = 1.0 | 
					
						
							|  |  |  | mindelta = 0 | 
					
						
							|  |  |  | regen = None | 
					
						
							|  |  |  | newpf = None | 
					
						
							|  |  |  | newtype = None | 
					
						
							|  |  |  | magnify = None | 
					
						
							|  |  |  | newwidth = None | 
					
						
							|  |  |  | newheight = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Function to turn a string into a float | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | atof_error = 'atof_error' # Exception if it fails | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def atof(s): | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		return float(eval(s)) | 
					
						
							|  |  |  | 	except: | 
					
						
							|  |  |  | 		raise atof_error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Main program -- mostly command line parsing | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	global speed, mindelta, regen, newpf, newtype, \ | 
					
						
							|  |  |  | 	       magnify, newwidth, newheight | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Parse command line | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		opts, args = getopt.getopt(sys.argv[1:], \ | 
					
						
							|  |  |  | 			  'M:h:m:p:r:s:t:w:x:y:') | 
					
						
							|  |  |  | 	except getopt.error, msg: | 
					
						
							|  |  |  | 		sys.stdout = sys.stderr | 
					
						
							|  |  |  | 		print 'Error:', msg, '\n' | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 		usage() | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xpf = ypf = None | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	# Interpret options | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		for opt, arg in opts: | 
					
						
							|  |  |  | 			if opt == '-M': magnify = atof(arg) | 
					
						
							|  |  |  | 			if opt == '-h': height = string.atoi(arg) | 
					
						
							|  |  |  | 			if opt == '-m': mindelta = string.atoi(arg) | 
					
						
							|  |  |  | 			if opt == '-p': xpf = ypf = string.atoi(arg) | 
					
						
							|  |  |  | 			if opt == '-r': regen = string.atoi(arg) | 
					
						
							|  |  |  | 			if opt == '-s': speed = atof(arg) | 
					
						
							|  |  |  | 			if opt == '-t': newtype = arg | 
					
						
							|  |  |  | 			if opt == '-w': newwidth = string.atoi(arg) | 
					
						
							|  |  |  | 			if opt == '-x': xpf = string.atoi(arg) | 
					
						
							|  |  |  | 			if opt == '-y': ypf = string.atoi(arg) | 
					
						
							|  |  |  | 	except string.atoi_error: | 
					
						
							|  |  |  | 		sys.stdout = sys.stderr | 
					
						
							|  |  |  | 		print 'Option', opt, 'requires integer argument' | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 	except atof_error: | 
					
						
							|  |  |  | 		sys.stdout = sys.stderr | 
					
						
							|  |  |  | 		print 'Option', opt, 'requires float argument' | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if xpf or ypf: | 
					
						
							|  |  |  | 		newpf = (xpf, ypf) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if newwidth or newheight: | 
					
						
							|  |  |  | 		if magnify: | 
					
						
							|  |  |  | 			sys.stdout = sys.stderr | 
					
						
							|  |  |  | 			print 'Options -w or -h are incompatible with -M' | 
					
						
							|  |  |  | 			sys.exit(2) | 
					
						
							|  |  |  | 		if not newheight: | 
					
						
							|  |  |  | 			newheight = newwidth * 3 / 4 | 
					
						
							|  |  |  | 		elif not newwidth: | 
					
						
							|  |  |  | 			newwidth = newheight * 4 / 3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Check filename arguments | 
					
						
							|  |  |  | 	if len(args) < 1: | 
					
						
							|  |  |  | 		args.append('film.video') | 
					
						
							|  |  |  | 	if len(args) < 2: | 
					
						
							|  |  |  | 		args.append('out.video') | 
					
						
							|  |  |  | 	if len(args) > 2: | 
					
						
							|  |  |  | 		usage() | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 	if args[0] == args[1]: | 
					
						
							|  |  |  | 		sys.stderr.write('Input file can\'t be output file\n') | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Do the right thing | 
					
						
							|  |  |  | 	sts = process(args[0], args[1]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	# Exit | 
					
						
							|  |  |  | 	sys.exit(sts) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Copy one file to another | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def process(infilename, outfilename): | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 	global newwidth, newheight, newpf | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1993-12-17 15:11:41 +00:00
										 |  |  | 		vin = VFile.BasicVinFile(infilename) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	except IOError, msg: | 
					
						
							|  |  |  | 		sys.stderr.write(infilename + ': I/O error: ' + `msg` + '\n') | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	except VFile.Error, msg: | 
					
						
							|  |  |  | 		sys.stderr.write(msg + '\n') | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 	except EOFError: | 
					
						
							|  |  |  | 		sys.stderr.write(infilename + ': EOF in video file\n') | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1993-12-17 15:11:41 +00:00
										 |  |  | 		vout = VFile.BasicVoutFile(outfilename) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	except IOError, msg: | 
					
						
							|  |  |  | 		sys.stderr.write(outfilename + ': I/O error: ' + `msg` + '\n') | 
					
						
							|  |  |  | 		return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-02-25 16:10:16 +00:00
										 |  |  | 	print '=== input file ===' | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 	vin.printinfo() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	vout.setinfo(vin.getinfo()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	scale = 0 | 
					
						
							|  |  |  | 	flip = 0 | 
					
						
							| 
									
										
										
										
											1993-09-28 16:46:15 +00:00
										 |  |  | 	decompress = 0 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-09-28 16:46:15 +00:00
										 |  |  | 	vinfmt = vin.format | 
					
						
							|  |  |  | 	if vinfmt == 'compress': | 
					
						
							|  |  |  | 		if not newtype or newtype == 'compress': | 
					
						
							|  |  |  | 			# compressed->compressed: copy compression header | 
					
						
							|  |  |  | 			vout.setcompressheader(vin.getcompressheader()) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			# compressed->something else: go via rgb-24 | 
					
						
							|  |  |  | 			decompress = 1 | 
					
						
							|  |  |  | 			vinfmt = 'rgb' | 
					
						
							|  |  |  | 	elif newtype == 'compress': | 
					
						
							|  |  |  | 		# something else->compressed: not implemented | 
					
						
							|  |  |  | 		sys.stderr.write('Sorry, conversion to compressed not yet implemented\n') | 
					
						
							|  |  |  | 		return 1 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	if newtype: | 
					
						
							|  |  |  | 		vout.setformat(newtype) | 
					
						
							|  |  |  | 		try: | 
					
						
							| 
									
										
										
										
											1993-09-28 16:46:15 +00:00
										 |  |  | 			convert = imgconv.getconverter(vinfmt, vout.format) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 		except imgconv.error, msg: | 
					
						
							|  |  |  | 			sys.stderr.write(str(msg) + '\n') | 
					
						
							|  |  |  | 			return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if newpf: | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 		xpf, ypf = newpf | 
					
						
							|  |  |  | 		if not xpf: xpf = vin.xpf | 
					
						
							|  |  |  | 		if not ypf: ypf = vout.ypf | 
					
						
							|  |  |  | 		newpf = (xpf, ypf) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 		vout.setpf(newpf) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if newwidth and newheight: | 
					
						
							|  |  |  | 		scale = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if vin.upside_down <> vout.upside_down or \ | 
					
						
							|  |  |  | 		  vin.mirror_image <> vout.mirror_image: | 
					
						
							|  |  |  | 		flip = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	inwidth, inheight = vin.getsize() | 
					
						
							|  |  |  | 	inwidth = inwidth / vin.xpf | 
					
						
							|  |  |  | 	inheight = inheight / vin.ypf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if magnify: | 
					
						
							|  |  |  | 		newwidth = int(vout.width * magnify) | 
					
						
							|  |  |  | 		newheight = int(vout.height * magnify) | 
					
						
							|  |  |  | 		scale = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if scale: | 
					
						
							|  |  |  | 		vout.setsize(newwidth, newheight) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		newwidth, newheight = vout.getsize() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if vin.packfactor <> vout.packfactor: | 
					
						
							|  |  |  | 		scale = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if scale or flip: | 
					
						
							|  |  |  | 		if vout.bpp not in (8, 32): | 
					
						
							|  |  |  | 			sys.stderr.write('Can\'t scale or flip this type\n') | 
					
						
							|  |  |  | 			return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newwidth = newwidth / vout.xpf | 
					
						
							|  |  |  | 	newheight = newheight / vout.ypf | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-02-25 16:10:16 +00:00
										 |  |  | 	print '=== output file ===' | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 	vout.printinfo() | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 	vout.writeheader() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	told = 0 | 
					
						
							|  |  |  | 	nin = 0 | 
					
						
							|  |  |  | 	nout = 0 | 
					
						
							|  |  |  | 	tin = 0 | 
					
						
							|  |  |  | 	tout = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 	while 1: | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 		try: | 
					
						
							|  |  |  | 			tin, data, cdata = vin.getnextframe() | 
					
						
							|  |  |  | 		except EOFError: | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 			break | 
					
						
							| 
									
										
										
										
											1993-09-28 16:46:15 +00:00
										 |  |  | 		if decompress: | 
					
						
							|  |  |  | 			data = vin.decompress(data) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 		nin = nin + 1 | 
					
						
							|  |  |  | 		if regen: | 
					
						
							|  |  |  | 			tout = nin * regen | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 		else: | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 			tout = tin | 
					
						
							|  |  |  | 		tout = int(tout / speed) | 
					
						
							|  |  |  | 		if tout - told < mindelta: | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		told = tout | 
					
						
							|  |  |  | 		if newtype: | 
					
						
							|  |  |  | 			data = convert(data, inwidth, inheight) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 		if scale: | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 			data = imageop.scale(data, vout.bpp/8, \ | 
					
						
							|  |  |  | 				  inwidth, inheight, newwidth, newheight) | 
					
						
							| 
									
										
										
										
											1993-02-25 14:50:27 +00:00
										 |  |  | 		if flip: | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 			x0, y0 = 0, 0 | 
					
						
							| 
									
										
										
										
											1993-02-25 16:10:16 +00:00
										 |  |  | 			x1, y1 = newwidth-1, newheight-1 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 			if vin.upside_down <> vout.upside_down: | 
					
						
							|  |  |  | 				y1, y0 = y0, y1 | 
					
						
							|  |  |  | 			if vin.mirror_image <> vout.mirror_image: | 
					
						
							|  |  |  | 				x1, x0 = x0, x1 | 
					
						
							|  |  |  | 			data = imageop.crop(data, vout.bpp/8, \ | 
					
						
							|  |  |  | 				  newwidth, newheight, x0, y0, x1, y1) | 
					
						
							| 
									
										
										
										
											1993-02-25 16:10:16 +00:00
										 |  |  | 		print 'Writing frame', nout | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | 		vout.writeframe(tout, data, cdata) | 
					
						
							|  |  |  | 		nout = nout + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vout.close() | 
					
						
							|  |  |  | 	vin.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Don't forget to call the main program | 
					
						
							| 
									
										
										
										
											1992-12-24 11:41:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-02-25 14:20:13 +00:00
										 |  |  | try: | 
					
						
							|  |  |  | 	main() | 
					
						
							|  |  |  | except KeyboardInterrupt: | 
					
						
							|  |  |  | 	print '[Interrupt]' |