[1208] | 1 | #!/bin/bash |
---|
| 2 | # |
---|
| 3 | # This shell script generates a parameter file suitable for use |
---|
| 4 | # with mpeg2encode from http://www.mpeg.org/MSSG/. |
---|
| 5 | # |
---|
| 6 | # make_mpeg2encode_parfile is part of a group of unix shell scripts to aid in converting a group |
---|
| 7 | # of still-frame images to an mpeg-1 animation. |
---|
| 8 | # More information can be found at http://marc.me.utexas.edu/mpeg_tools.html. |
---|
| 9 | # |
---|
| 10 | # |
---|
| 11 | # There is no error checking. It is basic but functional. |
---|
| 12 | # It relies upon: |
---|
| 13 | # /bin/sh |
---|
| 14 | # awk |
---|
| 15 | # identify (from ImageMagick, http://www.imagemagick.org) |
---|
| 16 | # |
---|
| 17 | # Usage: |
---|
| 18 | # make_mpeg2encode_parfile filelist |
---|
| 19 | # |
---|
| 20 | # where required arguemnts are: |
---|
| 21 | # |
---|
| 22 | # filelist - filenames, including directory, where the still frame images reside |
---|
| 23 | # |
---|
| 24 | # |
---|
| 25 | # Examples: |
---|
| 26 | # make_mpeg2encode_parfile /tmp/images/* |
---|
| 27 | # make_mpeg2encode_parfile /tmp/images/scenarioA*.tif |
---|
| 28 | # |
---|
| 29 | # where the /tmp/images directory contains files something like: |
---|
| 30 | # |
---|
| 31 | # frame.00001.tif |
---|
| 32 | # frame.00002.tif |
---|
| 33 | # frame.00003.tif |
---|
| 34 | # ... |
---|
| 35 | # frame.00486.tif |
---|
| 36 | # |
---|
| 37 | # The individual frames do not have to be tiff's; they can be any format 'convert' handles. |
---|
| 38 | # See notes within the 'imagetoppm' or 'imagetoyuv' scripts at |
---|
| 39 | # http://marc.me.utexas.edu/mpeg_tools.html. |
---|
| 40 | # |
---|
| 41 | # Result: mpeg2encode.par left in current working directory |
---|
| 42 | # |
---|
| 43 | # |
---|
| 44 | # Next possible steps to make a movie: |
---|
| 45 | # (1) ensure the images are converted from whatever format into either ppm or yuv with: |
---|
| 46 | # imagetoppm ./images/*.tif |
---|
| 47 | # or |
---|
| 48 | # imagetoyuv ./images/*.gif |
---|
| 49 | # |
---|
| 50 | # (2) run the encoder with: |
---|
| 51 | # mpeg2encode mpeg2encode.par movie.mpg |
---|
| 52 | # |
---|
| 53 | # For tips on how to combine 2 or more sequences of images into one mpeg, see the |
---|
| 54 | # 'renumber_sequence' script at http://marc.me.utexas.edu/mpeg_tools.html. |
---|
| 55 | # or use the 'rename' command and see http://www.tux.org/~mayer/linux/book.pdf. |
---|
| 56 | # |
---|
| 57 | # |
---|
| 58 | # Marc Compere |
---|
| 59 | # CompereM@asme.org |
---|
| 60 | # created : 18 September 2001 |
---|
| 61 | # modified: 20 January 2002 |
---|
| 62 | |
---|
| 63 | # development arg setup: |
---|
| 64 | # filelist=(`ls still_frames/test*ppm`) ; echo ${filelist[*]} |
---|
| 65 | |
---|
| 66 | |
---|
| 67 | parameter_set=1 # the PAL (-->2) parameter set is ImageMagick's default, but NTSC (-->1) seems to make |
---|
| 68 | # smaller mpeg's with similar playback quality |
---|
| 69 | |
---|
| 70 | if [ "$1" = "" ]; |
---|
| 71 | then |
---|
| 72 | echo " Usage:" |
---|
| 73 | echo " make_mpeg2encode_parfile filelist" |
---|
| 74 | echo |
---|
| 75 | echo " where the 'ppm' or 'yuv' string indicates which intermediate format to specify for mpeg2encode to use," |
---|
| 76 | echo " and where filelist is the list of filenames, including the directory, where the still frame images reside." |
---|
| 77 | echo |
---|
| 78 | echo " Examples:" |
---|
| 79 | echo " make_mpeg2encode_parfile /tmp/images/*" |
---|
| 80 | echo " make_mpeg2encode_parfile /tmp/images/scenarioA*.ppm" |
---|
| 81 | echo " or" |
---|
| 82 | echo " make_mpeg2encode_parfile yuv /tmp/images/*" |
---|
| 83 | echo " make_mpeg2encode_parfile ppm /tmp/images/scenarioA*.tif" |
---|
| 84 | echo |
---|
| 85 | echo |
---|
| 86 | echo "TYPICAL ANIMATION STEPS:" |
---|
| 87 | echo " (1) convert images from their native format to ppm or yuv with:" |
---|
| 88 | echo " imagetoppm ./images/scenario1*.tif" |
---|
| 89 | echo " imagetoyuv ./images/scenario1*.tif" |
---|
| 90 | echo " (2) make the encoder parameter file with:" |
---|
| 91 | echo " make_mpeg2encode_parfile ./images/scenario1*.ppm (use ppm images here to get image info properly in case padding was required)" |
---|
| 92 | echo " make_mpeg2encode_parfile ./images/scenario1*.tif (use tif images here if using yuv's to get image info properly)" |
---|
| 93 | echo " (3) run the encoder with:" |
---|
| 94 | echo " mpeg2encode mpeg2encode.par scenario1.mpg" $'\n\n' |
---|
| 95 | else |
---|
| 96 | |
---|
| 97 | filelist=($*) |
---|
| 98 | # assign input filename arglist |
---|
| 99 | |
---|
| 100 | if [ "$parameter_set" = "1" ]; |
---|
| 101 | then |
---|
| 102 | # set variables for NTSC |
---|
| 103 | fps=1 # specifying frames per second (this actually comes from frc spec and is only used in the comment string) |
---|
| 104 | Ngop=4 # 15 for NTSC |
---|
| 105 | frc=5 # 5 for NTSC |
---|
| 106 | vidfmt=2 # video format = 1->PAL, 2->NTSC |
---|
| 107 | Nmatcoef=4 # 5->PAL, 4->NTSC |
---|
| 108 | elif [ "$parameter_set" = "2" ]; |
---|
| 109 | then |
---|
| 110 | # set variables for PAL |
---|
| 111 | fps=25 # specifying frames per second (this actually comes from frc spec and is only used in the comment string) |
---|
| 112 | Ngop=12 # 12 for NTSC |
---|
| 113 | frc=3 # 3 for NTSC |
---|
| 114 | vidfmt=1 # video format = 1->PAL, 2->NTSC |
---|
| 115 | Nmatcoef=5 # 5->PAL, 4->NTSC |
---|
| 116 | else |
---|
| 117 | echo "mpeg2encode_preproc: invalid parameter_set number",$parameter_set |
---|
| 118 | echo "mpeg2encode_preproc: parameter_set should be 1 (for NTSC) or 2 (for PAL)" |
---|
| 119 | echo "mpeg2encode_preproc: exiting...." $'\n\n\n' |
---|
| 120 | fi |
---|
| 121 | |
---|
| 122 | |
---|
| 123 | # Set the rest of input parameters to write_parfile() |
---|
| 124 | parfile="mpeg2encode.par" # output parameter file |
---|
| 125 | statfile="/dev/null" # may be '-' for stdout or /dev/null (default) |
---|
| 126 | ipff=1 # input picture file format (only 1->yuv3 or 2->ppm used here) |
---|
| 127 | # note: using ipff=2 for ppm's seems to create skewed animations that appear to have the aspect |
---|
| 128 | # ratio way off, but changing the aspect ratio in the parameter file seems to do nothing... |
---|
| 129 | # --> use yuv's as the input file format to mpeg2encode (yuv is the 'convert' default) |
---|
| 130 | # note: ipff was set at 2 which means using the .ppm image format, but now that option |
---|
| 131 | # fails and causes mpeg2encode to crash. (?) Go figure. I'm now using the .yuv image format. |
---|
| 132 | # 10 January 2002 |
---|
| 133 | |
---|
| 134 | |
---|
| 135 | bitrate=1152000.0 # default was 5000000.0 (bits/sec), but 1152000.0 is mo'bettah |
---|
| 136 | |
---|
| 137 | |
---|
| 138 | # find Nframes |
---|
| 139 | Nframes=-1 # initially 0, but results in one extra filename. weird. |
---|
| 140 | for i in ${filelist[*]} |
---|
| 141 | do |
---|
| 142 | let Nframes=Nframes+1 |
---|
| 143 | done |
---|
| 144 | #echo $Nframes |
---|
| 145 | |
---|
| 146 | |
---|
| 147 | # find the common file (and directory name) prefix string to all image files: |
---|
| 148 | filenamelength=`echo ${filelist[0]} | awk '{print length}'` |
---|
| 149 | all_match=1 |
---|
| 150 | char_cnt=0 |
---|
| 151 | str1=(${filelist[0]}) |
---|
| 152 | str2=(${filelist[${Nframes}-1]}) |
---|
| 153 | while [ "${all_match}" = "1" -a "${char_cnt}" -le "${filenamelength}" ] ; do |
---|
| 154 | if [ "${str1:$char_cnt:1}" = "${str2:$char_cnt:1}" ] ; # compare the characters in the first and last filenames |
---|
| 155 | then |
---|
| 156 | #echo "characters in element $char_cnt match" ; |
---|
| 157 | let char_cnt=char_cnt+1 |
---|
| 158 | else |
---|
| 159 | all_match=0 |
---|
| 160 | #echo "characters in element $char_cnt DO NOT match, exiting..." ; |
---|
| 161 | fi |
---|
| 162 | done |
---|
| 163 | basefilename=${str1:0:$char_cnt} |
---|
| 164 | restofthefilename=${str1:$char_cnt} |
---|
| 165 | |
---|
| 166 | first_num=`echo ${restofthefilename} | awk -F. '{print $1}'` # this assumes the filename has an extension, ".something" |
---|
| 167 | maxnumchars=`echo $first_num | awk '{print length()}'` |
---|
| 168 | |
---|
| 169 | # note: |
---|
| 170 | # awk's array indicies are 1-based |
---|
| 171 | # bash's array indicies are 0-based |
---|
| 172 | |
---|
| 173 | |
---|
| 174 | # place hsize and vsize in ${sizes[0]} and ${sizes[1]} |
---|
| 175 | info=(`identify -ping ${filelist[0]}`) # use ImageMagick's identify command |
---|
| 176 | sizes=(`echo ${info[2]} | awk -Fx '{print $1}{print $2}'`) |
---|
| 177 | hsize=${sizes[0]} |
---|
| 178 | vsize=${sizes[1]} |
---|
| 179 | |
---|
| 180 | # determine if hsize is an even number or not... |
---|
| 181 | hsize_odd=$(( $(( hsize % 2)) ? 1 : 0 )) |
---|
| 182 | vsize_odd=$(( $(( vsize % 2)) ? 1 : 0 )) |
---|
| 183 | |
---|
| 184 | # ... if so, correct it by adding one (mpeg2encode seems to complain otherwise) |
---|
| 185 | # note: this is *only* useful if you are trying to convert a seqence of odd horizonal- or |
---|
| 186 | # vertical-sized yuv images. A mismatch in specified yuv image sizes and the actual size |
---|
| 187 | # used to create the yuv (i.e. from the original tif or gif or whatever) will generate a reasonably |
---|
| 188 | # acceptable mpeg. However, if ppm images require size-adjustment in the mpeg2encode.par |
---|
| 189 | # file then you're in touble --> this means the ppm image has been 'identify'ed as an odd-sized image |
---|
| 190 | # in either it's horizonal or vertical dimension and specifying a different number in the parameter |
---|
| 191 | # file will generate a bad mpeg. Use imagetoppm to convert the original file into a ppm and, in the |
---|
| 192 | # process, if hsize or vsize is not even-numbered, imagetoppm will pad the image with 'pnmpad' such |
---|
| 193 | # that this script will not require adjustment to get even-numbered hzize and vsizes. |
---|
| 194 | if [ "$hsize_odd" = "1" ]; |
---|
| 195 | then |
---|
| 196 | let hsize=hsize+1 |
---|
| 197 | fi |
---|
| 198 | if [ "$vsize_odd" = "1" ]; |
---|
| 199 | then |
---|
| 200 | let vsize=vsize+1 |
---|
| 201 | fi |
---|
| 202 | |
---|
| 203 | # variable descriptions: |
---|
| 204 | # fps - frame rate code, specifying frames per second |
---|
| 205 | # parfile - output parameter file |
---|
| 206 | # basefilename - text-string common to each filename (not including and leading directory names) |
---|
| 207 | # maxnumchars - number of characters in the largest number in the sequence, e.g. 2 for 10-99 frames, 3 for 100-999 frames, etc. |
---|
| 208 | # statfile - may be '-' for stdout (default=/dev/null) |
---|
| 209 | # ipff - input picture file format (only 1->yuv3 or 2->ppm used here) |
---|
| 210 | # Nframes - total number of frames (image files) within the sequence |
---|
| 211 | # Ngop - 12 or 15, number of frames within a Group Of Frames (GOP) |
---|
| 212 | # hsize - horizonal images size, from ImageMagick's identify command |
---|
| 213 | # vsize - horizonal images size, from ImageMagick's identify command |
---|
| 214 | # frc - framerate code, 1,2,3,4, or 5, see mpeg2encode documentation |
---|
| 215 | # bitrate - bits/sec, see mpeg2encode documentation |
---|
| 216 | # vidfmt - video format = 1->PAL, 2->NTSC, see mpeg2encode documentation |
---|
| 217 | # Nmatcoef - 5->PAL, 4->NTSC, see mpeg2encode documentation |
---|
| 218 | |
---|
| 219 | echo $'\t' "make_mpeg2encode_parfile: writing $parfile." |
---|
| 220 | echo "MPEG-1, $fps frames/sec, `date`, parameter file generated by make_mpeg2encode_parfile" > $parfile |
---|
| 221 | echo "$basefilename%0$maxnumchars""d /* name of source files */" >> $parfile |
---|
| 222 | echo "- /* name of reconstructed images (\"-\": dont store) */" >> $parfile |
---|
| 223 | echo "- /* name of intra quant matrix file (\"-\": default matrix) */" >> $parfile |
---|
| 224 | echo "- /* name of non intra quant matrix file (\"-\": default matrix) */" >> $parfile |
---|
| 225 | echo "$statfile /* name of statistics file (\"-\": stdout ) */" >> $parfile |
---|
| 226 | echo "$ipff /* input picture file format: 0=*.Y,*.U,*.V, 1=*.yuv, 2=*.ppm */" >> $parfile |
---|
| 227 | echo "$Nframes /* number of frames */" >> $parfile |
---|
| 228 | echo "1 /* number of first frame */" >> $parfile |
---|
| 229 | echo "00:00:00:00 /* timecode of first frame */" >> $parfile |
---|
| 230 | echo "$Ngop /* N (# of frames in GOP) */" >> $parfile |
---|
| 231 | echo "2 /* M (I/P frame distance) */" >> $parfile |
---|
| 232 | echo "1 /* ISO/IEC 11172-2 stream (0=MPEG-2, 1=MPEG-1)*/" >> $parfile |
---|
| 233 | echo "0 /* 0:frame pictures, 1:field pictures */" >> $parfile |
---|
| 234 | echo "${hsize} /* horizontal_size */" >> $parfile |
---|
| 235 | echo "${vsize} /* vertical_size */" >> $parfile |
---|
| 236 | echo "8 /* aspect_ratio_information 1=square pel, 2=4:3, 3=16:9, 4=2.11:1 */" >> $parfile |
---|
| 237 | echo "$frc /* frame_rate_code 1=23.976, 2=24, 3=25, 4=29.97, 5=30 frames/sec. */" >> $parfile |
---|
| 238 | echo "$bitrate /* bit_rate (bits/s) */" >> $parfile |
---|
| 239 | echo "112 /* vbv_buffer_size (in multiples of 16 kbit) */" >> $parfile |
---|
| 240 | echo "0 /* low_delay */" >> $parfile |
---|
| 241 | echo "1 /* constrained_parameters_flag */" >> $parfile |
---|
| 242 | echo "4 /* Profile ID: Simple = 5, Main = 4, SNR = 3, Spatial = 2, High = 1 */" >> $parfile |
---|
| 243 | echo "8 /* Level ID: Low = 10, Main = 8, High 1440 = 6, High = 4 */" >> $parfile |
---|
| 244 | echo "1 /* progressive_sequence */" >> $parfile |
---|
| 245 | echo "1 /* chroma_format: 1=4:2:0, 2=4:2:2, 3=4:4:4 */" >> $parfile |
---|
| 246 | echo "$vidfmt /* video_format: 0=comp., 1=PAL, 2=NTSC, 3=SECAM, 4=MAC, 5=unspec. */" >> $parfile |
---|
| 247 | echo "5 /* color_primaries */" >> $parfile |
---|
| 248 | echo "5 /* transfer_characteristics */" >> $parfile |
---|
| 249 | echo "$Nmatcoef /* matrix_coefficients */" >> $parfile |
---|
| 250 | echo "$hsize /* display_horizontal_size */" >> $parfile |
---|
| 251 | echo "$vsize /* display_vertical_size */" >> $parfile |
---|
| 252 | echo "0 /* intra_dc_precision (0: 8 bit, 1: 9 bit, 2: 10 bit, 3: 11 bit */" >> $parfile |
---|
| 253 | echo "0 /* top_field_first */" >> $parfile |
---|
| 254 | echo "1 1 1 /* frame_pred_frame_dct (I P B) */" >> $parfile |
---|
| 255 | echo "0 0 0 /* concealment_motion_vectors (I P B) */" >> $parfile |
---|
| 256 | echo "0 0 0 /* q_scale_type (I P B) */" >> $parfile |
---|
| 257 | echo "0 0 0 /* intra_vlc_format (I P B)*/" >> $parfile |
---|
| 258 | echo "0 0 0 /* alternate_scan (I P B) */" >> $parfile |
---|
| 259 | echo "0 /* repeat_first_field */" >> $parfile |
---|
| 260 | echo "1 /* progressive_frame */" >> $parfile |
---|
| 261 | echo "0 /* P distance between complete intra slice refresh */" >> $parfile |
---|
| 262 | echo "0 /* rate control: r (reaction parameter) */" >> $parfile |
---|
| 263 | echo "0 /* rate control: avg_act (initial average activity) */" >> $parfile |
---|
| 264 | echo "0 /* rate control: Xi (initial I frame global complexity measure) */" >> $parfile |
---|
| 265 | echo "0 /* rate control: Xp (initial P frame global complexity measure) */" >> $parfile |
---|
| 266 | echo "0 /* rate control: Xb (initial B frame global complexity measure) */" >> $parfile |
---|
| 267 | echo "0 /* rate control: d0i (initial I frame virtual buffer fullness) */" >> $parfile |
---|
| 268 | echo "0 /* rate control: d0p (initial P frame virtual buffer fullness) */" >> $parfile |
---|
| 269 | echo "0 /* rate control: d0b (initial B frame virtual buffer fullness) */" >> $parfile |
---|
| 270 | echo "2 2 11 11 /* P: forw_hor_f_code forw_vert_f_code search_width/height */" >> $parfile |
---|
| 271 | echo "1 1 3 3 /* B1: forw_hor_f_code forw_vert_f_code search_width/height */" >> $parfile |
---|
| 272 | echo "1 1 7 7 /* B1: back_hor_f_code back_vert_f_code search_width/height */" >> $parfile |
---|
| 273 | echo "1 1 7 7 /* B2: forw_hor_f_code forw_vert_f_code search_width/height */" >> $parfile |
---|
| 274 | echo "1 1 3 3 /* B2: back_hor_f_code back_vert_f_code search_width/height */" >> $parfile ; |
---|
| 275 | |
---|
| 276 | |
---|
| 277 | |
---|
| 278 | fi # end "if [ "$1" = "" ];" approximately on line 69 |
---|
| 279 | |
---|