rename .pl
[undvd.git] / encvid
blob75fea998cbb6170bdb511e40b727d663d39cd81c
1 #!/usr/bin/perl
3 # Author: Martin Matusiak <numerodix@gmail.com>
4 # Licensed under the GNU Public License, version 3.
6 use strict;
7 use Getopt::Long qw(:config no_ignore_case);
9 BEGIN {
10 use File::Basename;
11 push(@INC, dirname(grep(-l, $0) ? readlink $0 : $0));
12 require colors; colors->import(qw(:DEFAULT));
13 require common; common->import(qw(:DEFAULT $suite $defaults $tools));
17 my $usage = "Usage: " . s_b($suite->{tool_name}) . " "
18 . s_bb("<file(s)>")
19 . " [" . s_b("options") . "]
20 <file(s)> files to encode\n
21 --start start after this many seconds (usually for testing)
22 -e --end end after this many seconds (usually for testing)\n
23 -C do sanity check (check for missing tools)
24 -z --adv <show advanced options>
25 --version show " . $suite->{suite_name} . " version\n";
27 my $adv_usage = "Advanced usage: " . s_b($suite->{tool_name}) . " "
28 . s_bb("<file(s)>")
29 . " [" . s_b("options") . "]
30 -o --size output file size in mb (integer value)
31 --bpp bits per pixel (float value)
32 -1 force 1-pass encoding
33 -2 force 2-pass encoding
34 -c --crop autocrop video
35 -r --scale scale video to x:y (integer value or " . s_bb("0") . ") or " . s_bb("off") . " to disable
36 -f --smooth use picture smoothing filter
37 -D --dryrun dry run (display encoding parameters without encoding)\n
38 --cont set container format
39 --acodec set audio codec
40 --vcodec set video codec\n";
42 my ($opts_start, $opts_end, $target_size, $bpp, $autocrop);
43 my ($dry_run, $opts_acodec, $opts_vcodec, $opts_cont);
45 my $custom_scale = "off";
46 my $target_passes = 1;
47 my $prescale = $defaults->{prescale};
48 my $postscale = $defaults->{postscale};
50 my $parse = GetOptions(
51 "start=f"=>\$opts_start,
52 "e|end=f"=>\$opts_end,
54 "C"=> sub { init_cmds(1); exit; },
55 "z|adv"=> sub { print $adv_usage; exit; },
56 "version"=>\&print_version,
58 "o|size=i"=>\$target_size,
59 "bpp=f"=>\$bpp,
60 "1"=> sub { $target_passes = 1; },
61 "2"=> sub { $target_passes = 2; },
62 "c|crop"=> sub { $autocrop = 1; },
63 "r|scale=s"=>\$custom_scale,
64 "f|smooth"=> sub { $prescale .= "spp,"; $postscale = ",hqdn3d$postscale"; },
65 "D|dryrun"=> sub { $dry_run = 1; },
67 "cont=s"=>\$opts_cont,
68 "acodec=s"=>\$opts_acodec,
69 "vcodec=s"=>\$opts_vcodec,
72 print_tool_banner();
74 if (! $parse) {
75 print $usage;
76 exit 2;
79 my @startpos = ("-ss", $opts_start ? $opts_start : 0);
80 my @endpos;
81 if ($opts_end) {
82 push(@endpos, "-endpos", $opts_end);
85 my @files = @ARGV;
86 if (scalar @files < 1) {
87 nonfatal("No files to encode, exiting");
88 print $usage;
89 exit 2;
93 init_logdir();
96 # Set container and codecs
98 my $container = $opts_cont ? $opts_cont : $defaults->{container};
99 my ($audio_codec, $video_codec, $ext, @cont_args) = set_container_opts($opts_acodec,
100 $opts_vcodec, $container);
102 print " - Output format :: "
103 . "container: " . s_it($container)
104 . " audio: " . s_it($audio_codec)
105 . " video: " . s_it($video_codec) . "\n";
108 # Display dry-run status
110 if ($dry_run) {
111 print " * Performing dry-run\n";
112 print_title_line(1);
115 foreach my $file (@files) {
117 if (! -e $file) {
118 nonfatal("File %%%$file%%% does not exist");
119 next;
120 } elsif (-d $file) {
121 nonfatal("%%%$file%%% is a directory");
122 next;
125 my $title_name = $file;
126 $title_name =~ s/^(.*)\..*$/$1/g;
129 # Display encode status
131 if (! $dry_run) {
132 print " * Now encoding file " . s_bb(trunc(38, 1, $file, "..."));
133 if ($opts_start and $opts_end) {
134 print " [" . s_bb($opts_start) . "s - " . s_bb($opts_end) . "s]";
135 } elsif ($opts_start) {
136 print " [" . s_bb($opts_start) . "s -> ]";
137 } elsif ($opts_end) {
138 print " [ -> " . s_bb($opts_end) . "s]";
140 print "\n";
144 # Extract information from the title
146 my $title = examine_title($file);
148 # Init encoding target info
150 my $ntitle = copy_hashref($title);
151 $ntitle->{aformat} = $audio_codec;
152 $ntitle->{vformat} = $video_codec;
153 $ntitle->{filename} = "$title_name.$ext";
156 # Do we need to crop?
158 my $crop_arg;
159 if ($autocrop) {
160 my $est = get_crop_eta($ntitle->{length}, $ntitle->{fps});
161 print " + Finding out how much to crop... (est: ${est}min)\r";
162 my ($width, $height);
163 ($width, $height, $crop_arg) = crop_title($file);
164 if (! $width or ! $height or ! $crop_arg) {
165 fatal("Crop detection failed");
167 $ntitle->{width} = $width;
168 $ntitle->{height} = $height;
171 # Find out how to scale the dimensions
173 my ($width, $height) =
174 scale_title($ntitle->{width}, $ntitle->{height}, $custom_scale);
175 $ntitle->{width} = $width;
176 $ntitle->{height} = $height;
177 my $scale_arg = "scale=$width:$height";
179 # Estimate filesize of audio
181 $ntitle->{abitrate} = set_acodec_opts($container, $ntitle->{aformat},
182 $ntitle->{abitrate}, 1);
183 my $audio_size = compute_media_size($ntitle->{length}, $ntitle->{abitrate});
184 my @acodec_args = set_acodec_opts($container, $ntitle->{aformat},
185 $ntitle->{abitrate});
187 # Decide bpp
189 if ($bpp) {
190 $ntitle->{bpp} = $bpp;
191 } elsif ($target_size) {
192 my $video_size = $target_size - $audio_size;
193 $video_size = 1 if $video_size <= 0;
194 $ntitle->{bpp} = compute_bpp($ntitle->{width}, $ntitle->{height},
195 $ntitle->{fps}, $ntitle->{length}, $video_size);
196 } else {
197 $ntitle->{bpp} = set_bpp($video_codec, $target_passes);
200 # Reset the number of passes based on the bpp
202 if ($target_passes) {
203 $ntitle->{passes} = $target_passes;
204 } else {
205 $ntitle->{passes} = set_passes($video_codec, $ntitle->{bpp});
208 # Compute bitrate
210 $ntitle->{vbitrate} = compute_vbitrate($ntitle->{width},
211 $ntitle->{height}, $ntitle->{fps}, $ntitle->{bpp});
214 # Dry run
216 if ($dry_run) {
218 # Estimate output size
220 if ($target_size) {
221 $ntitle->{filesize} = $target_size;
222 } else {
223 my $video_size = compute_media_size($ntitle->{length},
224 $ntitle->{vbitrate});
225 $ntitle->{filesize} = int($video_size + $audio_size);
228 $ntitle->{filename} = "$title_name.$container";
230 print_title_line(0, $title);
231 print_title_line(0, $ntitle);
234 # Encode video
236 } else {
238 for (my $pass = 1; $pass <= $ntitle->{passes}; $pass++) {
239 my @vcodec_args = set_vcodec_opts($ntitle->{vformat},
240 $ntitle->{passes}, $pass, $ntitle->{vbitrate});
242 my @args = (@startpos, @endpos);
243 push(@args, "-vf", "${crop_arg}${prescale}${scale_arg}${postscale}");
244 push(@args, "-oac", @acodec_args);
245 push(@args, "-ovc", @vcodec_args);
246 push(@args, "-of", @cont_args);
248 run_encode(\@args, $file, $title_name, $ext, $ntitle->{length},
249 $ntitle->{passes}, $pass);
252 if (-f "$title_name.$ext.partial") {
253 rename("$title_name.$ext.partial", "$title_name.$ext");
256 if (-f "divx2pass.log") {
257 unlink("divx2pass.log");
260 remux_container($title_name, $ext, $ntitle->{fps}, $container,
261 $ntitle->{aformat}, $ntitle->{vformat});