Index: trunk/install/perl/foltialib.pl =================================================================== --- trunk/install/perl/foltialib.pl (リビジョン 70) +++ trunk/install/perl/foltialib.pl (リビジョン 83) @@ -22,4 +22,25 @@ $DBPass=""; + + + $FILESTATUSRESERVINGLONG = 10; + $FILESTATUSRESERVINGSHORT = 20; + $FILESTATUSRECORDING = 30; + $FILESTATUSRECTSSPLITTING = 40; + $FILESTATUSRECEND = 50; + $FILESTATUSWAITINGCAPTURE = 55; + $FILESTATUSCAPTURE = 60; + $FILESTATUSCAPEND = 70; + $FILESTATUSTHMCREATE = 72; + $FILESTATUSWAITINGTRANSCODE = 80; + $FILESTATUSTRANSCODETSSPLITTING = 90; + $FILESTATUSTRANSCODEFFMPEG = 100; + $FILESTATUSTRANSCODEWAVE = 110; + $FILESTATUSTRANSCODEAAC = 120; + $FILESTATUSTRANSCODEMP4BOX = 130; + $FILESTATUSTRANSCODEATOM = 140; + $FILESTATUSTRANSCODECOMPLETE = 150; + $FILESTATUSALLCOMPLETE = 200; + #------------------------------ @@ -258,4 +279,164 @@ +sub getpidbympegfilename { +#引き数:m2pfilename +#戻り値:PID +my $m2pfilename = $_[0] ; +if ($m2pfilename eq ""){ + return 0 ; +} + +my $DBQuery = "SELECT pid FROM foltia_subtitle WHERE m2pfilename = '$m2pfilename' LIMIT 1 "; +my $sth; +$sth = $dbh->prepare($DBQuery); +$sth->execute(); +#print "$DBQuery\n"; +my @pidinfo = $sth->fetchrow_array; +my $pid = $pidinfo[0]; + +if ($pid eq ""){ + return 0 ; +}else{ + return $pid; +} +}#end sub getpidbympegfilename + +sub changefilestatus { +#引き数:PID,updatestatus +#戻り値:エラーコード +my $pid = $_[0] ; +my $updatestatus = $_[1]; +if (($pid eq "" ) || ($updatestatus eq "")){ + return 0 ; +} + +if ($updatestatus > 0 ){ +my $DBQuery = "UPDATE foltia_subtitle SET filestatus = $updatestatus , lastupdate = now() WHERE pid = $pid "; +my $sth; +$sth = $dbh->prepare($DBQuery); +$sth->execute(); +return 1; +}else{ + &writelog("foltialib changefilestatus ERR Sttus invalid:$updatestatus"); + return 0 ; +} +}# end sub changefilestatus + + +sub getfilestatus { +#引き数:PID +#戻り値:ステータス + +#10:予約中(5分以上先) +#20:予約中(5分以内) +#30:録画中 +#40:TSSplit中 +#50:MPEG2録画終了 +#55 静止画キャプチャ待 +#60:静止画キャプ中 +#70:静止画キャプ終了 +#72:サムネイル作成済み(.THM) +#80:トラコン待 +#90:トラコン中:TSsplit +#100:トラコン中:H264 +#110:トラコン中:WAVE +#120:トラコン中:AAC +#130:トラコン中:MP4Box +#140:トラコン中:ATOM +#150:トラコン完了 +#200:全完了 +my $pid = $_[0] ; +if ($pid eq "" ){ + return 0 ; +} + +my $DBQuery = "SELECT filestatus FROM foltia_subtitle WHERE pid = $pid "; +my $sth; +$sth = $dbh->prepare($DBQuery); +$sth->execute(); + +my @statusinfo = $sth->fetchrow_array; +my $status = $statusinfo[0]; + +if ($status eq ""){ + return 0 ; +}else{ + return $status; +} + + +}# end sub getfilestatus + + +sub makemp4dir{ +#TIDが100以上の3桁の場合はそのまま +my $pspfilnamehd = $_[0]; +my $tid = $_[0]; +my $pspdirname = "$tid.localized/"; +$pspdirname = $recfolderpath."/".$pspdirname; + +#なければ作る +unless (-e $pspdirname ){ + system("$toolpath/perl/mklocalizeddir.pl $tid"); + #&writelog("recwrap mkdir $pspdirname"); +} +$pspdirname = "$tid.localized/mp4/"; +$pspdirname = $recfolderpath."/".$pspdirname; +#なければ作る +unless (-e $pspdirname ){ + mkdir $pspdirname ,0777; + #&writelog("recwrap mkdir $pspdirname"); +} +return ("$pspdirname"); +}#endsub makemp4dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1; Index: trunk/install/perl/updatem2pfiletable.pl =================================================================== --- trunk/install/perl/updatem2pfiletable.pl (リビジョン 69) +++ trunk/install/perl/updatem2pfiletable.pl (リビジョン 83) @@ -34,5 +34,5 @@ $sth->execute(); -while ($file = glob("$recfolderpath/*.m2p")) { +while ($file = glob("$recfolderpath/*.m2?")) { $file =~ s/$recfolderpath\///; $query = "insert into foltia_m2pfiles values ('$file')"; @@ -57,11 +57,11 @@ $filetid = $fileline[0]; $filetid =~ s/[^0-9]//g; - -$query = "insert into foltia_mp4files values ('$filetid','$fileline[2]')"; -$oserr = $dbh->do($query); +if (($filetid ne "" )&& ($fileline[2] ne "" )){ + $query = "insert into foltia_mp4files values ('$filetid','$fileline[2]')"; + $oserr = $dbh->do($query); #print "$filetid;$fileline[2];$query\n" # http://www.atmarkit.co.jp/fnetwork/rensai/sql03/sql1.html - -} +}#end if +}# end foreach $oserr = $dbh->commit; Index: trunk/install/perl/foltia_conf1.pl.template =================================================================== --- trunk/install/perl/foltia_conf1.pl.template (リビジョン 70) +++ trunk/install/perl/foltia_conf1.pl.template (リビジョン 83) @@ -15,14 +15,14 @@ $uhfbandtype = 1; # CATVなら1 UHF帯なら0 : 0=ntsc-bcast-jp 1=ntsc-cable-jp $rapidfiledelete = 1;#1なら削除ファイルは「mita」ディレクトリに移動。0なら即時削除 -$tunerinputnum = 6; #IO-DATA DV-MVP/RX,RX2,RX2W -$svideoinputnum = 7;#IO-DATA DV-MVP/RX,RX2,RX2W -$comvideoinputnum = 8;#IO-DATA DV-MVP/RX,RX2,RX2W +$tunerinputnum = 0; #IO-DATA DV-MVP/RX,RX2,RX2W +$svideoinputnum = 1;#IO-DATA DV-MVP/RX,RX2,RX2W +$comvideoinputnum= 2;#IO-DATA DV-MVP/RX,RX2,RX2W $haveirdaunit = 1;#Tira-2をつないでいるときに1,なければ0 $mp4filenamestyle = 1 ;#0:PSP ファームウェアver.2.80より前と互換性を持つファイル名 1;よりわかりやすいファイル名 $trconqty = 2; -#0:PSP/iPod XviD MPEG4(旧式):faacとMPEG4IPを使って変換 -#1:iPod Xvid MPEG4 標準画質 15fps 300kbps -#2:iPod H.264 中画質 24fps 300kbps -#3:iPod H.264 高画質 30fps 300kbps +#0:PSP/iPod XviD MPEG4(旧式):faacとMPEG4IPを使って変換(古い設定) +#1:iPod Xvid MPEG4 標準画質 15fps 300kbps / デジタル 360x202 24.00fps 300kbps +#2:iPod H.264 中画質 24fps 300kbps / デジタル 480x272 29.97fps 400kbps +#3:iPod H.264 高画質 30fps 300kbps / デジタル 640x352 29.97fps 600kbps $phptoolpath = $toolpath ;#php版の初期設定の位置。デフォルトではperlと同じ位置 Index: trunk/install/perl/digitaltvrecording.pl =================================================================== --- trunk/install/perl/digitaltvrecording.pl (リビジョン 83) +++ trunk/install/perl/digitaltvrecording.pl (リビジョン 83) @@ -0,0 +1,436 @@ +#!/usr/bin/perl +# +# Anime recording system foltia +# http://www.dcc-jpl.com/soft/foltia/ +# +#digitaltvrecording.pl +# friioをはじめとするデジタル録画プログラムを呼びだす録画モジュール。 +# +#usage digitaltvrecording.pl bandtype ch length(sec) [stationid] [sleeptype] [filename] [TID] [NO] [unittype] +#引数 +#bandtype : 0:地デジ 1:BSデジタル 2:CSデジタル +#ch :録画チャンネル (地デジはそのまま渡す、BS/CSデジタルは基本的にチャンネル BS1/BS2など同じ数時に) +#length(sec) :録画秒数 [必須項目] +#[stationid] :foltia stationid +#[sleeptype] :0かN Nならスリープなしで録画 +#[filename] :出力ファイル名 +#[TID] :しょぼかるタイトルID +#[NO] :その番組の放送話数 +#[unittype] :friioかfriioBSかユニデンチューナかHDUSかなど(未使用) +# +# DCC-JPL Japan/foltia project +# +# + +$path = $0; +$path =~ s/digitaltvrecording.pl$//i; +if ($pwd ne "./"){ +push( @INC, "$path"); +} + +#tvConfig.pl ------------------------------- +$extendrecendsec = 10; #recording end second. +#$startupsleeptime = 52; #process wait(MAX60sec) +$startupsleeptime = 27; #process wait(MAX60sec) +#------------------------------- + +require 'foltialib.pl'; + + &writelog("digitaltvrecording: DEBUG $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] $ARGV[4] $ARGV[5] $ARGV[6] $ARGV[7] $ARGV[8]"); + + +#準備 +&prepare; +#もし録画が走ってたら、止める +#$reclengthsec = &chkrecprocess(); +#&setbitrate; +#&chkextinput; +#$reclengthsec = $reclengthsec + $extendrecendsec ; + +&calldigitalrecorder; + +&writelog("digitaldigitaltvrecording:RECEND:$bandtype $recch $lengthsec $stationid $sleeptype $filename $tid $countno $unittype +"); + +# -- これ以下サブルーチン ---------------------------- + + +sub prepare{ + +#引数エラー処理 +$bandtype = $ARGV[0] ; +$recch = $ARGV[1] ; +$lengthsec = $ARGV[2] ; +$stationid = $ARGV[3] ; +$sleeptype = $ARGV[4] ; +$filename = $ARGV[5] ; +$tid = $ARGV[6] ; +$countno = $ARGV[7] ; +$unittype = $ARGV[8] ; + +if (($bandtype eq "" )|| ($recch eq "")|| ($lengthsec eq "")){ + print "usage digitaltvrecording.pl bandtype ch length(sec) [stationid] [sleeptype] [filename] [TID] [NO] [unittype]\n"; + exit; +} + +my $intval = $recch % 10; # 0〜9 sec +my $startupsleep = $startupsleeptime - $intval; # 18〜27 sec +$reclengthsec = $lengthsec + (60 - $startupsleep) + 1; # + +if ( $sleeptype ne "N"){ + &writelog("digitaltvrecording: DEBUG SLEEP $startupsleeptime:$intval:$startupsleep:$reclengthsec"); + sleep ( $startupsleep); + #2008/08/12_06:39:00 digitaltvrecording: DEBUG SLEEP 17:23:-6:367 +}else{ + &writelog("digitaltvrecording: DEBUG RAPID START"); +} +## recfriio このへんどうなってるの? +#if ($recunits > 1){ +#my $deviceno = $recunits - 1;#3枚差しのとき/dev/video2から使う +# $recdevice = "/dev/video$deviceno"; +# $recch = $ARGV[0] ; +#}else{ +##1枚差し +# $recdevice = "/dev/video0"; +# $recch = $ARGV[0] ; +#} + +$outputpath = "$recfolderpath"."/"; + +if ($countno eq "0"){ + $outputfile = $outputpath.$tid."--"; +}else{ + $outputfile = $outputpath.$tid."-".$countno."-"; +} +#2番目以降のクリップでファイル名指定があったら + if ($filename ne ""){ + + $outputfile = $filename ; + $outputfile = &filenameinjectioncheck($outputfile); + $outputfilewithoutpath = $outputfile ; + $outputfile = $outputpath.$outputfile ; + &writelog("digitaltvrecording: DEBUG FILENAME ne null \$outputfile $outputfile "); + }else{ + $outputfile .= `date +%Y%m%d-%H%M --date "1 min "`; + chomp($outputfile); + $outputfile .= ".m2t"; + $outputfilewithoutpath = $outputfile ; + &writelog("digitaltvrecording: DEBUG FILENAME is null \$outputfile $outputfile "); + } + + +@wday_name = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat"); +$sleepcounter = 0; +$cmd=""; + +#二重録りなど既に同名ファイルがあったら中断 +if ( -e "$outputfile" ){ + if ( -s "$outputfile" ){ + &writelog("digitaltvrecording :ABORT :recfile $outputfile exist."); + exit 1; + } +} + +}#end prepare + +sub calldigitalrecorderOld{ +# +# +#いまんところ白friioと黒friioのみ +# +# +my $oserr = 0; + +if ($bandtype == 0){ +# 地デジ friio +# b25,recfriioがあるか確認 + if ((-e "$toolpath/perl/tool/b25") && (-e "$toolpath/perl/tool/recfriio")){ + my $friiofifo = "$outputpath"."fifo-friio-"."$outputfilewithoutpath"; + my $b25fifo = "$outputpath"."fifo-b25-"."$outputfilewithoutpath"; + + if ((-e "$friiofifo") || (-e "$b25fifo")){ + &writelog("digitaltvrecording :ABORT :fifo is exist. It may be overwrite recording."); + exit 1; + }else{ + system ("mkfifo $friiofifo $b25fifo"); + # mkfifo fifo-friio-9999-01-20080810.m2t fifo-b25-9999-01-20080810.m2t + &writelog("digitaltvrecording DEBUG mkfifo $friiofifo $b25fifo: $?."); + # /home/foltia/perl/recfriio 27 30 ./fifo-friio-9999-01-20080810.m2t & /home/foltia/perl/b25 ./fifo-friio-9999-01-20080810.m2t ./fifo-b25-9999-01-20080810.m2t & dd if=./fifo-b25-9999-01-20080810.m2t of=/home/foltia/php/tv/9999-01-20080810.m2t bs=1M skip=10 +# system("$toolpath/perl/tool/recfriio $recch $reclengthsec $friiofifo & "); +# system("$toolpath/perl/tool/b25 $friiofifo $b25fifo &"); +# system("dd if=$b25fifo of=$outputfile bs=1M skip=10"); + &writelog("digitaltvrecording DEBUG $toolpath/perl/tool/recfriio $recch $reclengthsec $friiofifo & dd if=$friiofifo of=$b25fifo bs=1M skip=10 & $toolpath/perl/tool/b25 $b25fifo $outputfile: $?."); + system("dd if=$friiofifo of=$b25fifo bs=1M skip=10 & $toolpath/perl/tool/b25 $b25fifo $outputfile &"); + $oserr = system("$toolpath/perl/tool/recfriio $recch $reclengthsec $friiofifo "); + $oserr = $oserr >> 8; + system ("rm -rf $friiofifo $b25fifo"); + &writelog("digitaltvrecording DEBUG rm -rf $friiofifo $b25fifo: $?."); + if ($oserr > 0){ + # print "RECFRIIO RETURNS:$oserr\n"; + &writelog("digitaltvrecording :ERROR :friio is BUSY."); + # kill dd + $ddpid = `ps a | grep $friiofifo | grep -v grep`; + @ddpid = split(/ /,$ddpid); + $ddpid = $ddpid[0]; + chomp($ddpid); + $killcmd = "kill ".$ddpid; + system($killcmd); + &writelog("digitaltvrecording :DEBUG dd killed:$killcmd"); + + #kill b25 + $b25pid = `ps a | grep $b25fifo | grep -v grep`; + @b25pid = split(/ /,$b25pid); + $b25pid = $b25pid[0]; + chomp($b25pid); + $killcmd = "kill ".$b25pid; + system($killcmd); + &writelog("digitaltvrecording :DEBUG b25 killed:$killcmd"); + + system ("rm -rf $outputfile"); + + exit 2; + } + } + }else{ # エラー b25とrecfriioがありません + &writelog("digitaltvrecording :ERROR :recfriio or b25 not found. You must install $toolpath/b25 and $toolpath/recfriio."); + exit 1; + } + +}elsif($bandtype == 1){ + +# BS/CS friio +# b25,recfriioがあるか確認 + if ((-e "$toolpath/perl/tool/b25") && (-e "$toolpath/perl/tool/recfriiobs")){ + my $friiofifo = "$outputpath"."fifo-friioBS-"."$outputfilewithoutpath"; + my $b25fifo = "$outputpath"."fifo-b25-"."$outputfilewithoutpath"; + + if ((-e "$friiofifo") || (-e "$b25fifo")){ + &writelog("digitaltvrecording :ABORT :fifo is exist. It may be overwrite recording."); + exit 1; + }else{ + system ("mkfifo $friiofifo $b25fifo"); + &writelog("digitaltvrecording DEBUG mkfifo $friiofifo $b25fifo: $?."); + #recfriiobs用チャンネルリマップ + if ($recch == 101) { + $bssplitflag = $recch; + $recch = 22;#22 : NHK BS1/BS2 + }elsif($recch == 102){ + $bssplitflag = $recch; + $recch = 22;#22 : NHK BS1/BS2 + }elsif($recch == 103){ + $recch = 23;#23 : NHK hi + }elsif($recch == 141){ + $recch = 20;# 20 : BS-NTV + }elsif($recch == 151){ + $recch = 13;#13 : BS-Asahi + }elsif($recch == 161){ + $recch = 14;#14 : BS-i + }elsif($recch == 171){ + $recch = 16;#16 : BS-Japan + }elsif($recch == 181){ + $recch = 21;#21 : BS-Fuji + }elsif($recch == 191){ + $recch = 15;#15 : WOWOW + }elsif($recch == 192){ + $recch = 15;#15 : WOWOW + }elsif($recch == 193){ + $recch = 15;#15 : WOWOW + }elsif($recch == 211){ + $recch = 17;#17 : BS11 + }else{ + $recch = 19;#19 : TwellV + } + &writelog("digitaltvrecording DEBUG $toolpath/perl/tool/recfriiobs $recch $reclengthsec $friiofifo & dd if=$friiofifo of=$b25fifo bs=1M skip=10 & $toolpath/perl/tool/b25 $b25fifo $outputfile : $?."); + system("dd if=$friiofifo of=$b25fifo bs=1M skip=10 & $toolpath/perl/tool/b25 $b25fifo $outputfile &"); + $oserr = system("$toolpath/perl/tool/recfriiobs $recch $reclengthsec $friiofifo "); + $oserr = $oserr >> 8; + + system ("rm -rf $friiofifo $b25fifo"); + &writelog("digitaltvrecording DEBUG rm -rf $friiofifo $b25fifo: $?."); + if ($oserr > 0){ + # print "RECFRIIO RETURNS:$oserr\n"; + &writelog("digitaltvrecording :ERROR :friioBS is BUSY."); + # kill dd + $ddpid = `ps a | grep $friiofifo | grep -v grep`; + @ddpid = split(/ /,$ddpid); + $ddpid = $ddpid[0]; + chomp($ddpid); + $killcmd = "kill ".$ddpid; + system($killcmd); + &writelog("digitaltvrecording :DEBUG dd killed:$killcmd"); + + #kill b25 + $b25pid = `ps a | grep $b25fifo | grep -v grep`; + @b25pid = split(/ /,$b25pid); + $b25pid = $b25pid[0]; + chomp($b25pid); + $killcmd = "kill ".$b25pid; + system($killcmd); + &writelog("digitaltvrecording :DEBUG b25 killed:$killcmd"); + + system ("rm -rf $outputfile"); + + exit 2; + } + + #BS1/BS2などのスプリットを + if ($bssplitflag == 101){ + if (-e "$toolpath/perl/tool/TsSplitter.exe"){ + # BS1 + system("wine $toolpath/perl/tool/TsSplitter.exe -EIT -ECM -EMM -OUT \"$outputpath\" -HD -SD2 -SD3 -1SEG -LOGFILE -WAIT2 $outputfile"); + $splitfile = $outputfile; + $splitfile =~ s/\.m2t$/_SD1.m2t/; + if (-e "$splitfile"){ + system("rm -rf $outputfile ; mv $splitfile $outputfile"); + &writelog("digitaltvrecording DEBUG rm -rf $outputfile ; mv $splitfile $outputfile: $?."); + }else{ + &writelog("digitaltvrecording ERROR File not found:$splitfile."); + } + }else{ + &writelog("digitaltvrecording ERROR $toolpath/perl/tool/TsSplitter.exe not found."); + } + }elsif($bssplitflag == 102){ + if (-e "$toolpath/perl/tool/TsSplitter.exe"){ + # BS2 + system("wine $toolpath/perl/tool/TsSplitter.exe -EIT -ECM -EMM -OUT \"$outputpath\" -HD -SD1 -SD3 -1SEG -LOGFILE -WAIT2 $outputfile"); + $splitfile = $outputfile; + $splitfile =~ s/\.m2t$/_SD2.m2t/; + if (-e "$splitfile"){ + system("rm -rf $outputfile ; mv $splitfile $outputfile"); + &writelog("digitaltvrecording DEBUG rm -rf $outputfile ; mv $splitfile $outputfile: $?."); + }else{ + &writelog("digitaltvrecording ERROR File not found:$splitfile."); + } + }else{ + &writelog("digitaltvrecording ERROR $toolpath/perl/tool/TsSplitter.exe not found."); + } + }else{ + &writelog("digitaltvrecording DEBUG not split TS.$bssplitflag"); + }# endif #BS1/BS2などのスプリットを + + } + }else{ # エラー b25とrecfriioがありません + &writelog("digitaltvrecording :ERROR :recfriiobs or b25 not found. You must install $toolpath/perl/tool/b25 and $toolpath/perl/tool/recfriiobs."); + exit 1; + } +}elsif($bandtype == 2){ +}else{ + &writelog("digitaltvrecording :ERROR :Unsupported and type (digital CS)."); + exit 3; +} + + + +}#end calldigitalrecorderOld +#------------------------------------------------------------------------------------ +# +sub calldigitalrecorder{ +# +#いまんところ白friioと黒friioのみ +#2008/10/23 recfriio4仕様に変更 +# +my $oserr = 0; + +if ($bandtype == 0){ +# 地デジ friio +}elsif($bandtype == 1){ +# BS/CS friio + #recfriiobs用チャンネルリマップ + if ($recch == 101) { + $bssplitflag = $recch; + $recch = "b10";#22 : NHK BS1/BS2 + }elsif($recch == 102){ + $bssplitflag = $recch; + $recch = "b10";#22 : NHK BS1/BS2 + }elsif($recch == 103){ + $recch = "b11";#23 : NHK hi + }elsif($recch == 141){ + $recch = "b8";# 20 : BS-NTV + }elsif($recch == 151){ + $recch = "b1";#13 : BS-Asahi + }elsif($recch == 161){ + $recch = "b2";#14 : BS-i + }elsif($recch == 171){ + $recch = "b4";#16 : BS-Japan + }elsif($recch == 181){ + $recch = "b9";#21 : BS-Fuji + }elsif($recch == 191){ + $recch = "b3";#15 : WOWOW + }elsif($recch == 192){ + $recch = "b3";#15 : WOWOW + }elsif($recch == 193){ + $recch = "b3";#15 : WOWOW + }elsif($recch == 211){ + $recch = "b5";#17 : BS11 + }else{ + $recch = "b7";#19 : TwellV + } + # b6 # Star Channel + +}elsif($bandtype == 2){ +# 110度CSよくわかんない +}else{ + &writelog("digitaltvrecording :ERROR :Unsupported and type (digital CS)."); + exit 3; +} + + +# b25,recfriioがあるか確認 + if (-e "$toolpath/perl/tool/recfriio"){ + + if (! -e "$toolpath/perl/tool/friiodetect"){ + system("touch $toolpath/perl/tool/friiodetect"); + system("chown foltia:foltia $toolpath/perl/tool/friiodetect"); + system("chmod 775 $toolpath/perl/tool/friiodetect"); + &writelog("digitaltvrecording :DEBUG make lock file.$toolpath/perl/tool/friiodetect"); + } + &writelog("digitaltvrecording DEBUG recfriio --b25 --lockfile $toolpath/perl/tool/friiodetect $recch $reclengthsec $outputfile "); + $oserr = system("$toolpath/perl/tool/recfriio --b25 --lockfile $toolpath/perl/tool/friiodetect $recch $reclengthsec $outputfile "); + $oserr = $oserr >> 8; + if ($oserr > 0){ + &writelog("digitaltvrecording :ERROR :friio is BUSY.$oserr"); + exit 2; + } + }else{ # エラー recfriioがありません + &writelog("digitaltvrecording :ERROR :recfriio not found. You must install $toolpath/b25 and $toolpath/recfriio."); + exit 1; + } + +#BS1/BS2などのスプリットを +if ($bssplitflag == 101){ + if (-e "$toolpath/perl/tool/TsSplitter.exe"){ + # BS1 + system("wine $toolpath/perl/tool/TsSplitter.exe -EIT -ECM -EMM -OUT \"$outputpath\" -HD -SD2 -SD3 -1SEG -LOGFILE -WAIT2 $outputfile"); + $splitfile = $outputfile; + $splitfile =~ s/\.m2t$/_SD1.m2t/; + if (-e "$splitfile"){ + system("rm -rf $outputfile ; mv $splitfile $outputfile"); + &writelog("digitaltvrecording DEBUG rm -rf $outputfile ; mv $splitfile $outputfile: $?."); + }else{ + &writelog("digitaltvrecording ERROR File not found:$splitfile."); + } + }else{ + &writelog("digitaltvrecording ERROR $toolpath/perl/tool/TsSplitter.exe not found."); + } +}elsif($bssplitflag == 102){ + if (-e "$toolpath/perl/tool/TsSplitter.exe"){ + # BS2 + system("wine $toolpath/perl/tool/TsSplitter.exe -EIT -ECM -EMM -OUT \"$outputpath\" -HD -SD1 -SD3 -1SEG -LOGFILE -WAIT2 $outputfile"); + $splitfile = $outputfile; + $splitfile =~ s/\.m2t$/_SD2.m2t/; + if (-e "$splitfile"){ + system("rm -rf $outputfile ; mv $splitfile $outputfile"); + &writelog("digitaltvrecording DEBUG rm -rf $outputfile ; mv $splitfile $outputfile: $?."); + }else{ + &writelog("digitaltvrecording ERROR File not found:$splitfile."); + } + }else{ + &writelog("digitaltvrecording ERROR $toolpath/perl/tool/TsSplitter.exe not found."); + } +}else{ + &writelog("digitaltvrecording DEBUG not split TS.$bssplitflag"); +}# endif #BS1/BS2などのスプリットを + +}#end calldigitalrecorder + + Index: trunk/install/perl/captureimagemaker.pl =================================================================== --- trunk/install/perl/captureimagemaker.pl (リビジョン 1) +++ trunk/install/perl/captureimagemaker.pl (リビジョン 83) @@ -100,5 +100,5 @@ # $captureimgdir = "$tid"."-"."$countno"."-"."$date"."-"."$time"; $captureimgdir = $filename; -$captureimgdir =~ s/\.m2p$//; +$captureimgdir =~ s/\.m2p$|\.m2t$//; unless (-e "$capimgdirname/$captureimgdir"){ @@ -118,4 +118,10 @@ # 10秒ごとに -system ("mplayer -ss 00:00:10 -vo jpeg:outdir=$capimgdirname/$captureimgdir/ -vf crop=690:460:12:10,scale=160:120 -ao null -sstep 9 -v 3 $recfolderpath/$filename"); +if ($filename =~ /m2t$/){ + &writelog("captureimagemaker DEBUG mplayer -ss 00:00:10 -vo jpeg:outdir=$capimgdirname/$captureimgdir/ -vf scale=192:108 -ao null -sstep 9 -v 3 $recfolderpath/$filename"); + system ("mplayer -ss 00:00:10 -vo jpeg:outdir=$capimgdirname/$captureimgdir/ -vf scale=192:108 -ao null -sstep 9 -v 3 $recfolderpath/$filename"); +}else{ + &writelog("captureimagemaker DEBUG mplayer -ss 00:00:10 -vo jpeg:outdir=$capimgdirname/$captureimgdir/ -vf crop=690:460:12:10,scale=160:120 -ao null -sstep 9 -v 3 $recfolderpath/$filename"); + system ("mplayer -ss 00:00:10 -vo jpeg:outdir=$capimgdirname/$captureimgdir/ -vf crop=690:460:12:10,scale=160:120 -ao null -sstep 9 -v 3 $recfolderpath/$filename"); +} Index: trunk/install/perl/tvrecording.pl =================================================================== --- trunk/install/perl/tvrecording.pl (リビジョン 79) +++ trunk/install/perl/tvrecording.pl (リビジョン 83) @@ -5,5 +5,5 @@ # #tvrecording.pl -# record-v4l2.plに準備処理を加えた録画モジュール。 +# record-v4l2.plを呼びだす録画モジュール。 # #usage tvrecording.pl ch length(sec) [clip No(000-)] [filename] [bitrate(5)] [TID] [NO] [/dev/video0] @@ -44,5 +44,5 @@ #$startupsleeptime = 52; #process wait(MAX60sec) $startupsleeptime = 37; #process wait(MAX60sec) -#$startupsleeptime = 1; #process wait(MAX60sec) + #------------------------------- @@ -64,5 +64,6 @@ $recfolderpath = '/home/foltia/php/tv'; }#end sub getRecPath - +# +# -- ここからメイン ---------------------------- #準備 &prepare; @@ -74,9 +75,9 @@ $reclengthsec = $reclengthsec + $extendrecendsec ; +&callrecordv4l; + &writelog("tvrecording:$recch:$reclengthsec:$outputfile:$recdevice:$capturedeviceinputnum:$ivtvrecch:$stdbitrate:$peakbitrate"); -#------------------------------ - - +# -- これ以下サブルーチン ---------------------------- sub chkextinput{ @@ -87,5 +88,5 @@ $capturedeviceinputnum = 7 ; } - $capturedeviceinputName = "S-Video 0"; + $capturedeviceinputName = "S-Video 1"; $ivtvrecch = ''; }elsif($recch == -1){ @@ -95,5 +96,5 @@ $capturedeviceinputnum = 8; } - $capturedeviceinputName = "Composite 0"; + $capturedeviceinputName = "Composite 1"; $ivtvrecch = ''; }else{ @@ -103,5 +104,5 @@ $capturedeviceinputnum = 6 ; } - $capturedeviceinputName = "Tuner 0"; + $capturedeviceinputName = "Tuner 1"; $ivtvrecch = $recch; } @@ -304,15 +305,15 @@ $outputfile = $ARGV[3]; $outputfile = &filenameinjectioncheck($outputfile); + $outputfilewithoutpath = $outputfile ; $outputfile = $outputpath.$outputfile ; # $outputfile .= "$ARGV[3]"; # $outputfile .= `date +%Y%m%d-%H%M --date "1 min "`; - &writelog("tvrecording: DEBUG ARGV[3] ne null \$outputfile $outputfile "); - + &writelog("tvrecording: DEBUG ARGV[2] ne null \$outputfile $outputfile "); }else{ - $outputfile .= `date +%Y%m%d-%H%M --date "1 min "`; - chomp($outputfile); - $outputfile .= ".m2p"; -&writelog("tvrecording: DEBUG ARGV[3] is null \$outputfile $outputfile "); - + $outputfile .= `date +%Y%m%d-%H%M --date "1 min "`; + chomp($outputfile); + $outputfile .= ".m2p"; + $outputfilewithoutpath = $outputfile ; + &writelog("tvrecording: DEBUG ARGV[2] is null \$outputfile $outputfile "); } @@ -341,1490 +342,32 @@ }#end setbitrate -#------------------------------------------------------------------------------------------------- -# record-v4l2.pl created by James A. Pattie 04/10/2003 -# Copyright 2003 -# Purpose: to record from the specified channel for the specified amount -# of time to the video OutputDirectory under the channel-start time name as video.mpg. - -# -# You can always get the latest version of this script at -# http://www.pcxperience.org/ -# - -#2003.11.18 patched by DCC-JPL - -# 20030425 - 1.4 - Added devfs support based upon patch submitted by -# Jonathan Kolb -# 20030426 - 1.5 - Imported the ptune.pl functionality -# 20030426 - 1.6 - moved -F -> -L, -F now lets you specify the frequency to tune to. -# 20030427 - 1.7 - renamed to record_ivtv.pl per Kevin's request. Added -R option. -# 20030430 - 1.8 - fixing some comparisons that needed to be strings, etc. -# 20030504 - 1.9 - Migrating to Video::ivtv for video resolution support. -# 20030505 - 1.10- Replaced open w/ sysopen but it doesn't make a difference. -# Starting to replace the Standard code w/ Video::ivtv methods. -# Added the version numbers that I require to the use statements. -# 20030507 - 1.11- Migrated to using get/setFrequency from Video::ivtv 0.03. -# 20030510 - 1.12- Migrated to using get/setInput from Video::ivtv 0.04. Moved to using -# the exported method names rather than Video::ivtv::method(). -# Converted to using enumerateStandard(). -# Fixed the condition where switching Video Standards will most likely -# not get the correct channel and so would switch back with channel = 0 -# which is invalid. In this case I store the previous frequency, do the -# channel change but signal to restore the previous frequency on cleanup. -# Converted to using enumerateInput(). -# 20030512 - 1.13- Added initial support for setting the bitrate/bitrate_peak values. -# 20030513 - 1.14- Tweaked the bitrate values to be closer to real DVD bitrates. -# Added support for the .ivtvrc config file and User Profiles. -# 20030516 - 1.15- Updated to the OO interface that Video::ivtv 0.06 now requires. -# Cleaned up a lot of the global variables into a settings hash. -# Made the -S command add any config items you specified on the command line -# that were not in the Profile being updated. This way you can add new items. -# Made the config file work from a mapping hash so that we can easily add/remove -# config items in the future. -# 20030518 - 1.16- Fixed a Frequency bug that happened when changing Video Standards and the -# Frequency came from a user specified Profile. -# 20030519 - 1.17- Adding the rest of the Codec related options to the config file / defaults. -# Switched to using Getopt::Long. You can specify all config file options at -# least by a --long version and still by the original -X command option. -# Cleaned up the option parsing code to take advantage of the mappings hash. -# 20030520 - 1.18- Fixing the handling of the Profile command line option. -# 20030524 - 1.19- Cleaned up the output for -L/--list-freqtable. Changed --list -> --list-freqtable. -# Added support to detect the v4l2 driver in use and disable the ivtv "enhancements" -# if driver != "ivtv". -# Renamed to record-v4l2.pl to reflect the ability of this program to record from any -# v4l2 device but with special support for the ivtv driver. -# 20030524 - 1.20- Improving the Ctrl-C handling (cleanup before dying). It may take a second or two -# before the program exits, but it should exit after resetting anything it changed, unless -# you had specified not to reset the card. -# Allow layering of profiles by calling -P/--profile multiple times. Each profile will -# be layered over the last. You will not be able to create/update a profile if you -# specify more than one though. -# Fixed a bug that would cause a parameter from the profile to be set n times, where n was -# the number of characters in the mapping string that consisted of the single letter | and -# the long command option name. Ex: Channel has 'c|channel' so the Channel value was being -# set 9 times instead of just the first time if it was in the profile. -# 20030525 - 1.21- Fixed devfsd detection code as it was overriding what came from the config file. -# Adding --no-record option so that we can start to implement the replacement functionality for -# ptune.pl (ie. Set all values and then exit, do not reset the card and do not capture) -# 20030607 - 1.22- Adding --directory-format and --date-format options so that the user can specify the -# naming convention to use when specifying the directory the output file should be put in. -# Tweaked some of the defaults. -# Create the config file if it doesn't exist, regardless of the --save flag being specified. -# Added method error() to output an error condition that doesn't warrant the whole usage and -# converted all relevant usage() calls to error() calls. -# Added option --debug to dynamically on the fly enable debug output. -# 20030609 - 1.23- Added option --list-channels to display the currently selected frequency tables contents. -# Changed the default output directory to '.'. -# Moved $debug -> $settings{Debug} so it can be stored in the config file. This allows you to -# turn debugging on for only certain profiles, etc. -# Restructured some of the validity tests to only happen as long as we are recording since they -# do not need to be validated when we are not recording. Mainly to do with the output stuff. -# 20030610 - 1.24- Moved the tunerNum variable into the config file: TunerNum -# Added --tuner-num option to dynamically set it. -# 20030614 - 1.25- I now require Video::ivtv 0.09 to make sure everyone is using the version that fixes the known -# reported segfault issues. -# Added freqtable "custom" support so that people using the new feature in ptune-ui.pl and have -# set their default frequency table to be "custom" will just work when they specify channel X, etc. -# I'm now sorting the command line input since otherwise I can't guarantee the order options get -# processed in, but even that is wrong. I need to use Tie::IxHash, but that isn't standard. -# 20030626 - 1.26- Updated to cover the audio -> audio_bitmask changes that Video::ivtv 0.11 implemented to cover -# the ivtv_ioctl_codec structure changes. -# Implemented config file versioning so that I know when the Audio entry needs to be updated in case it -# comes back in a future version of the ivtv_ioctl_codec structure. -# 20030628 - 1.27- Adding --list-inputs and --list-standards to display the available inputs and video standards. -# 20030713 - 1.28- Added code to make sure the codec properties are proper when switching standard to PAL/SECAM. -# Added config options SetMSPMatrix, MSPInput, MSPOutput, MSPSleep to allow the user to specify if they -# want the msp matrix updated any time the Video Standard is changed and to specify what they want programmed. -# Bumping the config file version to 2 to account for the new options. -# 20030715 - 1.29- Adding the missing msp matrix reset code in the reset section. -# Adding codec checks to make sure that they are right for NTSC. -# Made it legal to specify the channel by itself without -c/--channel. - - -#use strict; -use Getopt::Long qw(:config no_ignore_case bundling); -use Fcntl; -use Video::Frequencies 0.03; -use Video::ivtv 0.12; -use Config::IniFiles; - -my $version="1.29"; -my $cfgVersion = "2"; -my $cfgVersionStr = "_configVersion_"; # hopefully unique [defaults] value to let me know what version the config file is. - -my @capabilities = (); # The cards capabilities - -my %settings = ( - Channel => $ivtvrecch , # default to the ivtv default channel - RecordDuration => $reclengthsec , # default to 59 minutes 50 seconds (in seconds) - This lets 2 back to back cron jobs work! - InputNum => $capturedeviceinputnum , # TV-Tuner 0 on GV-MVP/RX $capturedeviceinputnum - InputName => "$capturedeviceinputName", - OutputDirectory => "$recfolderpath", - VideoDevice => "$recdevice", - VideoWidth => "720", # 720x480-fullscreen NTSC - VideoHeight => "480", - VideoStandard => "NTSC", # NTSC, PAL or SECAM - VideoType => "mpeg", # mpeg, yuv - Bitrate => "$stdbitrate", - PeakBitrate => "$peakbitrate", # peak bitrate - Aspect => 2, - AudioBitmask => 0x00e9, - BFrames => 3, - DNRMode => 0, - DNRSpatial => 0, - DNRTemporal => 0, - DNRType => 0, - Framerate => 0, - FramesPerGOP => 15, - GOPClosure => 1, - Pulldown => 0, - StreamType => 0, # 10 = DVD format (almost) - OutputFileName => "$outputfile", - FrequencyTable => "$frequencyTable", # default to NTSC_CABLE mapping. - Frequency => "", # user specified frequency. - ResetCardSettings => 1, - ConfigFileName => "$ENV{HOME}/.ivtvrc", - UpdateConfigFile => 0, - UseConfigFile => 0, - UsingIvtvDriver => 1, # default to being able to use the ivtv "enhancements". - DontRecord => 0, # default to always recording data. - DirectoryFormatString => " ", # format string used to define the sub directory under OutputDirectory - DateTimeFormatString => "+%Y%m%d-%H%M", # format string used to represent the date/time if the user wants it in their DirectoryFormatString - # define the Codec related min/max values - minBitrate => 1, - maxBitrate => 14500000, - minPeakBitrate => 1500, - maxPeakBitrate => 16000000, - # msp matrix settings - SetMSPMatrix => 1, - MSPInput => 3, - MSPOutput => 1, - MSPSleep => 2, # number of seconds the card needs before we can set the msp matrix. - # other settings - Debug => 0,#DEBUG - TunerNum => 0, -); - - -print " $settings{InputNum} / $settings{InputName} /IVTVRECCH:$settings{Channel}/$recdevice \n\n" if $settings{Debug}; - - -my $result=""; -my @profileNames=(); # list of user defined sections to work with in the config file. -my %configIni; # config hash we tie to for Config::IniFiles. -my $ivtvObj = Video::ivtv->new(); - -# map the Settings/Config file parameter to the command line variable that specifies it. -my %mappings = ( - "Channel" => "c|channel", - "RecordDuration" => "t|duration", - "InputNum" => "i|inputnum", - "InputName" => "I|inputname", - "OutputDirectory" => "D|directory", - "VideoDevice" => "d|input", - "VideoWidth" => "W|width", - "VideoHeight" => "H|height", - "VideoStandard" => "s|standard", - "VideoType" => "T|type", - "Bitrate" => "b|bitrate", - "PeakBitrate" => "B|peakbitrate", - "Aspect" => "aspect", - "AudioBitmask" => "audio-bitmask", - "BFrames" => "bframes", - "DNRMode" => "dnrmode", - "DNRSpatial" => "dnrspatial", - "DNRTemporal" => "dnrtemporal", - "DNRType" => "dnrtype", - "Framerate" => "framerate", - "FramesPerGOP" => "framespergop", - "GOPClosure" => "gopclosure", - "Pulldown" => "pulldown", - "StreamType" => "streamtype", - "OutputFileName" => "o|output", - "FrequencyTable" => "f|freqtable", - "Frequency" => "F|frequency", - "ResetCardSettings" => "R|noreset", - "DirectoryFormatString" => "directory-format", - "DateTimeFormatString" => "date-format", - "Debug" => "debug", - "TunerNum" => "tuner-num", - "SetMSPMatrix" => "set-msp-matrix", - "MSPInput" => "msp-input", - "MSPOutput" => "msp-output", - "MSPSleep" => "msp-sleep", - "OutputMPGFileName" => "outputmpgfilename", - ); - -my %codecMappings = ( - "Aspect" => "aspect", - "AudioBitmask" => "audio_bitmask", - "BFrames" => "bframes", - "Bitrate" => "bitrate", - "PeakBitrate" => "bitrate_peak", - "DNRMode" => "dnr_mode", - "DNRSpatial" => "dnr_spatial", - "DNRTemporal" => "dnr_temporal", - "DNRType" => "dnr_type", - "Framerate" => "framerate", - "FramesPerGOP" => "framespergop", - "GOPClosure" => "gop_closure", - "Pulldown" => "pulldown", - "StreamType" => "stream_type", - ); - -# check for devfs support -if ( -e "/dev/.devfsd" ) -{ - $settings{VideoDevice} = "/dev/v4l/video0"; -} - -## check for the config file -#if (-f $settings{ConfigFileName}) -#{ -# $settings{UseConfigFile} = 1; -# -# # tie to it. -# tie %configIni, 'Config::IniFiles', (-file => $settings{ConfigFileName}) or die "Error: Opening config file '$settings{ConfigFileName}' failed! $!\n"; -# -# my $profile = "defaults"; -# if (exists $configIni{$profile}) -# { -# my $saveFile = 0; -# # check version of the config file. -# if (!exists $configIni{$profile}{$cfgVersionStr}) -# { -# print "Updating config file to version 1...\n"; -# -# # first version config file! Update the Audio -> AudioBitmask entries. -# $configIni{$profile}{$cfgVersionStr} = 1; -# -# # find all entries that have Audio and move to AudioBitmask. -# foreach my $p (keys %configIni) -# { -# if (exists $configIni{$p}{Audio}) -# { -# $configIni{$p}{AudioBitmask} = $configIni{$p}{Audio}; -# delete $configIni{$p}{Audio}; -# } -# } -# -# $saveFile = 1; # signal we need to save the config changes. -# } -# if ($configIni{$profile}{$cfgVersionStr} != $cfgVersion) -# { -# # we need to upgrade -# if ($configIni{$profile}{$cfgVersionStr} == 1) -# { -# print "Updating config file to version 2...\n"; -# # add the MSP Matrix related options. -# $configIni{$profile}{SetMSPMatrix} = $settings{SetMSPMatrix}; -# $configIni{$profile}{MSPInput} = $settings{MSPInput}; -# $configIni{$profile}{MSPOutput} = $settings{MSPOutput}; -# $configIni{$profile}{MSPSleep} = $settings{MSPSleep}; -# $configIni{$profile}{$cfgVersionStr} = 2; -# $saveFile = 1; -# } -# } -# -# if ($saveFile) -# { -# # now save the updated config file before we continue. -# tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed! $!\n"; -# } -# -# # update the defaults stored. -# foreach my $arg (keys %mappings) -# { -# if (exists $configIni{$profile}{$arg}) -# { -# $settings{$arg} = $configIni{$profile}{$arg}; -# print "settings{$arg} = '" . $settings{$arg} . "'\n"; -# } -# } -# } -# else -# { -# print "Warning: config file '$settings{ConfigFileName}' exists but does not have the\n[$profile] section! Use -S to create it without specifying -P.\n\n"; -# } -#} -#else # create the config file -#{ -# print "Auto Creating config file $settings{ConfigFileName}...\n"; -# my $profile = "defaults"; -# -# # we have to create the config file and tie to it. -# tie %configIni, 'Config::IniFiles', () or die "Error: Initializing config file '$settings{ConfigFileName}' failed! $!\n"; -# -# # now set the name to work with. -# tied(%configIni)->SetFileName($settings{ConfigFileName}) or die "Error: Setting config file to '$settings{ConfigFileName}' failed! $!\n"; -# -# $configIni{$profile} = {}; # make sure the section exists. -# -# foreach my $arg (keys %mappings) -# { -# $configIni{$profile}{$arg} = $settings{$arg}; -# print "configIni{$profile}{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug}; -# } -# -# # set the config file version -# $configIni{$profile}{$cfgVersionStr} = $cfgVersion; -# -# # write the config file out. -# tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed! $!\n"; -#} - -# build up the "custom" frequency table -my %customMap = (); -foreach my $profileName (keys %configIni) -{ - next if $profileName =~ /^(defaults)$/; - - if (exists $configIni{$profileName}{Frequency}) - { - $customMap{$profileName} = $configIni{$profileName}{Frequency}; - } -} -$CHANLIST{custom} = \%customMap; - -# enumerations -my @standards; -my %name2std; -my @inputs; -my %name2input; -my @codecInfo; # stores the Codec Info -my @newCodecInfo; # the version we mess with. -# Current settings (Input, Channel, Standard) -my $curinput; -my $curinputName; -my $std; -my $curstd = "???"; -my $curStandard = 0; # numeric representation. -my $curChannel = 0; -my $curFrequency = 0; - -my $tuner; -my $err; -my $v4l2input; - -my $tmpDirectoryStr = formatDirectoryString(); -my $versionStr = "record-v4l2.pl $version for use with http://ivtv.sf.net/"; -my $usageStr = <<"END_OF_USAGE"; -$versionStr - -Usage: record-v4l2.pl [--channel CHANNEL] [--duration TIME] - [--directory DIRECTORY] [--output OUTPUT] - [--directory-format FORMAT] [--date-format FORMAT] - [--input VIDEO_DEV][--width WIDTH --height HEIGHT] - [--standard STANDARD] [--type TYPE] - [--inputnum INPUT#] [--inputname INPUT NAME] - [--freqtable FREQENCY MAP] [--frequency FREQUENCY] - [--bitrate BITRATE] [--peakbitrate PEAK_BITRATE] - [--set-msp-matrix BOOL] [--msp-sleep SLEEP] - [--msp-input INPUT] [--msp-output OUTPUT] - [--profile PROFILE] [--list-freqtable] [--list-channels] - [--no-record] [--noreset] [--save] [--help] [--version] - [--aspect ASPECT] [--audio-bitmask AUDIO-BITMASK] [--bframes BFRAMES] - [--dnrmode DNRMODE] [--dnrspatial DNRSPATIAL] - [--dnrtemporal DNRTEMPORAL] [--dnrtype DNRTYPE] - [--framerate FRAMERATE] [--framespergop FRAMESPERGOP] - [--gopclosure GOPCLOSURE] [--pulldown PULLDOWN] - [--streamtype STREAMTYPE] [--debug] - [--tuner-num TUNERNUM] - [--list-inputs] [--list-standards] [CHANNEL] - - -c/--channel CHANNEL: channel number to switch to - NOTE: You can also specify the channel by itself. - Ex. record-v4l2.pl 73 - would change to channel 73 using the default settings - or the settings from your ~/.ivtvrc config file. - -t/--duration TIME: number of seconds to record - -D/--directory DIRECTORY: Base directory to record into - --directory-format FORMAT: format string that specifies the - sub-directory to create under the base directory that - the output file will be created in. This can be empty - to indicate no sub-directory should be created. - - Available tokens are: - %d - date formatted by --date-format - %I - input name recorded from - Any white space in the name is converted to - underscores (_). Ex. 'Tuner 0' => 'Tuner_0' - - %c - channel or "freq-#" frequency - - --date-format FORMAT: format string that specifies the - date format string to generate and substitute for - %d in the --directory-format string. - - Available tokens: see the date commands man page. - The string must start with a + (plus). - - -o/--output OUTPUT: name of file to create - -d/--input VIDEO_DEV: video device to capture from - -W/--width WIDTH: width of screen (720 for NTSC fullscreen) - -H/--height HEIGHT: height of screen (480 for NTSC fullscreen) - -s/--standard STANDARD: NTSC, PAL or SECAM - video standard to record in - -T/--type TYPE: mpeg or yuv output - -i/--inputnum INPUT#: - The index number of the input you want to use (0 -> n-1) - -I/--inputname INPUT NAME: The name of the input you want to use. - -f/--freqtable FREQUENCY MAP: Specify the frequency mapping to use. - -F/--frequency FREQUENCY: Specify the frequency to tune to. - ex. 517250 = NTSC Cable 73 (SCiFi) - --tuner-num TUNERNUM: Specify the tuner to use. - --set-msp-matrix BOOL: 1 - set the msp matrix after Video Standard changes - 0 - never set the msp matrix - Uses the --msp-input and --msp-output options. - --msp-sleep SLEEP: number of seconds the card needs before we can program - the msp matrix. - --msp-input INPUT: Specify the input parameter to program the msp matrix. - Valid values are from 1 - 8. - --msp-output OUTPUT: Specify the output parameter to program the msp matrix. - Valid values are from 0 - 3. - -L/--list-freqtable: - list all available frequency mappings that Video::Frequencies knows - --list-channels: lists all channels and their frequencies for the - specified frequency table being used. - --list-inputs: lists all inputs the v4l2 driver reports. - --list-standards: lists all Video Standards the v4l2 driver supports. - -R/--noreset: Do not Reset anything that was changed - (standard, channel, resolution, etc.) - --no-record: Do not create any directories, capture data or reset the card - back to original settings. This is the ptune.pl mode. - -h/--help: display this help - -v/--version: display the version of this program - --debug: turns on debug output - - Codec related options: - -b/--bitrate BITRATE: Specify the Bitrate to capture at - -B/--peakbitrate PEAK_BITRATE: Specify the Peak Bitrate to capture at - --aspect ASPECT: Specify the aspect value - --audio-bitmask AUDIO-BITMASK: Specify the audio bitmask value - --bframes BFRAMES: Specify the bframes value - --dnrmode DNRMODE: Specify the dnr_mode value - --dnrspatial DNRSPATIAL: Specify the dnr_spatial value - --dnrtemporal DNRTEMPORAL: Specify the dnr_temporal value - --dnrtype DNRTYPE: Specify the dnr_type value - --framerate FRAMERATE: Specify the framerate value - --framespergop FRAMESPERGOP: Specify the framespergop value - --gopclosure GOPCLOSURE: Specify the gop_closure value - --pulldown PULLDOWN: Specify the pulldown value - --streamtype STREAMTYPE: Specify the stream_type value - - Config file related options: - -P/--profile PROFILE: Override defaults and command line values with the - config entries in the section labeled [PROFILE] from the - config file $settings{ConfigFileName}. - Examples: -P NTSC-DVD, -P PAL-DVD, --profile MY-SETTINGS - - You can specify this option multiple times and each successive - profile will overlay the defaults and any previous profiles. - You will not be able to create/update a profile if you do - specify multiple profiles. - -S/--save: save the current values as the defaults in - $settings{ConfigFileName}. - If -P/--profile PROFILE is specified, then those values that exist in - the specified profile will be updated. If the profile doesn't exist, - then it will be created, but will have all possible config items - defined in it. It will be your responsibility to hand check the - config file and remove any config items you do not want set for - that profile. - Any options specified on the command line will override options - defined in the config file. - -Notes: - If you specify both -i/--inputnum and -I/--inputname then - -i/--inputnum will take precedence. - - If you specify both -c/--channel and -F/--frequency then - -F/--frequency will take precedence. - - If you use a Profile, it has the ability to override all command line - arguments, so check your Profile first if things seem to be ignored. - -Defaults: - --duration $settings{RecordDuration} --input $settings{VideoDevice} --width $settings{VideoWidth} --height $settings{VideoHeight} --standard $settings{VideoStandard} - --type $settings{VideoType} --directory $settings{OutputDirectory} --output $settings{OutputFileName} - --directory-format "$settings{DirectoryFormatString}" --date-format "$settings{DateTimeFormatString}" - --inputnum $settings{InputNum} --inputname '$settings{InputName}' --freqtable $settings{FrequencyTable} - --set-msp-matrix $settings{SetMSPMatrix} --msp-sleep $settings{MSPSleep} --msp-input $settings{MSPInput} --msp-output $settings{MSPOutput} - --bitrate $settings{Bitrate} --peakbitrate $settings{PeakBitrate} --aspect $settings{Aspect} --audio-bitmask $settings{AudioBitmask} --bframes $settings{BFrames} - --dnrmode $settings{DNRMode} --dnrspatial $settings{DNRSpatial} --dnrtemporal $settings{DNRTemporal} --dnrtype $settings{DNRType} - --framerate $settings{Framerate} --framespergop $settings{FramesPerGOP} --gopclosure $settings{GOPClosure} --pulldown $settings{Pulldown} --streamtype $settings{StreamType} - --tuner-num $settings{TunerNum} - - config file = '$settings{ConfigFileName}' - - If Channel = $settings{Channel}, this would create: - $tmpDirectoryStr$settings{OutputFileName} - - Note: This script relies on Perl Modules: Video::Frequencies, Video::ivtv, - Config::IniFiles and Getopt::Long. -END_OF_USAGE - -# handle user input here -my %opts; -#getopts('c:t:o:hd:W:H:s:T:D:vi:I:f:F:LRb:B:P:S', \%opts); -GetOptions(\%opts, "channel|c=s", "duration|t=i", "output|o=s", "help|h", "input|d=s", "width|W=i", "height|H=i", "standard|s=s", - "type|T=s", "directory|D=s", "version|v", "inputnum|i=i", "inputname|I=s", "freqtable|f=s", "frequency|F=i", "list-freqtable|L", - "noreset|R", "bitrate|b=i", "peakbitrate|B=i", "profile|P=s@", "save|S", "aspect=i", "audio-bitmask=s", "bframes=i", "dnrmode=i", "dnrspatial=i", - "dnrtemporal=i", "dnrtype=i", "framerate=i", "framespergop=i", "gopclosure=i", "pulldown=i", - "streamtype=i", "no-record", "directory-format=s", "date-format=s", "debug", "list-channels", - "tuner-num=i", "list-inputs", "list-standards", "set-msp-matrix=i", "msp-input=i", "msp-output=i", "outputmpgfilename=s"); -if (scalar keys %opts == 0 && @ARGV == 0) -{ - usage(0, ""); -} -foreach my $option (sort keys %opts) -{ - my $found = 0; - foreach my $mapName (keys %mappings) - { - if ($option =~ /^($mappings{$mapName})$/) - { - $settings{$mapName} = $opts{$option}; - $found = 1; - print "$mapName = '$opts{$option}'\n" if $settings{Debug}; - } - } - if (!$found) - { - # handle the non-settings cases. - if ($option =~ /^(L|list-freqtable)$/) - { - my $errStr = "\nAvailable Frequency Mappings:\n"; - foreach my $name (sort keys %CHANLIST) - { - $errStr .= "$name\n"; - } - print "$versionStr\n$errStr"; - exit 0; - } - elsif ($option eq "list-channels") - { - my $errStr = "\nAvailable Channels for $settings{FrequencyTable}:\n"; - foreach my $name (sort { $a <=> $b } keys %{$CHANLIST{$settings{FrequencyTable}}}) - { - $errStr .= "$name\t= $CHANLIST{$settings{FrequencyTable}}->{$name}\n"; - } - print "$versionStr\n$errStr"; - exit 0; - } - elsif ($option =~ /^(no-record)$/) - { - $settings{DontRecord} = 1; - } - elsif ($option =~ /^(S|save)$/) - { - $settings{UpdateConfigFile} = 1; - } - elsif ($option =~ /^(P|profile)$/) - { - @profileNames = @{$opts{$option}}; - } - elsif ($option =~ /^(v|version)$/) - { - print "$versionStr\n"; - exit 0; - } - elsif ($option =~ /^(h|help)$/) - { - usage(0, ""); - } - elsif ($option =~ /^(list-inputs|list-standards)$/) - { - # do nothing for now since they will be handled later. - } - - else - { - usage(1, "-$option is an unknown option!"); - } - } -} - -if (@profileNames) -{ - # loop over all profiles the user specified. - foreach my $profileName (@profileNames) - { - print "profile = '$profileName'\n" if $settings{Debug}; - # for now the profile can not be "defaults". - if ($profileName eq "defaults") - { - error(1, "Profile = '$profileName' is invalid!"); - } - if (exists $configIni{$profileName}) - { - # update defaults/override command line arguments that exist in this profile. - my $profileUpdating = (((exists $opts{S} || exists $opts{save}) && @profileNames == 1) ? 1 : 0); - my $profile = $profileName; - - foreach my $arg (keys %mappings) - { - foreach my $option (split(/\|/, $mappings{$arg})) # handle the long/short command option versions - { - #print "arg = '$arg', option = '$option'\n" if $settings{Debug}; - if (exists $configIni{$profile}{$arg} && !($profileUpdating && exists $opts{$option})) - { - $settings{$arg} = $configIni{$profile}{$arg}; - print "settings{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug}; - last; - } - } - } - } - else - { - if ($settings{UpdateConfigFile} && @profileNames == 1) - { - print "Warning: Profile = '$profileName' will be created.\n" if ($settings{Debug}); - } - else - { - error(1, "Profile = '$profileName' does not exist! You must specify -S/--save to create it."); - } - } - } -} - -# verify input - -if (@ARGV) -{ - if (exists $opts{c} || exists $opts{channel}) - { - print "Warning: ignoring channel argument and using '$ARGV[0]' instead.\n"; - } - $settings{Channel} = $ARGV[0]; -} - -if (!$settings{DontRecord}) -{ - print "RecordDuration = $settings{RecordDuration}\n" if $settings{Debug}; - - if ($settings{VideoType} !~ /^(mpeg|yuv)$/) - { - error(1, "Video Type = '$settings{VideoType}' is invalid!"); - } - if ($settings{VideoType} eq "yuv") - { - # see if we need to change our defaults. - if (!exists $opts{o} && !exists $opts{output}) - { - $settings{OutputFileName} = "video.yuv"; - } - if (!exists $opts{d} && !exists $opts{input}) - { - if ( -e "/dev/.devfsd" ) - { - $settings{VideoDevice} = "/dev/v4l/yuv0"; - } - else - { - $settings{VideoDevice} = "/dev/yuv0"; - } - } - } -} - -if ( ! -c "$settings{VideoDevice}") -{ - error(1, "Video Dev = '$settings{VideoDevice}' is invalid! $!"); -} - -# now that the video device has been semi validated, we can use it to lookup -# the inputs, standards, etc. and use that for validating some of the following -# pieces of user input. -sysopen($tuner, $settings{VideoDevice}, O_RDWR) or die "Error unable to open '$settings{VideoDevice}': $!"; -my $tunerFD = fileno($tuner); - -# get the current capabilities. -@capabilities = $ivtvObj->getCapabilities($tunerFD); -if (@capabilities != keys %{$ivtvObj->{capIndexes}}) -{ - error(1, "getCapabilities() failed!"); -} -if ($capabilities[$ivtvObj->{capIndexes}{driver}] ne "ivtv") -{ - $settings{UsingIvtvDriver} = 0; # we can't use the ivtv "enhancements". - print "Warning: V4l2 driver = '$capabilities[$ivtvObj->{capIndexes}{driver}]' does not support the ivtv \"enhancements\"!\n"; - print " All codec related options will be ignored.\n\n"; -} - -my $i; - -# get the current video standard -$std = $ivtvObj->getStandard($tunerFD); -if ($std > 0) -{ - printf("Standard: 0x%08x\n",$std) if ($settings{Debug}); -} -else -{ - die "Error: getStandard() failed!\n"; -} - -# get the current input -$curinput = $ivtvObj->getInput($tunerFD); -if ($curinput < 0) -{ - die "Error: getInput() failed!\n"; -} -printf("Input: 0x%08x\n",$curinput) if ($settings{Debug}); - -my $done=0; -# Standards -for ($i=0; !$done; ++$i) -{ - my($index,$std_id,$name,$frameperiod_n,$frameperiod_d,$framelines) = $ivtvObj->enumerateStandard($tunerFD, $i); - if ($index == -1) - { - $done = 1; - } - else - { - printf("%d 0x%08x %s %d/%d %d\n",$index,$std_id,$name,$frameperiod_n,$frameperiod_d,$framelines) if ($settings{Debug}); - push @standards, [($name,$std_id)]; - $name2std{$name} = $std_id; - if( (($std_id & $std) == $std)) - { - $curstd = $name; - $curStandard = $std; - } - } -} - -if (exists $opts{'list-standards'}) -{ - print "$versionStr\n"; - print "Available Video Standards:\n"; - foreach my $standard (@standards) - { - print "$standard->[0]\n"; - } - exit 0; -} - -$done=0; -# Inputs -for ($i=0; !$done; ++$i) -{ - my($index,$name,$type,$audioset,$tuner,$std,$status) = $ivtvObj->enumerateInput($tunerFD, $i); - if ($index == -1) - { - $done = 1; - } - else - { - push @inputs, $name; - $name2input{$name} = $index; - } -} -$curinputName = $inputs[$curinput]; - -if (exists $opts{'list-inputs'}) -{ - print "$versionStr\n"; - print "Available Inputs:\n"; - my $counter = 0; - foreach my $input (@inputs) - { - print "$counter: $input\n"; - $counter++; - } - exit 0; -} - -if ($settings{UsingIvtvDriver}) -{ - # get the current Codec Info - @codecInfo = $ivtvObj->getCodecInfo($tunerFD); - if (@codecInfo != keys %{$ivtvObj->{codecIndexes}}) - { - error(1, "getCodecInfo() failed!"); - } - @newCodecInfo = $ivtvObj->getCodecInfo($tunerFD); - if (@newCodecInfo != keys %{$ivtvObj->{codecIndexes}}) - { - error(1, "getCodecInfo() failed!"); - } -} - -# finish validating the user input. - -if (!$settings{DontRecord}) -{ - if ($settings{RecordDuration} !~ /^(\d+)$/) - { - error(1, "Time = '$settings{RecordDuration}' is invalid!"); - } - - if ( ! -d "$settings{OutputDirectory}") - { - error(1, "Directory = '$settings{OutputDirectory}' is invalid! $!"); - } - - # assume for now we are only generating mpeg files. -# if (($settings{VideoType} eq "mpeg" && $settings{OutputFileName} !~ /^.+\.mpg$/) || ($settings{VideoType} eq "yuv" && $settings{OutputFileName} !~ /^.+\.yuv$/)) -# { -# error(1, "Output = '$settings{OutputFileName}' is invalid!"); -# } -# - if ($settings{DateTimeFormatString} !~ /^(\+((\%.)|.)+)$/) - { - usage(1, "Date Format String = '$settings{DateTimeFormatString}' is invalid!"); - } -} - -if ($settings{VideoWidth} !~ /^(\d+)$/) -{ - error(1, "Width = '$settings{VideoWidth}' is invalid!"); -} - -if ($settings{VideoHeight} !~ /^(\d+)$/) -{ - error(1, "Height = '$settings{VideoHeight}' is invalid!"); -} - -if (!exists $name2std{$settings{VideoStandard}}) -{ - my $validStandards = join(", ", keys(%name2std)); - error(1, "Video Standard = '$settings{VideoStandard}' is invalid!\nValid Standards are: $validStandards"); -} - -if (exists $opts{i} || exists $opts{inputnum}) -{ - if ($settings{InputNum} < 0 || $settings{InputNum} >= scalar(@inputs)) - { - error(1, "Video Input = '$settings{InputNum}' is invalid!\nValid Inputs are from 0 - " . int(scalar(@inputs) - 1)); - } - $settings{InputName} = $inputs[$settings{InputNum}]; -} - -if ((exists $opts{I} || exists $opts{inputname}) && !(exists $opts{i} || exists $opts{inputnum})) -{ - if (!exists $name2input{$settings{InputName}}) - { - my $validInputs = join(", ", @inputs); - error(1, "Video Input Name = '$settings{InputName}' is invalid!\nValid Input Names are: $validInputs"); - } - $settings{InputNum} = $name2input{$settings{InputName}}; -} - -if (!exists $CHANLIST{$settings{FrequencyTable}}) -{ - error(1, "Frequency Table = '$settings{FrequencyTable}' is invalid!"); -} - -# only validate the channel if the input is a tuner. -if ($inputs[$settings{InputNum}] =~ /Tuner/) -{ - if ($settings{TunerNum} !~ /^(\d)$/) - { - error(1, "TunerNum = '$settings{TunerNum}' is invalid!"); - } - if (exists $opts{F} || exists $opts{frequency} || $settings{Frequency}) # the user may have specified a Frequency in their config file - { - if ($settings{Frequency} !~ /^(\d+)$/) - { - error(1, "Frequency = '$settings{Frequency}' is invalid!"); - } - $settings{Channel} = "freq-$settings{Frequency}"; # make sure we output the channel part. - } - # now verify that the channel exists in the frequency table! - else - { - if (!$settings{Channel}) - { - error(1, "channel = '$settings{Channel}' is invalid!"); - } - # first verify the freqency table is appropriate for the standard (NTSC, PAL, SECAM), - # unless they specified the frequency to tune to. - if ($settings{FrequencyTable} !~ /^(custom|$settings{VideoStandard})/i) - { - error(1, "You specified Video Standard '$settings{VideoStandard}' which is incompatible with Frequency Table '$settings{FrequencyTable}'!"); - } - if (!exists $CHANLIST{$settings{FrequencyTable}}->{$settings{Channel}}) - { - error(1, "Channel = '$settings{Channel}' does not exist in Frequency Table '$settings{FrequencyTable}'!"); - } - } - - # get the current channel/frequency value. - my $Frequency; - if(($Frequency = $ivtvObj->getFrequency($tunerFD, $settings{TunerNum})) >= 0) - { - my $freq = ($Frequency * 1000) / 16; - print "freq = $freq\n" if ($settings{Debug}); - # find the associated channel. - if ((!exists $opts{F} && !exists $opts{frequency} && !$settings{Frequency}) && ($curstd eq $settings{VideoStandard}) ) - { - foreach my $chan (keys %{$CHANLIST{$settings{FrequencyTable}}}) - { - if ($CHANLIST{$settings{FrequencyTable}}->{$chan} == $freq) - { - $curChannel = $chan; - } - } - print "curChannel = $curChannel\n" if ($settings{Debug}); - } - else - { - $curFrequency = $freq; - } - } - else - { - die "Error: getFrequency() failed!\n"; - } -} -else -{ - # set the channel = "" so we know to ignore it. - $settings{Channel} = ""; -} - -if ($settings{UsingIvtvDriver}) -{ - # validate the Codec related stuff. - if ($settings{Bitrate} < $settings{minBitrate} || $settings{Bitrate} > $settings{maxBitrate}) - { - error(1, "Bitrate = '$settings{Bitrate}' is invalid!"); - } - if ($settings{PeakBitrate} <= $settings{Bitrate}) - { - error(1, "PeakBitrate can not be less than or equal to Bitrate!"); - } - elsif ($settings{PeakBitrate} < $settings{minPeakBitrate} || $settings{PeakBitrate} > $settings{maxPeakBitrate}) - { - error(1, "PeakBitrate = '$settings{PeakBitrate}' is invalid!"); - } - - if ($settings{VideoStandard} !~ /^(NTSC)/) - { - my $warn = 0; - if ($settings{Framerate} == 0) - { - $settings{Framerate} = 1; - $warn = 1; - } - if ($settings{FramesPerGOP} == 15) - { - $settings{FramesPerGOP} = 12; - $warn = 1; - } - if ($warn) - { - print "Warning: Setting Framerate/FramesPerGOP to PAL settings for Video Standard '$settings{VideoStandard}'!\n\nYou should either specify on the command line or in the ~/.ivtvrc config file.\n"; - } - } - elsif ($settings{VideoStandard} =~ /^(NTSC)/) - { - my $warn = 0; - if ($settings{Framerate} == 1) - { - $settings{Framerate} = 0; - $warn = 1; - } - if ($settings{FramesPerGOP} == 12) - { - $settings{FramesPerGOP} = 15; - $warn = 1; - } - if ($warn) - { - print "Warning: Setting Framerate/FramesPerGOP to NTSC settings for Video Standard '$settings{VideoStandard}'!\n\nYou should either specify on the command line or in the ~/.ivtvrc config file.\n"; - } - } - - if ($settings{SetMSPMatrix} !~ /^(0|1)$/) - { - error(1, "SetMSPMatrix = '$settings{SetMSPMatrix}' is invalid! It can only be 0 or 1."); - } - if ($settings{MSPInput} < 1 || $settings{MSPInput} > 8) - { - error(1, "MSPInput = '$settings{MSPInput}' is invalid! It can only be 1 - 8."); - } - if ($settings{MSPOutput} < 0 || $settings{MSPOutput} > 3) - { - error(1, "MSPOutput = '$settings{MSPOutput}' is invalid! It can only be 0 - 3."); - } -} - -# update the config file if the user wants us to. -if ($settings{UpdateConfigFile}) -{ - my $profile; - if (@profileNames > 1) - { - print "Warning: Not updating config file as you have more than 1 profile specified!\n"; - } - elsif (@profileNames == 1) - { - $profile = $profileNames[0]; - } - else - { - $profile = "defaults"; - } - if ($profile) - { - my $createProfile = (exists $configIni{$profile} ? 0 : 1); - print "Creating Profile = '$profile': $createProfile\n" if ($settings{Debug}); - - if (!$settings{UseConfigFile}) - { - # we have to create the config file and tie to it. - tie %configIni, 'Config::IniFiles', () or die "Error: Initializing config file '$settings{ConfigFileName}' failed! $!\n"; - - # now set the name to work with. - tied(%configIni)->SetFileName($settings{ConfigFileName}) or die "Error: Setting config file to '$settings{ConfigFileName}' failed! $!\n"; - - $configIni{$profile} = {}; # make sure the section exists. - } - - foreach my $arg (keys %mappings) - { - foreach my $option (split(/\|/, $mappings{$arg})) # handle the long/short command option versions - { - if (exists $configIni{$profile}{$arg} || $createProfile || exists $opts{$option}) - { - $configIni{$profile}{$arg} = $settings{$arg}; - print "configIni{$profile}{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug}; - last; - } - } - } - - # write the config file out. - tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed! $!\n"; - } -} - -# this hash keeps track of those values I have to set back. -my %changedSettings = ( - resolution => 0, - standard => 0, - VideoType => 0, - InputNum => 0, - Channel => 0, - Frequency => 0, - codec => 0, - ); - -my $directoryName; -if (!$settings{DontRecord}) -{ - # make directory - #$directoryName = formatDirectoryString(); - #$result=`mkdir -p $directoryName`; - $directoryName = $settings{DirectoryFormatString}; -} - -# change the channel -if ($inputs[$settings{InputNum}] =~ /Tuner/) -{ - if (exists $opts{F} || exists $opts{frequency} || $settings{Frequency}) - { - if ($settings{Frequency} != $curFrequency) - { - $changedSettings{Frequency} = 1; - tuneFrequency($settings{Frequency}); - } - } - else - { - if ($curstd ne $settings{VideoStandard}) - { - # we have to set the channel regardless. - # but we want to tune back to the previous frequency. - $changedSettings{Frequency} = 1; - changeChannel($settings{Channel}); - } - elsif ($settings{Channel} ne $curChannel) - { - # otherwise we just changeChannel and restore the previous channel. - $changedSettings{Channel} = 1; - changeChannel($settings{Channel}); - } - } -} - -# set the video standard -if ($settings{VideoStandard} ne $curstd) -{ - $changedSettings{standard} = 1; - change_standard(); - - # see if we have to re-program the msp matrix - if ($settings{UsingIvtvDriver}) - { - if ($settings{SetMSPMatrix}) - { - print "Setting msp matrix: input = $settings{MSPInput}, output = $settings{MSPOutput}\n" if $settings{Debug}; - sleep ($settings{MSPSleep}); # sleep for 2 seconds to let card settle down. - $result = $ivtvObj->mspMatrixSet($tunerFD, $settings{MSPInput}, $settings{MSPOutput}); - if (not defined $result) - { - die "Error calling mspMatrixSet!\n"; - } - if (!$result) - { - die "Error in mspMatrixSet ioctl call!\n"; - } - } - } -} - -# set the input -if ($settings{InputNum} != $curinput || $settings{InputName} ne $curinputName) -{ - $changedSettings{InputNum} = 1; - if (!(exists $opts{i} || exists $opts{inputnum} || exists $opts{I} || exists $opts{inputname})) # our defaults are different than the current values! - { - ## print "Warning: Changing input from $curinputName to $settings{InputName}\n"; - &writelog("tvrecording: Changing input from $curinputName to $settings{InputName}"); - } - change_input(); -} - -# set the capture type - -# store the current width,height so we can restore afterwards -my ($oldWidth, $oldHeight) = $ivtvObj->getResolution($tunerFD); -print "oldWidth = '$oldWidth', oldHeight = '$oldHeight'\n" if ($settings{Debug}); - -if ($settings{VideoWidth} != $oldWidth || $settings{VideoHeight} != $oldHeight) -{ - $changedSettings{resolution} = 1; -} - -# specify the width,height to capture -if ($changedSettings{resolution}) -{ - $result = $ivtvObj->setResolution($tunerFD, $settings{VideoWidth}, $settings{VideoHeight}); - if (not defined $result) - { - die "Error calling setResolution!\n"; - } - if (!$result) - { - die "Error in setResolution ioctl call!\n"; - } -} - -if ($settings{UsingIvtvDriver}) -{ - # specify the codec options to capture mpeg's at. - foreach my $codecName (keys %codecMappings) - { - my $codecIndex = $ivtvObj->{codecIndexes}{$codecMappings{$codecName}}; - if ($codecInfo[$codecIndex] != $settings{$codecName}) - { - $changedSettings{codec} = 1; - $newCodecInfo[$codecIndex] = $settings{$codecName}; - print "new $codecName = '$settings{$codecName}', old $codecName = '$codecInfo[$codecIndex]'\n" if $settings{Debug}; - } - } -} - -if ($changedSettings{codec}) -{ - $result = $ivtvObj->setCodecInfo($tunerFD, @newCodecInfo); - if (!$result) - { - die "Error calling setCodecInfo()!\n"; - } -} - -if (!$settings{DontRecord}) -{ - # capture the video/audio to video.mpg - #print "directoryName:$directoryName, RecordDuration:$settings{RecordDuration},OutputFileName:$settings{OutputFileName}:tuner:$tuner ,OutputMPGFileName:$settings{OutputMPGFileName} \n"; - #directoryName:, RecordDuration:60,OutputFileName:/tv/JOAX-20040615-1411-000.MPG:tuner:GLOB(0x8224838) ,OutputMPGFileName: - captureVideo(directoryName => $directoryName, RecordDuration => $settings{RecordDuration}, - OutputFileName => $settings{OutputFileName}, tuner => $tuner ,OutputMPGFileName => $settings{OutputMPGFileName}); -} - -if ($settings{ResetCardSettings} && !$settings{DontRecord}) -{ - # restore Codec values - if ($changedSettings{codec}) - { - $result = $ivtvObj->setCodecInfo($tunerFD, @codecInfo); - if (!$result) - { - die "Error calling setCodecInfo()!\n"; - } - } - - # restore the previous width,height settings - if ($changedSettings{resolution}) - { - $result = $ivtvObj->setResolution($tunerFD, $oldWidth, $oldHeight); - if (not defined $result) - { - die "Error calling setResolution!\n"; - } - if (!$result) - { - die "Error in setResolution ioctl call!\n"; - } - } - - # restore the previous input setting - if ($changedSettings{InputNum}) - { - # reset back to the old input name - $settings{InputName} = $curinputName; - change_input(); - } - - # restore the previous video standard - if ($changedSettings{standard}) - { - $settings{VideoStandard} = $curstd; - change_standard(); - - # see if we have to re-program the msp matrix - if ($settings{UsingIvtvDriver}) - { - if ($settings{SetMSPMatrix}) - { - print "Setting msp matrix: input = $settings{MSPInput}, output = $settings{MSPOutput}\n" if $settings{Debug}; - sleep ($settings{MSPSleep}); # sleep for 2 seconds to let card settle down. - $result = $ivtvObj->mspMatrixSet($tunerFD, $settings{MSPInput}, $settings{MSPOutput}); - if (not defined $result) - { - die "Error calling mspMatrixSet!\n"; - } - if (!$result) - { - die "Error in mspMatrixSet ioctl call!\n"; - } - } - } - } - - # restore the previous channel - if ($changedSettings{Channel}) - { - changeChannel($curChannel); - } - if ($changedSettings{Frequency}) - { - tuneFrequency($curFrequency); - } -} - -# close the tuner device -close($tuner); - - -exit 0; - -# usage(returnValue, ErrorString) -# returnValue = 1 or 0 -# ErrorString = message you want to tell the user, but only if returnValue = 1. -sub usage -{ - my $errorCode = shift; - my $error = shift; - - print $usageStr; - print "\nError: $error\n" if ($errorCode == 1); - print "$error\n" if ($errorCode == 2); - - exit $errorCode; -} - -# error(returnValue, ErrorString) -# returnValue = 1 or 0 -# ErrorString = message you want to tell the user. -sub error -{ - my $errorCode = shift; - my $error = shift; - - print "$versionStr"; - print "\nError: $error\n"; - - exit $errorCode; -} - -# changes the input to $settings{InputNum} as long as it isn't = $curinput -sub change_input { - my $preinput = $name2input{$settings{InputName}}; - if($preinput != $curinput) - { - $curinput = $preinput; - print "input now $settings{InputName}, #$preinput\n" if ($settings{Debug}); - my $result = $ivtvObj->setInput($tunerFD, $preinput); - if (!$result) - { - die "Error: setInput($preinput) failed!\n"; - } - } -} - -# changes the video standard to $settings{VideoStandard} as long as it isn't = $curstd -sub change_standard { - my $standard = $name2std{$settings{VideoStandard}}; - if($standard != $curStandard) - { - $curStandard = $standard; - print "standard now $settings{VideoStandard}, #$standard\n" if ($settings{Debug}); - my $result = $ivtvObj->setStandard($tunerFD, $standard); - if (!$result) - { - die "Error: setStandard($standard) failed!\n"; - } - } -} - -# changes the channel -# takes the channel to change -sub changeChannel -{ - my $ch = shift; - my $freq = $CHANLIST{$settings{FrequencyTable}}->{$ch}; - my $driverf = ($freq * 16)/1000; - - print "Ch.$ch: $freq $driverf\n" if ($settings{Debug}); - - if (!$ivtvObj->setFrequency($tunerFD, $settings{TunerNum}, $driverf)) - { - die "Error: changeChannel($ch) failed!\n"; - } -} - -# tunes to the specified frequency -# takes the frequency to tune to -sub tuneFrequency -{ - my $freq = shift; - my $driverf = ($freq * 16)/1000; - - print "freq: $freq $driverf\n" if ($settings{Debug}); - - if (!$ivtvObj->setFrequency($tunerFD, $settings{TunerNum}, $driverf)) - { - die "Error: tuneFrequency($freq) failed!\n"; - } -} - -my $done = 0; - -sub catch_alarm { - $done = 1; -} -sub get_next_file_name -{ - - my $file_name = shift(@_); - $file_name =~ m/^(.+?)\-(\d{4})(\d{2})(\d{2})\-(\d{2})(\d{2})\-(\d{3})\.(.+?)$/; - - my $station = $1; - my $year = $2; - my $month = $3; - my $day = $4; - my $hour = $5; - my $min = $6; - my $seq = $7; - my $ext = $8; - $seq++; - my $new_file_name = sprintf("%s-%04d%02d%02d-%02d%02d-%03d.%s", - $station,$year,$month,$day,$hour,$min,$seq,$ext); - return $new_file_name -} - -# does the actual video capturing work. -# takes directoryName, RecordDuration, OutputFileName, tuner -sub captureVideo -{ - my %args = ( @_ ); - my $directoryName = $args{directoryName}; - my $RecordDuration = $args{RecordDuration}; - my $OutputFileName = $args{OutputFileName}; - my $tuner = $args{tuner}; - my $fname = "$directoryName/$OutputFileName"; -# "OutputMPGFileName" => "outputmpgfilename", -# my $OutputFileName = $args{OutputMPGFileName}; - my $OutputFileName = $args{OutputFileName}; -# my $fname = "$directoryName/$OutputFileName"; - my $fname = $args{OutputFileName}; - - - # setup global variables, signal handlers, etc. - - $SIG{ALRM} = \&catch_alarm; - $SIG{INT} = \&catch_alarm; # handle Ctrl-C - - # turn off file buffering. - #$|=1; - - # open the file for writing. - - - - sysopen(OUTPUT, "$fname", O_CREAT | O_WRONLY | O_LARGEFILE) or die "Error creating file '$fname': $!\n"; - - alarm($RecordDuration); - my $buf = ""; - my $len = 0; - while (!$done && read($tuner, $buf, 16384)) - { - $len += length($buf); -# if ($len >= $max_file_size ) -# { -# close(OUTPUT); -# $OutputFileName = get_next_file_name($OutputFileName); -## $fname = "$directoryName/$OutputFileName"; -# $fname = "$OutputFileName"; -# &writelog("tvrecording switch next clip.$fname"); -# sysopen(OUTPUT, "$fname", O_CREAT | O_WRONLY | O_LARGEFILE) -# or die "Error creating file '$fname': $!\n"; -# $len = 0; -# } - - # read from the device and write to the file. - print OUTPUT $buf; - } - - # close the file - close(OUTPUT); - - #$|=0; # turn file buffering back on. -} - -# returns the formatted directory string -sub formatDirectoryString -{ - my $temp = $settings{DirectoryFormatString}; - my $result = $settings{OutputDirectory}; - my %lookupTable = ( - "d" => `/bin/date "$settings{DateTimeFormatString}"`, - "I" => $settings{InputName}, - "c" => $settings{Channel}, - ); - - # fixup the InputName value - $lookupTable{I} =~ s/\s/_/g; - # cleanup the trailing slash on the date - chomp $lookupTable{d}; - - foreach my $option ("d", "I", "c") - { - $temp =~ s/\%$option/$lookupTable{$option}/g; - } - - $result .= "/" . ($temp ? "$temp/" : ""); - - return $result; -} - - - - - + +sub callrecordv4l{ + +#$frequency = `ivtv-tune -d $recdevice -t $frequencyTable -c $ivtvrecch | awk '{print $2}'|tr -d .`; +my $ivtvtuneftype = ''; +if ($frequencyTable eq "ntsc-cable-jp"){ + $ivtvtuneftype = 'japan-cable'; +}else{ + $ivtvtuneftype = 'japan-bcast'; +} +#print "ivtv-tune -d $recdevice -t $ivtvtuneftype -c $ivtvrecch\n"; +&writelog("tvrecording DEBUG ivtv-tune -d $recdevice -t $ivtvtuneftype -c $ivtvrecch"); +&writelog("tvrecording DEBUG $ENV{PATH}"); + +$frequency = `env PATH=PATH=/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/bin:/usr/bin:/home/foltia/bin ivtv-tune -d $recdevice -t $ivtvtuneftype -c $ivtvrecch`; +&writelog("tvrecording DEBUG frequency:$frequency"); +@frequency = split(/\s/,$frequency); +$frequency[1] =~ s/\.//gi; +$frequency = $frequency[1] ; +&writelog("tvrecording DEBUG frequency:$frequency"); + +my $recordv4lcallstring = "$toolpath/perl/record-v4l2.pl --frequency $frequency --duration $reclengthsec --input $recdevice --directory $recfolderpath --inputnum $capturedeviceinputnum --inputname '$capturedeviceinputName' --freqtable $frequencyTable --bitrate $stdbitrate --peakbitrate $peakbitrate --output $outputfilewithoutpath "; + +&writelog("tvrecording $recordv4lcallstring"); +&writelog("tvrecording DEBUG $ENV{HOME}/.ivtvrc"); +$oserr = `env HOME=$toolpath $recordv4lcallstring`; +&writelog("tvrecording DEBUG $oserr"); + +}#end callrecordv4l + Index: trunk/install/perl/addpidatq.pl =================================================================== --- trunk/install/perl/addpidatq.pl (リビジョン 1) +++ trunk/install/perl/addpidatq.pl (リビジョン 83) @@ -47,22 +47,39 @@ if ($titlecount[0] == 1 ){ -$DBQuery = "SELECT bitrate FROM foltia_tvrecord , foltia_subtitle WHERE foltia_tvrecord.tid = foltia_subtitle.tid AND pid='$pid' "; +$DBQuery = "SELECT bitrate,digital FROM foltia_tvrecord , foltia_subtitle WHERE foltia_tvrecord.tid = foltia_subtitle.tid AND pid='$pid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); @titlecount= $sth->fetchrow_array; $bitrate = $titlecount[0];#ビットレート取得 +if ($titlecount[1] >= 1){ + $usedigital = $titlecount[1];#デジタル優先フラグ +}else{ + $usedigital = 0; +} #PID抽出 $now = &epoch2foldate(`date +%s`); -$DBQuery = "SELECT stationrecch FROM foltia_station,foltia_subtitle WHERE foltia_subtitle.pid = '$pid' AND foltia_subtitle.stationid = foltia_station.stationid "; +#stationIDからrecch +$DBQuery = "SELECT stationrecch,digitalch ,digitalstationband ,foltia_station.stationid FROM foltia_station,foltia_subtitle WHERE foltia_subtitle.pid = '$pid' AND foltia_subtitle.stationid = foltia_station.stationid "; - -#stationIDからrecch $stationh = $dbh->prepare($DBQuery); $stationh->execute(); @stationl = $stationh->fetchrow_array; $recch = $stationl[0]; - +if ($recch eq ""){ + &writelog("addpidatq ERROR recch is NULL:$DBQuery."); + exit 1; +} +if ($stationl[1] => 1){ + $digitalch = $stationl[1]; +}else{ + $digitalch = 0; +} +if ($stationl[2] => 1){ + $digitalstationband = $stationl[2]; +}else{ + $digitalstationband = 0; +} $DBQuery = "SELECT * FROM foltia_subtitle WHERE pid='$pid' "; $sth = $dbh->prepare($DBQuery); @@ -109,11 +126,11 @@ } -Schedule::At::add (TIME => "$atdateparam", COMMAND => "$toolpath/perl/recwrap.pl $recch $reclength $bitrate $tid $countno $pid" , TAG => "$pid"."_R"); - &writelog("addpidatq TIME $atdateparam COMMAND $toolpath/perl/recwrap.pl $recch $reclength $bitrate $tid $countno $pid"); +Schedule::At::add (TIME => "$atdateparam", COMMAND => "$toolpath/perl/recwrap.pl $recch $reclength $bitrate $tid $countno $pid $stationid $usedigital $digitalstationband $digitalch" , TAG => "$pid"."_R"); + &writelog("addpidatq TIME $atdateparam COMMAND $toolpath/perl/recwrap.pl $recch $reclength $bitrate $tid $countno $pid $stationid $usedigital $digitalstationband $digitalch"); }#end #もし新開始時刻が15分移譲先なら再キュー }else{ -&writelog("addpidatq drop:expire $pid $startafter $now $startdatetime"); +&writelog("addpidatq drop:expire $pid $startafter $now $startdatetime"); }#放送が未来の日付なら Index: trunk/install/perl/ipodtranscode.pl =================================================================== --- trunk/install/perl/ipodtranscode.pl (リビジョン 70) +++ trunk/install/perl/ipodtranscode.pl (リビジョン 83) @@ -1,14 +1,10 @@ #!/usr/bin/perl -#usage ipodtranscode.pl /path/to/mpeg2.m2p mp4filenamestring /path/to/mpeg2/tid.localized/mp4/ PID [aspect] +#usage ipodtranscode.pl # # Anime recording system foltia # http://www.dcc-jpl.com/soft/foltia/ # -# # iPod MPEG4/H.264トラコン # ffmpegを呼び出して変換 -# ffmpegはiPodパッチあて版を想定している -# ffmpegの作り方は -# http://www.dcc-jpl.com/diary/ddata2006/02A.html#20060215-00 # # DCC-JPL Japan/foltia project @@ -18,5 +14,4 @@ use DBD::Pg; use Jcode; - $path = $0; @@ -25,19 +20,17 @@ push( @INC, "$path"); } - require "foltialib.pl"; -#引き数がアルか? -$recch = $ARGV[0] ; -if ($recch eq "" ){ - #引き数なしで実行されたら、終了 - print "usage ipodtranscode.pl /path/to/mpeg2.m2p mp4filenamestring /path/to/mpeg2/tid.localized/mp4/ PID [aspect]\n"; - exit; -} - -$inputmpeg2 = $ARGV[0]; -$mp4filenamestring = $ARGV[1]; -$mp4outdir = $ARGV[2]; -$pid = $ARGV[3]; -$aspect = $ARGV[4]; + + +# 二重起動の確認! +$processes = &processfind("ipodtranscode.pl"); +#$processes = $processes + &processfind("ffmpeg"); + +if ($processes > 1 ){ +&writelog("ipodtranscode processes exist. exit:"); +exit; +}else{ +#&writelog("ipodtranscode.pl Normal launch."); +} #DB初期化 @@ -46,5 +39,49 @@ $dbh = DBI->connect($data_source,$DBUser,$DBPass) ||die $DBI::error;; - +# タイトル取得 +#トラコンフラグがたっていてステータス50以上150未満のファイルを古い順にひとつ探す +# 数数える +#$DBQuery = "SELECT count(*) FROM foltia_subtitle, foltia_program, foltia_m2pfiles +#WHERE filestatus >= $FILESTATUSRECEND AND filestatus < $FILESTATUSTRANSCODECOMPLETE AND foltia_program.tid = foltia_subtitle.TID AND foltia_program.PSP = 1 AND foltia_m2pfiles.m2pfilename = foltia_subtitle.m2pfilename "; +#$sth = $dbh->prepare($DBQuery); +#$sth->execute(); +#@titlecount= $sth->fetchrow_array; +&writelog("ipodtranscode starting up."); + +$counttranscodefiles = &counttranscodefiles(); +if ($counttranscodefiles == 0){ + &writelog("ipodtranscode No MPEG2 files to transcode."); + exit; +} +sleep 30; + +while ($counttranscodefiles >= 1){ + +$DBQuery = "SELECT foltia_subtitle.pid,foltia_subtitle.tid,foltia_subtitle.m2pfilename,filestatus,foltia_program.aspect ,foltia_subtitle.countno +FROM foltia_subtitle, foltia_program, foltia_m2pfiles +WHERE filestatus >= $FILESTATUSRECEND AND filestatus < $FILESTATUSTRANSCODECOMPLETE AND foltia_program.tid = foltia_subtitle.TID AND foltia_program.PSP = 1 AND foltia_m2pfiles.m2pfilename = foltia_subtitle.m2pfilename +ORDER BY enddatetime ASC +LIMIT 1 "; + +$sth = $dbh->prepare($DBQuery); +$sth->execute(); +@dbparam = $sth->fetchrow_array; +#print "$dbparam[0],$dbparam[1],$dbparam[2],$dbparam[3],$dbparam[4],$dbparam[5]\n"; +&writelog("ipodtranscode DEBUG $DBQuery"); +&writelog("ipodtranscode DEBUG $dbparam[0],$dbparam[1],$dbparam[2],$dbparam[3],$dbparam[4],$dbparam[5]"); +$pid = $dbparam[0]; +$tid = $dbparam[1]; +$inputmpeg2 = $recfolderpath."/".$dbparam[2]; # path付き +$mpeg2filename = $dbparam[2]; # pathなし +$filestatus = $dbparam[3]; +$aspect = $dbparam[4];# 16,1 (超額縁),4,3 +$countno = $dbparam[5]; +$mp4filenamestring = &mp4filenamestringbuild($pid); + +&writelog("ipodtranscode DEBUG mp4filenamestring $mp4filenamestring"); +#展開ディレクトリ作成 +$pspdirname = &makemp4dir($tid); +$mp4outdir = $pspdirname ; +# 実際のトラコン # タイトル取得 if ($pid ne ""){ @@ -82,38 +119,226 @@ } -# アスペクト比 -if ($aspect == 16){ -$cropopt = " -croptop 70 -cropbottom 60 -cropleft 8 -cropright 14 -aspect 1.7777 "; -}else{ -$cropopt = " -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 "; -} + +if ($filestatus <= $FILESTATUSRECEND){ +} + +if ($filestatus <= $FILESTATUSWAITINGCAPTURE){ +#なにもしない +} + +if ($filestatus <= $FILESTATUSCAPTURE){ +#unlink +# Starlight breaker向けキャプチャ画像作成 +if (-e "$toolpath/perl/captureimagemaker.pl"){ + &writelog("ipodtranscode Call captureimagemaker $mpeg2filename"); +&changefilestatus($pid,$FILESTATUSCAPTURE); + system ("$toolpath/perl/captureimagemaker.pl $mpeg2filename"); +&changefilestatus($pid,$FILESTATUSCAPEND); +} +} + +if ($filestatus <= $FILESTATUSCAPEND){ +# サムネイル作る +&makethumbnail(); +&changefilestatus($pid,$FILESTATUSTHMCREATE); +} + +if ($filestatus <= $FILESTATUSWAITINGTRANSCODE){ +} + +$filenamebody = $inputmpeg2 ; +$filenamebody =~ s/.m2t$|.ts$|.m2p$|.mpg$//gi; +#デジタルかアナログか +if ($inputmpeg2 =~ /m2t$|ts$/i){ + #print "MPEG2-TS\n"; + + +if ($filestatus <= $FILESTATUSTRANSCODETSSPLITTING){ + unlink("${filenamebody}_tss.m2t"); + unlink("${filenamebody}_HD.m2t"); +} +if ($filestatus <= $FILESTATUSTRANSCODEFFMPEG){ + + # H.264出力 + $trcnmpegfile = $inputmpeg2 ; + # アスペクト比 + if ($aspect == 1){#超額縁 + $cropopt = " -croptop 150 -cropbottom 150 -cropleft 200 -cropright 200 "; + }elsif($aspect == 4){#SD + $cropopt = " -croptop 6 -cropbottom 6 -cropleft 8 -cropright 8 "; + }else{#16:9 + $cropopt = " -croptop 6 -cropbottom 6 -cropleft 8 -cropright 8 "; + } + # クオリティごとに + if (($trconqty eq "")||($trconqty == 1)){ + $ffmpegencopt = " -s 360x202 -deinterlace -r 24.00 -vcodec libx264 -g 300 -b 330000 -level 13 -loop 1 -sc_threshold 60 -partp4x4 1 -rc_eq 'blurCplx^(1-qComp)' -refs 3 -maxrate 700000 -async 50 -f h264 $filenamebody.264"; + }elsif($trconqty == 2){ + $ffmpegencopt = " -s 480x272 -deinterlace -r 29.97 -vcodec libx264 -g 300 -b 400000 -level 13 -loop 1 -sc_threshold 60 -partp4x4 1 -rc_eq 'blurCplx^(1-qComp)' -refs 3 -maxrate 700000 -async 50 -f h264 $filenamebody.264"; + }elsif($trconqty == 3){#640x352 + $ffmpegencopt = " -s 640x352 -deinterlace -r 29.97 -vcodec libx264 -g 100 -b 600000 -level 13 -loop 1 -sc_threshold 60 -partp4x4 1 -rc_eq 'blurCplx^(1-qComp)' -refs 3 -maxrate 700000 -async 50 -f h264 $filenamebody.264"; + } + &changefilestatus($pid,$FILESTATUSTRANSCODEFFMPEG); + &writelog("ipodtranscode ffmpeg $filenamebody.264"); + system ("ffmpeg -y -i $trcnmpegfile $cropopt $ffmpegencopt"); + + #もしエラーになったらTsSplitする + if (! -e "$filenamebody.264"){ + &changefilestatus($pid,$FILESTATUSTRANSCODETSSPLITTING); + unlink("${filenamebody}_tss.m2t"); + unlink("${filenamebody}_HD.m2t"); + if (-e "$toolpath/perl/tool/tss.py"){ + &writelog("ipodtranscode tss $inputmpeg2"); + system("$toolpath/perl/tool/tss.py $inputmpeg2"); + + }else{ + # TsSplit + &writelog("ipodtranscode TsSplitter $inputmpeg2"); + system("wine $toolpath/perl/tool/TsSplitter.exe -EIT -ECM -EMM -SD -1SEG -WAIT2 $inputmpeg2"); + } + if(-e "${filenamebody}_tss.m2t"){ + $trcnmpegfile = "${filenamebody}_tss.m2t"; + }elsif (-e "${filenamebody}_HD.m2t"){ + $trcnmpegfile = "${filenamebody}_HD.m2t"; + }else{ + &writelog("ipodtranscode ERR NOT Exist ${filenamebody}_HD.m2t"); + $trcnmpegfile = inputmpeg2 ; + } + #再ffmpeg + &changefilestatus($pid,$FILESTATUSTRANSCODEFFMPEG); + &writelog("ipodtranscode ffmpeg retry $filenamebody.264"); + system ("ffmpeg -y -i $trcnmpegfile $cropopt $ffmpegencopt"); + } + #もしエラーになったらcropやめる + if (! -e "$filenamebody.264"){ + #再ffmpeg + &changefilestatus($pid,$FILESTATUSTRANSCODEFFMPEG); + &writelog("ipodtranscode ffmpeg retry no crop $filenamebody.264"); + system ("ffmpeg -y -i $trcnmpegfile $ffmpegencopt"); + } +} +if ($filestatus <= $FILESTATUSTRANSCODEWAVE){ + # WAVE出力 + unlink("${filenamebody}.wav"); + &changefilestatus($pid,$FILESTATUSTRANSCODEWAVE); + &writelog("ipodtranscode mplayer $filenamebody.wav"); + system ("mplayer $trcnmpegfile -vc null -vo null -ao pcm:file=$filenamebody.wav:fast"); + +} +if ($filestatus <= $FILESTATUSTRANSCODEAAC){ + # AAC変換 + unlink("${filenamebody}.aac"); + &changefilestatus($pid,$FILESTATUSTRANSCODEAAC); + if (-e "$toolpath/perl/tool/neroAacEnc"){ + if (-e "$filenamebody.wav"){ + &writelog("ipodtranscode neroAacEnc $filenamebody.wav"); + system ("$toolpath/perl/tool/neroAacEnc -br 128000 -if $filenamebody.wav -of $filenamebody.aac"); + }else{ + &writelog("ipodtranscode ERR Not Found $filenamebody.wav"); + } + }else{ + #print "DEBUG $toolpath/perl/tool/neroAacEnc\n\n"; + &writelog("ipodtranscode faac $filenamebody.wav"); + system ("faac -b 128 -o $filenamebody.aac $filenamebody.wav "); + } + +} +if ($filestatus <= $FILESTATUSTRANSCODEMP4BOX){ + # MP4ビルド + unlink("${filenamebody}.base.mp4"); + &changefilestatus($pid,$FILESTATUSTRANSCODEMP4BOX); + &writelog("ipodtranscode MP4Box $filenamebody"); + system ("cd $recfolderpath ; MP4Box -fps 29.97 -add $filenamebody.264 -new $filenamebody.base.mp4"); +#$exit_value = $? >> 8; +#$signal_num = $? & 127; +#$dumped_core = $? & 128; +#&writelog("ipodtranscode DEBUG MP4Box -fps 29.97 -add:$exit_value:$signal_num:$dumped_core"); + + if (-e "$filenamebody.base.mp4"){ + system ("cd $recfolderpath ; MP4Box -add $filenamebody.aac $filenamebody.base.mp4"); +#$exit_value = $? >> 8; +#$signal_num = $? & 127; +#$dumped_core = $? & 128; +#&writelog("ipodtranscode DEBUG MP4Box -add $filenamebody.aac:$exit_value:$signal_num:$dumped_core"); + }else{ + &writelog("ipodtranscode ERR File not exist.$filenamebody.base.mp4"); + } + +} + +if ($filestatus <= $FILESTATUSTRANSCODEATOM){ + unlink("${mp4outdir}MAQ${mp4filenamestring}.MP4"); + # iPodヘッダ付加 + &changefilestatus($pid,$FILESTATUSTRANSCODEATOM); + &writelog("ipodtranscode ATOM $filenamebody"); + #system ("/usr/local/bin/ffmpeg -y -i $filenamebody.base.mp4 -vcodec copy -acodec copy -f ipod ${mp4outdir}MAQ${mp4filenamestring}.MP4"); + system ("cd $recfolderpath ; MP4Box -ipod $filenamebody.base.mp4"); +$exit_value = $? >> 8; +$signal_num = $? & 127; +$dumped_core = $? & 128; +&writelog("ipodtranscode DEBUG MP4Box -ipod:$exit_value:$signal_num:$dumped_core"); + system("mv $filenamebody.base.mp4 ${mp4outdir}MAQ${mp4filenamestring}.MP4"); + &writelog("ipodtranscode mv $filenamebody.base.mp4 ${mp4outdir}MAQ${mp4filenamestring}.MP4"); +# ipodtranscode mv /home/foltia/php/tv/1329-21-20080829-0017.base.mp4 /home/foltia/php/tv/1329.localized/mp4/MAQ-/home/foltia/php/tv/1329-21-20080829-0017.MP4 + +} +if ($filestatus <= $FILESTATUSTRANSCODECOMPLETE){ + # 中間ファイル消す + &changefilestatus($pid,$FILESTATUSTRANSCODECOMPLETE); + unlink("${filenamebody}_HD.m2t"); + unlink("${filenamebody}_tss.m2t"); + unlink("$filenamebody.264"); + unlink("$filenamebody.wav"); + unlink("$filenamebody.aac"); + unlink("$filenamebody.base.mp4"); + + &updatemp4file(); + +} + +}else{ #デジタルかアナログか + #print "MPEG2\n"; + # アスペクト比 + if ($aspect == 16){ + $cropopt = " -croptop 70 -cropbottom 60 -cropleft 8 -cropright 14 -aspect 16:9 "; + }else{ + $cropopt = " -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 "; + } # クオリティごとに -if (($trconqty eq "")||($trconqty == 1)){#sample:src 106.6sec encode 82sec x0.77 382kbps @Celeron2.6GHz - -$encodeoption = "-y -i $inputmpeg2 -vcodec xvid $cropopt -s 320x240 -b 300 -bt 128 -r 14.985 -bufsize 192 -maxrate 512 -minrate 0 -deinterlace -acodec aac -ab 128 -ar 24000 -ac 2 $movietitle ${mp4outdir}M4V${mp4filenamestring}.MP4"; +if (($trconqty eq "")||($trconqty == 1)){ +#$encodeoption = "-y -i $inputmpeg2 -vcodec xvid $cropopt -s 320x240 -b 300 -bt 128 -r 14.985 -bufsize 192 -maxrate 512 -minrate 0 -deinterlace -acodec aac -ab 128 -ar 24000 -ac 2 $movietitle ${mp4outdir}M4V${mp4filenamestring}.MP4"; $mp4file = "${mp4outdir}M4V${mp4filenamestring}.MP4"; - -}elsif($trconqty == 2){ #sample:src 106.6sec encode 117sec x1.1 597kbps @Celeron2.6GHz - -$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -s 320x240 -b 300 -r 24 -acodec aac -ar 32000 -ac 2 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +$encodeoption = "-y -i $inputmpeg2 vcodec libxvid $cropopt -s 320x240 -b 300 -bt 128 -r 14.985 -deinterlace -acodec libfaac -f ipod ${mp4outdir}M4V${mp4filenamestring}.MP4"; +#time ffmpeg -y -i /home/foltia/php/tv/trcntest/nanoha-As-op.mpg -vcodec libxvid -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 -s 320x240 -b 300 -bt 128 -r 14.985 -deinterlace -acodec libfaac -f ipod M4V-Nanoha-As-OP.MP4 +# 32sec +# 2.1MB +}elsif($trconqty == 2){ +#$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -s 320x240 -b 300 -r 24 -acodec aac -ar 32000 -ac 2 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; $mp4file = "${mp4outdir}MAQ${mp4filenamestring}.MP4"; - -}elsif($trconqty == 3){ #sample:src 106.6sec encode 364sec x3.4 528kbps @Celeron2.6GHz - -$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -acodec aac -ab 96 -vcodec h264 -maxrate 700 -minrate 0 -deinterlace -b 300 -ar 32000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 320x240 -r 30000/1001 -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +$encodeoption = "-y -i $inputmpeg2 -vcodec libx264 -croptop 8 $cropopt -s 320x240 -b 300 -bt 128 -r 24 -deinterlace -acodec libfaac -f ipod ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +#time ffmpeg -y -i /home/foltia/php/tv/trcntest/nanoha-As-op.mpg -vcodec libx264 -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 -s 320x240 -b 300 -bt 128 -r 24 -deinterlace -acodec libfaac -f ipod MAQ-Nanoha-As-OP.MP4 +# 2min22sec +# 6.4MB +}elsif($trconqty == 3){ +#$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -acodec aac -ab 96 -vcodec h264 -maxrate 700 -minrate 0 -deinterlace -b 300 -ar 32000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 320x240 -r 30000/1001 -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; $mp4file = "${mp4outdir}MAQ${mp4filenamestring}.MP4"; - -}elsif($trconqty == 4){ #sample:src 106.6sec encode 239sec x2.24 1036kbps @Celeron2.6GHz - -$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -s 480x360 -b 400 -r 24 -acodec aac -ar 32000 -ac 2 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +$encodeoption = "-y -i $inputmpeg2 -vcodec libx264 $cropopt -s 320x240 -b 380 -bt 128 -r 29.97 -deinterlace -acodec libfaac -f ipod ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +#time ffmpeg -y -i /home/foltia/php/tv/trcntest/nanoha-As-op.mpg -vcodec libx264 -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 -s 320x240 -b 380 -bt 128 -r 29.97 -deinterlace -acodec libfaac -f ipod MAQ-Nanoha-As-OP.MP4 +# 2m53.912s +# 7MB +}elsif($trconqty == 4){ +#$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -s 480x360 -b 400 -r 24 -acodec aac -ar 32000 -ac 2 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; $mp4file = "${mp4outdir}MAQ${mp4filenamestring}.MP4"; - -}elsif($trconqty == 5){ #sample:src 106.6sec encode 1012sec x9.49 727kbps @Celeron2.6GHz - -$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -acodec aac -ab 96 -vcodec h264 -maxrate 700 -minrate 0 -deinterlace -b 400 -ar 32000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 480x360 -r 30000/1001 -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +$encodeoption = "-y -i $inputmpeg2 -vcodec libx264 $cropopt -s 640x480 -b 500 -maxrate 700 -bt 128 -r 29.97 -deinterlace -acodec libfaac -f ipod ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +#time ffmpeg -y -i /home/foltia/php/tv/trcntest/nanoha-As-op.mpg -vcodec libx264 -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 -s 640x480 -b 500 -maxrate 700 -bt 128 -r 29.97 -deinterlace -acodec libfaac -f ipod MAQ-Nanoha-As-OP.MP4 +# 11m0.294s +# 20MB +}elsif($trconqty == 5){ +#$encodeoption = "-y -i $inputmpeg2 -target ipod -profile 51 -level 30 $cropopt -acodec aac -ab 96 -vcodec h264 -maxrate 700 -minrate 0 -deinterlace -b 400 -ar 32000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 480x360 -r 30000/1001 -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 $movietitle ${mp4outdir}MAQ${mp4filenamestring}.MP4"; $mp4file = "${mp4outdir}MAQ${mp4filenamestring}.MP4"; -} - - +$encodeoption = "-y -i $inputmpeg2 -vcodec libx264 -croptop 8 $cropopt -s 640x480 -b 500 -maxrate 700 -bt 128 -r 29.97 -deinterlace -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 -acodec libfaac -f ipod ${mp4outdir}MAQ${mp4filenamestring}.MP4"; +#time ffmpeg -y -i /home/foltia/php/tv/trcntest/nanoha-As-op.mpg -vcodec libx264 -croptop 8 -cropbottom 8 -cropleft 8 -cropright 14 -s 640x480 -b 500 -maxrate 700 -bt 128 -r 29.97 -deinterlace -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 -acodec libfaac -f ipod MAQ-Nanoha-As-OP.MP4 +# 14m14.033s +# 18MB +} $encodeoptionlog = $encodeoption; @@ -122,9 +347,92 @@ &writelog("ipodtranscode START QTY=$trconqty $encodeoptionlog"); #print "ffmpeg $encodeoptionlog \n"; -system ("/usr/local/bin/ffmpeg $encodeoption "); +&changefilestatus($pid,$FILESTATUSTRANSCODEFFMPEG); +system ("ffmpeg $encodeoption "); &writelog("ipodtranscode FFEND $inputmpeg2"); - -&writelog("ipodtranscode mp4psp -p $mp4file $movietitleeuc"); -system("/usr/local/bin/mp4psp -p $mp4file '$movietitleeuc' "); -&writelog("ipodtranscode mp4psp COMPLETE $mp4file "); - +&changefilestatus($pid,$FILESTATUSTRANSCODECOMPLETE); +#もう要らなくなった #2008/11/14 +#&writelog("ipodtranscode mp4psp -p $mp4file $movietitleeuc"); +#system("/usr/local/bin/mp4psp -p $mp4file '$movietitleeuc' "); +#&writelog("ipodtranscode mp4psp COMPLETE $mp4file "); + +&updatemp4file(); +}#endif #デジタルかアナログか + +$counttranscodefiles = &counttranscodefiles(); +############################ +#一回で終らせるように +#exit; +}# end while +#残りファイルがゼロなら +&writelog("ipodtranscode ALL COMPLETE"); +exit; + +#----------------------------------------------------------------------- +sub mp4filenamestringbuild(){ +#ファイル名決定 +#1329-19-20080814-2337.m2t +my @mpegfilename = split(/\./,$dbparam[2]) ; +my $pspfilname = "-".$mpegfilename[0] ; +return("$pspfilname"); +}#end sub mp4filenamestringbuild + + +sub makethumbnail(){ +#サムネール +my $outputfilename = $inputmpeg2 ;#フルパス +my $thmfilename = "MAQ${mp4filenamestring}.THM"; +&writelog("ipodtranscode DEBUG thmfilename $thmfilename"); + +system ("mplayer -ss 00:01:20 -vo jpeg:outdir=$pspdirname -ao null -sstep 1 -frames 3 -v 3 $outputfilename"); + +&writelog("ipodtranscode DEBUG mplayer -ss 00:01:20 -vo jpeg:outdir=$pspdirname -ao null -sstep 1 -frames 3 -v 3 $outputfilename"); + +if (-e "$pspdirname/$thmfilename"){ +$timestamp =`date "+%Y%m%d-%H%M%S"`; +chomp $timestamp; + system("convert -crop 160x120+1+3 -resize 165x126\! $pspdirname/00000002.jpg $pspdirname/$thmfilename".$timestamp.".THM"); +}else{ + system("convert -crop 160x120+1+3 -resize 165x126\! $pspdirname/00000002.jpg $pspdirname/$thmfilename"); +} +&writelog("ipodtranscode DEBUG convert -crop 160x120+1+3 -resize 165x126\! $pspdirname/00000002.jpg $pspdirname/$thmfilename"); + +system("rm -rf $pspdirname/0000000*.jpg "); +&writelog("ipodtranscode DEBUG rm -rf $pspdirname/0000000*.jpg"); + +}#endsub makethumbnail + +sub updatemp4file(){ +my $mp4filename = "MAQ${mp4filenamestring}.MP4"; + +if (-e "${mp4outdir}MAQ${mp4filenamestring}.MP4"){ +# MP4ファイル名をPIDレコードに書き込み + $DBQuery = "UPDATE foltia_subtitle SET PSPfilename = '$mp4filename' WHERE pid = '$pid' "; + $sth = $dbh->prepare($DBQuery); + $sth->execute(); +&writelog("ipodtranscode UPDATEsubtitleDB $DBQuery"); + +# MP4ファイル名をfoltia_mp4files挿入 + $DBQuery = "insert into foltia_mp4files values ('$tid','$mp4filename') "; + $sth = $dbh->prepare($DBQuery); + $sth->execute(); +&writelog("ipodtranscode UPDATEmp4DB $DBQuery"); + +&changefilestatus($pid,$FILESTATUSALLCOMPLETE); +}else{ +&writelog("ipodtranscode ERR MP4 NOT EXIST $pid/$mp4filename"); +} + + +}#updatemp4file + +sub counttranscodefiles(){ +my $DBQuery = "SELECT count(*) FROM foltia_subtitle, foltia_program, foltia_m2pfiles +WHERE filestatus >= $FILESTATUSRECEND AND filestatus < $FILESTATUSTRANSCODECOMPLETE AND foltia_program.tid = foltia_subtitle.TID AND foltia_program.PSP = 1 AND foltia_m2pfiles.m2pfilename = foltia_subtitle.m2pfilename "; +$sth = $dbh->prepare($DBQuery); +$sth->execute(); +my @titlecount= $sth->fetchrow_array; + +return ($titlecount[0]); + + +} Index: trunk/install/perl/deletemovie.pl =================================================================== --- trunk/install/perl/deletemovie.pl (リビジョン 1) +++ trunk/install/perl/deletemovie.pl (リビジョン 83) @@ -32,5 +32,5 @@ #ファイル名正当性チェック -if ($fname =~ /.m2p\z/){ +if ($fname =~ /.m2p$|.m2t$/){ }else{ Index: trunk/install/perl/record-v4l2.pl =================================================================== --- trunk/install/perl/record-v4l2.pl (リビジョン 83) +++ trunk/install/perl/record-v4l2.pl (リビジョン 83) @@ -0,0 +1,1617 @@ +#!/usr/bin/perl +# record-v4l2.pl created by James A. Pattie 04/10/2003 +# Copyright 2003-2004 +# Purpose: to record from the specified channel for the specified amount +# of time to the video OutputDirectory under the channel-start time name as video.mpg. + +# +# You can always get the latest version of this script at +# http://www.pcxperience.org/ +# + +# 20071016 Patched by DCC-JPL Japan / foltia project / http://www.dcc-jpl.com/soft/foltia/ + +# 20030425 - 1.4 - Added devfs support based upon patch submitted by +# Jonathan Kolb +# 20030426 - 1.5 - Imported the ptune.pl functionality +# 20030426 - 1.6 - moved -F -> -L, -F now lets you specify the frequency to tune to. +# 20030427 - 1.7 - renamed to record_ivtv.pl per Kevin's request. Added -R option. +# 20030430 - 1.8 - fixing some comparisons that needed to be strings, etc. +# 20030504 - 1.9 - Migrating to Video::ivtv for video resolution support. +# 20030505 - 1.10- Replaced open w/ sysopen but it doesn't make a difference. +# Starting to replace the Standard code w/ Video::ivtv methods. +# Added the version numbers that I require to the use statements. +# 20030507 - 1.11- Migrated to using get/setFrequency from Video::ivtv 0.03. +# 20030510 - 1.12- Migrated to using get/setInput from Video::ivtv 0.04. Moved to using +# the exported method names rather than Video::ivtv::method(). +# Converted to using enumerateStandard(). +# Fixed the condition where switching Video Standards will most likely +# not get the correct channel and so would switch back with channel = 0 +# which is invalid. In this case I store the previous frequency, do the +# channel change but signal to restore the previous frequency on cleanup. +# Converted to using enumerateInput(). +# 20030512 - 1.13- Added initial support for setting the bitrate/bitrate_peak values. +# 20030513 - 1.14- Tweaked the bitrate values to be closer to real DVD bitrates. +# Added support for the .ivtvrc config file and User Profiles. +# 20030516 - 1.15- Updated to the OO interface that Video::ivtv 0.06 now requires. +# Cleaned up a lot of the global variables into a settings hash. +# Made the -S command add any config items you specified on the command line +# that were not in the Profile being updated. This way you can add new items. +# Made the config file work from a mapping hash so that we can easily add/remove +# config items in the future. +# 20030518 - 1.16- Fixed a Frequency bug that happened when changing Video Standards and the +# Frequency came from a user specified Profile. +# 20030519 - 1.17- Adding the rest of the Codec related options to the config file / defaults. +# Switched to using Getopt::Long. You can specify all config file options at +# least by a --long version and still by the original -X command option. +# Cleaned up the option parsing code to take advantage of the mappings hash. +# 20030520 - 1.18- Fixing the handling of the Profile command line option. +# 20030524 - 1.19- Cleaned up the output for -L/--list-freqtable. Changed --list -> --list-freqtable. +# Added support to detect the v4l2 driver in use and disable the ivtv "enhancements" +# if driver != "ivtv". +# Renamed to record-v4l2.pl to reflect the ability of this program to record from any +# v4l2 device but with special support for the ivtv driver. +# 20030524 - 1.20- Improving the Ctrl-C handling (cleanup before dying). It may take a second or two +# before the program exits, but it should exit after resetting anything it changed, unless +# you had specified not to reset the card. +# Allow layering of profiles by calling -P/--profile multiple times. Each profile will +# be layered over the last. You will not be able to create/update a profile if you +# specify more than one though. +# Fixed a bug that would cause a parameter from the profile to be set n times, where n was +# the number of characters in the mapping string that consisted of the single letter | and +# the long command option name. Ex: Channel has 'c|channel' so the Channel value was being +# set 9 times instead of just the first time if it was in the profile. +# 20030525 - 1.21- Fixed devfsd detection code as it was overriding what came from the config file. +# Adding --no-record option so that we can start to implement the replacement functionality for +# ptune.pl (ie. Set all values and then exit, do not reset the card and do not capture) +# 20030607 - 1.22- Adding --directory-format and --date-format options so that the user can specify the +# naming convention to use when specifying the directory the output file should be put in. +# Tweaked some of the defaults. +# Create the config file if it doesn't exist, regardless of the --save flag being specified. +# Added method error() to output an error condition that doesn't warrant the whole usage and +# converted all relevant usage() calls to error() calls. +# Added option --debug to dynamically on the fly enable debug output. +# 20030609 - 1.23- Added option --list-channels to display the currently selected frequency tables contents. +# Changed the default output directory to '.'. +# Moved $debug -> $settings{Debug} so it can be stored in the config file. This allows you to +# turn debugging on for only certain profiles, etc. +# Restructured some of the validity tests to only happen as long as we are recording since they +# do not need to be validated when we are not recording. Mainly to do with the output stuff. +# 20030610 - 1.24- Moved the tunerNum variable into the config file: TunerNum +# Added --tuner-num option to dynamically set it. +# 20030614 - 1.25- I now require Video::ivtv 0.09 to make sure everyone is using the version that fixes the known +# reported segfault issues. +# Added freqtable "custom" support so that people using the new feature in ptune-ui.pl and have +# set their default frequency table to be "custom" will just work when they specify channel X, etc. +# I'm now sorting the command line input since otherwise I can't guarantee the order options get +# processed in, but even that is wrong. I need to use Tie::IxHash, but that isn't standard. +# 20030626 - 1.26- Updated to cover the audio -> audio_bitmask changes that Video::ivtv 0.11 implemented to cover +# the ivtv_ioctl_codec structure changes. +# Implemented config file versioning so that I know when the Audio entry needs to be updated in case it +# comes back in a future version of the ivtv_ioctl_codec structure. +# 20030628 - 1.27- Adding --list-inputs and --list-standards to display the available inputs and video standards. +# 20030713 - 1.28- Added code to make sure the codec properties are proper when switching standard to PAL/SECAM. +# Added config options SetMSPMatrix, MSPInput, MSPOutput, MSPSleep to allow the user to specify if they +# want the msp matrix updated any time the Video Standard is changed and to specify what they want programmed. +# Bumping the config file version to 2 to account for the new options. +# 20030715 - 1.29- Adding the missing msp matrix reset code in the reset section. +# Adding codec checks to make sure that they are right for NTSC. +# Made it legal to specify the channel by itself without -c/--channel. +# 20030822 - 1.30- Adding the missing codec value BitrateMode +# 20030927 - 1.31- Adding support to export the settings used as a shell or perl snippet for inclusion +# by scripts working with the recorded video files. +# Changing the default value of StreamType to 14 since that is near DVD quality. +# 20040306 - 1.32- Creating the parent directory if it doesn't exist. +# Making sure to update the InputName if the config specified a number so that input switching works 100%. +# Command line arguments now take precedence over Profile values, should have been this way always. :( +# 20040613 - 1.33- Removing the MSPMatrix related options and code. +# Adding a check for the 0.1.10 driver and not using the GOP_END ioctl if it is not that version. +# Brought it upto speed in regards to the 0.2.00rc1g driver - all known issues are now fixed. +# Added code to determine the version of the ivtv driver being used (0.1.10, 0.2.0, etc.) and +# output it in the video.settings file so we know what driver the capture was done with. + + +use strict; +use Getopt::Long qw(:config no_ignore_case bundling); +use Fcntl; +use Video::Frequencies 0.03; +use Video::ivtv 0.13; +use Config::IniFiles; + +my $version="1.33"; +my $cfgVersion = "3"; +my $cfgVersionStr = "_configVersion_"; # hopefully unique [defaults] value to let me know what version the config file is. +my $ivtvVersion = 0; # used to store the detected version of the driver. Needed for the CaptureLastGOP feature. + +my @capabilities = (); # The cards capabilities + +my %settings = ( + Channel => 4, # default to the ivtv default channel + RecordDuration => 3595, # default to 59 minutes 55 seconds (in seconds) - This lets 2 back to back cron jobs work! + InputNum => 0, # TV-Tuner 1 + InputName => "Tuner 1", + OutputDirectory => ".", + VideoDevice => "/dev/video0", + VideoWidth => "720", # 720x480-fullscreen NTSC + VideoHeight => "480", + VideoStandard => "NTSC-M", # L135 v060406.pl MMM "NTSC", # NTSC, PAL or SECAM + VideoType => "mpeg", # mpeg, yuv + BitrateMode => 0, # 0 = VBR, 1 = CBR + Bitrate => "6500000", + PeakBitrate => "8000000", # peak bitrate + Aspect => 2, + AudioBitmask => 0x00e9, + BFrames => 3, + DNRMode => 0, + DNRSpatial => 0, + DNRTemporal => 0, + DNRType => 0, + Framerate => 0, + FramesPerGOP => 15, + GOPClosure => 1, + Pulldown => 0, + StreamType => 14, # 0 = PS, 1 = TS, 2 = MPEG1, 3 = PES_AV, 5 = PES_V, 7 = PES_A, 10 = DVD, 11 = VCD, 12 = SVCD, 13 = DVD-Special 1, 14 = DVD-Special 2 + OutputFileName => "video.mpg", + FrequencyTable => "ntsc-cable", # default to NTSC_CABLE mapping. + Frequency => "", # user specified frequency. + ResetCardSettings => 1, + ConfigFileName => "$ENV{HOME}/.ivtvrc", + UpdateConfigFile => 0, + UseConfigFile => 0, + UsingIvtvDriver => 1, # default to being able to use the ivtv "enhancements". + DontRecord => 0, # default to always recording data. + DirectoryFormatString => "%I-%c-%d", # format string used to define the sub directory under OutputDirectory + DateTimeFormatString => "+%Y%m%d-%H%M", # format string used to represent the date/time if the user wants it in their DirectoryFormatString + # define the Codec related min/max values + minBitrate => 1, + maxBitrate => 14500000, + minPeakBitrate => 1150, + maxPeakBitrate => 16000000, + # output settings file settings + OutputSettings => 1, # bool 0 or 1 + OutputSettingsName => "video.settings", + OutputSettingsType => "shell", # shell or perl + # other settings + CaptureLastGOP => 1, # default to trying to Capture the Last GOP of the encoder stream. + Debug => 0, + TunerNum => 1, + v4l2DriverVersion => 0, + v4l2DriverVersionStr => "", + v4l2Driver => "", +); + +my $result=""; +my @profileNames=(); # list of user defined sections to work with in the config file. +my %profileOverloads = (); # hash of entries the Profiles overloaded so InputName <-> InputNum works properly. +my %configIni; # config hash we tie to for Config::IniFiles. +my $ivtvObj = Video::ivtv->new(); + +# map the Settings/Config file parameter to the command line variable that specifies it. +my %mappings = ( + "Channel" => "c|channel", + "RecordDuration" => "t|duration", + "InputNum" => "i|inputnum", + "InputName" => "I|inputname", + "OutputDirectory" => "D|directory", + "VideoDevice" => "d|input", + "VideoWidth" => "W|width", + "VideoHeight" => "H|height", + "VideoStandard" => "s|standard", + "VideoType" => "T|type", + "BitrateMode" => "bitrate-mode", + "Bitrate" => "b|bitrate", + "PeakBitrate" => "B|peakbitrate", + "Aspect" => "aspect", + "AudioBitmask" => "audio-bitmask", + "BFrames" => "bframes", + "DNRMode" => "dnrmode", + "DNRSpatial" => "dnrspatial", + "DNRTemporal" => "dnrtemporal", + "DNRType" => "dnrtype", + "Framerate" => "framerate", + "FramesPerGOP" => "framespergop", + "GOPClosure" => "gopclosure", + "Pulldown" => "pulldown", + "StreamType" => "streamtype", + "OutputFileName" => "o|output", + "FrequencyTable" => "f|freqtable", + "Frequency" => "F|frequency", + "ResetCardSettings" => "R|noreset", + "DirectoryFormatString" => "directory-format", + "DateTimeFormatString" => "date-format", + "Debug" => "debug", + "TunerNum" => "tuner-num", + "OutputSettings" => "output-settings", + "OutputSettingsName" => "output-settings-name", + "OutputSettingsType" => "output-settings-type", + "CaptureLastGOP" => "capture-last-gop", + ); + +my %codecMappings = ( + "Aspect" => "aspect", + "AudioBitmask" => "audio_bitmask", + "BFrames" => "bframes", + "BitrateMode" => "bitrate_mode", + "Bitrate" => "bitrate", + "PeakBitrate" => "bitrate_peak", + "DNRMode" => "dnr_mode", + "DNRSpatial" => "dnr_spatial", + "DNRTemporal" => "dnr_temporal", + "DNRType" => "dnr_type", + "Framerate" => "framerate", + "FramesPerGOP" => "framespergop", + "GOPClosure" => "gop_closure", + "Pulldown" => "pulldown", + "StreamType" => "stream_type", + ); + +# check for devfs support +if ( -e "/dev/.devfsd" ) +{ + $settings{VideoDevice} = "/dev/v4l/video0"; +} + +# check for the config file +if (-f $settings{ConfigFileName}) +{ + $settings{UseConfigFile} = 1; + + # tie to it. + tie %configIni, 'Config::IniFiles', (-file => $settings{ConfigFileName}) or die "Error: Opening config file '$settings{ConfigFileName}' failed! $!\n"; + + my $profile = "defaults"; + if (exists $configIni{$profile}) + { + my $saveFile = 0; + # check version of the config file. + if (!exists $configIni{$profile}{$cfgVersionStr}) + { + print "Updating config file to version 1...\n"; + + # first version config file! Update the Audio -> AudioBitmask entries. + $configIni{$profile}{$cfgVersionStr} = 1; + + # find all entries that have Audio and move to AudioBitmask. + foreach my $p (keys %configIni) + { + if (exists $configIni{$p}{Audio}) + { + $configIni{$p}{AudioBitmask} = $configIni{$p}{Audio}; + delete $configIni{$p}{Audio}; + } + } + + $saveFile = 1; # signal we need to save the config changes. + } + if ($configIni{$profile}{$cfgVersionStr} != $cfgVersion) + { + # we need to upgrade + if ($configIni{$profile}{$cfgVersionStr} == 1) + { + print "Updating config file to version 2...\n"; + # add the MSP Matrix related options. + $configIni{$profile}{SetMSPMatrix} = $settings{SetMSPMatrix}; + $configIni{$profile}{MSPInput} = $settings{MSPInput}; + $configIni{$profile}{MSPOutput} = $settings{MSPOutput}; + $configIni{$profile}{MSPSleep} = $settings{MSPSleep}; + $configIni{$profile}{$cfgVersionStr} = 2; + $saveFile = 1; + } + if ($configIni{$profile}{$cfgVersionStr} == 2) + { + print "Updating config file to version 3...\n"; + # remove the MSP Matrix related options from all profiles. + foreach my $p (keys %configIni) + { + foreach my $k (qw(SetMSPMatrix MSPInput MSPOutput MSPSleep)) + { + if (exists $configIni{$p}{$k}) + { + delete $configIni{$p}{$k}; + } + } + } + $configIni{$profile}{CaptureLastGOP} = 1; + $configIni{$profile}{$cfgVersionStr} = 3; + $saveFile = 1; + } + } + + if ($saveFile) + { + # now save the updated config file before we continue. + tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed! $!\n"; + } + + # update the defaults stored. + foreach my $arg (keys %mappings) + { + if (exists $configIni{$profile}{$arg}) + { + $settings{$arg} = $configIni{$profile}{$arg}; + #print "settings{$arg} = '" . $settings{$arg} . "'\n"; + } + } + } + else + { + print "Warning: config file '$settings{ConfigFileName}' exists but does not have the\n[$profile] section! Use -S to create it without specifying -P.\n\n"; + } +} +else # create the config file +{ + print "Auto Creating config file $settings{ConfigFileName}...\n"; + my $profile = "defaults"; + + # we have to create the config file and tie to it. + tie %configIni, 'Config::IniFiles', () or die "Error: Initializing config file '$settings{ConfigFileName}' failed! $!\n"; + + # now set the name to work with. + tied(%configIni)->SetFileName($settings{ConfigFileName}) or die "Error: Setting config file to '$settings{ConfigFileName}' failed! $!\n"; + + $configIni{$profile} = {}; # make sure the section exists. + + foreach my $arg (keys %mappings) + { + $configIni{$profile}{$arg} = $settings{$arg}; + print "configIni{$profile}{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug}; + } + + # set the config file version + $configIni{$profile}{$cfgVersionStr} = $cfgVersion; + + # write the config file out. + tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed! $!\n"; +} + +# build up the "custom" frequency table +my %customMap = (); +foreach my $profileName (keys %configIni) +{ + next if $profileName =~ /^(defaults)$/; + + if (exists $configIni{$profileName}{Frequency}) + { + $customMap{$profileName} = $configIni{$profileName}{Frequency}; + } +} +$CHANLIST{custom} = \%customMap; + +# enumerations +my @standards; +my %name2std; +my @inputs; +my %name2input; +my @codecInfo; # stores the Codec Info +my @newCodecInfo; # the version we mess with. +# Current settings (Input, Channel, Standard) +my $curinput; +my $curinputName; +my $std; +my $curstd = "???"; +my $curStandard = 0; # numeric representation. +my $curChannel = 0; +my $curFrequency = 0; + +my $tuner; +my $settingsFH; # File Handle for output settings. +my $err; +my $v4l2input; + +my $tmpDirectoryStr = formatDirectoryString(); +my $versionStr = "record-v4l2.pl $version for use with http://ivtv.sf.net/"; +my $usageStr = <<"END_OF_USAGE"; +$versionStr + +Usage: record-v4l2.pl [--channel CHANNEL] [--duration TIME] + [--directory DIRECTORY] [--output OUTPUT] + [--directory-format FORMAT] [--date-format FORMAT] + [--input VIDEO_DEV][--width WIDTH --height HEIGHT] + [--standard STANDARD] [--type TYPE] + [--inputnum INPUT#] [--inputname INPUT NAME] + [--freqtable FREQENCY MAP] [--frequency FREQUENCY] + [--bitrate-mode MODE] + [--bitrate BITRATE] [--peakbitrate PEAK_BITRATE] + [--profile PROFILE] [--list-freqtable] [--list-channels] + [--no-record] [--noreset] [--save] [--help] [--version] + [--aspect ASPECT] [--audio-bitmask AUDIO-BITMASK] [--bframes BFRAMES] + [--dnrmode DNRMODE] [--dnrspatial DNRSPATIAL] + [--dnrtemporal DNRTEMPORAL] [--dnrtype DNRTYPE] + [--framerate FRAMERATE] [--framespergop FRAMESPERGOP] + [--gopclosure GOPCLOSURE] [--capture-last-gop GOP_END] + [--pulldown PULLDOWN] [--streamtype STREAMTYPE] [--debug] + [--tuner-num TUNERNUM] [--output-settings BOOL] + [--output-settings-name FNAME] [--output-settings-type TYPE] + [--list-inputs] [--list-standards] [CHANNEL] + + -c/--channel CHANNEL: channel number to switch to + NOTE: You can also specify the channel by itself. + Ex. record-v4l2.pl 73 + would change to channel 73 using the default settings + or the settings from your ~/.ivtvrc config file. + -t/--duration TIME: number of seconds to record + -D/--directory DIRECTORY: Base directory to record into + --directory-format FORMAT: format string that specifies the + sub-directory to create under the base directory that + the output file will be created in. This can be empty + to indicate no sub-directory should be created. + + Available tokens are: + %d - date formatted by --date-format + %I - input name recorded from + Any white space in the name is converted to + underscores (_). Ex. 'Tuner 0' => 'Tuner_0' + + %c - channel or "freq-#" frequency + + --date-format FORMAT: format string that specifies the + date format string to generate and substitute for + %d in the --directory-format string. + + Available tokens: see the date commands man page. + The string must start with a + (plus). + + -o/--output OUTPUT: name of file to create + -d/--input VIDEO_DEV: video device to capture from + -W/--width WIDTH: width of screen (720 for NTSC fullscreen) + -H/--height HEIGHT: height of screen (480 for NTSC fullscreen) + -s/--standard STANDARD: NTSC, PAL or SECAM - video standard to record in + -T/--type TYPE: mpeg or yuv output + -i/--inputnum INPUT#: + The index number of the input you want to use (0 -> n-1) + -I/--inputname INPUT NAME: The name of the input you want to use. + -f/--freqtable FREQUENCY MAP: Specify the frequency mapping to use. + -F/--frequency FREQUENCY: Specify the frequency to tune to. + ex. 517250 = NTSC Cable 73 (SCiFi) + --tuner-num TUNERNUM: Specify the tuner to use. + -L/--list-freqtable: + list all available frequency mappings that Video::Frequencies knows + --list-channels: lists all channels and their frequencies for the + specified frequency table being used. + --list-inputs: lists all inputs the v4l2 driver reports. + --list-standards: lists all Video Standards the v4l2 driver supports. + -R/--noreset: Do not Reset anything that was changed + (standard, channel, resolution, etc.) + --no-record: Do not create any directories, capture data or reset the card + back to original settings. This is the ptune.pl mode. + -h/--help: display this help + -v/--version: display the version of this program + --debug: turns on debug output + --output-settings BOOL: Turns on or off the creation of the settings + file that contains perl or shell variables that + represent the settings used to record the video file. + This feature is ignored if --no-record specified. + --output-settings-name FNAME: The name of the file to write the settings to. + It must end in .settings. + --output-settings-type TYPE: Either 'shell' or 'perl'. + If 'shell', then all variables output are prefixed with REC_ + and are upper cased. Ex: StreamType => REC_STREAMTYPE="14" + If 'perl', then all variables output are created in the + %settings hash. Ex: StreamType => $settings{StreamType} = "14"; + + Codec related options: + --bitrate-mode MODE: 0 = VBR, 1 = CBR + -b/--bitrate BITRATE: Specify the Bitrate to capture at in Mbps + -B/--peakbitrate PEAK_BITRATE: Specify the Peak Bitrate to capture at in Mbps + --aspect ASPECT: Specify the aspect ratio + --audio-bitmask AUDIO-BITMASK: Specify the audio bitmask value + --bframes BFRAMES: Specify the number of B frames value + --dnrmode DNRMODE: Specify the dnr_mode value + --dnrspatial DNRSPATIAL: Specify the dnr_spatial value + --dnrtemporal DNRTEMPORAL: Specify the dnr_temporal value + --dnrtype DNRTYPE: Specify the dnr_type value + --framerate FRAMERATE: Specify the framerate value. 0 = 30fps, 1 = 25fps + --framespergop FRAMESPERGOP: Specify the GOP size + --gopclosure GOPCLOSURE: Specify if you want open/closed GOP's. + --capture-last-gop GOP_END: Specify if you want the encoder stream to try and + capture the last GOP, thus generating a 100% valid mpeg2 file. + 1 = yes (default), 0 = no. + --pulldown PULLDOWN: 1 = Inverse telecine on, 0 = off + --streamtype STREAMTYPE: Specify the stream_type value + Valid Values are: + 0 - PS + 1 - TS + 2 - MPEG1 + 3 - PES_AV + 5 - PES_V + 7 - PES_A + 10 - DVD + 11 - VCD + 12 - SVCD + 13 - DVD-Special 1 + 14 - DVD-Special 2 + + Config file related options: + -P/--profile PROFILE: Override defaults and command line values with the + config entries in the section labeled [PROFILE] from the + config file $settings{ConfigFileName}. + Examples: -P NTSC-DVD, -P PAL-DVD, --profile MY-SETTINGS + + You can specify this option multiple times and each successive + profile will overlay the defaults and any previous profiles. + You will not be able to create/update a profile if you do + specify multiple profiles. + -S/--save: save the current values as the defaults in + $settings{ConfigFileName}. + If -P/--profile PROFILE is specified, then those values that exist in + the specified profile will be updated. If the profile doesn't exist, + then it will be created, but will have all possible config items + defined in it. It will be your responsibility to hand check the + config file and remove any config items you do not want set for + that profile. + Any options specified on the command line will override options + defined in the config file. + +Notes: + If you specify both -i/--inputnum and -I/--inputname then + -i/--inputnum will take precedence. + + If you specify both -c/--channel and -F/--frequency then + -F/--frequency will take precedence. + + If you use a Profile, it has the ability to override all command line + arguments, so check your Profile first if things seem to be ignored. + +Defaults: + --duration $settings{RecordDuration} --input $settings{VideoDevice} --width $settings{VideoWidth} --height $settings{VideoHeight} --standard $settings{VideoStandard} + --type $settings{VideoType} --directory $settings{OutputDirectory} --output $settings{OutputFileName} + --directory-format "$settings{DirectoryFormatString}" --date-format "$settings{DateTimeFormatString}" + --inputnum $settings{InputNum} --inputname '$settings{InputName}' --freqtable $settings{FrequencyTable} --capture-last-gop $settings{CaptureLastGOP} + --bitrate $settings{Bitrate} --peakbitrate $settings{PeakBitrate} --aspect $settings{Aspect} --audio-bitmask $settings{AudioBitmask} --bframes $settings{BFrames} + --dnrmode $settings{DNRMode} --dnrspatial $settings{DNRSpatial} --dnrtemporal $settings{DNRTemporal} --dnrtype $settings{DNRType} + --framerate $settings{Framerate} --framespergop $settings{FramesPerGOP} --gopclosure $settings{GOPClosure} --pulldown $settings{Pulldown} --streamtype $settings{StreamType} + --tuner-num $settings{TunerNum} --output-settings $settings{OutputSettings} --output-settings-name $settings{OutputSettingsName} --output-settings-type $settings{OutputSettingsType} + + config file = '$settings{ConfigFileName}' + + If Channel = $settings{Channel}, this would create: + $tmpDirectoryStr$settings{OutputFileName} + + Note: This script relies on Perl Modules: Video::Frequencies, Video::ivtv, + Config::IniFiles and Getopt::Long. +END_OF_USAGE + +# handle user input here +my %opts; +#getopts('c:t:o:hd:W:H:s:T:D:vi:I:f:F:LRb:B:P:S', \%opts); +GetOptions(\%opts, "channel|c=s", "duration|t=i", "output|o=s", "help|h", "input|d=s", "width|W=i", "height|H=i", "standard|s=s", + "type|T=s", "directory|D=s", "version|v", "inputnum|i=i", "inputname|I=s", "freqtable|f=s", "frequency|F=i", "list-freqtable|L", + "noreset|R", "bitrate|b=i", "peakbitrate|B=i", "profile|P=s@", "save|S", "aspect=i", "audio-bitmask=s", "bframes=i", "dnrmode=i", "dnrspatial=i", + "dnrtemporal=i", "dnrtype=i", "framerate=i", "framespergop=i", "gopclosure=i", "pulldown=i", "capture-last-gop=i", + "streamtype=i", "no-record", "directory-format=s", "date-format=s", "debug", "list-channels", + "tuner-num=i", "list-inputs", "list-standards", "bitrate-mode=i", "output-settings=i", "output-settings-name=s", "output-settings-type=s"); +if (scalar keys %opts == 0 && @ARGV == 0) +{ + usage(0, ""); +} +foreach my $option (sort keys %opts) +{ + my $found = 0; + foreach my $mapName (keys %mappings) + { + if ($option =~ /^($mappings{$mapName})$/) + { + $settings{$mapName} = $opts{$option}; + $found = 1; + print "$mapName = '$opts{$option}'\n" if $settings{Debug}; + } + } + if (!$found) + { + # handle the non-settings cases. + if ($option =~ /^(L|list-freqtable)$/) + { + my $errStr = "\nAvailable Frequency Mappings:\n"; + foreach my $name (sort keys %CHANLIST) + { + $errStr .= "$name\n"; + } + print "$versionStr\n$errStr"; + exit 0; + } + elsif ($option eq "list-channels") + { + my $errStr = "\nAvailable Channels for $settings{FrequencyTable}:\n"; + foreach my $name (sort { $a <=> $b } keys %{$CHANLIST{$settings{FrequencyTable}}}) + { + $errStr .= "$name\t= $CHANLIST{$settings{FrequencyTable}}->{$name}\n"; + } + print "$versionStr\n$errStr"; + exit 0; + } + elsif ($option =~ /^(no-record)$/) + { + $settings{DontRecord} = 1; + } + elsif ($option =~ /^(S|save)$/) + { + $settings{UpdateConfigFile} = 1; + } + elsif ($option =~ /^(P|profile)$/) + { + @profileNames = @{$opts{$option}}; + } + elsif ($option =~ /^(v|version)$/) + { + print "$versionStr\n"; + exit 0; + } + elsif ($option =~ /^(h|help)$/) + { + usage(0, ""); + } + elsif ($option =~ /^(list-inputs|list-standards)$/) + { + # do nothing for now since they will be handled later. + } + else + { + usage(1, "-$option is an unknown option!"); + } + } +} + +if (@profileNames) +{ + # loop over all profiles the user specified. + foreach my $profileName (@profileNames) + { + print "profile = '$profileName'\n" if $settings{Debug}; + # for now the profile can not be "defaults". + if ($profileName eq "defaults") + { + error(1, "Profile = '$profileName' is invalid!"); + } + if (exists $configIni{$profileName}) + { + # update defaults that exist in this profile as long as the entry wasn't specified on the command line. + my $profile = $profileName; + + foreach my $arg (keys %mappings) + { + # handle the long/short command option versions + my $cmdSpecified = 0; + foreach my $option (split(/\|/, $mappings{$arg})) + { + if (exists $opts{$option}) + { + $cmdSpecified = 1; + last; + } + } + #print "arg = '$arg', option = '$option'\n" if $settings{Debug}; + if (exists $configIni{$profile}{$arg} && !$cmdSpecified) + { + $profileOverloads{$arg} = $settings{$arg}; # preserve the old value. + $settings{$arg} = $configIni{$profile}{$arg}; + print "settings{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug}; + } + } + } + else + { + if ($settings{UpdateConfigFile} && @profileNames == 1) + { + print "Warning: Profile = '$profileName' will be created.\n" if ($settings{Debug}); + } + else + { + error(1, "Profile = '$profileName' does not exist! You must specify -S/--save to create it."); + } + } + } +} + +# verify input + +if (@ARGV) +{ + if (exists $opts{c} || exists $opts{channel}) + { + print "Warning: ignoring channel argument and using '$ARGV[0]' instead.\n"; + } + $settings{Channel} = $ARGV[0]; +} + +my $directoryName; +if (!$settings{DontRecord}) +{ + print "RecordDuration = $settings{RecordDuration}\n" if $settings{Debug}; + + if ($settings{VideoType} !~ /^(mpeg|yuv)$/) + { + error(1, "Video Type = '$settings{VideoType}' is invalid!"); + } + if ($settings{VideoType} eq "yuv") + { + # see if we need to change our defaults. + if (!exists $opts{o} && !exists $opts{output}) + { + $settings{OutputFileName} = "video.yuv"; + } + if (!exists $opts{d} && !exists $opts{input}) + { + if ( -e "/dev/.devfsd" ) + { + $settings{VideoDevice} = "/dev/v4l/yuv0"; + } + else + { + $settings{VideoDevice} = "/dev/yuv0"; + } + } + } + + if ( ! -d "$settings{OutputDirectory}") + { + $result = `mkdir -p $settings{OutputDirectory}`; + } + # make directory + $directoryName = formatDirectoryString(); + $result=`mkdir -p $directoryName`; +} + +# verify the output-settings options +if ($settings{OutputSettings} !~ /^[01]$/) +{ + error(1, "OutputSettings = '$settings{OutputSettings}' is invalid!"); +} +if ($settings{OutputSettings} && $settings{DontRecord}) +{ + $settings{OutputSettings} = 0; # turn off feature since we are not recording. +} +if ($settings{OutputSettings}) +{ + if ($settings{OutputSettingsName} !~ /^(.+\.settings)$/) + { + error(1, "OutputSettingsName = '$settings{OutputSettingsName}' is invalid! It must end in .settings."); + } + if ($settings{OutputSettingsType} !~ /^(shell|perl)$/) + { + error(1, "OutputSettingsType = '$settings{OutputSettingsType}' is invalid! It must be either 'shell' or 'perl'."); + } + sysopen($settingsFH, "$directoryName/$settings{OutputSettingsName}", O_CREAT | O_WRONLY) or die "Error creating file '$settings{OutputSettingsName}': $!\n"; + outputSettingSetup(); +} + +if ( ! -c "$settings{VideoDevice}") +{ + error(1, "Video Dev = '$settings{VideoDevice}' is invalid! $!"); +} + +# now that the video device has been semi validated, we can use it to lookup +# the inputs, standards, etc. and use that for validating some of the following +# pieces of user input. +sysopen($tuner, $settings{VideoDevice}, O_RDWR) or die "Error unable to open '$settings{VideoDevice}': $!"; +my $tunerFD = fileno($tuner); + +outputSetting("VideoDevice"); + +# get the current capabilities. +@capabilities = $ivtvObj->getCapabilities($tunerFD); +if (@capabilities != keys %{$ivtvObj->{capIndexes}}) +{ + error(1, "getCapabilities() failed!"); +} +# calculate the driver version info. +my $driverVersionHex = sprintf("%08x", $capabilities[$ivtvObj->{capIndexes}{version}]); +$driverVersionHex =~ /^(\d{4})(\d{2})(\d{2})$/; +my $driverVersionMajor = int($1); +my $driverVersionMinor = int($2); +my $driverVersionPatch = int($3); +my $driverVersionStr = $driverVersionMajor . "." . $driverVersionMinor . "." . $driverVersionPatch; + +$settings{v4l2DriverVersion} = $capabilities[$ivtvObj->{capIndexes}{version}]; +$settings{v4l2DriverVersionStr} = $driverVersionStr; +$settings{v4l2Driver} = $capabilities[$ivtvObj->{capIndexes}{driver}]; +outputSetting("v4l2Driver"); +outputSetting("v4l2DriverVersion"); +outputSetting("v4l2DriverVersionStr"); + +if ($settings{Debug}) +{ + print "V4l2 Capabilities: driver='$capabilities[$ivtvObj->{capIndexes}{driver}]', version='$capabilities[$ivtvObj->{capIndexes}{version}]', '$driverVersionStr'\n"; +} +if ($capabilities[$ivtvObj->{capIndexes}{driver}] ne "ivtv") +{ + $settings{UsingIvtvDriver} = 0; # we can't use the ivtv "enhancements". + print "Warning: V4l2 driver = '$capabilities[$ivtvObj->{capIndexes}{driver}]' does not support the ivtv \"enhancements\"!\n"; + print " All codec and ivtv specific options will be ignored.\n\n"; +} +elsif ($capabilities[$ivtvObj->{capIndexes}{version}] <= 265) +{ + $settings{CaptureLastGOP} = 0; # we can't use the ivtv GOP_END feature. + print "Warning: ivtv driver is not new enough to use the GOP_END feature!\n"; +} +$ivtvVersion = $capabilities[$ivtvObj->{capIndexes}{version}]; + +my $i; + +# get the current video standard +$std = $ivtvObj->getStandard($tunerFD); +if ($std > 0) +{ + printf("Standard: 0x%08x\n",$std) if ($settings{Debug}); +} +else +{ + die "Error: getStandard() failed!\n"; +} + +# get the current input +$curinput = $ivtvObj->getInput($tunerFD); +if ($curinput < 0) +{ + die "Error: getInput() failed!\n"; +} +printf("Input: 0x%08x\n",$curinput) if ($settings{Debug}); + +# flags to indicate when we should stop reading from the card. +my $done=0; +my $stopGOP=0; # indicates if we are asking for the Last GOP +my $endStream=0; # indicates if we are in the final read state. +# Standards +for ($i=0; !$done; ++$i) +{ + my($index,$std_id,$name,$frameperiod_n,$frameperiod_d,$framelines) = $ivtvObj->enumerateStandard($tunerFD, $i); + if ($index == -1) + { + $done = 1; + } + else + { + printf("%d 0x%08x %s %d/%d %d\n",$index,$std_id,$name,$frameperiod_n,$frameperiod_d,$framelines) if ($settings{Debug}); + push @standards, [($name,$std_id)]; + $name2std{$name} = $std_id; + if( (($std_id & $std) == $std)) + { + $curstd = $name; + $curStandard = $std; + } + } +} + +if (exists $opts{'list-standards'}) +{ + print "$versionStr\n"; + print "Available Video Standards:\n"; + foreach my $standard (@standards) + { + print "$standard->[0]\n"; + } + exit 0; +} + +$done=0; +# Inputs +for ($i=0; !$done; ++$i) +{ + my($index,$name,$type,$audioset,$tuner,$std,$status) = $ivtvObj->enumerateInput($tunerFD, $i); + if ($index == -1) + { + $done = 1; + } + else + { + push @inputs, $name; + $name2input{$name} = $index; + } +} +$curinputName = $inputs[$curinput]; + +if (exists $opts{'list-inputs'}) +{ + print "$versionStr\n"; + print "Available Inputs:\n"; + my $counter = 0; + foreach my $input (@inputs) + { + print "$counter: $input\n"; + $counter++; + } + exit 0; +} + +if ($settings{UsingIvtvDriver}) +{ + # get the current Codec Info + @codecInfo = $ivtvObj->getCodecInfo($tunerFD); + if (@codecInfo != keys %{$ivtvObj->{codecIndexes}}) + { + error(1, "getCodecInfo() failed!"); + } + @newCodecInfo = $ivtvObj->getCodecInfo($tunerFD); + if (@newCodecInfo != keys %{$ivtvObj->{codecIndexes}}) + { + error(1, "getCodecInfo() failed!"); + } +} + +# finish validating the user input. + +if (!$settings{DontRecord}) +{ + if ($settings{RecordDuration} !~ /^(\d+)$/) + { + error(1, "Time = '$settings{RecordDuration}' is invalid!"); + } + + outputSetting("RecordDuration"); + outputSetting("OutputDirectory"); + + # assume for now we are only generating mpeg files. +# if (($settings{VideoType} eq "mpeg" && $settings{OutputFileName} !~ /^.+\.mpg$/) || ($settings{VideoType} eq "yuv" && $settings{OutputFileName} !~ /^.+\.yuv$/)) +# { +# error(1, "Output = '$settings{OutputFileName}' is invalid!"); +# } + + outputSetting("VideoType"); + outputSetting("OutputFileName"); + + if ($settings{DateTimeFormatString} !~ /^(\+((\%.)|.)+)$/) + { + usage(1, "Date Format String = '$settings{DateTimeFormatString}' is invalid!"); + } + + outputSetting("DateTimeFormatString"); +} + +if ($settings{VideoWidth} !~ /^(\d+)$/) +{ + error(1, "Width = '$settings{VideoWidth}' is invalid!"); +} + +outputSetting("VideoWidth"); + +if ($settings{VideoHeight} !~ /^(\d+)$/) +{ + error(1, "Height = '$settings{VideoHeight}' is invalid!"); +} + +outputSetting("VideoHeight"); + +if (!exists $name2std{$settings{VideoStandard}}) +{ + my $validStandards = join(", ", keys(%name2std)); + error(1, "Video Standard = '$settings{VideoStandard}' is invalid!\nValid Standards are: $validStandards"); +} + +outputSetting("VideoStandard"); + +if (exists $opts{i} || exists $opts{inputnum} || ($settings{InputNum} != $name2input{$settings{InputName}} && exists $profileOverloads{InputNum})) +{ + if ($settings{InputNum} < 0 || $settings{InputNum} >= scalar(@inputs)) + { + error(1, "Video Input = '$settings{InputNum}' is invalid!\nValid Inputs are from 0 - " . int(scalar(@inputs) - 1)); + } + $settings{InputName} = $inputs[$settings{InputNum}]; +} + +if ((exists $opts{I} || exists $opts{inputname} || $settings{InputNum} != $name2input{$settings{InputName}}) && !(exists $opts{i} || exists $opts{inputnum})) +{ + if (!exists $name2input{$settings{InputName}}) + { + my $validInputs = join(", ", @inputs); + error(1, "Video Input Name = '$settings{InputName}' is invalid!\nValid Input Names are: $validInputs"); + } + $settings{InputNum} = $name2input{$settings{InputName}}; +} + +outputSetting("InputName"); +outputSetting("InputNum"); + +if (!exists $CHANLIST{$settings{FrequencyTable}}) +{ + error(1, "Frequency Table = '$settings{FrequencyTable}' is invalid!"); +} + +outputSetting("FrequencyTable"); + +# only validate the channel if the input is a tuner. +if ($inputs[$settings{InputNum}] =~ /Tuner/) +{ + if ($settings{TunerNum} !~ /^(\d)$/) + { + error(1, "TunerNum = '$settings{TunerNum}' is invalid!"); + } + if (exists $opts{F} || exists $opts{frequency} || $settings{Frequency}) # the user may have specified a Frequency in their config file + { + if ($settings{Frequency} !~ /^(\d+)$/) + { + error(1, "Frequency = '$settings{Frequency}' is invalid!"); + } + $settings{Channel} = "freq-$settings{Frequency}"; # make sure we output the channel part. + } + # now verify that the channel exists in the frequency table! + else + { + if (!$settings{Channel}) + { + error(1, "channel = '$settings{Channel}' is invalid!"); + } +## start new MMM # first verify the freqency table is appropriate for the standard (NTSC, PAL, SECAM), + # unless they specified the frequency to tune to. + if ($settings{FrequencyTable} !~ /^(custom|$settings{VideoStandard})/i) + { + error(1, "You specified Video Standard '$settings{VideoStandard}' which is incompatible with Frequency Table '$settings{FrequencyTable}'!"); + } ## end new MMM + if (!exists $CHANLIST{$settings{FrequencyTable}}->{$settings{Channel}}) + { + error(1, "Channel = '$settings{Channel}' does not exist in Frequency Table '$settings{FrequencyTable}'!"); + } + } + + outputSetting("Channel"); + outputSetting("Frequency"); + + # get the current channel/frequency value. + my $Frequency; + if(($Frequency = $ivtvObj->getFrequency($tunerFD, $settings{TunerNum})) > 0) + { + my $freq = ($Frequency * 1000) / 16; + print "freq = $freq\n" if ($settings{Debug}); + # find the associated channel. + if ((!exists $opts{F} && !exists $opts{frequency} && !$settings{Frequency}) && ($curstd eq $settings{VideoStandard}) ) + { + foreach my $chan (keys %{$CHANLIST{$settings{FrequencyTable}}}) + { + if ($CHANLIST{$settings{FrequencyTable}}->{$chan} == $freq) + { + $curChannel = $chan; + } + } + print "curChannel = $curChannel\n" if ($settings{Debug}); + } + else + { + $curFrequency = $freq; + } + } + elsif ($Frequency < 0) + { + die "Error: getFrequency() failed!\n"; + } +} +else +{ + # set the channel = "" so we know to ignore it. + $settings{Channel} = ""; +} + +if ($settings{UsingIvtvDriver}) +{ + # validate the Codec related stuff. + if ($settings{BitrateMode} !~ /^(0|1)$/) + { + error(1, "BitrateMode = '$settings{BitrateMode}' is invalid!"); + } + if ($settings{Bitrate} < $settings{minBitrate} || $settings{Bitrate} > $settings{maxBitrate}) + { + error(1, "Bitrate = '$settings{Bitrate}' is invalid!"); + } + if ($settings{PeakBitrate} < $settings{Bitrate}) + { + error(1, "PeakBitrate can not be less than Bitrate!"); + } + elsif ($settings{PeakBitrate} == $settings{Bitrate} && !$settings{BitrateMode} == 1) + { + error(1, "PeakBitrate can not be equal to Bitrate in VBR Mode!"); + } + elsif ($settings{PeakBitrate} < $settings{minPeakBitrate} || $settings{PeakBitrate} > $settings{maxPeakBitrate}) + { + error(1, "PeakBitrate = '$settings{PeakBitrate}' is invalid!"); + } + + if ($settings{VideoStandard} !~ /^(NTSC)/) + { + my $warn = 0; + if ($settings{Framerate} == 0) + { + $settings{Framerate} = 1; + $warn = 1; + } + if ($settings{FramesPerGOP} == 15) + { + $settings{FramesPerGOP} = 12; + $warn = 1; + } + if ($warn) + { + print "Warning: Setting Framerate/FramesPerGOP to PAL settings for Video Standard '$settings{VideoStandard}'!\n\nYou should either specify on the command line or in the ~/.ivtvrc config file.\n"; + } + } + elsif ($settings{VideoStandard} =~ /^(NTSC)/) + { + my $warn = 0; + if ($settings{Framerate} == 1) + { + $settings{Framerate} = 0; + $warn = 1; + } + if ($settings{FramesPerGOP} == 12) + { + $settings{FramesPerGOP} = 15; + $warn = 1; + } + if ($warn) + { + print "Warning: Setting Framerate/FramesPerGOP to NTSC settings for Video Standard '$settings{VideoStandard}'!\n\nYou should either specify on the command line or in the ~/.ivtvrc config file.\n"; + } + } + + if ($settings{StreamType} < 0 || $settings{StreamType} > 14) + { + error(1, "StreamType = '$settings{StreamType}' is invalid!"); + } + + if ($settings{CaptureLastGOP} < 0 || $settings{CaptureLastGOP} > 1) + { + error(1, "CaptureLastGOP = '$settings{CaptureLastGOP}' is invalid!"); + } + + outputSetting("BitrateMode"); + outputSetting("Bitrate"); + outputSetting("PeakBitrate"); + outputSetting("SetMSPMatrix"); + outputSetting("MSPInput"); + outputSetting("MSPOutput"); + outputSetting("Framerate"); + outputSetting("FramesPerGOP"); + outputSetting("Aspect"); + outputSetting("AudioBitmask"); + outputSetting("BFrames"); + outputSetting("DNRMode"); + outputSetting("DNRSpatial"); + outputSetting("DNRTemporal"); + outputSetting("DNRType"); + outputSetting("GOPClosure"); + outputSetting("Pulldown"); + outputSetting("StreamType"); + outputSetting("CaptureLastGOP"); +} + +# update the config file if the user wants us to. +if ($settings{UpdateConfigFile}) +{ + my $profile; + if (@profileNames > 1) + { + print "Warning: Not updating config file as you have more than 1 profile specified!\n"; + } + elsif (@profileNames == 1) + { + $profile = $profileNames[0]; + } + else + { + $profile = "defaults"; + } + if ($profile) + { + my $createProfile = (exists $configIni{$profile} ? 0 : 1); + print "Creating Profile = '$profile': $createProfile\n" if ($settings{Debug}); + + if (!$settings{UseConfigFile}) + { + # we have to create the config file and tie to it. + tie %configIni, 'Config::IniFiles', () or die "Error: Initializing config file '$settings{ConfigFileName}' failed! $!\n"; + + # now set the name to work with. + tied(%configIni)->SetFileName($settings{ConfigFileName}) or die "Error: Setting config file to '$settings{ConfigFileName}' failed! $!\n"; + + $configIni{$profile} = {}; # make sure the section exists. + } + + foreach my $arg (keys %mappings) + { + foreach my $option (split(/\|/, $mappings{$arg})) # handle the long/short command option versions + { + if (exists $configIni{$profile}{$arg} || $createProfile || exists $opts{$option}) + { + $configIni{$profile}{$arg} = $settings{$arg}; + print "configIni{$profile}{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug}; + last; + } + } + } + + # write the config file out. + tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed! $!\n"; + } +} + +# this hash keeps track of those values I have to set back. +my %changedSettings = ( + resolution => 0, + standard => 0, + VideoType => 0, + InputNum => 0, + Channel => 0, + Frequency => 0, + codec => 0, + ); + +# change the channel +if ($inputs[$settings{InputNum}] =~ /Tuner/) +{ + if (exists $opts{F} || exists $opts{frequency} || $settings{Frequency}) + { + if ($settings{Frequency} != $curFrequency) + { + $changedSettings{Frequency} = 1; + tuneFrequency($settings{Frequency}); + } + } + else + { + if ($curstd ne $settings{VideoStandard}) + { + # we have to set the channel regardless. + # but we want to tune back to the previous frequency. + $changedSettings{Frequency} = 1; + changeChannel($settings{Channel}); + } + elsif ($settings{Channel} ne $curChannel) + { + # otherwise we just changeChannel and restore the previous channel. + $changedSettings{Channel} = 1; + changeChannel($settings{Channel}); + } + } +} + +# set the video standard +if ($settings{VideoStandard} ne $curstd) +{ + $changedSettings{standard} = 1; + change_standard(); +} + +# set the input +if ($settings{InputNum} != $curinput || $settings{InputName} ne $curinputName) +{ + $changedSettings{InputNum} = 1; + if (!(exists $opts{i} || exists $opts{inputnum} || exists $opts{I} || exists $opts{inputname} || exists $profileOverloads{InputNum} || exists $profileOverloads{InputName})) # our defaults are different than the current values! + { + print "Warning: Changing input from '$curinputName' to'$settings{InputName}'.\n"; + } + change_input(); +} + +# set the capture type + +# store the current width,height so we can restore afterwards +my ($oldWidth, $oldHeight) = $ivtvObj->getResolution($tunerFD); +print "oldWidth = '$oldWidth', oldHeight = '$oldHeight'\n" if ($settings{Debug}); + +if ($settings{VideoWidth} != $oldWidth || $settings{VideoHeight} != $oldHeight) +{ + $changedSettings{resolution} = 1; +} + +# specify the width,height to capture +if ($changedSettings{resolution}) +{ + $result = $ivtvObj->setResolution($tunerFD, $settings{VideoWidth}, $settings{VideoHeight}); + if (not defined $result) + { + die "Error calling setResolution!\n"; + } + if (!$result) + { + die "Error in setResolution ioctl call!\n"; + } +} + +if ($settings{UsingIvtvDriver}) +{ + # set the GOP_END flag if the user requested it. + if ($ivtvVersion > 265) # > 0.1.9 + { + $result = $ivtvObj->setEndGOP($tunerFD, $settings{CaptureLastGOP}); + if (!$result) + { +## L1312 macmil_co_jp MMM die "Error calling setEndGOP($settings{CaptureLastGOP})!\n"; + } + } + + # specify the codec options to capture mpeg's at. + foreach my $codecName (keys %codecMappings) + { + my $codecIndex = $ivtvObj->{codecIndexes}{$codecMappings{$codecName}}; + if ($codecInfo[$codecIndex] != $settings{$codecName}) + { + $changedSettings{codec} = 1; + $newCodecInfo[$codecIndex] = $settings{$codecName}; + print "new $codecName = '$settings{$codecName}', old $codecName = '$codecInfo[$codecIndex]'\n" if $settings{Debug}; + } + } +} + +if ($changedSettings{codec}) +{ + $result = $ivtvObj->setCodecInfo($tunerFD, @newCodecInfo); + if (!$result) + { +## L1334 macmil_co_jp MMM die "Error calling setCodecInfo()!\n"; + } +} + +if (!$settings{DontRecord}) +{ + close($settingsFH) if ($settings{OutputSettings}); + + # capture the video/audio to video.mpg + captureVideo(directoryName => $directoryName, RecordDuration => $settings{RecordDuration}, + OutputFileName => $settings{OutputFileName}, tuner => $tuner); +} + +if ($settings{ResetCardSettings} && !$settings{DontRecord}) +{ + # close and re-open the device since it appears to not like taking new settings if we ended capturing. + close($tuner); + sysopen($tuner, $settings{VideoDevice}, O_RDWR) or die "Error unable to open '$settings{VideoDevice}': $!"; + $tunerFD = fileno($tuner); + + # restore Codec values + if ($changedSettings{codec}) + { + $result = $ivtvObj->setCodecInfo($tunerFD, @codecInfo); + if (!$result) + { +## L1360 macmil_co_jp MMM die "Error calling setCodecInfo()!\n"; + } + } + + # restore the previous input setting + if ($changedSettings{InputNum}) + { + # reset back to the old input name + $settings{InputName} = $curinputName; + change_input(); + } + + # restore the previous video standard + if ($changedSettings{standard}) + { + $settings{VideoStandard} = $curstd; + change_standard(); + } + + # restore the previous width,height settings + if ($changedSettings{resolution}) + { + $result = $ivtvObj->setResolution($tunerFD, $oldWidth, $oldHeight); + if (not defined $result) + { + die "Error calling setResolution!\n"; + } + if (!$result) + { + die "Error in setResolution ioctl call! result = '$result', oldWidth = '$oldWidth', oldHeight = '$oldHeight'\n"; + } + } + + # restore the previous channel + if ($changedSettings{Channel} && $curChannel > 0) + { + changeChannel($curChannel); + } + if ($changedSettings{Frequency} && $curFrequency > 0) + { + tuneFrequency($curFrequency); + } +} + +# close the tuner device +close($tuner); + +exit 0; + +# usage(returnValue, ErrorString) +# returnValue = 1 or 0 +# ErrorString = message you want to tell the user, but only if returnValue = 1. +sub usage +{ + my $errorCode = shift; + my $error = shift; + + print $usageStr; + print "\nError: $error\n" if ($errorCode == 1); + print "$error\n" if ($errorCode == 2); + + exit $errorCode; +} + +# error(returnValue, ErrorString) +# returnValue = 1 or 0 +# ErrorString = message you want to tell the user. +sub error +{ + my $errorCode = shift; + my $error = shift; + + print "$versionStr"; + print "\nError: $error\n"; + + exit $errorCode; +} + +# changes the input to $settings{InputNum} as long as it isn't = $curinput +sub change_input { + my $preinput = $name2input{$settings{InputName}}; + if($preinput != $curinput) + { + $curinput = $preinput; + print "input now $settings{InputName}, #$preinput\n" if ($settings{Debug}); + my $result = $ivtvObj->setInput($tunerFD, $preinput); + if (!$result) + { + die "Error: setInput($preinput) failed!\n"; + } + } +} + +# changes the video standard to $settings{VideoStandard} as long as it isn't = $curstd +sub change_standard { + my $standard = $name2std{$settings{VideoStandard}}; + if($standard != $curStandard) + { + $curStandard = $standard; + print "standard now $settings{VideoStandard}, #$standard\n" if ($settings{Debug}); +## L1460 v060406.pl MMM my $result = $ivtvObj->setStandard($tunerFD, $standard); + if (!$result) + { +## L1463 v060406.pl MMM die "Error: setStandard($standard) failed!\n"; + } + } +} + +# changes the channel +# takes the channel to change +sub changeChannel +{ + my $ch = shift; + my $freq = $CHANLIST{$settings{FrequencyTable}}->{$ch}; + my $driverf = ($freq * 16)/1000; + + print "Ch.$ch: $freq $driverf\n" if ($settings{Debug}); + + if (!$ivtvObj->setFrequency($tunerFD, $settings{TunerNum}, $driverf)) + { + die "Error: changeChannel($ch) failed!\n"; + } +} + +# tunes to the specified frequency +# takes the frequency to tune to +sub tuneFrequency +{ + my $freq = shift; + my $driverf = ($freq * 16)/1000; + + print "freq: $freq $driverf\n" if ($settings{Debug}); + + if (!$ivtvObj->setFrequency($tunerFD, $settings{TunerNum}, $driverf)) + { + die "Error: tuneFrequency($freq) failed!\n"; + } +} + +my $done = 0; + +sub catch_alarm { + if ($settings{CaptureLastGOP}) + { + $stopGOP = 1; # signal we need to stop the stream and capture the last GOP. + } + else + { + $done = 1; # signal we are done. + } +} + +# does the actual video capturing work. +# takes directoryName, RecordDuration, OutputFileName, tuner +sub captureVideo +{ + my %args = ( @_ ); + my $directoryName = $args{directoryName}; + my $RecordDuration = $args{RecordDuration}; + my $OutputFileName = $args{OutputFileName}; + my $tuner = $args{tuner}; + my $fname = "$directoryName/$OutputFileName"; + + # setup global variables, signal handlers, etc. + + $SIG{ALRM} = \&catch_alarm; + $SIG{INT} = \&catch_alarm; # handle Ctrl-C + + # open the file for writing. + + sysopen(OUTPUT, "$fname", O_CREAT | O_WRONLY | O_LARGEFILE) or die "Error creating file '$fname': $!\n"; + + alarm($RecordDuration); + my $buf = ""; + while (!$done) + { + if ($stopGOP) + { + $stopGOP = 0; + $ivtvObj->stopEncoding($tuner); + $endStream = 1; + $done = 1; # signal we are done after this loop. + } + # read from the device and write to the file. (16384) 32768 + my $bytes = read($tuner, $buf, 16384); + if (!$bytes && $endStream) + { + last; + } + print OUTPUT $buf; + } + + # close the file + close(OUTPUT); +} + +# returns the formatted directory string +sub formatDirectoryString +{ + my $temp = $settings{DirectoryFormatString}; + my $result = $settings{OutputDirectory}; + my %lookupTable = ( + "d" => `/bin/date "$settings{DateTimeFormatString}"`, + "I" => $settings{InputName}, + "c" => $settings{Channel}, + ); + + # fixup the InputName value + $lookupTable{I} =~ s/\s/_/g; + # cleanup the trailing slash on the date + chomp $lookupTable{d}; + + foreach my $option ("d", "I", "c") + { + $temp =~ s/\%$option/$lookupTable{$option}/g; + } + + $result .= "/" . ($temp ? "$temp/" : ""); + + return $result; +} + +sub outputSettingSetup +{ + my $date = `/bin/date`; chomp $date; + + if ($settings{OutputSettingsType} eq "shell") + { + print $settingsFH "# Settings for Recording made on $date.\n"; + } + elsif ($settings{OutputSettingsType} eq "perl") + { + print $settingsFH "# Settings for Recording made on $date.\n"; + print $settingsFH "my %settings = ();\n"; + } +} + +# outputs the specified setting and it's value to the +# settings file represented by $settingsFH in the +# specified language. +sub outputSetting +{ + my $setting = shift; + my $value = $settings{$setting}; + + return if (!$settings{OutputSettings}); + + if ($settings{OutputSettingsType} eq "shell") + { + print $settingsFH "REC_" . uc($setting) . "=\"$value\"\n"; + } + elsif ($settings{OutputSettingsType} eq "perl") + { + print $settingsFH "\$settings{$setting} = \"$value\";\n"; + } +} Index: trunk/install/perl/recwrap.pl =================================================================== --- trunk/install/perl/recwrap.pl (リビジョン 70) +++ trunk/install/perl/recwrap.pl (リビジョン 83) @@ -1,4 +1,4 @@ #!/usr/bin/perl -#usage recwrap.pl ch length(sec) [bitrate(5)] [TID] [NO] [PID] +#usage recwrap.pl ch length(sec) [bitrate(5)] [TID] [NO] [PID] [stationid] [digitalflag] [digitalband] [digitalch] # # Anime recording system foltia @@ -39,20 +39,63 @@ $tid = $ARGV[3] ; $countno = $ARGV[4] ; -$pid = $ARGV[5] ; +$pid = $ARGV[5] ; +$stationid = $ARGV[6] ; +$usedigital = $ARGV[7] ; +$digitalstationband = $ARGV[8] ; +$digitalch= $ARGV[9] ; + +#DB初期化 + my $data_source = sprintf("dbi:%s:dbname=%s;host=%s;port=%d", + $DBDriv,$DBName,$DBHost,$DBPort); + $dbh = DBI->connect($data_source,$DBUser,$DBPass) ||die $DBI::error;; + + +if ($usedigital == 1){ + $extension = ".m2t";#TSの拡張子 +}else{ + $extension = ".m2p";#MPEG2の拡張子 +} $outputfile = `date +%Y%m%d-%H%M --date "1 min "`; chomp($outputfile); + if ($tid == 0){ - $outputfilename = "0--".$outputfile."-".$recch.".m2p"; + $outputfilename = "0--".$outputfile."-".$recch.$extension; $mp4newstylefilename = "-0--".$outputfile."-".$recch; }else{ if ($countno == 0){ - $outputfilename = $tid ."--".$outputfile.".m2p"; + $outputfilename = $tid ."--".$outputfile.$extension; $mp4newstylefilename = "-" . $tid ."--".$outputfile; }else{ - $outputfilename = $tid ."-".$countno."-".$outputfile.".m2p"; + $outputfilename = $tid ."-".$countno."-".$outputfile.$extension; $mp4newstylefilename = "-" . $tid ."-".$countno."-".$outputfile; } } + +if ($usedigital == 1){ +#デジタルなら +&writelog("recwrap RECSTART DIGITAL $digitalstationband $digitalch $reclength $stationid 0 $outputfilename $tid $countno friio"); +#録画 +$starttime = (`date +%s`); +$oserr = system("$toolpath/perl/digitaltvrecording.pl $digitalstationband $digitalch $reclength $stationid 0 $outputfilename $tid $countno friio"); +$oserr = $oserr / 256; + +if ($oserr == 1){ + &writelog("recwrap ABORT recfile exist. [$outputfilename] $digitalstationband $digitalch $reclength $stationid 0 $outputfilename $tid $countno"); + exit; +}elsif ($oserr == 2){ + &writelog("recwrap ERR 2:friio busy;retry."); + &continuousrecordingcheck;#もうすぐ終わる番組をkill + sleep(2); + $oserr = system("$toolpath/perl/digitaltvrecording.pl $digitalstationband $digitalch $reclength $stationid N $outputfilename $tid $countno friio"); + $oserr = $oserr / 256; + if ($oserr == 2){ + &writelog("recwrap ERR 2:friio busy;Giving up digital recording."); + } +}elsif ($oserr == 3){ +&writelog("recwrap ABORT:ERR 3"); +exit ; +} +}else{ #リモコン操作 # $haveirdaunit = 1;リモコンつないでるかどうか確認 @@ -71,6 +114,7 @@ exit; }#end if - -&writelog("recwrap RECSTART $recch $reclength 0 $outputfilename $bitrate $tid $countno $pid"); +# アナログ録画 +&writelog("recwrap RECSTART $recch $reclength 0 $outputfilename $bitrate $tid $countno $pid $usedigital $digitalstationband $digitalch"); + #録画 #system("$toolpath/perl/tvrecording.pl $recch $reclength 0 $outputfile $bitrate $tid $countno"); @@ -83,10 +127,22 @@ exit; } + +}#endif #デジタル優先フラグ + #デバイスビジーで即死してないか検出 $now = (`date +%s`); if ($now < $starttime + 100){ #録画プロセス起動してから100秒以内に戻ってきてたら + $retrycounter == 0; while($now < $starttime + 100){ + if($retrycounter >= 5){ + &writelog("recwrap WARNING Giving up recording."); + last; + } &writelog("recwrap retry recording $now $starttime"); + #アナログ録画 $starttime = (`date +%s`); +if($outputfilename =~ /.m2t$/){ + $outputfilename =~ s/.m2t$/.m2p/; +} $oserr = system("$toolpath/perl/tvrecording.pl $recch $reclength N $outputfilename $bitrate $tid $countno"); $now = (`date +%s`); @@ -96,67 +152,73 @@ exit; }# if + $retrycounter++; }# while } # if - &writelog("recwrap RECEND [$outputfilename] $recch $reclength 0 0 $bitrate $tid $countno $pid"); -#DB初期化 - my $data_source = sprintf("dbi:%s:dbname=%s;host=%s;port=%d", - $DBDriv,$DBName,$DBHost,$DBPort); - $dbh = DBI->connect($data_source,$DBUser,$DBPass) ||die $DBI::error;; # m2pファイル名をPIDレコードに書き込み - $DBQuery = "UPDATE foltia_subtitle SET - m2pfilename = '$outputfilename' - WHERE pid = '$pid' "; + $DBQuery = "UPDATE foltia_subtitle SET m2pfilename = '$outputfilename' WHERE pid = '$pid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); -&writelog("recwrap UPDATEDB $DBQuery"); +&writelog("recwrap DEBUG UPDATEDB $DBQuery"); +&changefilestatus($pid,$FILESTATUSRECEND); # m2pファイル名をPIDレコードに書き込み - $DBQuery = "insert into foltia_m2pfiles values ('$outputfilename')"; + $DBQuery = "insert into foltia_m2pfiles values ('$outputfilename')"; $sth = $dbh->prepare($DBQuery); $sth->execute(); -&writelog("recwrap UPDATEDB $DBQuery"); +&writelog("recwrap DEBUG UPDATEDB $DBQuery"); # Starlight breaker向けキャプチャ画像作成 if (-e "$toolpath/perl/captureimagemaker.pl"){ &writelog("recwrap Call captureimagemaker $outputfilename"); +&changefilestatus($pid,$FILESTATUSCAPTURE); system ("$toolpath/perl/captureimagemaker.pl $outputfilename"); -} - - - -# PSP ------------------------------------------------------ -#PSPトラコン必要かどうか -$DBQuery = "SELECT psp,aspect,title FROM foltia_program WHERE tid = '$tid' "; +&changefilestatus($pid,$FILESTATUSCAPEND); +} + + + +# MPEG4 ------------------------------------------------------ +#MPEG4トラコン必要かどうか +$DBQuery = "SELECT psp,aspect,title FROM foltia_program WHERE tid = '$tid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); @psptrcn= $sth->fetchrow_array; - if ($psptrcn[0] == 1 ){#トラコン番組 - - -#PSPムービーディレクトリがアルかどうか +if ($psptrcn[0] == 1 ){#トラコン番組 +&writelog("recwrap Launch ipodtranscode.pl"); +exec ("$toolpath/perl/ipodtranscode.pl"); +exit; +# +# ここから下は旧エンコード#2008/12/23 +# 新エンコードはDBを見て未完了MPEG2を順次トラコン処理、 +# 分散エンコードもきっとラクチンに対応可能 +# 新エンコードではXviD/M4VスタイルとPSPファイル名対応を廃止 + +&changefilestatus($pid,80); +#MPEG4ムービーディレクトリがあるかどうか #TIDが100以上の3桁の場合はそのまま my $pspfilnamehd = ""; - $pspfilnamehd = $tid; +$pspfilnamehd = $tid; +&makemp4dir($tid); $pspdirname = "$tid.localized/"; $pspdirname = $recfolderpath."/".$pspdirname; #なければ作る -unless (-e $pspdirname ){ - system("$toolpath/perl/mklocalizeddir.pl $tid"); - #&writelog("recwrap mkdir $pspdirname"); -} +#unless (-e $pspdirname ){ +# system("$toolpath/perl/mklocalizeddir.pl $tid"); +# #&writelog("recwrap mkdir $pspdirname"); +#} $pspdirname = "$tid.localized/mp4/"; $pspdirname = $recfolderpath."/".$pspdirname; #なければ作る -unless (-e $pspdirname ){ - mkdir $pspdirname ,0777; - #&writelog("recwrap mkdir $pspdirname"); -} +#unless (-e $pspdirname ){ +# mkdir $pspdirname ,0777; +# #&writelog("recwrap mkdir $pspdirname"); +#} #ファイル名決定 @@ -350,7 +412,5 @@ # MP4ファイル名をPIDレコードに書き込み - $DBQuery = "UPDATE foltia_subtitle SET - PSPfilename = '$mp4filename' - WHERE pid = '$pid' "; + $DBQuery = "UPDATE foltia_subtitle SET PSPfilename = '$mp4filename' WHERE pid = '$pid' "; $sth = $dbh->prepare($DBQuery); $sth->execute(); @@ -358,12 +418,95 @@ # MP4ファイル名をfoltia_mp4files挿入 - $DBQuery = "insert into foltia_mp4files values ('$tid','$mp4filename') "; + $DBQuery = "insert into foltia_mp4files values ('$tid','$mp4filename') "; $sth = $dbh->prepare($DBQuery); $sth->execute(); &writelog("recwrap UPDATEmp4DB $DBQuery"); +&changefilestatus($pid,200); }#PSPトラコンあり - - - +sub continuousrecordingcheck(){ +my $now = `date +%s --date "2 min "`; +&writelog("recwrap DEBUG continuousrecordingcheck() now $now"); +my @processes =`ps ax | grep recfriio`; + +my $psline = ""; +my @processline = ""; +my $pid = ""; +my @pid; +my $sth; +foreach (@processes){ + if (/friiodetect/) { + if (/^.[0-9]*\s/){ + push(@pid, $&); + }#if + }#if +}#foreach + +if (@pid > 0){ +my @filenameparts; +my $tid = ""; +my $startdate = ""; +my $starttime = ""; +my $startdatetime = ""; +my @recfile; +my $endtime = ""; +my $endtimeepoch = ""; +foreach $pid (@pid){ +#print "DEBUG PID $pid\n"; +&writelog("recwrap DEBUG continuousrecordingcheck() PID $pid"); + + my @lsofoutput = `/usr/sbin/lsof -p $pid`; + my $filename = ""; + #print "recfolferpath $recfolderpath\n"; + foreach (@lsofoutput){ + if (/m2t/){ + @processline = split(/\s+/,$_); + $filename = $processline[8]; + #print "DEBUG $_ \n"; + #print "DEBUG $processline[0]/$processline[1]/$processline[2]/$processline[3]/$processline[4]/$processline[5]/$processline[6]/$processline[7]/$processline[8] \n"; + $filename =~ s/$recfolderpath\///; + #print "DEBUG FILENAME $filename\n"; + &writelog("recwrap DEBUG continuousrecordingcheck() FILENAME $filename"); + # 1520-9-20081201-0230.m2t + @filenameparts = split(/-/,$filename); + $tid = $filenameparts[0]; + $startdate = $filenameparts[2]; + $starttime = $filenameparts[3]; + $startdatetime = $filenameparts[2].$filenameparts[3]; + #DBから録画中番組のデータ探す + $DBQuery = " +SELECT foltia_subtitle.tid,foltia_subtitle.countno,foltia_subtitle.subtitle,foltia_subtitle.startdatetime ,foltia_subtitle.enddatetime ,foltia_subtitle.lengthmin ,foltia_tvrecord.bitrate , foltia_subtitle.startoffset , foltia_subtitle.pid ,foltia_tvrecord.digital +FROM foltia_subtitle ,foltia_tvrecord +WHERE +foltia_tvrecord.tid = foltia_subtitle.tid AND +foltia_tvrecord.tid = $tid AND +foltia_subtitle.startdatetime = $startdatetime AND +foltia_tvrecord.digital = 1"; + &writelog("recwrap DEBUG continuousrecordingcheck() $DBQuery"); + $sth = $dbh->prepare($DBQuery); + &writelog("recwrap DEBUG continuousrecordingcheck() prepare"); + $sth->execute(); + &writelog("recwrap DEBUG continuousrecordingcheck() execute"); + @recfile = $sth->fetchrow_array; + &writelog("recwrap DEBUG continuousrecordingcheck() @recfile $recfile[0] $recfile[1] $recfile[2] $recfile[3] $recfile[4] $recfile[5] $recfile[6] $recfile[7] $recfile[8] $recfile[9] "); + #終了時刻 + $endtime = $recfile[4]; + $endtimeepoch = &foldate2epoch($endtime); + &writelog("recwrap DEBUG continuousrecordingcheck() $recfile[0] $recfile[1] $recfile[2] $recfile[3] $recfile[4] $recfile[5] endtimeepoch $endtimeepoch"); + if ($endtimeepoch < $now){#まもなく終わる番組なら + #kill + system("kill $pid"); + &writelog("recwrap recording process killed $pid/$endtimeepoch/$now"); + } + }#endif m2t + }#foreach lsofoutput +}#foreach +}else{ +#print "DEBUG fecfriio NO PID\n"; +&writelog("recwrap No recording process killed."); +} +}#endsub + + +