1 #! /ufs/guido/bin/sgi/python
3 # Universal (non-interactive) CMIF video file copier.
8 # - Manipulate the time base:
9 # = resample at a fixed rate
10 # = divide the time codes by a speed factor (to make it go faster/slower)
11 # = drop frames that are less than n msec apart (to accomodate slow players)
12 # - Convert to a different format
13 # - Magnify (scale) the image
16 # Usage function (keep this up-to-date if you change the program!)
19 print 'Usage: Vcopy [options] [infile [outfile]]'
23 print '-t type : new image type (default unchanged)'
25 print '-M magnify : image magnification factor (default unchanged)'
26 print '-w width : output image width (default height*4/3 if -h used)'
27 print '-h height : output image height (default width*3/4 if -w used)'
29 print '-p pf : new x and y packfactor (default unchanged)'
30 print '-x xpf : new x packfactor (default unchanged)'
31 print '-y ypf : new y packfactor (default unchanged)'
33 print '-m delta : drop frames closer than delta msec (default 0)'
34 print '-r delta : regenerate input time base delta msec apart'
35 print '-s speed : speed change factor (default unchanged)'
37 print 'infile : input file (default film.video)'
38 print 'outfile : output file (default out.video)'
42 sys
.path
.append('/ufs/guido/src/video')
63 # Function to turn a string into a float
65 atof_error
= 'atof_error' # Exception if it fails
74 # Main program -- mostly command line parsing
77 global speed
, mindelta
, regen
, newpf
, newtype
, \
78 magnify
, newwidth
, newheight
82 opts
, args
= getopt
.getopt(sys
.argv
[1:], \
83 'M:h:m:p:r:s:t:w:x:y:')
84 except getopt
.error
, msg
:
85 sys
.stdout
= sys
.stderr
86 print 'Error:', msg
, '\n'
95 if opt
== '-M': magnify
= atof(arg
)
96 if opt
== '-h': height
= string
.atoi(arg
)
97 if opt
== '-m': mindelta
= string
.atoi(arg
)
98 if opt
== '-p': xpf
= ypf
= string
.atoi(arg
)
99 if opt
== '-r': regen
= string
.atoi(arg
)
100 if opt
== '-s': speed
= atof(arg
)
101 if opt
== '-t': newtype
= arg
102 if opt
== '-w': newwidth
= string
.atoi(arg
)
103 if opt
== '-x': xpf
= string
.atoi(arg
)
104 if opt
== '-y': ypf
= string
.atoi(arg
)
105 except string
.atoi_error
:
106 sys
.stdout
= sys
.stderr
107 print 'Option', opt
, 'requires integer argument'
110 sys
.stdout
= sys
.stderr
111 print 'Option', opt
, 'requires float argument'
117 if newwidth
or newheight
:
119 sys
.stdout
= sys
.stderr
120 print 'Options -w or -h are incompatible with -M'
123 newheight
= newwidth
* 3 / 4
125 newwidth
= newheight
* 4 / 3
127 # Check filename arguments
129 args
.append('film.video')
131 args
.append('out.video')
135 if args
[0] == args
[1]:
136 sys
.stderr
.write('Input file can\'t be output file\n')
140 sts
= process(args
[0], args
[1])
146 # Copy one file to another
148 def process(infilename
, outfilename
):
149 global newwidth
, newheight
, newpf
152 vin
= VFile
.BasicVinFile(infilename
)
154 sys
.stderr
.write(infilename
+ ': I/O error: ' + `msg`
+ '\n')
156 except VFile
.Error
, msg
:
157 sys
.stderr
.write(msg
+ '\n')
160 sys
.stderr
.write(infilename
+ ': EOF in video file\n')
164 vout
= VFile
.BasicVoutFile(outfilename
)
166 sys
.stderr
.write(outfilename
+ ': I/O error: ' + `msg`
+ '\n')
169 print '=== input file ==='
172 vout
.setinfo(vin
.getinfo())
179 if vinfmt
== 'compress':
180 if not newtype
or newtype
== 'compress':
181 # compressed->compressed: copy compression header
182 vout
.setcompressheader(vin
.getcompressheader())
184 # compressed->something else: go via rgb-24
187 elif newtype
== 'compress':
188 # something else->compressed: not implemented
189 sys
.stderr
.write('Sorry, conversion to compressed not yet implemented\n')
192 vout
.setformat(newtype
)
194 convert
= imgconv
.getconverter(vinfmt
, vout
.format
)
195 except imgconv
.error
, msg
:
196 sys
.stderr
.write(str(msg
) + '\n')
201 if not xpf
: xpf
= vin
.xpf
202 if not ypf
: ypf
= vout
.ypf
206 if newwidth
and newheight
:
209 if vin
.upside_down
<> vout
.upside_down
or \
210 vin
.mirror_image
<> vout
.mirror_image
:
213 inwidth
, inheight
= vin
.getsize()
214 inwidth
= inwidth
/ vin
.xpf
215 inheight
= inheight
/ vin
.ypf
218 newwidth
= int(vout
.width
* magnify
)
219 newheight
= int(vout
.height
* magnify
)
223 vout
.setsize(newwidth
, newheight
)
225 newwidth
, newheight
= vout
.getsize()
227 if vin
.packfactor
<> vout
.packfactor
:
231 if vout
.bpp
not in (8, 32):
232 sys
.stderr
.write('Can\'t scale or flip this type\n')
235 newwidth
= newwidth
/ vout
.xpf
236 newheight
= newheight
/ vout
.ypf
238 print '=== output file ==='
250 tin
, data
, cdata
= vin
.getnextframe()
254 data
= vin
.decompress(data
)
260 tout
= int(tout
/ speed
)
261 if tout
- told
< mindelta
:
265 data
= convert(data
, inwidth
, inheight
)
267 data
= imageop
.scale(data
, vout
.bpp
/8, \
268 inwidth
, inheight
, newwidth
, newheight
)
271 x1
, y1
= newwidth
-1, newheight
-1
272 if vin
.upside_down
<> vout
.upside_down
:
274 if vin
.mirror_image
<> vout
.mirror_image
:
276 data
= imageop
.crop(data
, vout
.bpp
/8, \
277 newwidth
, newheight
, x0
, y0
, x1
, y1
)
278 print 'Writing frame', nout
279 vout
.writeframe(tout
, data
, cdata
)
286 # Don't forget to call the main program
290 except KeyboardInterrupt: