1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
#!/usr/bin/perl
use Video::Capture::V4l;
use Video::RTjpeg;
$|=1;
$SIG{PIPE} = 'IGNORE';
$stream = "/tmp/vstream";
require $stream;
$mpegencode = "/root/cvt/mpeg_movie-1.6.0/video_in/mpeg_encode";
my $gop = 8;
$tmpdir = "/tmp/encode$$/";
$tmpdir = "/tmp/encode";
mkdir $tmpdir, 0700;
$fsize = $w*$h*2;
$partlen = $fps*60;
$partlen = $gop*100;
my @dec;
sub new_vdecoder {
my $number = @dec;
my $decp = do { local *DECODER_READER };
my $decc = do { local *DECODER_WRITER };
pipe $decp, $decc;
if (fork==0) {
my ($buf, $tables);
open DATA, "<$outprefix.v$number" or die;
read DATA, $buf, 4;
my ($tlen) = unpack "N*", $buf;
read DATA, $tables, $tlen;
Video::RTjpeg::init_decompress($tables, $w, $h);
while (read DATA, $buf, 8) {
my ($time, $size) = unpack "N*", $buf;
print $decc pack "N", $time;
read DATA, $buf, $size;
print $decc Video::RTjpeg::decompress $buf;
}
exit;
}
push @dec, $decp;
}
my @nframeid;
sub next_frame {
my $min = 1e30;
my $buf;
my $minid;
for (0..$#dec) {
unless (defined $nframeid[$_]) {
read $dec[$_], $buf, 4;
$nframeid[$_] = unpack "N", $buf;
}
($min,$minid) = ($nframeid[$_],$_) if $nframeid[$_] < $min && defined $nframeid[$_];
}
read $dec[$minid], $buf, $fsize;
undef $nframeid[$minid];
($buf, $min);
}
new_vdecoder for 1..$vencoders;
my $part = 0;
sub do_encode {
my ($pstart, $pframes) = @_;
$pframes = sprintf "%06d", $pframes-1;
$part = sprintf "%03d", $part+1;
open TEMPLATE, ">$tmpdir/param" or die;
print TEMPLATE <<EOF;
OUTPUT $outprefix.$part.mpg
#PATTERN IBBBPBBB
PATTERN IBBBPBBBPBBBPBBBPBBBPBBBPBBBPBBB
FORCE_ENCODE_LAST_FRAME
# You must specify the type of the input files. The choices are:
# YUV, PPM, JMOVIE, Y, JPEG, PNM
#
BASE_FILE_FORMAT YUV
# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running
YUV_SIZE ${w}x$h
# EYUV or UCB are the same as previous versions of this encoder.
# (All the Y's, then U's then V's, in 4:2:0 subsampling.)
# Other formats, such as Abekas, Phillips, or a general format are
# permissible, the general format is a string of Y's, U's, and V's
# to specify the file order.
INPUT_FORMAT EYUV
INPUT_CONVERT *
# number of frames in a GOP.
#
# since each GOP must have at least one I-frame, the encoder will find the
# the first I-frame after GOP_SIZE frames to start the next GOP
#
# later, will add more flexible GOP signalling
#
GOP_SIZE $partlen
# number of slices in a frame
#
# 1 is a good number. another possibility is the number of macroblock rows
# (which is the height divided by 16)
#
SLICES_PER_FRAME $w
# directory to get all input files from (makes this file easier to read)
INPUT_DIR $tmpdir
# There are a bunch of ways to specify the input files.
# from a simple one-per-line listing, to the following
# way of numbering them. See the manual for more information.
INPUT
# '*' is replaced by the numbers 01, 02, 03, 04
# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11
# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11
# if I instead do [1-11+3], it would be 1, 4, 7, 10
# the program assumes none of your input files has a name ending in ']'
# if you do, too bad!!!
#
#
frame*.yuv [000000-$pframes]
END_INPUT
# Many of the remaining options have to do with the motion search and qscale
# FULL or HALF -- must be upper case
PIXEL HALF
# means +/- this many pixels for both P and B frame searches
# specify two numbers if you wish to serc different ranges in the two.
RANGE 10
# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}
PSEARCH_ALG LOGARITHMIC
# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}
#
# note that EXHAUSTIVE is really, really, really slow
#
BSEARCH_ALG CROSS2
#
# these specify the q-scale for I, P, and B frames
# (values must be between 1 and 31)
# These are the Qscale values for the entire frame in variable bit-rate
# mode, and starting points (but not important) for constant bit rate
#
IQSCALE 8
PQSCALE 10
BQSCALE 25
# this must be ORIGINAL or DECODED
REFERENCE_FRAME DECODED
# for parallel parameters see parallel.param in the exmaples subdirectory
# if you want constant bit-rate mode, specify it as follows (number is bits/sec):
#BIT_RATE 2000000
# To specify the buffer size (327680 is default, measused in bits, for 16bit words)
#BUFFER_SIZE 800000
# The frame rate is the number of frames/second (legal values:
# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60
FRAME_RATE $fps
# There are many more options, see the users manual for examples....
# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.
#PARALLEL_TEST_FRAMES 3
#PARALLEL_CHUNK_TAPER
#PARALLEL
#localhost1 root $mpegencode
#localhost2 root $mpegencode
#END_PARALLEL
EOF
close TEMPLATE;
$ENV{HOST} = "localhost";
system $mpegencode, "-quiet", "10", "$tmpdir/param";
}
my ($frame, $pstart, $pframe) = (0, 0, 0);
Video::RTjpeg::init_decompress("x" x (128*4), $w, $h);
while (my ($buf, $framex) = next_frame) {
print ".";
while ($frame < $framex) {
if ($pframe == $partlen) {
do_encode $pstart, $pframe;
$pstart = $frame;
$pframe = 0;
}
#$buf2 = Video::RTjpeg::yuvrgb($buf); open DISPLAY, "| display -size ${w}x$h rgb:-" or die; print DISPLAY $buf2; close DISPLAY;
open FRAME, sprintf ">$tmpdir/frame%06d.yuv", $pframe;
print FRAME $buf;
close FRAME;
$frame++;
$pframe++;
print "s" if $frame != $framex;
}
last if $frame >= $nframe;
}
do_encode $pstart, $pframe;
|