From b56ad458cad0a06ca3308c2e81de1cac83cfc27d Mon Sep 17 00:00:00 2001 From: James Meyer Date: Thu, 26 Mar 2009 11:20:28 -0500 Subject: mythnuv2mkv: Add. Ref FS#294 --- abs/extra-testing/mythnuv2mkv/PKGBUILD | 16 + abs/extra-testing/mythnuv2mkv/mythnuv2mkv.sh | 2759 ++++++++++++++++++++++++++ 2 files changed, 2775 insertions(+) create mode 100644 abs/extra-testing/mythnuv2mkv/PKGBUILD create mode 100644 abs/extra-testing/mythnuv2mkv/mythnuv2mkv.sh diff --git a/abs/extra-testing/mythnuv2mkv/PKGBUILD b/abs/extra-testing/mythnuv2mkv/PKGBUILD new file mode 100644 index 0000000..e0e97e6 --- /dev/null +++ b/abs/extra-testing/mythnuv2mkv/PKGBUILD @@ -0,0 +1,16 @@ +pkgname=mythnuv2mkv +pkgver=1.44 +pkgrel=1 +conflicts=() +pkgdesc="Converts MythTV nuv or mpg files to mkv, mp4 or avi files. It can be run as a MythTV User Job or at command line to convert MythTV recordings or stand alone files." +depends=(perl mplayer wget bc imagemagick lame x264 faac faad2 mkvtoolnix vorbis-tools gpac ) +arch=('i686') +license=('GPL') +source=(mythnuv2mkv.sh) + +install='' +build() { + mkdir -p $startdir/pkg/usr/bin + install -m 0755 mythnuv2mkv.sh $startdir/pkg/usr/bin/mythnuv2mkv.sh +} + diff --git a/abs/extra-testing/mythnuv2mkv/mythnuv2mkv.sh b/abs/extra-testing/mythnuv2mkv/mythnuv2mkv.sh new file mode 100644 index 0000000..4d3e95f --- /dev/null +++ b/abs/extra-testing/mythnuv2mkv/mythnuv2mkv.sh @@ -0,0 +1,2759 @@ +#!/bin/bash +# @(#)$Header: /home/mythtv/mythtvrep/scripts/mythnuv2mkv.sh,v 1.44 2009/03/18 20:11:57 mythtv Exp $ +# Auric 2007/07/10 http://web.aanet.com.au/auric/ +########################################################################################################## +# +# Convert MythRecording & MythVideo nuv or mpg files to mkv mp4 or avi. +# +######### Vars you may want to set for your environment ###################################################### +# Default aspect for Myth Recording mpg files. It will try to work it out but if it can't will use this. +readonly DEFAULTMPEG2ASPECT="NA" # 4:3 or 16:9 +# What to separate Title SeasonEpisode SubTitle with +readonly SEP="," +# Crop input +CROP="ON" # ON | OFF, can also change with --crop argument +# Delete recording after successful transcode. Only for transcode out of MythRecording. (Actually just sets to high priority autoexpire.) +DELETEREC="OFF" # ON | OFF, can also change with --deleterec argument +# Include denoise filter +DENOISE="OFF" # ON | OFF, can also change with --denoise argument +# Include deblock filter +DEBLOCK="OFF" # ON | OFF, can also change with --deblock argument +# Include deinterlace filter. +# SOURCENAME is ON for that source. Can have multiple. e.g. DEINTERLACE="Cabel,FTA1" +DEINTERLACE="ON" # ON | OFF | SOURCENAME,SOURCENAME can also change with --deinterlace argument. +# Include inverse Telecine filter (Experimental. Can someone from NTSC/ATSC land try this?). +# invtelecine filter is never added if deinterlace has been added. +INVTELECINE="OFF" # ON | OFF, can also change with --invtelecine argument. +# number passes +PASS="two" # one | two, can also change with --pass argument +# number of threads. Only used by lavc and xvid (x.264 auto calculates threads) +THREADS=1 +# avi encoder lavc or xvid +AVIVID="lavc" # lavc | xvid, can also change with --contype=avi,xvid argument +# container +CONTYPE="mkv" # mkv | mp4 | avi, can also change with --contype argument or name of script. +# mkv audio encoder aac or ogg +MKVAUD="aac" # aac | ogg, can also change with --contype=mkv,ogg argument +# add your own filters if you want +POSTVIDFILTERS="" #must include , at end +ENDVIDFILTERS="" #must include , at end +########################################################################################################## +USAGE='mythnuv2mkv.sh [--jobid=%JOBID%] [--contype=avi|mkv|mp4] [--quality=low|med|high|480|576|720|1080] [--pass=one|two] [--denoise=ON|OFF] [--deblock=ON|OFF] [--deleterec=ON|OFF] [--crop=ON|OFF] [--deinterlace=ON|OFF|SOURCENAME] [--invtelecine=ON|OFF] [--maxrunhours=int] [--findtitle=string] [--copydir=directory] "--chanid=chanid --starttime=starttime" | file ... +Must have either --chanid=chanid and --starttime=starttime or a plain filename. These can be mixed. e.g. - +mythnuv2mkv.sh --chanid=1232 --starttime=20071231235900 video1 video2 --chanid=1235 --starttime=20071231205900 +--jobid=%JOBID% + Add this when run as a User Job. Enables update status in the System Status Job Queue screen and the Job Queue Comments field in MythWeb. Also enables stop/pause/resume of job. +--contype=avi|mkv|mp4 (default name of script. e.g. mythnuv2mkv.sh will default to mkv. mythnuv2avi.sh will default to avi) + (Note Videos staying in MythRecord will always default to avi) + avi - Video mpeg4 Audio mp3 (--contype=avi,xvid will use xvid instead of lavc) + mkv - Video h.264 Audio aac (--contype=mkv,ogg will use ogg Vorbis Audio) + mp4 - Video h.264 Audio aac +--quality=low|med|high|720|1080 (default med) Mostly affects resolution. + low - 448x336(4:3) or 592x336(16:9) + med - 512x384(4:3) or 624x352(16:9) + high - 528x400(4:3) or 656x368(16:9) + 480 - 640x480(4:3) or 848x480(16:9) + 576 - 768x576(4:3) or 1024x576(16:9) + 720 - 1280x720(16:9) (You probably need VDAPU to play this) + 1080 - 1920x1088(16:9) (You probably need VDAPU to play this) +--pass=one|two (default two) + --quality --pass and --contype can be passed as any argument and will only take effect on files after them. + e.g. mythnuv2mkv.sh videofile1 --chanid=2033 --starttime=20070704135700 --pass=one video3 --quality=low video4 + videofile1 and chanid=2033/starttime=20070704135700 will be two pass med quality (defaults) + video3, one pass med quality + video4, one pass low quality +--maxrunhours=int (default process all files) + Stop processing files after int hours. (Will complete the current file it is processing.) +--findtitle="string" + Prints tile, chanid, starttime of programs matching string. +--copydir=directory + mkv/mp4/avi file will be created in directory. Source nuv will be retained. i.e you are copying the source rather than replacing it. + If the source was a CHANID/STARTIME it will be renamed to TITLE,S##E##,SUBTITLE. S##E## is the Season and Episode number. All punctuation characters are removed. + If directory is under MythVideoDir, imdb will be searched, a MythVideo db entry created and a coverfile file created if one was not available at imdb. +--denoise=[ON|OFF] (default OFF) + Include hqdn3d denoise filter. +--deblock=[ON|OFF] (default OFF) + Include pp7 deblock filter. +--deleterec=[ON|OFF] (default OFF) + Delete the recording after successful transcode. (Actually just sets high priority autoexpire and moves to Deleted group.) +--crop=[ON|OFF] (default ON) + Crop 8 pixels of each side. +--deinterlace==[ON|OFF|SOURCENAME] (default ON) + Include pp=fd deinterlace filter. + SOURCENAME is ON for that source. Can have multiple. e.g. DEINTERLACE="Cabel,FTA1" +--invtelecine=[ON|OFF] (default OFF) + Include pullup inverse telecine filter. + Note/ This filter will not be added if a deinterlace filter has been added. + +Logs to /var/tmp/mythnuv2mkvPID.log and to database if "log MythTV events to database" is enabled in mythtv. +Cutlists are always honored. +Sending the mythnuv2mkv.sh process a USR1 signal will cause it to stop after completing the current file. +e.g. kill -s USR1 PID +If run as a Myth Job, you can find the PID in the System Status Job Queue or Log Entries screens as [PID] + +Typical usage. + +Myth User Job +PATH/mythnuv2mkv.sh --jobid=%JOBID% --copydir /mythvideodirectory --chanid=%CHANID% --starttime=%STARTTIME% +This will convert nuv to mkv and copy it to /mythvideodirectory. +This is what I do. Record things in Myth Recording and anything I want to keep, use this to convert to mkv and store in Myth Video. +NOTE. System Status Job Queue screen and the Job Queue Comments field in MythWeb always report job Completed Successfully even if it actually failed. + +Myth Video +Record program +mythrename.pl --link --format %T-%S --underscores --verbose (mythrename.pl is in the mythtv contrib directory +cp from your mythstore/show_names/PROGRAM to your MythVideo directory +use video manager to add imdb details +nuv files work fine in MythVideo, but if you need to convert them to mkv/mp4/avi, or need to reduce their size +run mythnuv2mkv.sh MythVideo_file.nuv + +Myth Recording +Record program +run mythnuv2mkv.sh --findtitle="title name" +get chanid and starttime +run mythnuv2mkv.sh --chanid=chanid --starttime=starttime +NOTE You cannot edit a avi/mp4/mkv file in Myth Recording. So do all your editing in the nuv file before you convert to avi. +NOTE You cannot play a mkv/mp4 file in Myth Recording. +I would in general recommend leaving everything in Myth Recording as nuv. + +Version: $Revision: 1.44 $ $Date: 2009/03/18 20:11:57 $ +' +REQUIREDAPPS=' +Required Applications +For all contypes +mythtranscode. +perl +mplayer http://www.mplayerhq.hu/design7/news.html +mencoder http://www.mplayerhq.hu/design7/news.html +wget http://www.gnu.org/software/wget/ +ImageMagick http://www.imagemagick.org/script/index.php +For avi +mp3lame http://www.mp3dev.org +xvid http://www.xvid.org/ +For mkv and mp4 contypes +x264 http://www.videolan.org/developers/x264.html +faac http://sourceforge.net/projects/faac/ +faad2 http://sourceforge.net/projects/faac/ +For mkv contype +mkvtoolnix http://www.bunkus.org/videotools/mkvtoolnix/ +For mkv,ogg contype +vorbis-tools http://www.vorbis.com/ +For mp4 contype +MP4Box http://gpac.sourceforge.net/index.php +' +HELP=${USAGE}${REQUIREDAPPS} + +##### Mapping ############################################################################################# +# Maps tvguide categories to mythvideo ones. This will need to be managed individually. +# Either use the defaults below or create a mythnuv2mkv-category-mappings file in the same +# directory as this and enter data same format as below. +readonly CMAPFILE="$(dirname ${0})/mythnuv2mkv-category-mappings" +if [ -f "$CMAPFILE" ] +then + . "$CMAPFILE" +else + # NOTE: Remove any spaces from XMLTV category. e.g. "Mystery and Suspense" is MysteryandSuspense + # XMLTV Category ; Myth videocategory + readonly Animated=1 ; mythcat[1]="Animation" + readonly Biography=2 ; mythcat[2]="Documentary" + readonly Historical=3 ; mythcat[3]="Documentary" + readonly CrimeDrama=4 ; mythcat[4]="CrimeDrama" + readonly MysteryandSuspense=5 ; mythcat[5]="Mystery" + readonly Technology=6 ; mythcat[6]="Documentary" + readonly ScienceFiction=7 ; mythcat[7]="Sci-Fi" + readonly Science_Fiction=8 ; mythcat[8]="Sci-Fi" + readonly art=9 ; mythcat[9]="Musical" + readonly History=10 ; mythcat[10]="Documentary" + readonly SciFi=11 ; mythcat[11]="Sci-Fi" + readonly ScienceNature=12 ; mythcat[12]="Science" +fi + +########################################################################################################### +PATH=~mythtv/bin:${HOME}/bin:$PATH:/usr/local/bin +readonly AVIREQPROGS="mencoder mythtranscode mplayer perl wget convert" +readonly AVIREQLIBS="libmp3lame.so libxvidcore.so" +readonly MP4REQPROGS="mencoder mythtranscode mplayer perl wget convert faac MP4Box" +readonly MP4REQLIBS="libx264.so libfaac.so" +readonly MKVREQPROGS="mencoder mythtranscode mplayer perl wget convert faac oggenc mkvmerge" +readonly MKVREQLIBS="libx264.so libfaac.so" +########################################################### +readonly DENOISEFILTER="hqdn3d" +readonly DEBLOCKFILTER="pp7" +readonly DEINTERLACEFILTER="pp=fd" +readonly INVTELECINEFILTER="pullup" +readonly FAACCHANCONFIG="-I 5,6" +readonly CROPSIZE=8 +readonly TE_SCALE43="NA" # NA +readonly ST_SCALE43="NA" # NA +readonly FE_SCALE43="640:480" # 1.32 +readonly FS_SCALE43="768:576" # 1.32 +readonly HIGH_SCALE43=528:400 # 1.32 +readonly MED_SCALE43=512:384 # 1.333 +readonly LOW_SCALE43=448:336 # 1.333 +readonly TE_SCALE169="1920:1088" # 1.778 +readonly ST_SCALE169="1280:720" # 1.778 +readonly FE_SCALE169="848:480" # 1.766 +readonly FS_SCALE169="1024:576" # 1.778 +readonly HIGH_SCALE169=656:368 # 1.783 +readonly MED_SCALE169=624:352 # 1.773 +readonly LOW_SCALE169=592:336 # 1.762 +# Default +SCALE43=$MED_SCALE43 +SCALE169=$MED_SCALE169 +########################################################### +## CQ ## Quote from mencoder documentation +#The CQ depends on the bitrate, the video codec efficiency and the movie resolution. In order to raise the CQ, typically you would +#downscale the movie given that the bitrate is computed in function of the target size and the length of the movie, which are constant. +#With MPEG-4 ASP codecs such as Xvid and libavcodec, a CQ below 0.18 usually results in a pretty blocky picture, because there are +#not enough bits to code the information of each macroblock. (MPEG4, like many other codecs, groups pixels by blocks of several pixels +#to compress the image; if there are not enough bits, the edges of those blocks are visible.) It is therefore wise to take a CQ ranging +# from 0.20 to 0.22 for a 1 CD rip, and 0.26-0.28 for 2 CDs rip with standard encoding options. More advanced encoding options such as +#those listed here for libavcodec and Xvid should make it possible to get the same quality with CQ ranging from 0.18 to 0.20 for a 1 CD +#rip, and 0.24 to 0.26 for a 2 CD rip. With MPEG-4 AVC codecs such as x264, you can use a CQ ranging from 0.14 to 0.16 with standard +#encoding options, and should be able to go as low as 0.10 to 0.12 with x264's advanced encoding settings. +######################## +# These map to --quality=low|med|high option. +#### AVI lavc mpeg4 #### +readonly HIGH_LAVC_CQ=0.22 +readonly MED_LAVC_CQ=0.21 +readonly LOW_LAVC_CQ=0.20 +readonly HIGH_LAVC_OPTS="vcodec=mpeg4:threads=${THREADS}:mbd=2:trell:v4mv:last_pred=2:dia=-1:vmax_b_frames=2:vb_strategy=1:cmp=3:subcmp=3:precmp=0:vqcomp=0.6" +# high, med & low will use same settings just CQ and resolution different +# This make encoding slow. Swap following if you want lower quality to also mean faster encoding speed. +#readonly MED_LAVC_OPTS="vcodec=mpeg4:mbd=2:trell:v4mv" +#readonly LOW_LAVC_OPTS="vcodec=mpeg4:mbd=2" +readonly MED_LAVC_OPTS="$HIGH_LAVC_OPTS" +readonly LOW_LAVC_OPTS="$HIGH_LAVC_OPTS" +#### AVI xvid mpeg4 #### +readonly HIGH_XVID_CQ=0.22 +readonly MED_XVID_CQ=0.21 +readonly LOW_XVID_CQ=0.20 +readonly HIGH_XVID_OPTS="threads=${THREADS}:quant_type=mpeg:me_quality=6:chroma_me:chroma_opt:trellis:hq_ac:vhq=4:bvhq=1" +readonly MED_XVID_OPTS="$HIGH_XVID_OPTS" +readonly LOW_XVID_OPTS="$HIGH_XVID_OPTS" +#### AVI lavc/xvid mp3 #### +readonly HIGH_MP3_ABITRATE=256 +readonly MED_MP3_ABITRATE=192 +readonly LOW_MP3_ABITRATE=128 +#### MP4/MKV h.263/aac,ogg #### +readonly HIGH_X264_CQ=0.15 +readonly MED_X264_CQ=0.14 +readonly LOW_X264_CQ=0.13 +# H.264 Extended profile (quicktime) level set in QLEVEL +readonly HIGH_X264EXT_OPTS="nocabac:bframes=2:nob_pyramid:threads=auto:direct_pred=auto:subq=6:frameref=5" +# high, med & low will use same settings just CQ and resolution different +# This make encoding slow. Swap following if you want lower quality to also mean faster encoding speed. +#readonly MED_X264EXT_OPTS="level_idc=31:nocabac:bframes=2:nob_pyramid:threads=auto:subq=5:frameref=4" +#readonly LOW_X264EXT_OPTS="level_idc=31:nocabac:bframes=2:nob_pyramid:threads=auto:subq=4:frameref=3" +readonly MED_X264EXT_OPTS="$HIGH_X264EXT_OPTS" +readonly LOW_X264EXT_OPTS="$HIGH_X264EXT_OPTS" +# H.264 High profile level set in QLEVEL +readonly HIGH_X264HIGH_OPTS="bframes=3:b_pyramid:weight_b:threads=auto:direct_pred=auto:subq=6:frameref=5:partitions=all:8x8dct:mixed_refs:me=umh:trellis=1" +# high, med & low will use same settings just CQ and resolution different +# This make encoding slow. Swap following if you want lower quality to also mean faster encoding speed. +#readonly MED_X264HIGH_OPTS="level_idc=31:bframes=3:b_pyramid:weight_b:threads=auto:subq=5:frameref=4:8x8dct" +#readonly LOW_X264HIGH_OPTS="level_idc=31:bframes=3:b_pyramid:weight_b:threads=auto:subq=4:frameref=3" +readonly MED_X264HIGH_OPTS="$HIGH_X264HIGH_OPTS" +readonly LOW_X264HIGH_OPTS="$HIGH_X264HIGH_OPTS" +# AAC +readonly HIGH_AAC_AQUAL=100 +readonly MED_AAC_AQUAL=90 +readonly LOW_AAC_AQUAL=80 +# OGG +readonly HIGH_OGG_AQUAL=6 +readonly MED_OGG_AQUAL=5 +readonly LOW_OGG_AQUAL=4 +# Defaults +LAVC_OPTS=$MED_LAVC_OPTS +LAVC_CQ=$MED_LAVC_CQ +XVID_OPTS=$MED_XVID_OPTS +XVID_CQ=$MED_XVID_CQ +MP3_ABITRATE=$MED_MP3_ABITRATE +AAC_AQUAL=$MED_AAC_AQUAL +OGG_AQUAL=$MED_OGG_AQUAL +X264EXT_OPTS="level_idc=31:$MED_X264EXT_OPTS" +X264_OPTS="level_idc=31:$MED_X264HIGH_OPTS" +X264_CQ=$MED_X264_CQ +if echo "$(basename $0)" | grep -i 'mkv' >/dev/null 2>&1 +then + CONTYPE="mkv" + QUICKTIME_MP4="NO" +elif echo "$(basename $0)" | grep -i 'mp4' >/dev/null 2>&1 +then + CONTYPE="mp4" + QUICKTIME_MP4="NO" +elif echo "$(basename $0)" | grep -i 'mov' >/dev/null 2>&1 +then + #TODO. Not working yet don't use mov + CONTYPE="mp4" + QUICKTIME_MP4="YES" +elif echo "$(basename $0)" | grep -i 'avi' >/dev/null 2>&1 +then + CONTYPE="avi" + QUICKTIME_MP4="NO" +fi +########################################################### +# ON or OFF +# debug mode +DEBUG="OFF" +DEBUGSQL="OFF" +DEBUGSG="OFF" +# Print INFO messages +INFO="ON" +# Save(via a rename) or delete nuv file. Only for transcode back into MythRecording. +SAVENUV="OFF" + +[ "$DEBUGSQL" = "ON" ] && DEBUG="ON" + +##### Functions ########################################### +scriptlog() { +local LEVEL="$1" +shift +local PRIORITY +local HIGHLIGHTON +local HIGHLIGHTOFF + if [ "$LEVEL" = "BREAK" ] + then + echo "--------------------------------------------------------------------------------" | tee -a $LOGFILE + return 0 + elif [ "$LEVEL" = "ERROR" ] + then + PRIORITY=4 + HIGHLIGHTON="${REDFG}" + HIGHLIGHTOFF="${COLOURORIG}" + # Global + FINALEXIT=1 + elif [ "$LEVEL" = "SUCCESS" ] + then + PRIORITY=5 + HIGHLIGHTON="${GREENFG}" + HIGHLIGHTOFF="${COLOURORIG}" + elif [ "$LEVEL" = "START" -o "$LEVEL" = "STOP" ] + then + PRIORITY=5 + HIGHLIGHTON="${BOLDON}" + HIGHLIGHTOFF="${ALLOFF}" + elif [ "$LEVEL" = "DEBUG" ] + then + [ "$DEBUG" = "ON" ] || return + PRIORITY=7 + HIGHLIGHTON="" + HIGHLIGHTOFF="" + elif [ "$LEVEL" = "NOHEADER" ] + then + # Also no db logging + echo "$*" | tee -a $LOGFILE + return + else + [ "$INFO" = "ON" ] || return + LEVEL="INFO" + PRIORITY=6 + HIGHLIGHTON="" + HIGHLIGHTOFF="" + fi + echo "${HIGHLIGHTON}$(date +%d/%m,%H:%M) [${$}] $LEVEL $*${HIGHLIGHTOFF}" | tee -a $LOGFILE + + [ "$DBLOGGING" -eq 1 ] && insertmythlogentry "$PRIORITY" "$LEVEL" "${$}" "$*" +} + +chkreqs() { +local REQPROGS="$1" +local REQLIBS="$2" +local TMP +local MENCODER + for TMP in $REQPROGS + do + if ! which "$TMP" >/dev/null 2>&1 + then + scriptlog ERROR "Can't find program $TMP." + scriptlog ERROR "$REQUIREDAPPS" + return 1 + fi + done + MENCODER=$(which mencoder) + for TMP in $REQLIBS + do + if ! ldd $MENCODER | grep -i "${TMP}.*=>.*${TMP}" >/dev/null 2>&1 + then + scriptlog ERROR "mencoder may not support $TMP." + scriptlog ERROR "$REQUIREDAPPS" + return 1 + fi + done + return 0 +} + +versioncheck() { +local PRODUCT="$1" + case $PRODUCT in + mkvmerge) + VER=$(mkvmerge -V | awk '/mkvmerge/ {print $2}') + OLDIFS="$IFS"; IFS="."; set - $VER; IFS="$OLDIFS" + MAJ=$(echo "$1" | tr -d [:alpha:]); MIN="$2"; PAT="$3" + MKVMERGE251BUG="NO" + if [ "$VER" = "v2.5.1" ] + then + scriptlog INFO "mkvmerge v2.5.1. There is a known bug with this version. Workaround applied." + MKVMERGE251BUG="YES" + elif [ "$MAJ" -lt 2 -o \( "$MAJ" -eq 2 -a "$MIN" -lt 2 \) ] + then + scriptlog INFO "mkvmerge $VER. This will not work with 29.97 fps video (NTSC). You need at least v2.2.0" + fi + scriptlog DEBUG "mkvmerge $VER" + ;; + esac +} + +calcbitrate() { +local ASPECT=$1 +local SCALE=$2 +local CQ=$3 +local W +local H +local BITRATE + W=$(echo $SCALE | cut -d ':' -f1) + H=$(echo $SCALE | cut -d ':' -f2) + BITRATE=$(echo "((($H^2 * $ASPECT * 25 * $CQ) / 16 ) * 16) / 1000" | bc) + echo $BITRATE +} + +getsetting() { +local VALUE="$1" +local HOST=$(hostname) +local DATA + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select data from settings where value = "$VALUE" and hostname like "${HOST}%"; + EOF) + if [ -z "$DATA" ] + then + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select data from settings where value = "$VALUE" and (hostname is NULL or hostname = ""); + EOF) + fi + echo "$DATA" +} + +getstoragegroupdirs() { + mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select distinct dirname from storagegroup; + EOF +} + +hascutlist() { +local CHANID="$1" +local STARTTIME="$2" +local DATA + [ -n "$CHANID" ] || return 1 + DATA=$(mysql --batch --skip-column-name --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select cutlist from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + [ "$DATA" -eq 1 ] && return 0 || return 1 +} + +getrecordfile() { +local CHANID="$1" +local STARTTIME="$2" +local DEBUG="$3" +local HOST=$(hostname) +local DATA +local RECFILE + [ -n "$CHANID" ] || return 1 + # Storage groups + if [ "$DEBUG" = "ON" ] + then + scriptlog INFO "CHANID $CHANID STARTTIME $STARTTIME HOST $HOST" + DATA=$(mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select * from storagegroup; + select chanid,starttime,title,subtitle,basename,storagegroup from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + scriptlog INFO "Tables" + scriptlog NOHEADER "$DATA" + fi + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select concat(a.dirname, "/", b.basename) from storagegroup a, recorded b where b.chanid = $CHANID and b.starttime = "$STARTTIME" and b.storagegroup = a.groupname and a.hostname like "${HOST}%"; + EOF) + [ "$DEBUG" = "ON" ] && scriptlog INFO "Try 1 Data $DATA" + while read RECFILE + do + [ "$DEBUG" = "ON" ] && scriptlog INFO "Try 1 Check $RECFILE" + [ -f "${RECFILE}" ] && break + done < <(echo "$DATA") + if [ ! -f "$RECFILE" ] + then + # Pre Storage groups + local RFP=$(getsetting RecordFilePrefix) + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select concat("$RFP", "/", basename) from recorded where chanid = $CHANID and starttime = "$STARTTIME" limit 1; + EOF) + [ "$DEBUG" = "ON" ] && scriptlog INFO "Try 2 $RFP,$DATA" + RECFILE="$DATA" + fi + [ -f "$RECFILE" ] && echo "$RECFILE" +} + +getsourcename() { +local CHANID="$1" + [ -n "$CHANID" ] || return 1 + mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select b.displayname from channel a, cardinput b where a.chanid = $CHANID and a.sourceid = b.sourceid; + EOF +} + +gettitle() { +local CHANID="$1" +local STARTTIME="$2" + [ -n "$CHANID" ] || return 1 + mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select title, subtitle from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF +} + +findchanidstarttime() { +local SEARCHTITLE="$1" + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select title, subtitle, chanid, date_format(starttime, '%Y%m%d%H%i%s'), storagegroup from recorded where title like "%${SEARCHTITLE}%"; + EOF +} + +updatemetadata() { +local NEW="$1" +local CHANID="$2" +local STARTTIME="$3" +local NFSIZE + NFSIZE=$(stat -c %s "$NEW") + NEW=$(basename "$NEW") + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + update recorded set + basename = "$NEW", + filesize = $NFSIZE, + bookmark = 0, + editing = 0, + cutlist = 0, + commflagged = 0 + where chanid = $CHANID and starttime = "$STARTTIME"; + delete from recordedmarkup where chanid = $CHANID and starttime = "$STARTTIME"; + delete from recordedseek where chanid = $CHANID and starttime = "$STARTTIME"; + EOF +} + +createvideocover() { +local FILENAME="$1" +local ASPECT="$2" +local THDIR="${FIFODIR}/THDIR" +local THUMB_NAME=$(basename "$FILENAME" | sed -e 's/\.[am][vkp][iv4]$/\.png/') +local THUMB_PATH="${CFDIR}/${THUMB_NAME}" +local CURWD +local TH + { + CURWD=$(pwd) + mkdir $THDIR && cd $THDIR || return 1 + nice -19 mplayer -really-quiet -nojoystick -nolirc -nomouseinput -ss 00:02:00 -aspect $ASPECT -ao null -frames 50 -vo png:z=5 "$FILENAME" + TH=$(ls -1rt | tail -1) + [ -f "$TH" ] || return + if [ $ASPECT = "16:9" ] + then + convert "$TH" -resize 720x404! THWS.png + else + cp "$TH" THWS.png + fi + mv THWS.png "$THUMB_PATH" + cd $CURWD + rm -rf "$THDIR" + } >/dev/null 2>&1 + echo "$THUMB_PATH" +} + +getsearchtitle() { +local CHANID="$1" +local STARTTIME="$2" +local TI +local ST +local SEARCHTITLE + [ -n "$CHANID" ] || return 1 + TI=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select title from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + ST=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select subtitle from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + if [ -n "$TI" -a -n "$ST" ] + then + SEARCHTITLE="${TI}:${ST}" + elif [ -n "$TI" ] + then + SEARCHTITLE="${TI}" + fi + echo $SEARCHTITLE +} + +lookupinetref() { +# : is used to separate Title and SubTitle in SEARCHTITLE +local SEARCHTITLE="$1" +local CHANID="$2" +local STARTTIME="$3" +local IMDBCMD +local IMDBRES +local IMDBSTR="" +# INETREF will be 00000000 if not found +local INETREF=00000000 +local SERIES +local EPISODE +local YEAR +local TMP + { + IMDBCMD=$(getsetting MovieListCommandLine) + # This is dependent on imdb.pl and will not work with any MovieListCommandLine due to use of s=ep option. + set - $IMDBCMD + IMDBCMD="$1 $2" + IMDBRES=$($IMDBCMD "$SEARCHTITLE") + if [ -n "$IMDBRES" -a $(echo "$IMDBRES" | wc -l) -eq 1 ] + then + IMDBSTR="$IMDBRES" + elif [ -n "$CHANID" ] + then + YEAR=$(getyear $CHANID $STARTTIME) + if [ "$YEAR" -gt 1800 ] + then + for C in 0 1 -1 + do + TMP=$(echo "$IMDBRES" | grep $(( $YEAR + $C ))) + [ -n "$TMP" -a $(echo "$TMP" | wc -l) -eq 1 ] && IMDBSTR="$TMP" && break + done + fi + fi + if [ -n "$IMDBSTR" ] + then + INETREF=$(echo "$IMDBSTR" | awk -F'[^0-9]' '{print $1}') + echo $INETREF | grep '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]*$' >/dev/null 2>&1 || INETREF=00000000 + fi + if [ "$INETREF" -eq 00000000 ] + then + # Try looking for episode + OLDIFS="$IFS"; IFS=":"; set - $SEARCHTITLE; IFS="$OLDIFS" + SERIES="$1" ; EPISODE="$2" + if [ -n "$SERIES" -a -n "$EPISODE" ] + then + # option s=ep is for episode lookup + IMDBSTR=$($IMDBCMD s=ep "$EPISODE") + if which agrep >/dev/null 2>&1 + then + IMDBSTR=$(echo "$IMDBSTR" | agrep -i -s -2 "$SERIES" | sort -n | head -1 | cut -d':' -f2-) + else + IMDBSTR=$(echo "$IMDBSTR" | grep -i "$SERIES") + fi + if [ $(echo "$IMDBSTR" | wc -l) -eq 1 ] + then + INETREF=$(echo "$IMDBSTR" | awk -F'[^0-9]' '{print $1}') + echo $INETREF | grep '^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]*$' >/dev/null 2>&1 || INETREF=00000000 + fi + fi + fi + scriptlog DEBUG "inetref $INETREF" + } >/dev/null 2>&1 + echo $INETREF +} + +getseriesepisode() { +local CHANID="$1" +local STARTTIME="$2" +local INETREF="$3" +local DATA +local SE + [ -n "$CHANID" ] || return 1 + { + # STARTTIME is not always the same in both tables for matching programs. ??? + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select syndicatedepisodenumber from recorded a,recordedprogram b + where a.chanid = $CHANID and a.starttime = "$STARTTIME" and a.chanid = b.chanid + and a.title = b.title and a.subtitle = b.subtitle; + EOF) + DATA=$(echo "$DATA" | awk -F '[SE]' '/S/ {printf("S%02dE%02d\n",$3,$2)}') + if echo "$DATA" | grep '^S[0-9][0-9]E[0-9][0-9]$' >/dev/null 2>&1 + then + SE="$DATA" + elif [ $INETREF -gt 0 ] + then + # Lets try passing imdb page + wget -o /dev/null -O "${FIFODIR}/${INETREF}.html" "http://www.imdb.com/title/tt${INETREF}/" + SE=$(awk '/Season.*Episode/ { + a=match($0,/Season ([0-9]+)/,s);b=match($0,/Episode ([0-9]+)/,e);if(a>0 && b>0){printf("S%02dE%02d\n",s[1],e[1]);exit} + }' "${FIFODIR}/${INETREF}.html") + fi + scriptlog DEBUG "series episode $SE" + } >/dev/null 2>&1 + echo "$SE" | grep '^S[0-9][0-9]E[0-9][0-9]$' +} + +createfiletitleSEsubtitle() { +local CHANID="$1" +local STARTTIME="$2" +local SE="$3" +local DATA +local T +local S + [ -n "$CHANID" ] || return 1 + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select title from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + T=$(echo $DATA | tr -d '[:cntrl:]' | tr -d '[:punct:]' | tr '[:space:]' '_') + + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select subtitle from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + S=$(echo $DATA | tr -d '[:cntrl:]' | tr -d '[:punct:]' | tr '[:space:]' '_') + + if [ -n "$T" -a -n "$SE" -a -n "$S" ] + then + echo "${T}${SEP}${SE}${SEP}${S}" + elif [ -n "$T" -a -n "$S" ] + then + echo "${T}${SEP}${S}" + else + echo "${T}" + fi +} + +createvideometadata() { +local FILENAME="$1" +local TITLE="$2" +local ASPECT="$3" +local CHANID="$4" +local STARTTIME="$5" +local INETREF="$6" +# SE may be null +local SE="$7" +local DIRECTOR="Unknown" +#local PLOT="None" +local PLOT="$(getplot $CHANID $STARTTIME)" +local MOVIERATING="NR" +#local YEAR=1895 +local YEAR="$(getyear $CHANID $STARTTIME)" +local USERRATING=0 +local RUNTIME=0 +local COVERFILE="No Cover" +local GENRES="" +local COUNTRIES="" +local CATEGORY="" +local TI +local ST +local IMDBCMD +local IMDBSTR +local GTYPE +local TH +local SE +local S +local E +local WHERE +local INSERT +local TMP +local IDS +local INTID +local COUNT + # Title name generation is a mess. Should do something better + if hasvideometadata "$FILENAME" + then + scriptlog INFO "$FILENAME already has a videometdata entry" + return 0 + else + # Since I strip special characters in TITLE, use chanid/starttime for metadata title. + if [ -n "$CHANID" ] + then + TI=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select title from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + ST=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select subtitle from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + if [ -n "$TI" -a -n "$SE" -a -n "$ST" ] + then + TITLE="\\\"${TI}\\\" ${SE} ${ST}" + elif [ -n "$TI" -a -n "$ST" ] + then + TITLE="\\\"${TI}\\\" ${ST}" + elif [ -n "$TI" ] + then + TITLE="${TI}" + fi + fi + if [ $INETREF -gt 0 ] + then + IMDBCMD=$(getsetting MovieDataCommandLine) + IMDBSTR=$($IMDBCMD $INETREF | sed -e 's/"/\\"/g') + TMP=$(echo "$IMDBSTR" | grep '^Title' | cut -d':' -f2- | sed -e 's/^ *//') + if [ -n "$TMP" ] + then + # Try and put series and episode number back in. Based on imdb placing quotes around series name. A bit dodgy + if [ -n "$SE" ] + then + TMP=$(echo "$TMP" | awk -v s=${SE} '{ + r=match($0,/"(.*)" (.*)/,m) + if(r>0) { print("\\\""m[1]"\\\" "s" "m[2]) } + else { print($0) } + }' | sed -e 's/\\\\"/\\"/g') + fi + TITLE="$TMP" + fi + TMP=$(echo "$IMDBSTR" | grep '^Year' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && YEAR="$TMP" + TMP=$(echo "$IMDBSTR" | grep '^Director' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && DIRECTOR="$TMP" + TMP=$(echo "$IMDBSTR" | grep '^Plot' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && PLOT="$TMP" + TMP=$(echo "$IMDBSTR" | grep '^UserRating' | grep -v '[<>\"]' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && USERRATING="$TMP" + TMP=$(echo "$IMDBSTR" | grep '^MovieRating' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && MOVIERATING="$TMP" + TMP=$(echo "$IMDBSTR" | grep '^Runtime' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && RUNTIME="$TMP" + IMDBCMD=$(getsetting MoviePosterCommandLine) + IMDBCOVER=$($IMDBCMD $INETREF) + if [ -n "$IMDBCOVER" ] + then + GTYPE=$(echo $IMDBCOVER | sed -e 's/.*\(\....\)/\1/') + wget -o /dev/null -O ${CFDIR}/${INETREF}${GTYPE} $IMDBCOVER + [ -f ${CFDIR}/${INETREF}${GTYPE} ] && COVERFILE="${CFDIR}/${INETREF}${GTYPE}" + fi + TMP=$(echo "$IMDBSTR" | grep '^Genres' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && GENRES="$TMP" + TMP=$(echo "$IMDBSTR" | grep '^Countries' | cut -d':' -f2- | sed -e 's/^ *//') + [ -n "$TMP" ] && COUNTRIES="$TMP" + fi + if ! [ -f "$COVERFILE" ] + then + scriptlog INFO "Creating cover file." + TH=$(createvideocover "$FILENAME" $ASPECT) + [ -f ${TH} ] && COVERFILE="${TH}" + fi + scriptlog INFO "Creating videometadata entry. Inetref:$INETREF. Title:$TITLE" + if [ "$DEBUGSQL" = "ON" ] + then + cat <<-EOF + insert into videometadata set + title = "$TITLE", + director = "$DIRECTOR", + plot = "$PLOT", + rating = "$MOVIERATING", + inetref = "$INETREF", + year = $YEAR, + userrating = $USERRATING, + length = $RUNTIME, + showlevel = 1, + filename = "$FILENAME", + coverfile = "$COVERFILE", + childid = -1, + browse = 1, + playcommand = NULL, + category = 0; + EOF + fi + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + insert into videometadata set + title = "$TITLE", + director = "$DIRECTOR", + plot = "$PLOT", + rating = "$MOVIERATING", + inetref = "$INETREF", + year = $YEAR, + userrating = $USERRATING, + length = $RUNTIME, + showlevel = 1, + filename = "$FILENAME", + coverfile = "$COVERFILE", + childid = -1, + browse = 1, + playcommand = NULL, + category = 0; + EOF + CATEGORY=$(getcategory "$CHANID" "$STARTTIME") + if [ -n "$GENRES" -o -n "$COUNTRIES" -o -n "$CATEGORY" ] + then + INTID=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select intid from videometadata where filename = "$FILENAME"; + EOF) + fi + if [ -n "$INTID" ] + then + # This will not create new genres, countries or categories. + if [ -n "$GENRES" ] + then + scriptlog DEBUG "Will check for genres $GENRES" + OLDIFS="$IFS"; IFS=','; set - $GENRES; IFS="$OLDIFS" + COUNT="$#" + WHERE="" + for TMP in "$@" + do + TMP=$(echo $TMP | tr [A-Z] [a-z]) + [ -n "$WHERE" ] && WHERE="$WHERE or lcase(genre) = \"$TMP\"" || WHERE="where lcase(genre) = \"$TMP\"" + done + [ "$DEBUGSQL" = "ON" ] && echo "select intid from videogenre $WHERE" + IDS=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select intid from videogenre $WHERE; + EOF) + for TMP in $IDS + do + INSERT="$INSERT insert into videometadatagenre set idvideo = $INTID, idgenre = $TMP;" + done + [ "$COUNT" -gt $(echo "$IDS" | wc -l) ] && scriptlog INFO "Not all genres $GENRES found" + fi + + if [ -n "$COUNTRIES" ] + then + scriptlog DEBUG "Will check for countries $COUNTRIES" + OLDIFS="$IFS"; IFS=','; set - $COUNTRIES; IFS="$OLDIFS" + COUNT="$#" + WHERE="" + for TMP in "$@" + do + TMP=$(echo $TMP | tr [A-Z] [a-z]) + [ -n "$WHERE" ] && WHERE="$WHERE or lcase(country) = \"$TMP\"" || WHERE="where lcase(country) = \"$TMP\"" + done + [ "$DEBUGSQL" = "ON" ] && echo "select intid from videocountry $WHERE" + IDS=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select intid from videocountry $WHERE; + EOF) + for TMP in $IDS + do + INSERT="$INSERT insert into videometadatacountry set idvideo = $INTID, idcountry = $TMP;" + done + [ "$COUNT" -gt $(echo "$IDS" | wc -l) ] && scriptlog INFO "Not all countries $COUNTRIES found" + fi + + if [ -n "$CATEGORY" ] + then + CATEGORY=$(echo "$CATEGORY" | tr -d ' ') + OLDIFS="$IFS"; IFS='/'; set - $CATEGORY; IFS="$OLDIFS" + for TMP in "$@" + do + # Use mappings + [ -n "${mythcat[$TMP]}" ] && TMP=${mythcat[$TMP]} + [ "$DEBUGSQL" = "ON" ] && echo "select intid from videocategory where lcase(category) = lcase("$TMP")" + IDS=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} mythconverg <<-EOF + select intid from videocategory where lcase(category) = lcase("$TMP"); + EOF) + if [ -n "$IDS" ] + then + INSERT="$INSERT update videometadata set category = $IDS where intid = $INTID;" + scriptlog INFO "Added to category $TMP" + # only 1 category + break + else + scriptlog INFO "Category $TMP does not exist" + fi + done + fi + + if [ -n "$INSERT" ] + then + [ "$DEBUGSQL" = "ON" ] && echo "$INSERT" + mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} mythconverg <<-EOF + $INSERT + EOF + fi + fi + fi + return 0 +} + +hasvideometadata() { +local FILENAME="$1" +local DATA + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select intid from videometadata where filename = "$FILENAME"; + EOF) + echo $DATA | grep '^[0-9][0-9][0-9]*$' >/dev/null 2>&1 && return 0 || return 1 +} + +deleterecording() { +local CHANID="$1" +local STARTTIME="$2" + [ -n "$CHANID" ] || return 1 + mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + update recorded set recgroup = "Deleted", autoexpire = 999 where chanid = $CHANID and starttime = "$STARTTIME"; + EOF +} + +insertmythlogentry() { +local PRIORITY="$1" +local LEVEL="$2" +local PID="$3" +local DETAILS="$(echo $4 | tr -d '[:cntrl:]' | tr -d '[\\\"]')" +local DATETIME=$(date '+%Y%m%d%H%M%S') +local HOST=$(hostname) + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + insert into mythlog set + module = "mythnuv2mkv.sh", + priority = $PRIORITY, + acknowledged = 0, + logdate = $DATETIME, + host = "$HOST", + message = "mythnuv2mkv.sh [$PID] $LEVEL", + details = "$DETAILS"; + EOF +} + +getjobqueuecmds() { +local JOBID="$1" +local DATA +local JQCMDSTR[0]="RUN" +local JQCMDSTR[1]="PAUSE" +local JQCMDSTR[2]="RESUME" +local JQCMDSTR[4]="STOP" +local JQCMDSTR[8]="RESTART" + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select cmds from jobqueue where id = $JOBID; + EOF) + echo ${JQCMDSTR[$DATA]} +} + +setjobqueuecmds() { +local JOBID="$1" +local CMDSSTR="$2" +local CMDS + if echo "$CMDSSTR" | egrep '^[0-9]+$' >/dev/null 2>&1 + then + CMDS=$CMDSSTR + elif [ "$CMDSSTR" = "RUN" ] + then + CMDS=0 + fi + if [ -n "$CMDS" ] + then + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + update jobqueue set cmds = $CMDS where id = $JOBID; + EOF + else + scriptlog ERROR "Invalid Job Queue Command." + fi +} + +getjobqueuestatus() { +local JOBID="$1" +local DATA +local JQSTATUSSTR[0]="UNKNOWN" +local JQSTATUSSTR[1]="QUEUED" +local JQSTATUSSTR[2]="PENDING" +local JQSTATUSSTR[3]="STARTING" +local JQSTATUSSTR[4]="RUNNING" +local JQSTATUSSTR[5]="STOPPING" +local JQSTATUSSTR[6]="PAUSED" +local JQSTATUSSTR[7]="RETRY" +local JQSTATUSSTR[8]="ERRORING" +local JQSTATUSSTR[9]="ABORTING" +local JQSTATUSSTR[256]="DONE" +local JQSTATUSSTR[272]="FINISHED" +local JQSTATUSSTR[288]="ABORTED" +local JQSTATUSSTR[304]="ERRORED" +local JQSTATUSSTR[320]="CANCELLED" + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select status from jobqueue where id = $JOBID; + EOF) + echo ${JQSTATUSSTR[$DATA]} +} + +setjobqueuestatus() { +local JOBID="$1" +local STATUSSTR="$2" +local STATUS + if echo "$STATUSSTR" | egrep '^[0-9]+$' >/dev/null 2>&1 + then + STATUS=$STATUSSTR + elif [ "$STATUSSTR" = "RUNNING" ] + then + STATUS=4 + elif [ "$STATUSSTR" = "PAUSED" ] + then + STATUS=6 + elif [ "$STATUSSTR" = "ABORTING" ] + then + STATUS=9 + elif [ "$STATUSSTR" = "FINISHED" ] + then + STATUS=272 + elif [ "$STATUSSTR" = "ERRORED" ] + then + STATUS=304 + fi + if [ -n "$STATUS" ] + then + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + update jobqueue set status = $STATUS where id = $JOBID; + EOF + else + scriptlog ERROR "Invalid Job Queue Status." + fi +} + +getjobqueuecomment() { +local JOBID="$1" +local COMMENT="$2" + mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select comment from jobqueue where id = $JOBID; + EOF +} + +setjobqueuecomment() { +local JOBID="$1" +local COMMENT="$2" + mysql --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + update jobqueue set comment = "$COMMENT" where id = $JOBID; + EOF +} + +# My channelprofiles table for setting aspect at channel level. +# See http://web.aanet.com.au/auric/?q=node/1 +# You probably don't have it. +getchannelaspect() { +local CHANID=$1 +local DATA + { + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} ${DBName} <<-EOF + select aspectratio from channelprofiles + where channum = (select channum from channel where chanid = $CHANID) + and sourceid = (select sourceid from channel where chanid = $CHANID); + EOF) + case $DATA in + 16:9|4:3) true ;; + '') DATA=$DEFAULTMPEG2ASPECT ;; + *) DATA=NA ;; + esac + } >/dev/null 2>&1 + echo $DATA +} + +# aspect ratio of the V4L or MPEG capture card associated with CHANID +# No good for any other type of card. e.g. DVB. +querycardaspect() { +local CHANID=$1 +local DATA + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} ${DBName} <<-EOF + select value from codecparams where name = 'mpeg2aspectratio' + and profile = (select id from recordingprofiles where name = 'default' + and profilegroup = (select id from profilegroups + where cardtype = (select cardtype from capturecard + where cardid = (select cardid from cardinput + where sourceid = (select sourceid from channel + where chanid = $CHANID) + ) + ) + ) + ); + EOF) + [ "$DATA" != "4:3" -a "$DATA" != "16:9" ] && DATA="NA" + echo $DATA +} + +getaviinfo() { +local FILE="$1" +shift +local PROPS="$@" +local MPOP +local TMP +local p +local RES +local ASPECTFOUNDIN +readonly width=1 ; infokey[1]="ID_VIDEO_WIDTH" +readonly height=2 ; infokey[2]="ID_VIDEO_HEIGHT" +readonly fps=3 ; infokey[3]="ID_VIDEO_FPS" +readonly audio_sample_rate=4 ; infokey[4]="ID_AUDIO_RATE" +readonly audio_channels=5 ; infokey[5]="ID_AUDIO_NCH" +readonly aspect=6 ; infokey[6]="ID_VIDEO_ASPECT" + MPOP=$(mplayer -really-quiet -nojoystick -nolirc -nomouseinput -vo null -ao null -frames 0 -identify "$FILE" 2>/dev/null) + for p in $PROPS + do + [ -n "${infokey[$p]}" ] && p=${infokey[$p]} + case $p in + "finfo") + TMP="NA" + ;; + "ID_VIDEO_ASPECT") + TMP="$(echo "$MPOP" | awk -F'=' '/ID_VIDEO_ASPECT/ {if($2>1.1 && $2<1.5)print "4:3";if($2>1.6 && $2<2)print "16:9"}')" + [ "$TMP" != "4:3" -a "$TMP" != "16:9" ] && TMP="NA" + ASPECTFOUNDIN="File" + if [ "$TMP" = "NA" ] && echo "$FILE" | grep '\.mpg$' >/dev/null 2>&1 && [ -n "$CHANID" ] + then + TMP=$(getchannelaspect $CHANID) + ASPECTFOUNDIN="Channel" + fi + if [ "$TMP" = "NA" ] && echo "$FILE" | grep '\.mpg$' >/dev/null 2>&1 && [ -n "$CHANID" ] + then + TMP=$(querycardaspect $CHANID) + ASPECTFOUNDIN="Card" + fi + if [ "$TMP" = "NA" ] && echo "$FILE" | grep '\.mpg$' >/dev/null 2>&1 + then + TMP=$DEFAULTMPEG2ASPECT + ASPECTFOUNDIN="Default" + fi + TMP="$TMP,$ASPECTFOUNDIN" + ;; + "ID_VIDEO_HEIGHT") + TMP="$(echo "$MPOP" | grep $p | tail -1 | cut -d'=' -f2)" + [ "$TMP" = "1080" ] && TMP="1088" # HD FIX + ;; + *) + TMP="$(echo "$MPOP" | grep $p | tail -1 | cut -d'=' -f2)" + ;; + esac + [ -z "$RES" ] && RES="$TMP" || RES="${RES}:${TMP}" + done + echo "$RES" +} + +getnuvinfo() { +export NUVINFOFILE="$1" +shift +export NUVINFOPROPS="$@" + PROPS=$(sed -n '/^#STARTNUVINFO$/,/#ENDNUVINFO/p' $CMD | perl) + echo "$PROPS" +} + +getvidinfo() { +local FILE="$1" +shift +local PROPS="$@" +local RES + if echo "$FILE" | grep '\.nuv' >/dev/null 2>&1 + then + RES=$(getnuvinfo "$FILE" $PROPS) + else + RES=$(getaviinfo "$FILE" $PROPS) + fi + echo "$RES" +} + +getaspect() { +local FILE="$1" +local ASPECT="NA" + ASPECT=$(getvidinfo "$FILE" aspect) + echo "$ASPECT" | grep ',' >/dev/null 2>&1 || ASPECT="$ASPECT,File" + echo "$ASPECT" +} + +stoptime() { +local STARTSECS=$1 +local MAXRUNHOURS=$2 +local CURSECS +local ENDSECS + [ "$MAXRUNHOURS" = "NA" ] && return 1 + CURSECS=$(date +%s) + ENDSECS=$(( $STARTSECS + ( $MAXRUNHOURS * 60 * 60 ) )) + [ "$ENDSECS" -gt "$CURSECS" ] && return 1 || return 0 +} + +checkoutput() { +local INPUT="$1" +local OUTPUT="$2" +local MENCODERRES=$3 +local VIDFOR +local OUTSIZE +local INSIZE +local RAT +local SCANOUTFILE +local LCOUNT +local ECOUNT +local INFRAMES +local OUTFRAMES +local DIFF + VIDFOR=$(getvidinfo "$OUTPUT" ID_VIDEO_FORMAT) + if [ "$VIDFOR" != "FMP4" -a "$VIDFOR" != "h264" -a "$VIDFOR" != "avc1" -a "$VIDFOR" != "avc1" -a "$VIDFOR" != "XVID" ] + then + scriptlog ERROR "$OUTPUT does not look like correct avi/mp4/mkv file." + return 1 + fi + + OUTSIZE=$(stat -c %s "$OUTPUT" 2>/dev/null || echo 0) + if [ "$OUTSIZE" -eq 0 ] + then + scriptlog ERROR "$OUTPUT zero length." + return 1 + fi + + INSIZE=$(stat -c %s "$INPUT" 2>/dev/null || echo 0) + RAT=$(( $INSIZE / $OUTSIZE )) + if ! hascutlist $CHANID $STARTTIME && [ "$RAT" -gt 16 ] + then + scriptlog ERROR "ratio between $INPUT and $OUTPUT sizes greater than 16." + return 1 + fi + + SCANOUTFILE="${FIFODIR}/mplayerscan-out" + nice mplayer -benchmark -nojoystick -nolirc -nomouseinput -vo null -ao null -speed 10 "$OUTPUT" 2>&1 | tr '\r' '\n' >$SCANOUTFILE 2>&1 + LCOUNT=$(wc -l $SCANOUTFILE 2>/dev/null | awk '{T=$1} END {if(T>0){print T}else{print 0}}') + if [ "$LCOUNT" -lt 1000 ] + then + scriptlog ERROR "mplayer line count ($LCOUNT) to low on $OUTPUT." + return 1 + fi + ECOUNT=$(egrep -ic 'sync|error|skip|damaged|overflow' $SCANOUTFILE) + if [ "$ECOUNT" -gt 5 ] + then + scriptlog ERROR "mplayer error count ($ECOUNT) to great on $OUTPUT." + return 1 + fi + + # Latest mplayer does not output frame count + #if [ -f "$MENCODERRES" ] + #then + # OUTFRAMES=$(tail -40 $SCANOUTFILE | awk '/A-V:/ {if(match($5,"/"))F=$5;if(match($6,"/"))F=$6;if(match($7,"/"))F=$7;if(match($8,"/"))F=$8;if(match($9,"/"))F=$9} END {print substr(F,index(F,"/")+1)}') + # INFRAMES=$(tail -40 $MENCODERRES | awk '/Video stream:/ {F=$12} END {print F}') + # scriptlog INFO "Frames $INFRAMES $INPUT." + # scriptlog INFO "Frames $OUTFRAMES $OUTPUT." + # if echo ${INFRAMES} : ${OUTFRAMES} | grep '[0-9] : [0-9]' >/dev/null 2>&1 + # then + # DIFF=$([ $INFRAMES -gt $OUTFRAMES ] && echo $(( $INFRAMES - $OUTFRAMES )) || echo $(( $OUTFRAMES - $INFRAMES ))) + # else + # DIFF=100000 + # fi + # if [ "$DIFF" -gt 10 ] + # then + # scriptlog ERROR "Frame count difference of $DIFF to big on $OUTPUT." + # return 1 + # fi + #fi + + return 0 +} + +getcategory() { +local CHANID="$1" +local STARTTIME="$2" +local DATA + [ -n "$CHANID" ] || return 1 + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select category from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + echo $DATA | tr -d '[:cntrl:]' | tr -d '[:punct:]' +} + +getplot() { +local CHANID="$1" +local STARTTIME="$2" +local DATA + [ -n "$CHANID" ] || return 1 + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select description from recorded where chanid = $CHANID and starttime = "$STARTTIME"; + EOF) + echo $DATA | tr -d '[:cntrl:]' | tr -d '[:punct:]' +} + +getyear() { +local CHANID="$1" +local STARTTIME="$2" +local DATA + [ -n "$CHANID" ] || return 1 + # STARTTIME is not always the same in both tables for matching programs. ??? + DATA=$(mysql --batch --skip-column-names --user=${DBUserName} --password=${DBPassword} -h ${DBHostName} ${DBName} <<-EOF + select airdate from recorded a,recordedprogram b + where a.chanid = $CHANID and a.starttime = "$STARTTIME" and a.chanid = b.chanid + and a.title = b.title and a.subtitle = b.subtitle; + EOF) + [ -n "$DATA" -a $DATA -gt 1800 ] && echo $DATA || echo $(date +%Y) +} + +encloseincontainer() { +local OUTBASE="$1" +local FPS="$2" +local AUDEXT="$3" +local CONTYPE="$4" +local ASPECT="$5" +local TITLE="$6" + if [ -f "${OUTBASE}_video.h264" -o "${OUTBASE}_audio.${AUDEXT}" ] + then + if [ "$CONTYPE" = "mkv" ] + then + if [ "$MKVMERGE251BUG" = "YES" ] + then + LANG=C mkvmerge --default-duration 0:${FPS}fps --aspect-ratio 0:${ASPECT} --title "$TITLE" \ + "${OUTBASE}_video.h264" "${OUTBASE}_audio.${AUDEXT}" -o "${OUTBASE}.mkv" + RET=$? ; [ $RET -eq 1 ] && RET=0 # mkvmerge return code of 1 is only a warning + else + mkvmerge --default-duration 0:${FPS}fps --aspect-ratio 0:${ASPECT} --title "$TITLE" \ + "${OUTBASE}_video.h264" "${OUTBASE}_audio.${AUDEXT}" -o "${OUTBASE}.mkv" + RET=$? ; [ $RET -eq 1 ] && RET=0 # mkvmerge return code of 1 is only a warning + fi + elif [ "$CONTYPE" = "mp4" ] + then + MP4Box -add "${OUTBASE}_video.h264:par=1:1" -add "${OUTBASE}_audio.${AUDEXT}" -fps $FPS "${OUTBASE}.mp4" + RET=$? + fi + if [ $RET -eq 0 ] + then + [ "$DEBUG" != "ON" ] && rm -f "${OUTBASE}_video.h264" "${OUTBASE}_audio.${AUDEXT}" + else + [ "$DEBUG" != "ON" ] && rm -f "${OUTBASE}_video.h264" "${OUTBASE}_audio.${AUDEXT}" "${OUTBASE}.mkv" >/dev/null 2>&1 + return 1 + fi + else + scriptlog ERROR "${OUTBASE}_video.h264 or ${OUTBASE}_audio.${AUDEXT} does not exist." + return 1 + fi + return 0 +} + +logtranstime () { +local START=$1 +local END=$2 +local ORIGINALFILESIZE=$3 +local NEWFILESIZE=$4 + TMP=$(( $(date -u -d"${END}" +%s) - $(date -u -d"${START}" +%s) )) + DAYS=$(( $TMP / 60 / 60 / 24 )) + HOURS=$(( $TMP / 60 / 60 - ($DAYS * 24) )) + MINUTES=$(( $TMP / 60 - ( ($HOURS * 60)+($DAYS * 24 * 60) ) )) + SECONDS=$(( $TMP - ( ($MINUTES * 60)+($HOURS * 60 * 60)+($DAYS * 24 * 60 * 60) ) )) + scriptlog INFO "RUNTIME: $DAYS days $HOURS hours $MINUTES minutes and $SECONDS seconds. Original filesize: $ORIGINALFILESIZE New filesize: $NEWFILESIZE" +} + +cleanup() { +local SIG="$1" +local JOBID="$2" +local OUTPUT="$3" +local OUTBASE +local TRANPID + scriptlog DEBUG "$SIG Clean up." + if [ "$SIG" = "ABRT" ] + then + scriptlog ERROR "Job Aborted. Removing incomplete $OUTPUT." + OUTBASE=$(echo "$OUTPUT" | sed -e 's/\.[ma][pv][4i]$//') + [ "$DEBUG" != "ON" ] && rm -f "${OUTBASE}.avi" "${OUTBASE}_video.h264" "${OUTBASE}_audio.aac" "${OUTBASE}_audio.ogg" "${OUTBASE}.mp4" "${OUTBASE}.mkv" >/dev/null 2>&1 + fi + + TRANPID=$(jobs -l | awk '/mythtranscode/ {P=$2" "P} END {print P}') + if [ -n "$TRANPID" ] + then + scriptlog DEBUG "Killing mythtranscode [$TRANPID]" + ps -p $TRANPID >/dev/null 2>&1 && kill $TRANPID >/dev/null 2>&1 + fi + + if [ "$FINALEXIT" -eq 0 ] + then + [ "$DEBUG" != "ON" ] && rm -rf "$FIFODIR" >/dev/null 2>&1 + scriptlog INFO "Exiting. Successful." + if [ "$JOBID" -ne 99999999 ] + then + setjobqueuestatus "$JOBID" "FINISHED" + setjobqueuecomment "$JOBID" "[${$}] Successfully Completed" + fi + exit 0 + else + scriptlog INFO "Exiting. Errored." + if [ "$JOBID" -ne 99999999 ] + then + setjobqueuestatus "$JOBID" "ERRORED" + setjobqueuecomment "$JOBID" "[${$}] Errored" + fi + #exit 1 + #exit 304 + # Only error code jobqueue.cpp interprets is 246. This is translated to "unable to find executable". + scriptlog ERROR "This error could be for many reasons. Mythtv will report unable to find executable, this is incorrect." + exit 246 + fi +} + +MYSQLLIST="~mythtv/.mythtv/mysql.txt ~/.mythtv/mysql.txt /.mythtv/mysql.txt /usr/local/share/mythtv/mysql.txt /usr/share/mythtv/mysql.txt /etc/mythtv/mysql.txt /usr/local/etc/mythtv/mysql.txt mysql.txt" +for m in $MYSQLLIST +do + [ -f $m ] && . $m && break +done +if [ -z "$DBName" ] +then + echo "Can't find mysql.txt" + exit 1 +fi + +##### BG Monitor ##################################### +# This will be fired off in background to update the jobqueue comment and process stop/pause/resume requests. +if echo "$1" | egrep -i '\-\-monitor=' >/dev/null 2>&1 +then + readonly MONJOBID=$(echo "$1" | cut -d'=' -f2) + readonly MONPID="$2" + readonly MONTRANSOP="$3" + readonly LOGFILE="$4" + readonly DBLOGGING=$(getsetting "LogEnabled") + + [ "$MONJOBID" -ne 99999999 -a -n "$MONPID" ] || exit 1 + + PAUSEALREADYPRINTED="" ; RESUMEALREADYPRINTED="" + + scriptlog INFO "Starting monitoring process." + sleep 5 + while ps -p $MONPID >/dev/null 2>&1 + do + JQCMD=$(getjobqueuecmds "$MONJOBID") + if [ "$JQCMD" = "PAUSE" ] + then + JQSTATUS=$(getjobqueuestatus "$MONJOBID") + if [ "$JQSTATUS" != "PAUSED" ] + then + MENCODERPID=$(ps --ppid $MONPID | awk '/mencoder/ {print $1}') + if [ -n "$MENCODERPID" ] + then + PAUSEALREADYPRINTED="" + STARTPAUSESECS=$(date +%s) + kill -s STOP $MENCODERPID + setjobqueuestatus "$MONJOBID" "PAUSED" + SAVEDCC=$(getjobqueuecomment "$MONJOBID") + setjobqueuecomment "$MONJOBID" "[$MONPID] Paused for 0 Seconds" + scriptlog STOP "Job Paused due to job queue pause request." + else + [ -z "$PAUSEALREADYPRINTED" ] && scriptlog ERROR "Sorry, could not pause. Will keep trying" + PAUSEALREADYPRINTED=TRUE + fi + else + NOW=$(date +%s) + PAUSESECS=$(( $NOW - $STARTPAUSESECS )) + PAUSEMINS=$(( $PAUSESECS / 60 )) + PAUSEHOURS=$(( $PAUSEMINS / 60 )) + PAUSEMINS=$(( $PAUSEMINS - ( $PAUSEHOURS * 60 ) )) + PAUSESECS=$(( $PAUSESECS - ( ( $PAUSEHOURS * 60 * 60 ) + ( $PAUSEMINS * 60 ) ) )) + setjobqueuecomment "$MONJOBID" "[$MONPID] Paused for $PAUSEHOURS Hrs $PAUSEMINS Mins $PAUSESECS Secs" + fi + elif [ "$JQCMD" = "RESUME" ] + then + JQSTATUS=$(getjobqueuestatus "$MONJOBID") + if [ "$JQSTATUS" != "RUNNING" ] + then + MENCODERPID=$(ps --ppid $MONPID | awk '/mencoder/ {print $1}') + if [ -n "$MENCODERPID" ] + then + RESUMEALREADYPRINTED="" + kill -s CONT $MENCODERPID + setjobqueuestatus "$MONJOBID" "RUNNING" + setjobqueuecomment "$MONJOBID" "$SAVEDCC" + scriptlog START "Job resumed due to job queue resume request." + setjobqueuecmds "$MONJOBID" "RUN" + else + [ -z "$RESUMEALREADYPRINTED" ] && scriptlog ERROR "Sorry, could not resume. Will keep trying" + RESUMEALREADYPRINTED=TRUE + fi + fi + elif [ "$JQCMD" = "STOP" ] + then + setjobqueuestatus "$MONJOBID" "ABORTING" + setjobqueuecomment "$MONJOBID" "[$MONPID] Stopping" + scriptlog STOP "Stopping due to job queue stop request." + setjobqueuecmds "$MONJOBID" "RUN" + kill -s ABRT $MONPID + sleep 2 + kill $MONPID + elif [ "$JQCMD" = "RESTART" ] + then + scriptlog ERROR "Sorry, can't restart job." + setjobqueuecmds "$MONJOBID" "RUN" + else + CC=$(getjobqueuecomment "$MONJOBID") + if echo "$CC" | grep 'audio pass' >/dev/null 2>&1 + then + PASSNU="audio pass" + elif echo "$CC" | grep 'Single video pass' >/dev/null 2>&1 + then + PASSNU="Single video pass" + elif echo "$CC" | grep '1st video pass' >/dev/null 2>&1 + then + PASSNU="1st video pass" + elif echo "$CC" | grep '2nd video pass' >/dev/null 2>&1 + then + PASSNU="2nd video pass" + else + sleep 15 + continue + fi + PCTLINE=$(tail -10 $MONTRANSOP | grep 'mythtranscode:' | cut -c39- | tail -1) + [ -n "$PASSNU" -a -n "$PCTLINE" ] && setjobqueuecomment "$MONJOBID" "[$MONPID] $PASSNU $PCTLINE" + fi + sleep 15 + done + exit +fi + +##### Globals ######################################## +readonly CMD="$0" +readonly LOGFILE="/var/tmp/mythnuv2mkv${$}.log" +readonly FIFODIR="/var/tmp/mythnuv2mkv${$}" +readonly MENCODEROP="${FIFODIR}/mencoder.op" +readonly TRANSOP="${FIFODIR}/transcode.op" +readonly STOPREQUEST="${FIFODIR}/STOPREQUEST" +readonly CFDIR=$(getsetting "VideoArtworkDir") +if ! tty >/dev/null 2>&1 +then + readonly BOLDON="" + readonly ALLOFF="" + readonly REDFG="" + readonly GREENFG="" + readonly COLOURORIG="" + [ "$DEBUG" = "ON" ] && exec 3>/var/tmp/DEBUG || exec 3>/dev/null + exec 1>&3 + exec 2>&3 +else + readonly BOLDON=`tput bold` + readonly ALLOFF=`tput sgr0` + readonly REDFG=`tput setaf 1` + readonly GREENFG=`tput setaf 2` + readonly COLOURORIG=`tput op` +fi +# DBLOGGING is reverse to shell true/false +DBLOGGING=0 +OUTPUT="" +JOBID=99999999 +FINALEXIT=0 +STARTSECS="NA" +MAXRUNHOURS="NA" + +##### Main ########################################### +if echo "$1" | egrep -i '\-help|\-usage|\-\?' >/dev/null 2>&1 +then + echo "$HELP" + exit 1 +fi + +if [ "$CONTYPE" = "mkv" ] +then + chkreqs "$MKVREQPROGS" "$MKVREQLIBS" || exit 1 + versioncheck "mkvmerge" +elif [ "$CONTYPE" = "mp4" ] +then + chkreqs "$MP4REQPROGS" "$MP4REQLIBS" || exit 1 +elif [ "$CONTYPE" = "avi" ] +then + chkreqs "$AVIREQPROGS" "$AVIREQLIBS" || exit 1 +fi + +trap 'cleanup ABRT "$JOBID" "$OUTPUT"' INT ABRT +trap 'touch $STOPREQUEST ; scriptlog INFO "USR1 received. Will stop after current file completes."' USR1 +trap 'cleanup EXIT "$JOBID"' EXIT +mkdir ${FIFODIR} >/dev/null 2>&1 + +for INPUT in "$@" +do + if stoptime $STARTSECS $MAXRUNHOURS + then + scriptlog STOP "Stopping due to max runtime $MAXRUNHOURS." + scriptlog BREAK + break + fi + if [ -f "$STOPREQUEST" ] + then + scriptlog STOP "Stopping due to USR1 request." + scriptlog BREAK + break + fi + + # Jobid from myth user job %JOBID% + if echo "$INPUT" | grep -i '\-\-jobid=' >/dev/null 2>&1 + then + JOBID=$(echo "$INPUT" | cut -d'=' -f2) + DBLOGGING=$(getsetting "LogEnabled") + continue + fi + + if echo "$INPUT" | grep -i '\-\-findtitle=' >/dev/null 2>&1 + then + SEARCHTITLE=$(echo "$INPUT" | cut -d'=' -f2) + MATCHTITLE=$(findchanidstarttime "$SEARCHTITLE") + echo "$MATCHTITLE" + exit 0 + fi + + if echo "$INPUT" | grep -i '\-\-maxrunhours=' >/dev/null 2>&1 + then + STARTSECS=$(date +%s) + MAXRUNHOURS=$(echo "$INPUT" | cut -d'=' -f2) + scriptlog INFO "Max Run Hours set to $MAXRUNHOURS." + continue + fi + + if echo "$INPUT" | grep -i '\-\-debugsg' >/dev/null 2>&1 + then + DEBUGSG="ON" + scriptlog INFO "DEBUGSG set ON." + continue + fi + if echo "$INPUT" | grep -i '\-\-debug=' >/dev/null 2>&1 + then + DEBUG=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + scriptlog INFO "Debug set to $DEBUG." + continue + fi + if echo "$INPUT" | grep -i '\-\-info=' >/dev/null 2>&1 + then + INFO=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + scriptlog INFO "Info set to $INFO." + continue + fi + if echo "$INPUT" | grep -i '\-\-savenuv=' >/dev/null 2>&1 + then + SAVENUV=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + scriptlog INFO "SaveNUV set to $SAVENUV." + continue + fi + + if echo "$INPUT" | grep -i '\-\-denoise=' >/dev/null 2>&1 + then + DENOISE=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + if echo "$DENOISE" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + POSTVIDFILTERS="${POSTVIDFILTERS}${DENOISEFILTER}," + scriptlog INFO "Denoise filter added." + else + POSTVIDFILTERS=$(echo ${POSTVIDFILTERS} | sed -e 's/'${DENOISEFILTER}',//') + scriptlog INFO "Denoise filter removed." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-deblock=' >/dev/null 2>&1 + then + DEBLOCK=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + if echo "$DEBLOCK" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + POSTVIDFILTERS="${POSTVIDFILTERS}${DEBLOCKFILTER}," + scriptlog INFO "Deblock filter added." + else + POSTVIDFILTERS=$(echo ${POSTVIDFILTERS} | sed -e 's/'${DEBLOCKFILTER}',//') + scriptlog INFO "Deblock filter removed." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-deinterlace=' >/dev/null 2>&1 + then + DEINTERLACE=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + if echo "$DEINTERLACE" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + scriptlog INFO "Deinterlace filter made available." + else + scriptlog INFO "Deinterlace filter made unavailable." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-invtelecine=' >/dev/null 2>&1 + then + INVTELECINE=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + if echo "$INVTELECINE" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + scriptlog INFO "Invtelecine filter made available." + else + scriptlog INFO "Invtelecine filter made unavailable." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-crop=' >/dev/null 2>&1 + then + CROP=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + scriptlog INFO "Crop set to $CROP." + continue + fi + + if echo "$INPUT" | grep -i '\-\-deleterec=' >/dev/null 2>&1 + then + DELETEREC=$(echo "$INPUT" | cut -d'=' -f2 | tr [a-z] [A-Z]) + scriptlog INFO "Delete Recording set to $DELETEREC." + continue + fi + + if echo "$INPUT" | grep -i '\-\-copydir=' >/dev/null 2>&1 + then + COPYDIR=$(echo "$INPUT" | cut -d'=' -f2) + if [ -d "$COPYDIR" -a -w "$COPYDIR" ] + then + scriptlog INFO "Video will be located in $COPYDIR." + else + scriptlog ERROR "$COPYDIR does not exist or is not writable. Continuing but result will be left in source directory unless $COPYDIR is created before job completes." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-contype=' >/dev/null 2>&1 + then + TMP=$(echo "$INPUT" | cut -d'=' -f2 | tr [A-Z] [a-z]) + OLDIFS="$IFS"; IFS=","; set - $TMP; IFS="$OLDIFS" + TMP1="$1" ; TMP2="$2" + if [ "$TMP1" = "mp4" ] + then + if [ -n "$CHANID" -a -z "$COPYDIR" ] + then + scriptlog ERROR "Changed to $TMP1 failed. mp4 not supported in MythRecord." + elif ! chkreqs "$MP4REQPROGS" "$MP4REQLIBS" + then + scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements." + else + CONTYPE="mp4" + QUICKTIME_MP4="NO" + scriptlog INFO "Changed to $CONTYPE." + fi + elif [ "$TMP1" = "mov" ] + then + if [ -n "$CHANID" -a -z "$COPYDIR" ] + then + scriptlog ERROR "Changed to $TMP1 failed. mov not supported in MythRecord." + elif ! chkreqs "$MP4REQPROGS" "$MP4REQLIBS" + then + scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements." + else + CONTYPE="mp4" + QUICKTIME_MP4="YES" + scriptlog INFO "Changed to $CONTYPE (mov)." + fi + elif [ "$TMP1" = "mkv" ] + then + if [ -n "$CHANID" -a -z "$COPYDIR" ] + then + scriptlog ERROR "Changed to $TMP1 failed. mkv not supported in MythRecord." + elif ! chkreqs "$MKVREQPROGS" "$MKVREQLIBS" + then + scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements." + else + CONTYPE="mkv" + QUICKTIME_MP4="NO" + [ "$TMP2" = "ogg" ] && MKVAUD="ogg" + [ "$TMP2" = "acc" ] && MKVAUD="acc" + scriptlog INFO "Changed to ${CONTYPE},${MKVAUD}." + fi + elif [ "$TMP1" = "avi" ] + then + if ! chkreqs "$AVIREQPROGS" "$AVIREQLIBS" + then + scriptlog ERROR "Changed to $TMP1 failed. Missing Requirements." + else + CONTYPE="avi" + QUICKTIME_MP4="NO" + [ "$TMP2" = "xvid" ] && AVIVID="xvid" + [ "$TMP2" = "lavc" ] && AVIVID="lavc" + [ "$TMP2" = "divx" ] && AVIVID="lavc" + scriptlog INFO "Changed to ${CONTYPE},${AVIVID}." + fi + else + scriptlog ERROR "Changed to $TMP1 failed. Invalid contype." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-pass=' >/dev/null 2>&1 + then + TMP=$(echo "$INPUT" | cut -d'=' -f2 | tr [A-Z] [a-z]) + if [ "$TMP" = "one" -o "$TMP" = "1" ] + then + scriptlog INFO "Changed to $TMP pass." + PASS="one" + elif [ "$TMP" = "two" -o "$TMP" = "2" ] + then + scriptlog INFO "Changed to $TMP pass." + PASS="two" + else + scriptlog ERROR "Changed to $TMP failed. Invalid contype." + fi + continue + fi + + if echo "$INPUT" | grep -i '\-\-quality=' >/dev/null 2>&1 + then + QLEVEL=$(echo "$INPUT" | cut -d'=' -f2) + if echo "$QLEVEL" | grep -i "high" >/dev/null 2>&1 + then + SCALE43=$HIGH_SCALE43 + SCALE169=$HIGH_SCALE169 + LAVC_CQ=$HIGH_LAVC_CQ + LAVC_OPTS=$HIGH_LAVC_OPTS + XVID_CQ=$HIGH_XVID_CQ + XVID_OPTS=$HIGH_XVID_OPTS + MP3_ABITRATE=$HIGH_MP3_ABITRATE + X264_CQ=$HIGH_X264_CQ + X264EXT_OPTS="level_idc=31:$HIGH_X264EXT_OPTS" + X264_OPTS="level_idc=31:$HIGH_X264HIGH_OPTS" + AAC_AQUAL=$HIGH_AAC_AQUAL + OGG_AQUAL=$HIGH_OGG_AQUAL + elif echo "$QLEVEL" | grep -i "med" >/dev/null 2>&1 + then + SCALE43=$MED_SCALE43 + SCALE169=$MED_SCALE169 + LAVC_CQ=$MED_LAVC_CQ + LAVC_OPTS=$MED_LAVC_OPTS + XVID_CQ=$MED_XVID_CQ + XVID_OPTS=$MED_XVID_OPTS + MP3_ABITRATE=$MED_MP3_ABITRATE + X264_CQ=$MED_X264_CQ + X264EXT_OPTS="level_idc=31:$MED_X264EXT_OPTS" + X264_OPTS="level_idc=31:$MED_X264HIGH_OPTS" + AAC_AQUAL=$MED_AAC_AQUAL + OGG_AQUAL=$MED_OGG_AQUAL + elif echo "$QLEVEL" | grep -i "low" >/dev/null 2>&1 + then + SCALE43=$LOW_SCALE43 + SCALE169=$LOW_SCALE169 + LAVC_CQ=$LOW_LAVC_CQ + LAVC_OPTS=$LOW_LAVC_OPTS + XVID_CQ=$LOW_XVID_CQ + XVID_OPTS=$LOW_XVID_OPTS + MP3_ABITRATE=$LOW_MP3_ABITRATE + X264_CQ=$LOW_X264_CQ + X264EXT_OPTS="level_idc=31:$LOW_X264EXT_OPTS" + X264_OPTS="level_idc=31:$LOW_X264HIGH_OPTS" + AAC_AQUAL=$LOW_AAC_AQUAL + OGG_AQUAL=$LOW_OGG_AQUAL + elif echo "$QLEVEL" | egrep -i "480" >/dev/null 2>&1 + then + # 720 scale, high everything else + SCALE43=$FE_SCALE43 + SCALE169=$FE_SCALE169 + LAVC_CQ=$HIGH_LAVC_CQ + LAVC_OPTS=$HIGH_LAVC_OPTS + XVID_CQ=$HIGH_XVID_CQ + XVID_OPTS=$HIGH_XVID_OPTS + MP3_ABITRATE=$HIGH_MP3_ABITRATE + X264_CQ=$HIGH_X264_CQ + X264EXT_OPTS="level_idc=31:$HIGH_X264EXT_OPTS" + X264_OPTS="level_idc=31:$HIGH_X264HIGH_OPTS" + AAC_AQUAL=$HIGH_AAC_AQUAL + OGG_AQUAL=$HIGH_OGG_AQUAL + elif echo "$QLEVEL" | egrep -i "576" >/dev/null 2>&1 + then + # 720 scale, high everything else + SCALE43=$FS_SCALE43 + SCALE169=$FS_SCALE169 + LAVC_CQ=$HIGH_LAVC_CQ + LAVC_OPTS=$HIGH_LAVC_OPTS + XVID_CQ=$HIGH_XVID_CQ + XVID_OPTS=$HIGH_XVID_OPTS + MP3_ABITRATE=$HIGH_MP3_ABITRATE + X264_CQ=$HIGH_X264_CQ + X264EXT_OPTS="level_idc=31:$HIGH_X264EXT_OPTS" + X264_OPTS="level_idc=31:$HIGH_X264HIGH_OPTS" + AAC_AQUAL=$HIGH_AAC_AQUAL + OGG_AQUAL=$HIGH_OGG_AQUAL + elif echo "$QLEVEL" | egrep -i "720" >/dev/null 2>&1 + then + # 720 scale, high everything else + SCALE43=$ST_SCALE43 + SCALE169=$ST_SCALE169 + LAVC_CQ=$HIGH_LAVC_CQ + LAVC_OPTS=$HIGH_LAVC_OPTS + XVID_CQ=$HIGH_XVID_CQ + XVID_OPTS=$HIGH_XVID_OPTS + MP3_ABITRATE=$HIGH_MP3_ABITRATE + X264_CQ=$HIGH_X264_CQ + X264EXT_OPTS="level_idc=31:$HIGH_X264EXT_OPTS" + X264_OPTS="level_idc=31:$HIGH_X264HIGH_OPTS" + AAC_AQUAL=$HIGH_AAC_AQUAL + OGG_AQUAL=$HIGH_OGG_AQUAL + elif echo "$QLEVEL" | grep -i "1080" >/dev/null 2>&1 + then + # 1080 scale, high everything else + SCALE43=$TE_SCALE43 + SCALE169=$TE_SCALE169 + LAVC_CQ=$HIGH_LAVC_CQ + LAVC_OPTS=$HIGH_LAVC_OPTS + XVID_CQ=$HIGH_XVID_CQ + XVID_OPTS=$HIGH_XVID_OPTS + MP3_ABITRATE=$HIGH_MP3_ABITRATE + X264_CQ=$HIGH_X264_CQ + X264EXT_OPTS="level_idc=41:$HIGH_X264EXT_OPTS" + X264_OPTS="level_idc=41:$HIGH_X264HIGH_OPTS" + AAC_AQUAL=$HIGH_AAC_AQUAL + OGG_AQUAL=$HIGH_OGG_AQUAL + fi + scriptlog INFO "Changed to $QLEVEL quality." + continue + fi + + if echo "$INPUT" | grep -i '\-\-chanid=' >/dev/null 2>&1 + then + CHANID=$(echo "$INPUT" | cut -d'=' -f2) + continue + fi + if echo "$INPUT" | grep -i '\-\-starttime=' >/dev/null 2>&1 + then + STARTTIME=$(echo "$INPUT" | cut -d'=' -f2) + if [ -z "$CHANID" ] + then + scriptlog ERROR "Skipping $STARTTIME. chanid not specified." + scriptlog ERROR "--chanid must be specified before --starttime." + scriptlog BREAK + unset STARTTIME + continue + fi + if [ "$DEBUGSG" = "ON" ] + then + INPUT=$(getrecordfile "$CHANID" "$STARTTIME" "$DEBUGSG") + scriptlog INFO "$INPUT" + scriptlog BREAK + exit $FINALEXIT + fi + INPUT=$(getrecordfile "$CHANID" "$STARTTIME") + if [ -z "$INPUT" ] + then + scriptlog ERROR "Skipping $CHANID $STARTTIME. Did not match a recording." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + if [ ! -f "$INPUT" ] + then + scriptlog ERROR "Could not find Recording. ($INPUT)" + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + TITLE=$(gettitle $CHANID $STARTTIME) + MTINFILE="" + MTSOURCE="--chanid $CHANID --starttime $STARTTIME" + hascutlist $CHANID $STARTTIME && MTSOURCE="--honorcutlist $MTSOURCE" + scriptlog INFO "$CHANID $STARTTIME matches $TITLE ($INPUT)" + else + echo "$INPUT" | grep '^\/' >/dev/null 2>&1 || INPUT="`pwd`/${INPUT}" + MTINFILE="--infile" + MTSOURCE="$INPUT" + fi + + if [ ! -f "$INPUT" ] + then + scriptlog ERROR "Skipping $INPUT does not exist." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + + if echo "$INPUT" | grep -v '\.[nm][up][vg]$' >/dev/null 2>&1 + then + scriptlog ERROR "Skipping $INPUT not a nuv or mpg file." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + + OUTBASE=$(echo "$INPUT" | sed -e 's/\.[nm][up][vg]$//') + OUTPUT="${OUTBASE}.${CONTYPE}" + if [ -f "$OUTPUT" ] + then + scriptlog ERROR "Skipping $INPUT. $OUTPUT already exists." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + + INSIZE=$(( `stat -c %s "${INPUT}"` / 1024 )) + FREESPACE=$(df -k "$INPUT" | awk 'END {print $3}') + if [ $(( $FREESPACE - $INSIZE )) -lt 10000 ] + then + scriptlog ERROR "Stopping due to disk space shortage." + scriptlog BREAK + break + fi + + [ "$QUICKTIME_MP4" = "YES" ] && X264_OPTS="$X264EXT_OPTS" + + FILEINFO=$(getvidinfo "$INPUT" width height fps audio_sample_rate audio_channels) + OLDIFS="$IFS"; IFS=":"; set - $FILEINFO; IFS="$OLDIFS" + INWIDTH="$1"; INHEIGHT="$2"; INFPS="$3"; INARATE="$4"; CHANNELS="$5" + if [ "$#" -ne 5 ] + then + scriptlog ERROR "Skipping $INPUT. Could not obtain vid format details" + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + if [ "$INWIDTH" = 720 -a "$INHEIGHT" = 576 ] + then + FORMAT="576i or 576p" + elif [ "$INWIDTH" = 720 -a "$INHEIGHT" = 480 ] + then + FORMAT="480i or 480p" + elif [ "$INWIDTH" = 1280 -a "$INHEIGHT" = 720 ] + then + FORMAT="720p" + elif [ "$INWIDTH" = 1920 -a "$INHEIGHT" = 1088 ] + then + FORMAT="1080i or 1080p" + else + FORMAT="Unknown" + fi + + ASPECTSTR="NA";ASPECTFOUNDIN="NA" + TMP=$(getaspect "$INPUT") + ASPECTSTR=$(echo "$TMP" | cut -d',' -f1) + ASPECTFOUNDIN=$(echo "$TMP" | cut -d',' -f2) + if [ "$ASPECTSTR" != "4:3" -a "$ASPECTSTR" != "16:9" ] + then + scriptlog ERROR "Skipping $INPUT. Aspect is $ASPECTSTR must be 16:9 or 4:3." + scriptlog ERROR "If this is a mpg file make sure to set DEFAULTMPEG2ASPECT at top of this script." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + scriptlog INFO "$FORMAT ${INWIDTH}x${INHEIGHT} $ASPECTSTR (Found in $ASPECTFOUNDIN) $INFPS FPS Audio Rate $INARATE Channels $CHANNELS" + + # Channel mapping + FAACCCOPT="" + case "$CHANNELS" in + 1*|2*|3*|4*) true ;; + 5*|6*) FAACCCOPT="$FAACCHANCONFIG" ;; + *) scriptlog ERROR "Audio channels $CHANNELS invalid." + scriptlog BREAK + unset CHANID STARTTIME + continue + ;; + esac + + # Aspect/Scale/Crop opts + if [ "$ASPECTSTR" = "4:3" ] + then + ASPECT=1.333333333 + SCALE=$SCALE43 + if [ "$SCALE" = "NA" ] + then + scriptlog ERROR "Skipping $INPUT Aspect 4:3 which is not supported for quality $QLEVEL" + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + elif [ "$ASPECTSTR" = "16:9" ] + then + ASPECT=1.77777777778 + SCALE=$SCALE169 + fi + SCALESTR=$( echo $SCALE | tr ':' 'x' ) + SCALEMEN="scale=${SCALE}," + + OLDIFS="$IFS"; IFS=":"; set - $SCALE; IFS="$OLDIFS" + OUTWIDTH="$1"; OUTHEIGHT="$2" + if [ "$OUTWIDTH" = "$INWIDTH" -a "$OUTHEIGHT" = "$INHEIGHT" ] + then + CROPSCALE="" + scriptlog INFO "Input and Output same resolution. crop,scale disabled." + elif echo "$CROP" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + if [ "$OUTWIDTH" -gt "$INWIDTH" -o "$OUTHEIGHT" -gt "$INHEIGHT" ] + then + scriptlog INFO "Output is a greater scale than input. This is not sensible." + fi + CROPX=$CROPSIZE + CROPY=$CROPSIZE + CROPW=$(( $INWIDTH - ( 2 * $CROPX ) )) + CROPH=$(( $INHEIGHT - ( 2 * $CROPY ) )) + CROPVAL="${CROPW}:${CROPH}:${CROPX}:${CROPY}" + CROPMEN="crop=${CROPVAL}," + CROPSCALE="${CROPMEN}${SCALEMEN}" + scriptlog INFO "Crop to $CROPVAL. Scale to $SCALESTR." + else + CROPSCALE="${SCALEMEN}" + scriptlog INFO "Scale to $SCALESTR." + fi + + # Filter opts + OUTFPS="$INFPS" ; MENOUTFPS="" + POSTVIDFILTERS=$(echo ${POSTVIDFILTERS} | sed -e 's/'"${INVTELECINEFILTER}"',//') + POSTVIDFILTERS=$(echo ${POSTVIDFILTERS} | sed -e 's/'"${DEINTERLACEFILTER}"',//') + [ -n "$CHANID" ] && SOURCENAME=$(getsourcename $CHANID) + # Progressive then skip Deinterlace/Invtelecine + if echo $INFPS | egrep '^23|^24' >/dev/null 2>&1 + then + # Keep 23.976 FPS otherwise mencoder will convert to 29.97 + OUTFPS="23.976" + scriptlog INFO "Input $INFPS FPS. OUTFPS set to $OUTFPS." + elif [ "$FORMAT" = "720p" -o "$FORMAT" = "1080p" ] + then + scriptlog INFO "$FORMAT. Deinterlace/Invtelecine filter not needed." + # Deinterlace options + elif echo "$DEINTERLACE" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + POSTVIDFILTERS="${POSTVIDFILTERS}${DEINTERLACEFILTER}," + scriptlog INFO "Deinterlace filter added." + echo "$INFPS" | grep '^29' >/dev/null 2>&1 && + scriptlog INFO "You may need Invtelecine rather than Deinterlace. (--deinterlace=NO --invtelecine=YES)." + echo "$FORMAT" | egrep -i '576p|480p|720p|1080p' >/dev/null 2>&1 && + scriptlog INFO "If progressive this is wrong use --deinterlace=NO." + elif [ -n "$SOURCENAME" ] && echo "$DEINTERLACE" | grep -i "$SOURCENAME" >/dev/null 2>&1 + then + POSTVIDFILTERS="${POSTVIDFILTERS}${DEINTERLACEFILTER}," + scriptlog INFO "Source $SOURCENAME. Deinterlace filter added." + echo "$INFPS" | grep '^29' >/dev/null 2>&1 && + scriptlog INFO "You may need Invtelecine rather than Deinterlace. (--deinterlace=NO --invtelecine=YES)." + echo "$FORMAT" | egrep -i '576p|480p|720p|1080p' >/dev/null 2>&1 && + scriptlog INFO "If progressive this is wrong use --deinterlace=NO." + # Invtelecine options + elif echo "$INVTELECINE" | egrep -i 'ON|YES' >/dev/null 2>&1 && echo $INFPS | egrep '^24|^25' >/dev/null 2>&1 + then + # Very unusual to have PAL/DVB telecine video + scriptlog INFO "Input $INFPS FPS. Invtelecine filter not supported." + elif echo "$INVTELECINE" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + POSTVIDFILTERS="${POSTVIDFILTERS}${INVTELECINEFILTER}," + OUTFPS="23.976" + scriptlog INFO "Invtelecine filter added." + fi + [ "$OUTFPS" = "23.976" ] && MENOUTFPS="-ofps 24000/1001" + [ -n "$POSTVIDFILTERS" ] && POSTVIDFILTERS="${POSTVIDFILTERS}softskip," + + # Encoder opts + # Force avi for videos staying in MythRecord + if [ "$CONTYPE" = "avi" ] || [ -n "$CHANID" -a -z "$COPYDIR" ] + then + if [ "$AVIVID" = "xvid" ] + then + VBITRATE=$(calcbitrate $ASPECT $SCALE $XVID_CQ) + PASSCMD="pass" + VIDEOCODEC="-ovc xvid -xvidencopts ${XVID_OPTS}:bitrate=${VBITRATE}" + VIDEXT="xvid" + elif [ "$AVIVID" = "lavc" ] + then + VBITRATE=$(calcbitrate $ASPECT $SCALE $LAVC_CQ) + PASSCMD="vpass" + VIDEOCODEC="-ovc lavc -lavcopts ${LAVC_OPTS}:vbitrate=${VBITRATE}" + VIDEXT="lavc" + else + scriptlog ERROR "Skipping $INPUT. Unsupported avi encoder" + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + ABITRATE=$MP3_ABITRATE + AUDIOCODEC="-oac mp3lame -lameopts vbr=2:br=${ABITRATE}" + AUDEXT="mp3" + MENOUT1STPASS="-aspect $ASPECT -force-avi-aspect $ASPECTSTR -o /dev/null" + MENOUTOPT="-aspect $ASPECT -force-avi-aspect $ASPECTSTR -o" + MENOUTFILE="$OUTPUT" + elif [ "$CONTYPE" = "mp4" ] + then + VBITRATE=$(calcbitrate $ASPECT $SCALE $X264_CQ) + AQUAL=$AAC_AQUAL + PASSCMD="pass" + VIDEOCODEC="-ovc x264 -x264encopts ${X264_OPTS}:bitrate=${VBITRATE}" + VIDEXT="h264" + AUDIOCODEC="-oac copy" + AUDEXT="aac" + MENOUT1STPASS="-of rawvideo -o /dev/null" + MENOUTOPT="-of rawvideo -o" + MENOUTFILE="${OUTBASE}_video.h264" + elif [ "$CONTYPE" = "mkv" ] + then + VBITRATE=$(calcbitrate $ASPECT $SCALE $X264_CQ) + if [ "$MKVAUD" = "ogg" ] + then + AQUAL=$OGG_AQUAL + AUDEXT="ogg" + elif [ "$MKVAUD" = "aac" ] + then + AQUAL=$AAC_AQUAL + AUDEXT="aac" + else + scriptlog ERROR "Skipping $INPUT. Unsupported mkv encoder" + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + PASSCMD="pass" + VIDEOCODEC="-ovc x264 -x264encopts ${X264_OPTS}:bitrate=${VBITRATE}" + VIDEXT="h264" + AUDIOCODEC="-oac copy" + MENOUT1STPASS="-of rawvideo -o /dev/null" + MENOUTOPT="-of rawvideo -o" + MENOUTFILE="${OUTBASE}_video.h264" + else + scriptlog ERROR "Skipping $INPUT. Incorrect video contype selected. $CONTYPE" + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + + MENOPTS="${VIDEOCODEC} \ + ${AUDIOCODEC} \ + -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS" + scriptlog INFO "MENCODEROPTS: $MENOPTS." + + RETCODE=0 + # Fireoff a background monitoring job to update the job queue details + [ "$JOBID" -ne 99999999 ] && $CMD --monitor=$JOBID ${$} $TRANSOP $LOGFILE & + + #Start time + ENCSTARTTIME=$(date +%Y-%m-%d\ %H:%M:%S) + ORIGINALFILESIZE=$(du -h "$INPUT" | cut -f1) + + # mp4/mkv have seperate Audio/Video transcodes. + if [ "$AUDEXT" = "aac" ] + then + scriptlog START "Starting $AUDEXT audio trans of $INPUT. quality $AQUAL." + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] audio pass started" + + if [ ! -f "${OUTBASE}_audio.${AUDEXT}" ] + then + rm -f ${FIFODIR}/*out $TRANSOP $MENCODEROP + if [ -n "$MTINFILE" ] + then + nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir $FIFODIR | tee -a $TRANSOP & + else + nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir $FIFODIR | tee -a $TRANSOP & + fi + sleep 10 + # Throw away video + nice -n 19 dd bs=512k if=${FIFODIR}/vidout of=/dev/null & + nice -n 19 faac ${FIFODIR}/audout -P -R $INARATE -C $CHANNELS $FAACCCOPT -X -q $AQUAL --mpeg-vers 4 -o "${OUTBASE}_audio.${AUDEXT}" + RETCODE=$? + sleep 10 + if [ $RETCODE -ne 0 ] + then + scriptlog ERROR "Skipping $INPUT. Problem with audio pass." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + fi + elif [ "$AUDEXT" = "ogg" ] + then + scriptlog START "Starting $AUDEXT audio trans of $INPUT. quality $AQUAL." + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] audio pass started" + + if [ ! -f "${OUTBASE}_audio.${AUDEXT}" ] + then + rm -f ${FIFODIR}/*out $TRANSOP $MENCODEROP + if [ -n "$MTINFILE" ] + then + nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir $FIFODIR | tee -a $TRANSOP & + else + nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir $FIFODIR | tee -a $TRANSOP & + fi + sleep 10 + # Throw away video + nice -n 19 dd bs=512k if=${FIFODIR}/vidout of=/dev/null & + nice -n 19 oggenc --raw-chan=${CHANNELS} --raw-rate=${INARATE} --quality=${AQUAL} -o "${OUTBASE}_audio.${AUDEXT}" ${FIFODIR}/audout + RETCODE=$? + sleep 10 + if [ $RETCODE -ne 0 ] + then + scriptlog ERROR "Skipping $INPUT. Problem with audio pass." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + fi + fi + + if [ "$PASS" = "one" ] + then + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Single video pass started." + scriptlog START "Starting $VIDEXT Single video pass trans of $INPUT. vbr $VBITRATE abr $ABITRATE." + if [ ! -f "$MENOUTFILE" ] + then + rm -f ${FIFODIR}/*out $TRANSOP $MENCODEROP + if [ -n "$MTINFILE" ] + then + nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir $FIFODIR | tee -a $TRANSOP & + else + nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir $FIFODIR | tee -a $TRANSOP & + fi + sleep 10 + nice -n 19 mencoder -idx -noskip \ + ${FIFODIR}/vidout -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \ + -audiofile ${FIFODIR}/audout -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \ + ${VIDEOCODEC} \ + ${AUDIOCODEC} \ + -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \ + $MENOUTOPT "$MENOUTFILE" | tee -a $MENCODEROP + RETCODE=$? + sleep 10 + fi + else + scriptlog START "Starting $VIDEXT 1st video pass trans of $INPUT. vbr $VBITRATE abr $ABITRATE." + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] 1st video pass started." + if [ ! -f "$MENOUTFILE" ] + then + rm -f ${FIFODIR}/*out $TRANSOP $MENCODEROP + if [ -n "$MTINFILE" ] + then + nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir $FIFODIR | tee -a $TRANSOP & + else + nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir $FIFODIR | tee -a $TRANSOP & + fi + sleep 10 + nice -n 19 mencoder -idx \ + ${FIFODIR}/vidout -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \ + -audiofile ${FIFODIR}/audout -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \ + ${VIDEOCODEC}:${PASSCMD}=1:turbo -passlogfile ${FIFODIR}/2pass.log \ + ${AUDIOCODEC} \ + -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \ + $MENOUT1STPASS + RETCODE=$? + sleep 10 + if [ $RETCODE -ne 0 ] + then + scriptlog ERROR "Skipping $INPUT. Problem with 1st video pass of 2." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + fi + + scriptlog START "Starting $VIDEXT 2nd video pass trans of $INPUT. vbr $VBITRATE abr $ABITRATE." + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] 2nd video pass started." + if [ ! -f "$MENOUTFILE" ] + then + rm -f ${FIFODIR}/*out $TRANSOP $MENCODEROP + if [ -n "$MTINFILE" ] + then + nice -n 19 mythtranscode --profile autodetect $MTINFILE "$MTSOURCE" --fifodir $FIFODIR | tee -a $TRANSOP & + else + nice -n 19 mythtranscode --profile autodetect $MTSOURCE --fifodir $FIFODIR | tee -a $TRANSOP & + fi + sleep 10 + nice -n 19 mencoder -idx -noskip \ + ${FIFODIR}/vidout -demuxer rawvideo -rawvideo w=${INWIDTH}:h=${INHEIGHT}:fps=${INFPS} \ + -audiofile ${FIFODIR}/audout -audio-demuxer rawaudio -rawaudio rate=${INARATE}:channels=${CHANNELS} \ + ${VIDEOCODEC}:${PASSCMD}=2 -passlogfile ${FIFODIR}/2pass.log \ + ${AUDIOCODEC} \ + -vf ${POSTVIDFILTERS}${CROPSCALE}${ENDVIDFILTERS}harddup -sws 7 $MENOUTFPS \ + $MENOUTOPT "$MENOUTFILE" | tee -a $MENCODEROP + RETCODE=$? + sleep 10 + fi + fi + + if [ $RETCODE -ne 0 ] + then + scriptlog ERROR "Skipping $INPUT. Problem with final video pass. $OUTPUT may exist." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + + if [ -n "$CHANID" ] + then + SEARCHTITLE=$(getsearchtitle "$CHANID" "$STARTTIME") + INETREF=$(lookupinetref "$SEARCHTITLE" "$CHANID" "$STARTTIME") + SERIESEPISODE=$(getseriesepisode "$CHANID" "$STARTTIME" "$INETREF") + TITLE=$(createfiletitleSEsubtitle "$CHANID" "$STARTTIME" "$SERIESEPISODE") + else + TITLE=$(basename "$OUTPUT" | sed -e 's/\.[am][vkp][iv4]$//') + fi + + if [ "$CONTYPE" = "mp4" -o "$CONTYPE" = "mkv" ] + then + scriptlog START "Joining ${OUTBASE}_video.h264 ${OUTBASE}_audio.${AUDEXT} in $CONTYPE container." + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Joining in $CONTYPE container." + if ! encloseincontainer "$OUTBASE" $OUTFPS $AUDEXT $CONTYPE $ASPECTSTR $TITLE + then + scriptlog ERROR "$CONTYPE container Failed for $OUTPUT." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + fi + + scriptlog START "Checking $OUTPUT." + [ "$JOBID" -ne 99999999 ] && setjobqueuecomment "$JOBID" "[${$}] Checking result." + if ! checkoutput "$INPUT" "$OUTPUT" "$MENCODEROP" + then + mv "$OUTPUT" "${OUTPUT}-SUSPECT" + scriptlog ERROR "$OUTPUT may be faulty. Saved as ${OUTPUT}-SUSPECT. $INPUT kept." + scriptlog BREAK + unset CHANID STARTTIME + continue + fi + + if [ -n "$COPYDIR" ] + then + # Is this a good idea? + #CATEGORY=$(getcategory "$CHANID" "$STARTTIME") + #[ -n "$CATEGORY" ] + #then + # COPYDIR="${COPYDIR}/${CATEGORY}" + #fi + [ -d "$COPYDIR" ] || mkdir -p "$COPYDIR" + COPYFILE="${TITLE}.${CONTYPE}" + while [ -f "${COPYDIR}/${COPYFILE}" ] + do + COUNT=$(( ${COUNT:=0} + 1 )) + COPYFILE="${TITLE}_${COUNT}.${CONTYPE}" + done + if cp "$OUTPUT" "${COPYDIR}/${COPYFILE}" + then + rm -f "$OUTPUT" + scriptlog SUCCESS "Successful trans. $INPUT trans to ${COPYDIR}/${COPYFILE}. $INPUT kept" + MYTHVIDDIR=$(getsetting VideoStartupDir) + if [ "$QUICKTIME_MP4" = "YES" ] + then + OLDFILE="${COPYDIR}/${COPYFILE}" + COPYFILE=$(echo "$COPYFILE" | sed -e 's/mp4$/mov/') + mv "$OLDFILE" "${COPYDIR}/${COPYFILE}" + fi + if echo "$COPYDIR" | grep "$MYTHVIDDIR" >/dev/null 2>&1 + then + createvideometadata "${COPYDIR}/${COPYFILE}" "$TITLE" "$ASPECTSTR" "$CHANID" "$STARTTIME" "$INETREF" "$SERIESEPISODE" + fi + if echo "$DELETEREC" | egrep -i 'ON|YES' >/dev/null 2>&1 + then + scriptlog INFO "Deleting recording." + deleterecording "$CHANID" "$STARTTIME" + fi + NEWFILESIZE=$(du -h "${COPYDIR}/${COPYFILE}" | cut -f1) + else + scriptlog ERROR "Successful trans but copy to ${COPYDIR}/${COPYFILE} bad. $INPUT trans to $OUTPUT. $INPUT kept" + fi + else + if [ -n "$CHANID" ] + then + scriptlog INFO "Updating MythRecord db to $OUTPUT." + updatemetadata "$OUTPUT" "$CHANID" "$STARTTIME" + # mythcommflag --rebuild does not work correctly for avi files. + # Without this you can't edit files, but with it seeks don't work correctly. + #scriptlog INFO "Rebuilding seektable for $OUTPUT." + #mythcommflag --chanid "$CHANID" --starttime "$STARTTIME" --rebuild >/dev/null + rm -f "${INPUT}.png" + fi + [ "$DEBUG" = "ON" -o "$SAVENUV" = "ON" ] && mv "$INPUT" "${INPUT}OK-DONE" + [ "$DEBUG" != "ON" -a "$SAVENUV" != "ON" ] && rm -f "$INPUT" + scriptlog SUCCESS "Successful trans to $OUTPUT. $INPUT removed." + NEWFILESIZE=$(du -h "$OUTPUT" | cut -f1) + fi + # End time + ENCENDTIME=$(date +%Y-%m-%d\ %H:%M:%S) + logtranstime "$ENCSTARTTIME" "$ENCENDTIME" "$ORIGINALFILESIZE" "$NEWFILESIZE" + scriptlog BREAK + unset CHANID STARTTIME +done +exit $FINALEXIT + + +#STARTNUVINFO +#!/usr/bin/perl +# $Date: 2009/03/18 20:11:57 $ +# $Revision: 1.44 $ +# $Author: mythtv $ +# +# mythtv::nuvinfo.pm +# +# exports one routine: nuv_info($path_to_nuv) +# This routine inspects a specified nuv file, and returns information about +# it, gathered either from its nuv file structure +# +# Auric grabbed from nuvexport and Modified. Thanks to the nuvexport guys, I never would have been able to work this out +# +# finfo version width height desiredheight desiredwidth pimode aspect fps videoblocks audioblocks textsblocks keyframedist video_type audio_type audio_sample_rate audio_bits_per_sample audio_channels audio_compression_ratio audio_quality rtjpeg_quality rtjpeg_luma_filter rtjpeg_chroma_filter lavc_bitrate lavc_qmin lavc_qmax lavc_maxqdiff seektable_offset keyframeadjust_offset + +# Byte swap a 32-bit number from little-endian to big-endian + sub byteswap32 { + # Read in a 4-character string + my $in = shift; + my $out = $in; + + if ($Config{'byteorder'} == 4321) { + substr($out, 0, 1) = substr($in, 3, 1); + substr($out, 3, 1) = substr($in, 0, 1); + substr($out, 1, 1) = substr($in, 2, 1); + substr($out, 2, 1) = substr($in, 1, 1); + } + + return $out; + } + +# Byte swap a 64-bit number from little-endian to big-endian + sub byteswap64 { + # Read in a 8-character string + my $in = shift; + my $out = $in; + + if ($Config{'byteorder'} == 4321) { + substr($out, 4, 4) = byteswap32(substr($in, 0, 4)); + substr($out, 0, 4) = byteswap32(substr($in, 4, 4)); + } + + return $out; + } + +# Opens a .nuv file and returns information about it + sub nuv_info { + my $file = shift; + my(%info, $buffer); + # open the file + open(DATA, $file) or die "Can't open $file: $!\n\n"; + # Read the file info header + read(DATA, $buffer, 72); + # Byte swap the buffer + if ($Config{'byteorder'} == 4321) { + substr($buffer, 20, 4) = byteswap32(substr($buffer, 20, 4)); + substr($buffer, 24, 4) = byteswap32(substr($buffer, 24, 4)); + substr($buffer, 28, 4) = byteswap32(substr($buffer, 28, 4)); + substr($buffer, 32, 4) = byteswap32(substr($buffer, 32, 4)); + substr($buffer, 40, 8) = byteswap64(substr($buffer, 40, 8)); + substr($buffer, 48, 8) = byteswap64(substr($buffer, 48, 8)); + substr($buffer, 56, 4) = byteswap32(substr($buffer, 56, 4)); + substr($buffer, 60, 4) = byteswap32(substr($buffer, 60, 4)); + substr($buffer, 64, 4) = byteswap32(substr($buffer, 64, 4)); + substr($buffer, 68, 4) = byteswap32(substr($buffer, 68, 4)); + } + # Unpack the data structure + ($info{'finfo'}, # "NuppelVideo" + \0 + $info{'version'}, # "0.05" + \0 + $info{'width'}, + $info{'height'}, + $info{'desiredheight'}, # 0 .. as it is + $info{'desiredwidth'}, # 0 .. as it is + $info{'pimode'}, # P .. progressive, I .. interlaced (2 half pics) [NI] + $info{'aspect'}, # 1.0 .. square pixel (1.5 .. e.g. width=480: width*1.5=720 for capturing for svcd material + $info{'fps'}, + $info{'videoblocks'}, # count of video-blocks -1 .. unknown 0 .. no video + $info{'audioblocks'}, # count of audio-blocks -1 .. unknown 0 .. no audio + $info{'textsblocks'}, # count of text-blocks -1 .. unknown 0 .. no text + $info{'keyframedist'} + ) = unpack('Z12 Z5 xxx i i i i a xxx d d i i i i', $buffer); + # Perl occasionally over-reads on the previous read() + seek(DATA, 72, 0); + # Read and parse the first frame header + read(DATA, $buffer, 12); + # Byte swap the buffer + if ($Config{'byteorder'} == 4321) { + substr($buffer, 4, 4) = byteswap32(substr($buffer, 4, 4)); + substr($buffer, 8, 4) = byteswap32(substr($buffer, 8, 4)); + } + my ($frametype, + $comptype, + $keyframe, + $filters, + $timecode, + $packetlength) = unpack('a a a a i i', $buffer); + # Parse the frame + die "Illegal nuv file format: $file\n\n" unless ($frametype eq 'D'); + # Read some more stuff if we have to + read(DATA, $buffer, $packetlength) if ($packetlength); + # Read the remaining frame headers + while (12 == read(DATA, $buffer, 12)) { + # Byte swap the buffer + if ($Config{'byteorder'} == 4321) { + substr($buffer, 4, 4) = byteswap32(substr($buffer, 4, 4)); + substr($buffer, 8, 4) = byteswap32(substr($buffer, 8, 4)); + } + # Parse the frame header + ($frametype, + $comptype, + $keyframe, + $filters, + $timecode, + $packetlength) = unpack('a a a a i i', $buffer); + # Read some more stuff if we have to + read(DATA, $buffer, $packetlength) if ($packetlength); + # Look for the audio frame + if ($frametype eq 'X') { + # Byte swap the buffer + if ($Config{'byteorder'} == 4321) { + substr($buffer, 0, 4) = byteswap32(substr($buffer, 0, 4)); + substr($buffer, 12, 4) = byteswap32(substr($buffer, 12, 4)); + substr($buffer, 16, 4) = byteswap32(substr($buffer, 16, 4)); + substr($buffer, 20, 4) = byteswap32(substr($buffer, 20, 4)); + substr($buffer, 24, 4) = byteswap32(substr($buffer, 24, 4)); + substr($buffer, 28, 4) = byteswap32(substr($buffer, 28, 4)); + substr($buffer, 32, 4) = byteswap32(substr($buffer, 32, 4)); + substr($buffer, 36, 4) = byteswap32(substr($buffer, 36, 4)); + substr($buffer, 40, 4) = byteswap32(substr($buffer, 40, 4)); + substr($buffer, 44, 4) = byteswap32(substr($buffer, 44, 4)); + substr($buffer, 48, 4) = byteswap32(substr($buffer, 48, 4)); + substr($buffer, 52, 4) = byteswap32(substr($buffer, 52, 4)); + substr($buffer, 56, 4) = byteswap32(substr($buffer, 56, 4)); + substr($buffer, 60, 8) = byteswap64(substr($buffer, 60, 8)); + substr($buffer, 68, 8) = byteswap64(substr($buffer, 68, 8)); + } + my $frame_version; + ($frame_version, + $info{'video_type'}, + $info{'audio_type'}, + $info{'audio_sample_rate'}, + $info{'audio_bits_per_sample'}, + $info{'audio_channels'}, + $info{'audio_compression_ratio'}, + $info{'audio_quality'}, + $info{'rtjpeg_quality'}, + $info{'rtjpeg_luma_filter'}, + $info{'rtjpeg_chroma_filter'}, + $info{'lavc_bitrate'}, + $info{'lavc_qmin'}, + $info{'lavc_qmax'}, + $info{'lavc_maxqdiff'}, + $info{'seektable_offset'}, + $info{'keyframeadjust_offset'} + ) = unpack('ia4a4iiiiiiiiiiiill', $buffer); + # Found the audio data we want - time to leave + last; + } + # Done reading frames - let's leave + else { + last; + } + } + # Close the file + close DATA; + # Make sure some things are actually numbers + $info{'width'} += 0; + $info{'height'} += 0; + # HD fix + if ($info{'height'} == 1080) { + $info{'height'} = 1088; + } + # Make some corrections for myth bugs + $info{'audio_sample_rate'} = 44100 if ($info{'audio_sample_rate'} == 42501 || $info{'audio_sample_rate'} =~ /^44\d\d\d$/); + # NEIL Don't know why he hard set it? + # $info{'aspect'} = '4:3'; + # Cleanup + $info{'aspect'} = aspect_str($info{'aspect'}); + $info{'aspect_f'} = aspect_float($info{'aspect'}); + # Return + return %info; + } + + sub aspect_str { + my $aspect = shift; + # Already in ratio format + return $aspect if ($aspect =~ /^\d+:\d+$/); + # European decimals... + $aspect =~ s/\,/\./; + # Parse out decimal formats + if ($aspect == 1) { return '1:1'; } + elsif ($aspect =~ m/^1.3/) { return '4:3'; } + elsif ($aspect =~ m/^1.7/) { return '16:9'; } + elsif ($aspect == 2.21) { return '2.21:1'; } + # Unknown aspect + print STDERR "Unknown aspect ratio: $aspect\n"; + return $aspect.':1'; + } + + sub aspect_float { + my $aspect = shift; + # European decimals... + $aspect =~ s/\,/\./; + # In ratio format -- do the math + if ($aspect =~ /^\d+:\d+$/) { + my ($w, $h) = split /:/, $aspect; + return $w / $h; + } + # Parse out decimal formats + if ($aspect eq '1') { return 1; } + elsif ($aspect =~ m/^1.3/) { return 4 / 3; } + elsif ($aspect =~ m/^1.7/) { return 16 / 9; } + # Unknown aspect + return $aspect; + } + +my %info = nuv_info($ENV{'NUVINFOFILE'}); +my $c = 0; +foreach my $key (split(' ', $ENV{'NUVINFOPROPS'})) { + ($c++ < 1) and print "$info{$key}" or print ":$info{$key}"; +} +print "\n"; +#ENDNUVINFO + +########################################################################################################### +License Notes: +-------------- + +This software product is licensed under the GNU General Public License +(GPL). This license gives you the freedom to use this product and have +access to the source code. You can modify this product as you see fit +and even use parts in your own software. If you choose to do so, you +also choose to accept that a modified product or software that use any +code from mythnuv2mkv.sh MUST also be licensed under the GNU General Public +License. + +In plain words, you can NOT sell or distribute mythnuv2mkv.sh, a modified +version or any software product based on any parts of mythnuv2mkv.sh as a +closed source product. Likewise you cannot re-license this product and +derivates under another license other than GNU GPL. + +See also the article, "Free Software Matters: Enforcing the GPL" by +Eben Moglen. http://emoglen.law.columbia.edu/publications/lu-13.html +########################################################################################################### -- cgit v0.12