#!/bin/bash
#
# Version:          0.6.4
#
# Licence:          GPL
#
# 2004-05-22        Giacomo Comes <encode2mpeg at users.sourceforge.net>
# 2007-10-18                      <encode2mpeg at email.it>
#
# Purpose:          Convert anything MPlayer can play to AVI/VCD/SVCD/DVD MPEG
#
#   encode2mpeg is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License version 2 as
#   published by the Free Software Foundation.

#   encode2mpeg is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with encode2mpeg; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

###############################################################################
#### start
###############################################################################
VCDENC=$(locale charmap)
VCDENC=${VCDENC//-}
export LC_ALL=POSIX
set -B +f
shopt -u xpg_echo nullglob
shopt -s extglob
PROGNAME=${0##*/}
PROGFILE=$(type -p "$0")
VERSION=$(awk '$2=="Version:"{print $3;exit}' <"$PROGFILE")
BROWSER=

###############################################################################
#### functions 1/3
###############################################################################
OptionsText () {
    echo
    echo "Options can be uses for DIRECT, MPEG and AVI Mode as specified,"
    echo "if nothing is specified the option is valid for every Mode"
    echo "Arguments enclosed in [ ] are optional"
    echo
    echo "Quickstart: $PROGNAME -doc stdvid.html"
}
###############################################################################
ModeText () {
    echo
    echo -e "\t\t\t\t\t avionly  encode"
    echo -e "The running Mode is selected by the\t    x       x       AVI      Mode"
    echo -e "  presence or the absence of the\t                    DIRECT   Mode"
    echo -e "  options -avionly, -encode\t\t\t    x       MPEG     Mode"
}
###############################################################################
usage () {
    echo -e "Usage: $PROGNAME options source\nOptions:"
    sed -n '/^#### PARSING/,/^done/!d;/^done/q;/^[ 	]*-[^)]*)/,/#-/!d;s/)$//;s/) *#/ /;s/#-/# /;s/	*#L.$//;s/#//;p' "$PROGFILE"
    ModeText
    OptionsText
}
###############################################################################
shortusage () {
    echo -e "\n$PROGNAME  v. $VERSION  Copyright (C) 2004-2007 Giacomo Comes\n"
    echo "This is free software; see the source for copying conditions.  There is NO"
    echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,"
    echo "to the extent permitted by law."
    echo
    echo "Usage: $PROGNAME options source"
    echo "Options:"
    sed -n '/^#### PARSING/,/^done/!d;/^done/q;/^[ 	]*-[^)]*)/!d;s/)$//;s/) *#/ /;s/	*#L.$//;p' "$PROGFILE"
    OptionsText
}
###############################################################################
mp_identify () {
    mplayer -msglevel identify=6 -vo md5sum:outfile=/dev/null -ao null -nocache -frames 0 "$@" 2>/dev/null
}
###############################################################################
id_find () {
    local ID=$1
    shift
    mp_identify "$@" | awk -v id=$ID -F= '$1==id{t=$2}END{print t}'
}
###############################################################################
mlistopt () {
    mplayer -list-options 2>&1 | awk '$1=="Name"{m=1}{if(m&&$1!="Name"&&$1!=""&&$1!="Total:")print "\""$1"\""}'
}
###############################################################################
do_log () {
    echo "$1"
    ((LG)) && echo "$1" >>"$output".log || WARN="$WARN${WARN:+\n}$1"
}
###############################################################################
isarg () {
    if [[ ${2:0:1} = - || ! $2 || $2 = help ]]; then
        [[ ${2:0:1} = - ]] && echo "**ERROR: [$PROGNAME] invalid argument '$2' for option '$1'"
        [[ ! $2 ]] && echo "**ERROR: [$PROGNAME] invalid null argument for option '$1'"
        "$PROGFILE" -norc -l | awk -v i=$1 'BEGIN{i="(^|\\|)"i"($|\\|)"}{if($0~/^        -/||$0~/^$/)m=0;if($0~/^        -/&&$1~i)m=1;if(m)print}'
        exit 1
    fi
    if [[ $2 = doc ]]; then
        show_html ${3:+$3.html}
        exit
    fi
}
###############################################################################
pr_time () {
    date '+%j %H %M %S' | awk '{print $1*86400+$2*3600+$3*60+$4}'
}
###############################################################################
get_abr () {
    local INFO ABR
    INFO=$(mp_identify "${MPLAYEROPT[@]}" ${dvddev:+-dvd-device "$dvddev"} "$@" | grep '^ID_')
    ABR=$(echo "$INFO" | grep '^ID_AUDIO_BITRATE' | tail -1 | cut -f2 -d=)
    case $(echo "$INFO" | grep '^ID_AUDIO_CODEC' | cut -f2 -d=) in
        dvdpcm) abr=$((abr+ABR/1024)) ;;
        *)      abr=$((abr+ABR/1000)) ;;
    esac
}
###############################################################################
help_subopts () {
    local last i UNIT PREFIX
    UNIT=("" I II III IV V VI VII VIII IX)
    PREFIX=("" X XX XXX XL L LX LXX LXXX XC C)
    last=$(printf "%0${#OPTSVAR[*]}d" 0 | tr '0' ':')
    echo "permitted suboptions values for '$1 $(for ((i=1;i<=${#OPTSVAR[*]};i++)); do echo -n "${PREFIX[i/10]}${UNIT[i%10]}${last:$i:1}" ; done)'"
    for ((i=1;i<=${#OPTSVAR[*]};i++)); do
        echo -e "    ${PREFIX[i/10]}${UNIT[i%10]}: ${OPTSHLP[i-1]}"
        echo "        ${OPTSVAL[i-1]}"
    done
    echo "currently: '$1 $(for ((i=1;i<=${#OPTSVAR[*]};i++)); do echo -en "${!OPTSVAR[i-1]}${last:$i:1}" ; done)'"
    exit
}
###############################################################################
parse_subopts () {
    local first last n i subopt
    [[ $2 = list ]] && help_subopts $1
    n=${2//[^:]}
    last=$n
    n=$((${#n}+1))
    for ((i=0;i<n;i++)); do
        subopt=$(echo $2 | cut -f$((i+1)) -d:)
        if [[ $subopt ]]; then
            [[ $subopt = help || $subopt = list ]] && help_subopts $1
            echo "${OPTSVAL[i]}" | tr ' ' '\012' | grep -q -e "^$subopt\$" || \
              ! echo "**ERROR invalid suboption value '$1 $first${subopt}$last' (permitted values: ${OPTSVAL[i]})" || exit 1
            eval ${OPTSVAR[i]}=$subopt
        fi
        first=${first}:
        last=${last#?}
    done
    if ((DEBUG)); then
        for ((i=0;i<${#OPTSVAR[*]};i++)); do
            s="--DEBUG: ${OPTSVAR[i]}=\${${OPTSVAR[i]}[*]}"
            do_log "$(eval echo "$s")"
        done 
    fi
}
###############################################################################
get_arguments_from_file () {
    isarg "$2" "$1"
    ARRAY=()
    if [[ -r $1 ]]; then
        while read ARRAY[${#ARRAY[*]}] ; do
            :
        done <"$1"
    else
        echo "**ERROR: [$PROGNAME] file '$1' argument of '$2' not found" && exit 1
    fi
}
###############################################################################
get_pwd () {
    pushd &>/dev/null "$1"
    echo "$PWD/$2"
    popd &>/dev/null
}
###############################################################################
show_html () {
    local i LIST HTML PREFIX OPTION INSTDOCDIR SRCDOCDIR PACKMANDOCDIR
    INSTDOCDIR=${PROGFILE%/bin/$PROGNAME}/share/doc/encode2mpeg
    PACKMANDOCDIR=${PROGFILE%/bin/$PROGNAME}/share/doc/packages/encode2mpeg/doc
    [[ ! -d $INSTDOCDIR && -d $PACKMANDOCDIR ]] && INSTDOCDIR=$PACKMANDOCDIR
    SRCDOCDIR=${PROGFILE%/$PROGNAME}/doc
    if [[ -f $INSTDOCDIR/encode2mpeg.html ]]; then
        HTML=$(get_pwd "$INSTDOCDIR" encode2mpeg.html)
    elif [[ -f $SRCDOCDIR/encode2mpeg.html ]]; then
        HTML=$(get_pwd "$SRCDOCDIR" encode2mpeg.html)
    else
        HTML="http://encode2mpeg.sourceforge.net"
    fi
    if [[ -f $INSTDOCDIR/html/$1 ]]; then
        HTML=$(get_pwd "$INSTDOCDIR/html" $1)
    elif [[ -f $SRCDOCDIR/html/$1 ]]; then
        HTML=$(get_pwd "$SRCDOCDIR/html" $1)
    elif [[ $1 && ! -d $INSTDOCDIR/html && ! -d $SRCDOCDIR/html ]]; then
        HTML="http://encode2mpeg.sourceforge.net/html/$1"
    fi
    LIST=(seamonkey firefox mozilla)
    [[ ${HTML:0:1} = / ]] && PREFIX=file:// || PREFIX=
    for ((i=0;i<${#LIST[*]};i++)); do
        type ${LIST[i]} &>/dev/null && ${LIST[i]} -remote 'openURL('"$PREFIX$HTML"',new-tab)' 2>/dev/null && return
    done
    LIST=(seamonkey firefox mozilla opera konqueror epiphany galeon)
    if [[ $BROWSER ]]; then
        type "$BROWSER" &>/dev/null && LIST=("$BROWSER") || echo "++ WARN: default browser '$BROWSER' not found, using builtin browser list"
    fi
    for ((i=0;i<${#LIST[*]};i++)); do
        if type "${LIST[i]}" &>/dev/null; then
            case ${LIST[i]} in
                opera) OPTION=--newpage ;;
                epiphany|galeon) OPTION=--new-tab ;;
                *) OPTION= ;;
            esac
            "${LIST[i]}" $OPTION "$HTML" &
            return
        fi
    done
}
###############################################################################
parse_ch () {
    local I LF FR SR
    I=$1
    echo $I | grep -q '\.' && LF=${I##*.} I=${I%.*} || LF=0
    echo $I | grep -q '/' && FR=${I%%/*} SR=${I##*/} || FR=$I SR=0
    if ((FR+SR+LF>0&&FR+SR+LF<=6)); then
        mpegchannels=$((FR+SR+LF))
        case $FR$SR$LF in
          # 321|320|311|221|310|220|211|301|210|300|201) chconf=$FR$SR$LF ;;
            321|320|311|221|310|220|211|210|201) chconf=$FR$SR$LF ;;
        esac
        ((LF)) && [[ ! $chconf ]] && chconf="xx1"
    fi
}
###############################################################################
xmlchar () {
    echo "$1" | sed 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;s/"/\&quot;/g'
}
###############################################################################
xmlunchar () {
    echo "$1" | sed 's/&amp;/\&/g;s/&lt;/</g;s/&gt;/>/g;s/&quot;/"/g'
}
###############################################################################
opt_ign () {
    do_log "++ WARN: [$PROGNAME] argument of '$1 $2' out of range, ignoring option $1"
}
###############################################################################
opt_def () {
    do_log "++ WARN: [$PROGNAME] argument of '$1 $2' out of range, using $1 $3"
}

###############################################################################
#### variable initialization
###############################################################################
abr=;asr=;vbr=;vfr=;videonorm=;frameformat=;output=;audioformat=;mp1=;mp2=;mp3=;ac3=;dts=;lpcm=;aac=;normalize=;volume=;multiaudio=;mpegchannels=;quiet=;resume=;blank=;encode=;ofps=;mono=;usesbr=;sbr=;clear=;keep=;frames=;avisplit=;channels=;vcustom=;acustom=;cpu=;interlaced=;mpegaspect=;intra_matrix=;inter_matrix=;fixavi=;mpeg=;crop=;audioid=;dvdaudiolang=;bframes=;firstchap=;lastchap=;dvdtrack=;addchapter=;cdi=;mpegfixaspect=;nowait=;vf=;frameres=;trick=;autocrop=;afm=;cache=;removecache=;turbo=;dvddev=;srate=;fourcc=;menu=;menubg=;rotate=;menuvtsbg=;autosync=;telecine=;AFMT=;telesrc=;vcodec=;vrfyumnt=;burniso=;verify=;fixasync=;removedir=;MPGRES=;GOP=;TXTSUBOPT=;usespeed=;testmca=;chconf=;noodml=;pictsrc=;slideaudio=;audioonly=;norc=;rawsub=;vobsubsrc=;af=;lavf=;subrender=;harddup=;overburn=;cartoon=;ocr=;ocropts=;ISOINFO=;bakiter=;singletrack=;ocrterm=;nomamenu=;cacher=;cachep=;pngremove=;abrset=;unsupported=;VIDEOATTR=;novobcopy=;audioonlytxt=;audioonlybg=;audioonlyopt=;menubgopt=
unset encsid encsdx encsla addsub addsdx addsla addsdl savecache txtsub txtsubopts ocrtopt
zoom=0
scale=1
fast=1
MAXSTEP=6 # burn is the default
step=$MAXSTEP
split=0
mpegmbr=0
overscan=0
iter=0
hispeed=0
dvdtitle=0
BGTITLE=1
TANIM=0
TFMT=png
TMODE=0
TKFRM=0
TSECS=5
TPART=4
TPARTSEC=15
TFONTSIZE=1
TFONTBG=1
TLINES=2
TCPR=2
MENUERR=0
DVDPLAY=0
MENUOS=0
TSETB=1
DVDFS=1
VTSMBG=0
TSALL=0
MASP=1
menufix=0
dvdsub=0
cdburndevice=0,0,0
dvdburndevice=/dev/cdrecorder
fsize=;fint=;ffrac=;fpre=;audiosize=0
ASPECT=(1 1 4/3 16/9 2.21)
ARES=(576 576 768 1024 1272)
CH6LIST=(l r ls rs c lfe)
TOOL=
MPEG2ENCOPT=;YUVSCALEROPT=;YUVDENOISE=;MPLEXOPT=;VCDIMAGEROPT=;DVDAUTHOROPT=;CDRDAOOPT=;GROWISOFSOPT=;MUSICINOPT=
unset MPLAYEROPT MPLEXSTREAM MENCODEROPT
LPCMPAR=
SUBLANG=
unset SUBTEXT AUDIOTEXT CHAPTERTEXT TITLESET EXTWAV PROFILE MSRC MEXTRAARG MEXTRATXT MEXTRAOPT
MEXTRAIND=( 0 )
unset CLEAN ftest
BURNLIST=() thumboffset=()
DEBUG=0
LAVC=
WARN=
LOG=
LOGPROC=
LG=0
SVN=0
MAXFIX=20
timelen=0
slidefps=1
extrachapter=0
default_intra=8,16,19,22,26,27,29,34,16,16,22,24,27,29,34,37,19,22,26,27,29,34,34,38,22,22,26,27,29,34,37,40,22,26,27
default_intra=$default_intra,29,32,35,40,48,26,27,29,32,35,40,48,58,26,27,29,34,38,46,56,69,27,29,35,38,46,56,69,83
default_inter=16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
default_inter=$default_inter,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
hires_intra=8,16,18,20,24,25,26,30,16,16,20,23,25,26,30,30,18,20,22,24,26,28,29,31,20,21,23,24,26,28,31,31,21,23,24
hires_intra=$hires_intra,25,28,30,30,33,23,24,25,28,30,30,33,36,24,25,26,29,29,31,34,38,25,26,28,29,31,34,38,42
hires_inter=$default_inter
kvcd_intra=8,9,12,22,26,27,29,34,9,10,14,26,27,29,34,37,12,14,18,27,29,34,37,38,22,26,27,31,36,37,38,40,26,27,29
kvcd_intra=$kvcd_intra,36,39,38,40,48,27,29,34,37,38,40,48,58,29,34,37,38,40,48,58,69,34,37,38,40,48,58,69,79
kvcd_inter=16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26
kvcd_inter=$kvcd_inter,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44
tmpgenc_intra=8,16,19,22,26,27,29,34,16,16,22,24,27,29,34,37,19,22,26,27,29,34,34,38,22,22,26,27,29,34,37,40,22,26,27
tmpgenc_intra=$tmpgenc_intra,29,32,35,40,48,26,27,29,32,35,40,40,58,26,27,29,34,38,46,56,69,27,29,35,38,46,56,69,83
tmpgenc_inter=16,17,18,19,20,21,22,23,17,18,19,20,21,22,23,24,18,19,20,21,22,23,24,25,19,20,21,22,23,24,26,27,20,21,22
tmpgenc_inter=$tmpgenc_inter,23,25,26,27,28,21,22,23,24,26,27,28,30,22,23,24,26,27,28,30,31,23,24,25,27,28,30,31,33
TXTSUBDEF=( languageId nolang delay 0 font arial.ttf size 28 bottom-margin 30 characterset ISO8859-1 movie-height-reduction 0 fps default )
AVISUBDEF=( format SubViewer name-extension null fileformat unix version-number off delay 0 fps default suffix default )
OCRDEF=( ocrengine auto name-extension %o_%i_%l fileformat unix version-number off suffix srt subedit off ocrterm auto geometry default trim off)

(($#)) || ! shortusage || exit 1
CMD=( "$@" )

#### options array
MOPT=( $(mlistopt | grep -v -e : -e '*') 
       $(mlistopt | sed -n '/:/s/:.*/"/p' | uniq) 
       $(mplayer -vfhelp 2>&1 | awk '/vf-/{printf("\"%s\"\n",$1)}') 
       $(mplayer -zrhelp 2>/dev/null | awk '$1~/^-zr/{printf("\"%s\"\n",substr($1,2))}') )

###############################################################################
#### check rc file
###############################################################################
if [[ -s ~/.encode2mpegrc ]]; then
    for ((i=0;i<${#CMD[*]};i++)); do
        [[ ${CMD[i]} = -norc ]] && norc=1 && break
    done
    if [[ ! $norc ]] && ! awk '{if($1~"^#")exit 1}' ~/.encode2mpegrc ; then
        do_log "++ WARN: [$PROGNAME] ~/.encode2mpegrc appears to contain comments, ignoring it" >/dev/null
        norc=1
    fi
    [[ ! $norc ]] && set -- $(<~/.encode2mpegrc) "$@"
fi

###############################################################################
#### arguments parsing
###############################################################################
while (($#)) ; do
#### PARSING
    case $1 in
        -h|-help)
            #-list the available options
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 
            shortusage
            exit
            ;;
        -l|-longhelp)
            #-print this help page
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 
            usage
            exit
            ;;
        -doc|-documentation) #[[<browser>:][<html page>]]
            #-show the html documentation
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 
            [[ ${2%:*} != "$2" ]] && BROWSER=${2%:*}
            show_html ${2#*:}
            exit
            ;;
        -noshowlog)
            #-do not show the log file
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 
            quiet=1
            ;;
        -o|-output) #<filename>
            #-filename of the output stream
            echo "$2" | grep -q '/' && [[ ! -d ${2%/*} ]] && echo "**ERROR: [$PROGNAME] directory ${2%/*} argument of '$1' not found" && exit 1
            output=$2
            shift
            ;;
        -a) #<n>						[DIRECT,MPEG]
            # aspect ratio     VCD SVCD  DVD
            #     1 -    1:1    x    *    x	x = mpeg2enc and mencoder
            #     2 -    4:3    x    x    x	* = mencoder only
            #     3 -   16:9    x    x    x
            #-    4 -  2.21:1        *    x
            MPEG2ENCOPT="$MPEG2ENCOPT -a $2"
            [[ $2 -eq 0 ]] && MPEG2ENCOPT="${MPEG2ENCOPT% ${2}} 1"
            mpegaspect=$2
            isarg $1 "$2" direct
            shift
            ;;
        -mpegfixaspect) #[pad|crop]			[DIRECT,MPEG]
            # force the aspect ratio of the source video to match the one
            # specified with -a; this can be done padding the video with
            #-black lines or cropping the video; the default is padding
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 aspect
            mpegfixaspect=0
            if [[ $2 = pad || $2 = crop ]]; then
                [[ $2 = crop ]] && mpegfixaspect=1
                shift
            fi
            ;;
        -rotate) #<0-3>					[AVI,MPEG]
            # rotate the source video by 90 degrees; set -mpegfixaspect;
            # 0 rotate clockwise and flip, 1 rotate clockwise
            #-2 rotate counterclockwise, 3 rotate counterclockwise and flip
            rotate=1
            isarg $1 "$2" aspect
            echo "$2" | grep -q '^[0-3]$' && rotate=$2 || opt_def $1 "$2" $rotate 
            shift
            : ${mpegfixaspect:=0}
            ;;
        -overscan) #<n>
            # shrink the video of n% and surround it with black borders,
            # n can be 1-99, using 10 should make visible on a TV the full video
            # image; if n is negative, the result is a magnification of the 
            # central part of the image; n>0 set -mpegfixaspect pad, n<0 set
            #--mpegfixaspect crop; in AVI Mode n can only be positive
            isarg $1 "${2#-}" $( ((step==1)) && echo Avi || echo aspect)
            echo "$2" | grep -qE '^-?[0-9]?[0-9]$' && overscan=$2 || opt_ign $1 "$2"
            [[ ${2:0:1} = - ]] && mpegfixaspect=1 || mpegfixaspect=0
            shift
            ;;
        -abr) #<n>
            #-audio bit rate of the VCD/SVCD/DVD [MP2:224,MP3:128,AC3:448]
            if [[ $2 = list ]]; then
                sed '/^check_abr/,/case/!d;/'"$audioformat"':/!d;/[^0-9]'"$asr"'/!d;s/[^)]*)//;s/  */ /g;s/^/'"$audioformat $asr"'/' "$PROGFILE"
                exit
            fi
            abr=$2
            abrset=$2
            isarg $1 "$2" direct
            shift
            ;;
        -asr) #<n>					[DIRECT]
            # audio sample rate of the VCD/SVCD/DVD [VCD/SVCD:44100,DVD:48000]
            #-for AVI Mode and MPEG Mode use MPlayer's option -srate
            asr=$2
            isarg $1 "$2" direct
            shift
            ;;
        -vbr|-vbitrate) #<n>
            #-video bit rate [VCD:1152,SVCD:2500,DVD:7500,AVI:16000]
            vbr=$2
            isarg $1 "$2" $( ((step==1)) && echo Avi || echo direct)
            shift
            ;;
        -vfr) #<n>
            # video frame rate of the output stream
            # [NTSC/VCD:4,NTSC/SVCD-DVD:1,PAL:3,AVI:2]
            #     1 - 24000.0/1001.0 (NTSC 3:2 pulldown converted FILM) 
            #     2 - 24.0 (NATIVE FILM) 
            #     3 - 25.0 (PAL/SECAM VIDEO / converted FILM) 
            #     4 - 30000.0/1001.0 (NTSC VIDEO) 
            #     5 - 30.0
            #     6 - 50.0 (PAL FIELD RATE) 
            #     7 - 60000.0/1001.0 (NTSC FIELD RATE) 
            #-    8 - 60.0
            vfr=$2
            isarg $1 "$2" direct
            shift
            ;;
        -n|-video-norm) #<n|p|s>				[DIRECT,MPEG]
            # set the video norm of the VCD/SVCD/DVD; NTSC is USA standard,
            # PAL is European standard and SECAM is French standard; concerning
            #-VCD/SVCD/DVD encoding, SECAM is equivalent to PAL
            case $2 in
                n|N|ntsc|NTSC)   videonorm=n ;;
                p|P|pal|PAL)     videonorm=p ;;
                s|S|secam|SECAM) videonorm=s ;;
                doc|help) isarg $1 $2 direct ;;
                *) echo "**ERROR: [$PROGNAME] invalid argument '$2' for option '$1'" ; "$PROGFILE" -norc $1 help ; exit 1 ;;
            esac
            shift
            ;;
        -p|-pulldown|-telecine) #				[DIRECT,MPEG]
            # set a flag in the output stream of the SVCD/DVD that tell the
            # decoder to play the movie as NTSC video using "3:2 pull-down"
            #-instead of "-vfr 4" use "-vfr 1 -p" (smaller output stream) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            telecine=1
            ;;
        -res) #<1-7> 					[DIRECT,MPEG]
            # force one of the following video resolutios:
            #                      PAL            NTSC
            #		1	352x288		352x240 (VCD) 
            #		2	352x576		352x480 (CVD) 
            #		3	480x576		480x480 (SVCD) 
            #		4	528x576		528x480 (KVCD) 
            #		5	544x576		544x480 (KVCD) 
            #		6	704x576		704x480 (DVB) 
            #-		7	720x576		720x480 (DVD) 
            isarg $1 "$2" direct
            echo "$2" | grep -q '^[1-7]$' && MPGRES=$2 || opt_ign $1 "$2"
            shift
            ;;
        -gop) #<n>
            # set the number of pictures per GOP; the default value is the one
            #-required by the standard 
            isarg $1 "$2" direct
            GOP=$2
            shift
            ;;
        -kvcd) #<1-4> 					[DIRECT,MPEG]
            # generate KVCD (www.kvcd.net) compliant frames on output; the
            # following resolutions are possible:
            #		  PAL		  NTSC		GOP
            #	1	528x576		528x480		24
            #	2	528x576		528x480		def
            #	3	544x576		544x480		24
            #-	4	544x576		544x480		def
            isarg $1 "$2" direct
            a=1
            echo "$2" | grep -q '^[1-4]$' && a=$2 || opt_def $1 "$2" $a
            shift 2
            set -- " " -qmatrix kvcd -res $((3+(a+1)/2)) $([[ $a == [13] ]] && echo "-gop 24") "$@"
            ;;
        -vcd) # 						[DIRECT,MPEG]
            #-generate VCD compliant frames on output (default) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            frameformat=VCD
            ;;
        -svcd) #[1-2] 					[DIRECT,Npeg]
            # generate SVCD compliant frames on output; the following resolutions
            # are possible:        PAL            NTSC
            #		1	480x576		480x480
            #		2	352x288		352x240
            #-default is 1
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            frameformat=SVCD
            frameres=1
            echo "$2" | grep -q '^[1-2]$' && frameres=$2 && shift
            ;;
        -svcdht) #					[DIRECT,MPEG]
            # enable the VCD header trick; this trick could allow to play SVCD on
            # DVD player that does not support SVCD. For more details see:
            #-http://www.videohelp.com/svcd
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            trick=1
            ;;
        -dvd) #[1-5] 					[DIRECT,MPEG]
            # generate DVD compliant frames on output; the following resolutions
            # are possible:        PAL            NTSC
            #		1	720x576		720x480
            #		2	704x576		704x480
            #		3	480x576		480x480 (non standard DVD-SVCD) 
            #		4	352x576		352x480
            #		5	352x288		352x240
            #-default is 1
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            frameformat=DVD
            frameres=1
            echo "$2" | grep -q '^[1-5]$' && frameres=$2 && shift
            ;;
        -dvdaudiolang) #<code,code,...>			[DIRECT,MPEG]
            # ISO 639 langauges codes to be associated with each audio
            #-stream of the DVD
            dvdaudiolang=$2
            isarg $1 "$2" direct
            shift
            ;;
        -dvdvideoattr) #<nopanscan|noletterbox|crop>	[DIRECT,MPEG]
            # add a video attribute to the dvd image; nopanscan or noletterbox
            #-are allowed with -a 3 (16:9) and crop is allowed with -a 2 (4:3) 
            isarg $1 "$2" direct
            echo $2 | grep -q -e nopanscan -e noletterbox -e crop && VIDEOATTR=$2 || opt_ign $1 "$2"
            shift
            ;;
        -addchapter) #<time,time,...|step-total|copy>	[DIRECT,MPEG]
            # insert chapters; if the argument is a list t1,t2,t3,... it
            # specifies where to put the chapters, if the argument is the couple
            # of values t1-t2, the chapters are at 0,t1,2*t1,3*t1,...,n*t1 with
            # n*t1 <= t2, if the argument is the word "copy", the chapters are
            #-the same as in the source DVD
            addchapter=$2
            isarg $1 "$2" chapters
            shift
            ;;
        -nochapter) #					[DIRECT,MPEG]
            #-do not insert chapters
            addchapter=
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            ;;
        -addsub) #<sid0,sid1,...|copy>			[DIRECT,MPEG]
            # copy the specified subtitle stream(s) or copy all the subtitles 
            #-streams if the argument is the word "copy"
            addsub=( ${2//,/ } )
            isarg $1 "$2" chapters
            shift
            ;;
        -addsdx) #<sid0,sid1,...>				[DIRECT,MPEG]
            # if you copy subtitle 2 and 4 and you want them to have id 0 and 1
            #-use -addsub 2,4 -addsdx 0,1
            addsdx=( ${2//,/ } )
            isarg $1 "$2" chapters
            shift
            ;;
        -addsla) #<sla0,sla1,...>				[DIRECT,MPEG]
            #-see doc/html/chapters.html
            addsla=( ${2//,/ } )
            isarg $1 "$2" chapters
            shift
            ;;
        -vobsubsrc) #<vobsub file>			[DIRECT,MPEG]
            # specify the vobsub source file to use together with the option
            #--addsub
            vobsubsrc=$2
            if [[ ! -f $2.idx || ! -f $2.sub ]]; then
                if [[ $2 = doc || $2 = help || ! $2 ]]; then
                    isarg $1 "$2" chapters
                else
                    [[ ! -f $2.idx ]] && echo "**ERROR: [$PROGNAME] vobsub file '$2.idx' not found"
                    [[ ! -f $2.sub ]] && echo "**ERROR: [$PROGNAME] vobsub file '$2.sub' not found"
                    exit 1
                fi
            fi
            shift
            ;;
        -txtsub) #<text subtitle file>
            #-add the subtitle to a SVCD/DVD or convert a text subtitle
            txtsub[${#txtsub[*]}]=$2
            if [[ ! -f $2 ]]; then
                [[ $2 = doc || $2 = help || ! $2 ]] && isarg $1 "$2" $([[ $mpeg || $step -gt 1 ]] && echo chapters || echo profile) || \
                  ! echo "**ERROR: [$PROGNAME] subtitle file '$2' not found" || exit 1
            fi
            shift
            ;;
        -txtsubopts) #<opt1:opt2:...>
            # text subtitles options; see doc/html/profile.html (AVI Mode) or
            # doc/html/chapters.html ; for a list of all the default values
            #-type -txtsubopts list
            if [[ $2 = list ]]; then
                ((step==1)) && for ((a=0;a<${#AVISUBDEF[*]}/2;a++)) ; do ((a)) && echo -n ":" ; echo -n "${AVISUBDEF[2*a+1]}" ; done || \
                  for ((a=0;a<${#TXTSUBDEF[*]}/2;a++)) ; do ((a)) && echo -n ":" ; echo -n "${TXTSUBDEF[2*a+1]}" ; done
                echo ; exit
            fi
            ((${#txtsub[*]})) || ! echo "**ERROR: [$PROGNAME] you must use option '-txtsub' before option '$1' " || exit 1
            txtsubopts[${#txtsub[*]}-1]=$2
            isarg $1 "$2" $([[ $mpeg || $step -gt 1 ]] && echo chapters || echo profile)
            shift
            ;;
        -dvdsdx) #<mode,id,mode,id,...+mode,id,...+...>	[DIRECT,MPEG]
            # set the subtitle id for each stream mode, mode can be: normal,
            #-widescreen, letterbox or panscan; a + separes each subtitle track
            SUBSTREAMATTR=( ${2//+/ } )
            dvdsub=${#SUBSTREAMATTR[*]}
            isarg $1 "$2" chapters
            shift
            ;;
        -ocr) #						[AVI]
            #-enable conversion of graphic subtitles to text subtitles
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 ocr
            ocr=1
            ;;
        -ocropts) #<opt1:opt2:...>			[AVI]
            # graphic subtitles to text subtitles conversion options, see
            #-doc/html/ocr.html
            if [[ $2 = list ]]; then
                n=$(echo $ocropts | awk -F: '{print NF}')
                n=$((${#OCRDEF[*]}/2>n?${#OCRDEF[*]}/2:n))
                for ((a=0;a<n;a++)); do
                    ((a)) && echo -n ":"
                    o=$(echo $ocropts | awk -F: -v i=$a '{print $(i+1)}')
                    [[ $o ]] && echo -n $o || echo -n "[${OCRDEF[2*a+1]}]"
                done
                echo ; exit
            fi
            if [[ $ocropts ]]; then
                n=$(echo $2 | awk -F: '{print NF}')
                for ((a=1;a<=n;a++)); do
                    o=$(echo $2 | awk -F: -v i=$a '{print $i}')
                    [[ $o ]] && ocropts=$(echo $ocropts | awk -F: -v i=$a '{for(a=1;a<i;a++)printf($a":");printf("'$o'");for(a=i+1;a<=NF;a++)printf(":"$a)}')
                done
            else
                ocropts=$2
            fi
            isarg $1 "$2" ocr
            shift
            ;;
        -menu) #						[DIRECT,MPEG]
            #-add menu to VCD/SVCD/DVD
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            menu=1
            ;;
        -menuopts) #<opt1:opt2:...>			[DIRECT,MPEG]
            # menu creation options; for a list of all the options and the
            #-permitted values type -menuopts list
            isarg $1 "$2" menu
            OPTSVAR=(BGTITLE   TCPR          TANIM TLINES    DVDPLAY TSALL MASP)
            OPTSVAL=("0 1 2 3" "0 1 2 3 4 5" "0 1" "1 2 3 4" "0 1" "0 1 2" "0 1 2")
            OPTSHLP=("write the title on the background image/titlebar" \
                     "chapter submenu thumbnails per row" \
                     "chapter submenu thumbnail mode: still frame/animated" \
                     "chapter submenu thumbnail title lines" \
                     "after inserting the disk in a player: show the menu/play the first title" \
                     "using -titleset, create a 'play all' button: no/yes/yes repeat" \
                     "menu aspect: 4/3 16/9noletterbox 16/9nopanscan" \
                    )
            parse_subopts $1 $2
            shift
            ;;
        -menuadvopts) #<opt1:opt2:...>			[DIRECT,MPEG]
            # menu creation advanced options; for a list of all the options and
            #-the permitted values type -menuadvopts list
            isarg $1 "$2" menu
            OPTSVAR=(TFMT              TMODE   TKFRM TSECS                               TFONTSIZE   TFONTBG TPART \
                     TPARTSEC                             MENUOS VTSMBG    TSETB DVDFS)
            OPTSVAL=("jpg png pnm tga" "0 1 2" "0 1" "1 2 3 4 5 6 7 8 10 12 14 16 20 30" "1 2 3 4 5" "0 1" "1 2 3 4 5 6 7 8 9" \
                     "5 10 15 20 25 30 35 40 45 50 55 60" "0 1"  "0 1 2 3" "0 1" "0 1")
            OPTSHLP=("chapter submenu thumbnail format" \
                     "chapter submenu thumbnail selection: bigger file/first frame/last frame" \
                     "chapter submenu thumbnail extraction: Intra keyframes/all frames" \
                     "chapter submenu thumbnail scan time (seconds)" \
                     "chapter submenu thumbnail title font size (1 smaller, 5 bigger)" \
                     "chapter submenu thumbnail title background style" \
                     "chapter submenu thumbnail movie parts" \
                     "chapter submenu thumbnail movie single part length (seconds)" \
                     "use TV overscan area for menu" \
                     "VTSM thumb: no/menubg/chapter/file" \
                     "navigation buttons only with more than 4 titles" \
                     "using -title, create the DVD filesystem too" \
                    )
            parse_subopts $1 $2
            shift
            ;;
        -menuextra) #"txt" [@:op1:..] <file1> [<file2>..]	[DIRECT,MPEG]
            # create an extra menu with picture gallery or slideshow, see
            #-doc/html/menu.html
            isarg $1 "$2" menu
            a=$1
            MEXTRATXT[${#MEXTRATXT[*]}]=$2
            shift
            [[ ${2:0:2} = @: ]] && MEXTRAOPT[${#MEXTRATXT[*]}-1]=${2:2} && shift
            if [[ $2 = -readfile ]]; then
                get_arguments_from_file "$3" "$2"
                for ((n=0;n<${#ARRAY[*]};n++)); do
                    if [[ ${ARRAY[n]} ]]; then
                        [[ ! -r ${ARRAY[n]} ]] && echo "**ERROR: [$PROGNAME] file '${ARRAY[n]}', line $((n+1)) of '$a -readfile $3', not found" && exit 1
                    else
                        unset ARRAY[n]
                    fi
                done
                MEXTRAARG=( "${MEXTRAARG[@]}" "${ARRAY[@]}" )
                shift 2
            else
                isarg $a "$2" menu
                while [[ ${2:0:1} != - && $# -gt 1 ]]; do
                    if [[ -r $2 || ${2:0:5} = mf:// ]]; then
                        if [[ ${2:0:5} = mf:// ]]; then
                            ( IFS=,
                              for b in ${2#mf://} ; do
                                  [[ -r $b ]] || ! echo "**ERROR: [$PROGNAME] file 'mf://$b' argument of '$a ${MEXTRATXT[${#MEXTRATXT[*]}-1]}' not found" || exit 1
                              done 
                            ) || exit 1
                        fi
                        MEXTRAARG[${#MEXTRAARG[*]}]=$2
                        shift
                        [[ $2 = -- ]] && shift && break
                    else
                        echo "**ERROR: [$PROGNAME] file '$2' argument of '$a' not found"
                        exit 1
                    fi
                done
            fi 
            MEXTRAIND[${#MEXTRAIND[*]}]=${#MEXTRAARG[*]}
            ;;
        -menuthumboffset) #<time,time,....>		[DIRECT,MPEG]
            #-chapter submenu thumbnail offset time
            isarg $1 "$2" menu
            thumboffset=( $(echo $2 | awk -F, '{for(a=1;a<=NF;a++){if(a==1&&$a=="")$1="0";if($a=="")$a=m;else m=$a;printf("%s ",$a)}}') )
            shift
            ;;
        -menubg) #<bgimage> [@:opt]			[DIRECT,MPEG]
            # specify an image for the menu background; opt can be: 0 (default) 
            # [bgimage scaled to fit the screen], 1 [bgimage scaled keeping its
            #-aspect ratio]
            menubg=$2
            if [[ ! -f $2 ]]; then
                [[ $2 = doc || $2 = help || ! $2 ]] && isarg $1 "$2" menu || ! echo "**ERROR: [$PROGNAME] file '$2' not found" || exit 1
            fi
            shift
            [[ ${2:0:2} = @: ]] && menubgopt=${2:2} && shift
            ;;
        -menuvtsbg) #<vtsbgimage>				[DIRECT,MPEG]
            #-specify an image for the root menu
            menuvtsbg=$2
            if [[ ! -f $2 ]]; then
                [[ $2 = doc || $2 = help || ! $2 ]] && isarg $1 "$2" menu || ! echo "**ERROR: [$PROGNAME] file '$2' not found" || exit 1
            fi
            shift
            VTSMBG=3
            ;;
        -menuchaptertext) #"text 1" "text 2" ...		[DIRECT,MPEG]
            #-text to insert under each thumbnail in the chapter submenu
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            if [[ $2 = -readfile ]]; then
                get_arguments_from_file "$3" "$1 $2"
                CHAPTERTEXT=( "${ARRAY[@]}" )
                shift 2
            else
                while [[ ${2:0:1} != - && $# -gt 1 ]]; do
                    CHAPTERTEXT[${#CHAPTERTEXT[*]}]=$2
                    shift
                    [[ $2 = -- ]] && shift && break
                done
            fi 
            ;;
        -menuaudiotext) #"text 1" "text 2" ...		[DIRECT,MPEG]
            # text to insert in the audio submenu, default is to use the
            #-langauges specified with -dvdaudiolang
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            if [[ $2 = -readfile ]]; then
                get_arguments_from_file "$3" "$1 $2"
                AUDIOTEXT=( "${ARRAY[@]}" )
                shift 2
            else
                while [[ ${2:0:1} != - && $# -gt 1 ]]; do
                    AUDIOTEXT[${#AUDIOTEXT[*]}]=$2
                    shift
                    [[ $2 = -- ]] && shift && break
                done
            fi 
            ;;
        -menusubtext) #"text 1" "text 2" ...		[DIRECT,MPEG]
            # text to insert in the subtitle submenu, default is to use the
            #-langauges specified with -addsla
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            if [[ $2 = -readfile ]]; then
                get_arguments_from_file "$3" "$1 $2"
                SUBTEXT=( "${ARRAY[@]}" )
                shift 2
            else
                while [[ ${2:0:1} != - && $# -gt 1 ]]; do
                    SUBTEXT[${#SUBTEXT[*]}]=$2
                    shift
                    [[ $2 = -- ]] && shift && break
                done
            fi 
            ;;
        -menufix) #					[DIRECT,MPEG]
            # use a workaroung to avoid random ImageMagick errors during
            #-chapter's sumbenu creation
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            menufix=1
            ;;
        -cdburndevice) #<dev>				[DIRECT,MPEG]
            #-burn device used by cdrdao, default is 0,0,0
            cdburndevice=$2
            isarg $1 "$2" direct
            shift
            ;;
        -dvdburndevice) #<dev>				[DIRECT,MPEG]
            #-burn device used by growisofs, default is /dev/cdrecorder
            dvdburndevice=$2
            isarg $1 "$2" direct
            shift
            ;;
        -cdi) #<path to CD-i application files> 		[DIRECT,MPEG]
            #-add CD-i compatibility for VCD, see the README
            cdi=$2
            isarg $1 "$2" direct
            shift
            ;;
        -avi) #						[AVI]
            #-this option just set the following: -encode 3:3:2 -vfr 2 -avionly
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            shift
            set -- " " -encode 3:3:2 -vfr 2 -avionly "$@"
            ;;
        -dvd2dvd) #					[MPEG]
            # this option set the following:
            #--dvd -mpeg -encode 0:0:1 -addchapter copy -addsub copy
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            shift
            set -- " " -dvd -mpeg -encode 0:0:1 -addchapter copy -addsub copy "$@"
            ;;
        -stdvid) #<n>					[DIRECT,MPEG]
            # set some proper options in order make a standard VCD/SVCD/DVD
            #	1 - VCD  4 - SVCD  7 - DVD/mp2  10 - DVD/acopy    DIRECT Mode
            #-	3 - VCD  6 - SVCD  9 - DVD/mp2  12 - DVD/acopy      MPEG Mode
            #	2 - VCD  5 - SVCD  8 - DVD/mp2  11 - DVD/acopy  INDIRECT Mode
            case $2 in
                1|4|7) OPT="-mp2 toolame" ;;
                3|6|2|5) mencoder -oac help 2>/dev/null | grep -q t[wo]olame && OPT="-mpeg -encode 7:3:1 -srate 44100" || \
                       OPT="-mpeg -encode 1:3:1 -mp2 toolame -asr 44100 -replex" ;;
                9|8) mencoder -oac help 2>/dev/null | grep -q t[wo]olame && OPT="-mpeg -encode 7:3:2 -srate 48000" || \
                       OPT="-mpeg -encode 1:3:2 -mp2 toolame -asr 48000 -replex" ;;
                10) OPT="-acopy" ;;
                12) OPT="-mpeg -encode 0:3:2" ;;
                doc|help) isarg $1 $2 stdvid ;;
                *) echo "**ERROR: [$PROGNAME] invalid argument '$2' for option '$1'" && exit 1 ;;
            esac
            case $2 in
                [1-3]) S=VCD ;;
                [4-6]) OPT="-svcd $OPT" ; S=SVCD ;;
                [7-9]|1[0-2]) OPT="-dvd $OPT" ; S=DVD ;;
            esac
            OPT="$OPT -mpegfixaspect -addchapter copy"
            do_log "   INFO: [$PROGNAME] creating a $S with: '$OPT'"
            shift 2
            set -- " " $OPT "$@"
            ;;
        -replex) #					[MPEG]
            # in MPEG Mode, if possible, mencoder will create the video and 
            # audio stream and multiplex them in a single step. With -replex,
            #-the video and audio stream will be multiplexed with mplex
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 mpeg
            fast=
            ;;
        -vcodec) #<mpeg1|mpeg2|mpeg4|xvid>		[AVI,MPEG]
            #-force the selected video codec [VCD:mpeg1,SVCD-DVD:mpeg2,AVI:mpeg4]
            isarg $1 "$2" Avi
            [[ $2 == mpeg[124] || $2 = xvid || $2 = ffv1 ]] && vcodec=$2 && [[ ${vcodec:4:1} == [12] ]] && vcodec=${vcodec}video
            shift
            ;;
        -qmatrix) #<kvcd|tmpgenc|default|hi-res>
            # mpeg2enc custom quantization matrices: kvcd produce a smaller
            #-output stream, hi-res is good for hi-quality source material
            case $2 in
                kvcd|tmpgenc|default|hi-res)
                    MPEG2ENCOPT="$MPEG2ENCOPT -K $2"
                    intra_matrix=$(eval echo \$${2/-}_intra)
                    inter_matrix=$(eval echo \$${2/-}_inter)
                    ;;
                *)
                    MPEG2ENCOPT="$MPEG2ENCOPT -K default"
                    intra_matrix=
                    inter_matrix=
                    ;;
            esac
            isarg $1 "$2" direct
            shift
            ;;
        -mpeg1vbr) #					[DIRECT,MPEG]
            # produce a VCD/MPEG-1 variable bit rate stream, the output stream
            # is smaller and a complete movie could fit in one VCD; check if
            #-your hardware player support variable bit rate VCD
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            MPEG2ENCOPT="$MPEG2ENCOPT -q 8"
            LAVC=":vrc_buf_size=327"
            ;;
        -cbr)
            #-force the use of constant bit rate video encoding
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 $([[ $step -eq 1 ]] && echo Avi || echo direct)
            cbr=1
            MPEG2ENCOPT="$MPEG2ENCOPT --cbr"
            ;;
        -mpegmbr) #<n>					[MPEG]
            # set the maximum video bit rate; the default is the value of vbr;
            #-a value of 0 remove the limit
            mpegmbr=$2
            [[ $2 -eq 0 ]] && mpegmbr=
            isarg $1 "$2" mpeg
            shift
            ;;
        -mp1) #[mp2enc|encode|copy]			[DIRECT,MPEG]
            # create mp1 audio with with one of mp2enc, encode or copy the 
            #-source (mp1) audio stream; see the README
            audioformat=mp1
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            if [[ $2 = mp2enc || $2 = encode || $2 = copy ]]; then
                mp1=$2
                shift
            fi
            ;;
        -mp2) #[mp2enc|toolame|mencoder|copy|musicin|mctoolame]	[DIRECT,MPEG]
            # create mp2 audio with one of mp2enc, toolame, mencoder[libavcodec]
            # musicin, mctoolame or copy the source (mp2) audio stream;
            # for musicin or mctoolame you need to use -mpegchannels <3-6> too;
            #-default: mp2enc (ch 1-2), musicin (ch 3-6) 
            audioformat=mp2
            if [[ $2 = doc || $2 = help ]]; then
                ((${mpegchannels:-2}<3)) && isarg $1 $2 direct || isarg $1 $2 multichannel
            fi
            if [[ $2 = mp2enc || $2 = toolame || $2 = mencoder || $2 = copy || $2 = musicin || $2 = mctoolame ]]; then
                mp2=$2
                shift
            fi
            ;;
        -mp3) #[lame|mencoder|copy]			[DIRECT,MPEG]
            # create mp3 audio with lame or mencoder[libavcodec] or copy the
            #-source (mp3) audio stream, default lame
            audioformat=mp3
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            if [[ $2 = lame || $2 = mencoder || $2 = copy ]]; then
                mp3=$2
                shift
            fi
            ;;
        -ac3) #[mencoder|copy]				[DIRECT,MPEG]
            # create ac3 audio with mencoder[libavcodec] or copy the source
            #-(ac3) audio stream, default mencoder
            audioformat=ac3
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            if [[ $2 = mencoder || $2 = copy ]]; then
                ac3=$2
                shift
            fi
            ;;
        -dts) #[copy]					[DIRECT,MPEG]
            #-copy the source (dts) audio stream
            audioformat=dts
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            if [[ $2 = copy ]]; then
                dts=$2
                shift
            fi
            ;;
        -lpcm) #						[DIRECT,MPEG]
            #-create an uncompressed lpcm audio stream [48000 or 96000 kHz]
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            audioformat=lpcm
            lpcm=mplayer
            ;;
        -acopy) #						[DIRECT,MPEG]
            #-copy the source audio streams
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 mpeg
            audioformat=acopy
            acopy=copy
            ;;
        -mpegchannels) #<1-6>				[DIRECT,MPEG]
            # number of channels of the MPEG audio stream, 1-6 for ac3 and lpcm;
            # 1-2 for mp1, mp2 and mp3; 3-6 for mp2 Multichannel Audio; for the
            #-AVI audio stream use MPlayer's option -channels
            mpegchannels=2
            [[ $mp2 = musicin || $mp2 = mctoolame ]] && isarg $1 "$2" multichannel || isarg $1 "$2" direct
            parse_ch $2
            shift
            ;;
        -normalize)
            #-normalize to the audio stream(s) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 $([[ $encode ]] && echo Avi || echo direct)
            normalize=1
            ;;
        -volume) #<n>
            # change amplitude of the audio stream; less than 1.0 decreases,
            #-greater than 1.0 increases (float) 
            volume=$2
            isarg $1 "$2" direct
            shift
            ;;
        -multiaudio) #<aid0,aid1,...>
            # put more than one audio stream in the output stream, aid is the
            # number you pass the -aid option of mplayer; AVI stream can have 
            # only MP3 or AC3 (avimerge limitation), SVCD/DVD stream can have 
            # MP1,MP2,MP3,AC3,DTS,LPCM but vcdimager will complain if the SVCD
            #-has AC3 or LPCM, VCD can only have 1 audio channel 
            multiaudio=${2//,/ }
            isarg $1 "$2" direct
            shift
            ;;
        -noscale) #					[DIRECT,MPEG]
            # encode2mpeg automatically scales the video according to the MPEG
            # profile chosen, this option disables this feature; used mainly
            #-for debug purposes
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            scale=
            ;;
        -monochrome)
            #-create B/W video or avoid color artifacts in B/W source streams
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            YUVSCALEROPT="$YUVSCALEROPT -O MONOCHROME"
            ;;
        -sync-offset) #<n>				[DIRECT,MPEG]
            #-adjust the audio/video synchronization; see -O in man mplex
            isarg $1 "${2#-}" direct
            MPLEXOPT="$MPLEXOPT -O $2"
            shift
            ;;
        -auto-sync-offset) #				[DIRECT,MPEG]
            # adjust automatically the audio/video synchronization; useful only
            # when using -encode 0:0:1 or -mc 0 and muxing with mplex; tested
            #-with TS streams, it may not work properly with other streams
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            autosync=1
            ;;
        -toolopts) #<yuvdenoise|y4mdenoise|yuvscaler|mpeg2enc|mplex|mplayer|
                   #vcdimager|dvdauthor|cdrdao|growisofs|musicin> <options>
            # all the following options are passed to the specified tool;
            # in DIRECT Mode the denoiser (yuvdenoise/y4mdenoise) is not used by
            #-default, to turn it on specify it once as argument of -toolopts
            TOOL=$2
            [[ $TOOL = yuvdenoise ]] && YUVDENOISE=yuvdenoise
            [[ $TOOL = y4mdenoise ]] && YUVDENOISE="y4mdenoise -v 0"
            isarg $1 $2
            shift
            ;;
        -split) #<n>					[DIRECT,MPEG]
            # split the resulting MPEG stream in <n> MB chunks. [800]
            #-this is the default in DIRECT Mode
            split=$2
            isarg $1 "$2" direct
            shift
            ;;
        -nosplit) #					[DIRECT,MPEG]
            # do not split the resulting MPEG stream; this is the default
            #-in MPEG Mode
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            split=
            ;;
        -avisplit) #<n>					[AVI]
            # split the AVI stream in <n> MB chunks, default is unsplit,
            #-it requires -avionly
            avisplit=$2
            isarg $1 "$2" Avi
            shift
            ;;
        -resume)
            #-resume a previous incomplete run
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            resume=1
            if [[ $2 = clear ]]; then
                clear=$3
                isarg $1 $3
                shift 2
            fi
            ;;
        -keep)
            # once an intermediate stream is not necessary any more it is
            # deleted; with this option you keep all of them; AVI and MPEG
            #-streams are never deleted
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            keep=1
            ;;
        -blank) #						[DIRECT,MPEG]
            #-blank a cd before burning it
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            blank=1
            ;;
        -nowait) #					[DIRECT,MPEG]
            #-do not ask for a keypress before starting the burning process
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            nowait=1
            ;;
        -cacheonly)
            #-do only cache related tasks
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 cache
            step=0
            ;;
        -avionly) #					[AVI]
            #-create only the AVI stream
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            step=1
            ;;
        -streamonly) #					[DIRECT,MPEG]
            #-create only the elementary stream (video and audio) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            step=2
            ;;
        -mpegonly) #					[DIRECT,MPEG]
            #-create the MPEG stream (and remove the elementary stream) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            step=3
            ;;
        -imageonly) #					[DIRECT,MPEG]
            #-create the binary image (S/VCD) or the DVD filesystem
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            step=4
            ;;
        -isoonly) #					[DIRECT,MPEG]
            #-create the DVD iso image; normally it is never created
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct
            step=5
            ;;
        -burniso|-burnudf)
            # put the encoded stream in a iso/udf filesystem and burn it to a DVD
            # disk; files already present on the DVD disk are preserved, use
            #--blank to erase them (for a DVD RW) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 verify
            [[ $1 = -burnudf ]] && burniso=2 || burniso=1
            ;;
        -verify)
            # verify the integrity of the burned media; recomended; it may happen
            # that the DVD burn process shows no errors, but the disk content is
            #-not 100% identical to the source due to a bad media
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 verify
            verify=1
            ;;
        -encode) #<n:m:i> 				[AVI,MPEG] 
            # the parameter n:m:i selects the audio codec, video codec options
            # and number of pass for mencoder, possible values are:
            #   n                   m				i
            #   0 copy              0 copy			1 
            #   1 pcm               1 libavcodec/xvid MPEG	2
            #   2 mp3lame/fast      2 as 1 + mbd=2		3
            #   3 mp3lame/standard  3 as 1 + compression opts
            #   4 libavcodec/mp2    4 as 1 + quality opts
            #   5 libavcodec/mp3
            #   6 libavcodec/ac3    for m=[2-4] and i>1 turbo is on
            #   7 toolame/mp2	    i<=2 for xvid
            #-  8 libfaac/aac
            encode=5:3:2
            isarg $1 "$2" $([[ $mpeg ]] && echo mpeg || echo Avi)
            echo "$2" | grep -qE '^[0-8]:[0-4]:[1-9](,[0-9]+)?$' && encode=$2 || opt_def $1 "$2" $encode
            shift
            ;;
        -telecinesrc) #					[MPEG]
            # if you use -encode n:0:i in MPEG Mode, encode2mpeg needs to know
            # if the source NTSC MPEG is telecined, otherwise the stream copy may
            # not work properly; normally encode2mpeg is able to detect telecined
            # sources, but, if the source MPEG is mixed, part not telecined and
            # part telecined, encode2mpeg may fail to detect it. In such case,
            #-you can use this option to specify a telecined source.
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 mpeg
            telesrc=1
            ;;
        -turbo) #<0-1>					[AVI,MPEG]
            # disable (0) or force (1) turbo mode for the first pass of N pass
            #-encoding (N>1) 
            isarg $1 "$2" Avi
            echo "$2" | grep -q '^[0-1]$' && turbo=$2 || opt_ign $1 "$2"
            shift
            ;;
        -hispeed) #					[AVI,MPEG]
            # increase the encoding speed of 25-50% (with -encode n:1:1); the
            # output video stream will be bigger and can have poor quality; this
            # option is mainly intented for testing, but it can be used if you
            #-want to create more quickly an MPEG-4/AVI or a DVD
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            hispeed=1
            ;;
        -bframes) #<0-4>					[AVI,MPEG]
            # specify the number of B frames; if -encode is n:3:i the default 2,
            #-otherwise the default is no B frames; for VCD the default is 2
            isarg $1 "$2" Avi
            echo "$2" | grep -q '^[0-4]$' && bframes=$2 || opt_ign $1 "$2"
            shift
            ;;
        -vcustom) #<libavcodec options>			[AVI,MPEG]
            # specify a custom set of video options for libavcodec, use with
            #--encode n:1:i
            vcustom=$2
            isarg $1 "$2" Avi
            shift
            ;;
        -acustom) #<mp3lame/faac options>			[AVI,MPEG]
            # specify a custom set of lame options (with -encode 2:m:i) or faac
            #-options (with -encode 8:m:i)
            acustom=$2
            isarg $1 "$2" Avi
            shift
            ;;
        -encsid) #<sid0,sid1,...>
            #-dump the DVD vobsub, sid is the number you give the -sid option
            # of MPlayer.
            encsid=( ${2//,/ } )
            isarg $1 "$2" subtitle
            shift
            ;;
        -encsdx) #<sid0,sid1,...>
            # if you dump subtitle 2 and 4 and you want them to have id 0 and 1
            #-use -encsid 2,4 -encsdx 0,1
            encsdx=( ${2//,/ } )
            isarg $1 "$2" subtitle
            shift
            ;;
        -encsla) #<sla0,sla1,...>
            #-see doc/html/subtitle.html
            encsla=( ${2//,/ } )
            isarg $1 "$2" subtitle
            shift
            ;;
        -usespeed) #					[DIRECT,MPEG]
            # do frame rate conversion changing the playback speed; this option
            # can be used if you are converting from NTSC 24fps, with or without
            # telecine, to PAL 25fps and viceversa; during normal frame rate
            # conversion, frames are skipped or duplicated as needed; with this
            #-option all the frames are encoded
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 mpeg
            usespeed=1
            ;;
        -usesbr) #[1-6|>100]				[AVI,MPEG]
            # use the suggested video bitrate to set the output stream size
            #   1 - for 650MB CD 		4 - for 2 x 650MB CD
            #   2 - for 700MB CD (default) 	5 - for 2 x 700MB CD
            #   3 - for 800MB CD 		6 - for 2 x 800MB CD
            #   n where n > 100 will set the file size to n MB
            #-with -multiaudio you must to set the streamsize in MB
            usesbr=2
            SBR=(650 700 800 "2 x 650" "2 x 700" "2 x 800")
            echo "$2" | grep -q '^[1-6]$' && usesbr=$2 && shift
            echo "$2" | grep -qE '^[1-9][0-9]{2,}$' && usesbr=$2 && shift
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            ;;
        -setaspect) #<n>					[AVI,MPEG]
            # scale and encode the video keeping the required aspect ratio,
            # if necessary add black lines to keep the final resolution multiple
            # of 16; n can be:
            #       1 expand        2 shrink        >100 set width to n
            # no black lines are added if n is negative; examples:
            #   1   a 720x576 16/9 PAL video is encoded at 1024x576
            #   1   a 720x480 16/9 NTSC video is encoded at 864x480 (bl. lines) 
            #  -1   a 720x480 16/9 NTSC video is encoded at 854x480
            #   2   a 720x480 4/3 NTSC video is encoded at 640x480
            #   512 encode the video at 512x384 (4/3) or 512x288 (16/9) 
            # optimal width: 
            #    640 512 320, 704 576 448 384 (4/3) 
            #-   512, 624 368, 654 622 592 542 510 480 398 366 336 (16/9) 
            zoom=2
            echo "$2" | grep -qE '^-?[1-9][0-9]*$' && zoom=$2
            isarg $1 "${2#-}" Avi
            ((zoom>2&&zoom<9)) && echo "**ERROR: [$PROGNAME] option $1 accept different argument's value now" && isarg $1 help
            shift
            ;;
        -ofps) #<n>					[AVI]
            # set the video frame per second of the AVI stream, useful if you
            #-want an unusual value (for example 15 fps) 
            ofps=$2
            isarg $1 "$2" Avi
            shift
            ;;
        -profile) #<profile name>				[AVI]
            # select a DivX/MPEG-4 profile; run 'encode2mpeg -profile doc' for
            #-more informations and the complete list of available profiles
            case $2 in
                [Dd][iI][vV][xX][Hh][Aa]) PROFILE=( "DivX Handheld"                     176 200  0  800   $((32*8*1024/1000))   537 15 dxnhandheld ) ;;
                [Dd][iI][vV][xX][Pp][Oo]) PROFILE=( "DivX Portable"                     352 768  1  8000  $((384*8*1024/1000)) 4854 30 dxnport ) ;;
                [Dd][iI][vV][xX][Hh][tT]) PROFILE=( "DivX Home Theater"                 720 4000 1  8000  $((384*8*1024/1000)) 4854 30 dxnht ) ;;
                [Dd][iI][vV][xX][Hh][dD]) PROFILE=( "DivX High Def"                    1280 8000 2  16000 $((768*8*1024/1000)) 9708 30 dxnhdtv ) ;;
                [sS][pP][lL]0)            PROFILE=( "MPEG-4 Simple Profile L0"          176 64   "" vbr   $((10*2*8*1024/1000))  "" 15 sp0 ) ;;
                [sS][pP][lL]1)            PROFILE=( "MPEG-4 Simple Profile L1"          176 64   "" vbr   $((10*2*8*1024/1000))  "" 15 sp1 ) ;;
                [sS][pP][lL]2)            PROFILE=( "MPEG-4 Simple Profile L2"          352 128  "" vbr   $((40*2*8*1024/1000))  "" 15 sp2 ) ;;
                [sS][pP][lL]3)            PROFILE=( "MPEG-4 Simple Profile L3"          352 384  "" vbr   $((40*2*8*1024/1000))  "" 15 sp3 ) ;;
                [aA][sS][pP][lL]0)        PROFILE=( "MPEG-4 Advanced Simple Profile L0" 176 128  "" vbr   $((10*2*8*1024/1000))  "" 30 asp0 ) ;;
                [aA][sS][pP][lL]1)        PROFILE=( "MPEG-4 Advanced Simple Profile L1" 176 128  "" vbr   $((10*2*8*1024/1000))  "" 30 asp1 ) ;;
                [aA][sS][pP][lL]2)        PROFILE=( "MPEG-4 Advanced Simple Profile L2" 352 384  "" vbr   $((40*2*8*1024/1000))  "" 15 asp2 ) ;;
                [aA][sS][pP][lL]3)        PROFILE=( "MPEG-4 Advanced Simple Profile L3" 352 768  "" vbr   $((40*2*8*1024/1000))  "" 30 asp3 ) ;;
                [aA][sS][pP][lL]4)        PROFILE=( "MPEG-4 Advanced Simple Profile L4" 352 3000 "" vbr   $((80*2*8*1024/1000))  "" 30 asp4 ) ;;
                [aA][sS][pP][lL]5)        PROFILE=( "MPEG-4 Advanced Simple Profile L5" 720 8000 "" vbr   $((112*2*8*1024/1000)) "" 30 asp5 ) ;;
                doc|help) isarg $1 $2 profile ;;
                *) echo "**ERROR: [$PROGNAME] invalid profile '$2'" && exit 1 ;;
            esac
            harddup=1
            shift 2
            set -- " " -fixavi -vbr $((${vbr:-16000}<${PROFILE[2]}?${vbr:-16000}:${PROFILE[2]})) -setaspect $((zoom?zoom:${PROFILE[1]}/160*160)) "$@"
            ;;
        -crop) #<w:h:x:y>					[AVI,MPEG]
            #-cropping window. See -vf crop in MPlayer man page.
            crop=$2
            isarg $1 "$2" Avi
            shift
            ;;
        -autocrop) #					[AVI,MPEG]
            #-autodetect the cropping window; WARNING: it may not work properly.
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            autocrop=1
            ;;
        -cpu) #<n>
            #-number of cpu to use, default all the cpu present in the system
            cpu=1
            isarg $1 "$2" Avi
            echo "$2" | grep -q '^[1-8]$' && cpu=$2 || opt_ign $1 "$2"
            shift
            ;;
        -interlaced)
            #-turn on optimization for interlaced source video. 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 $([[ $mpeg ]] && echo direct || echo Avi)
            interlaced=1
            ;;
        -cartoon) #[1-2]					[AVI,MPEG]
            # turn on optimization for anime/cartoon source video, the argument 2
            #-selects more aggressive options than argument 1 (the default) 
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            cartoon=1
            echo "$2" | grep -q '^[12]$' && cartoon=$2 && shift || opt_def $1 "$2" $cartoon
            ;;
        -fixavi) #					[AVI]
            # use this option if seek or fast forward do not work with your
            #-player
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            fixavi=1
            ;;
        -fixasync) #					[AVI]
            # due to a bug of MEncoder, there could be an a/v sync problem if you
            # create an AVI with vbr mp3 audio (-encode 3:m:i); this option
            #-enables a different encoding sequence that should avoid it
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi
            fixasync=1
            ;;
        -title) #						[DIRECT,MPEG]
            #-the created MPEG will be a title of a multititle DVD
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            dvdtitle=1
            BGTITLE=2
            ((VTSMBG<2)) && VTSMBG=2
            ;;
        -titleset) #"title 1" "title 2" ...		[DIRECT,MPEG]
            #-specify the titles of a multititle DVD
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 menu
            while [[ ${2:0:1} != - && $# -gt 1 ]]; do
                [[ -f $2.dvd.xml ]] || ! echo "**ERROR: [$PROGNAME] file $2.dvd.xml not found; did you create the title '$2' with the option -title?" || \
                  exit 1
                TITLESET[${#TITLESET[*]}]=$2
                shift
            done
            ;;
        -video|-videos) #					[DIRECT,MPEG]
            # syntax: -video <source stream> <options>
            # syntax: -videos <video 1> <video 2> ...
            # make the source stream(s) a chapter of the VCD/SVCD/DVD; it creates
            #-always a binary image (S/VCD) or a DVD filesystem
            ((step==1)) && echo "**ERROR: [$PROGNAME] '$1' and '-avionly' cannot be used together" && exit 1
            ((!step)) && echo "**ERROR: [$PROGNAME] '$1' and '-cacheonly' cannot be used together" && exit 1
            ((step<4)) && step=4 && do_log "++ WARN: [$PROGNAME] found option $1, assuming -imageonly"
            isarg $1 "${2#-}" videos
            a=$1
            shift
            unset RUNOPT
            while [[ $# -gt 0 && $1 != $a ]] ; do
                [[ $a = -videos && ! -f $1 ]] && echo "**ERROR: [$PROGNAME] file '$1' argument of '$a' not found" && exit 1
                RUNOPT=( "${RUNOPT[@]}" "$1" )
                shift
            done
            if ((!iter)); then
                unset COMMONOPT
                for ((i=0;i<${#CMD[*]};i++)); do
                    [[ ${CMD[i]} = $a ]] && break
                    COMMONOPT[i]=${CMD[i]}
                done
                [[ $a = -video ]] && FIRSTRUNOPT=( "${RUNOPT[@]}" ) || FIRSTRUNOPT=( "${RUNOPT[0]}" )
                STARTTIME=$(pr_time)
                [[ $resume ]] || rm -f "$output".mpg "$output"[0-9][0-9].mpg
            fi
            iter=$((++iter))
            if [[ ! $resume ]]; then
                ((!$#)) && set -- -resume "${FIRSTRUNOPT[@]}"
                set -- " " "$@"
                if [[ $a = -video ]]; then
                    "$PROGFILE" ${norc:+-norc} "${COMMONOPT[@]}" "${RUNOPT[@]}" -o "$output"$(printf "%02d" $iter) -mpegonly -nosplit -noshowlog
                    ret=$? ; (( ret )) && echo "**ERROR: [$PROGNAME] run for '$a ${RUNOPT[@]}' has failed" && exit $ret
                else
                    for ((i=0;i<${#RUNOPT[*]};i++)); do
                        "$PROGFILE" ${norc:+-norc} "${COMMONOPT[@]}" "${RUNOPT[i]}" -o "$output"$(printf "%02d" $((iter+i))) -mpegonly -nosplit -noshowlog
                        ret=$? ; (( ret )) && echo "**ERROR: [$PROGNAME] run '$a ${RUNOPT[i]}' has failed" && exit $ret
                    done
                    iter=$((iter+i-1))
                    ((iter > 1)) && cp "${output}"01.log "$output".log
                fi
                ((iter==1)) && cp "${output}"01.log "$output".log
            else
                if [[ -f "$output".log ]]; then
                    set -- " " "${FIRSTRUNOPT[@]}"
                    bakiter=0
                    rm -f "$output".log.log
                    mv "$output".log "$output".log.log
                    sed '1,/^ JOBEND:/!d' "$output".log.log >"$output".log
                    tail -1 "$output".log.log >>"$output".log
                else
                    iter=0
                    set -- " " $a "${RUNOPT[@]}" "$@"
                    resume=
                fi
            fi
            ;;
        -cachedvd) #<dir> <mount point>
            # cache the content of a DVD in <dir>; <mount point> is the directory
            #-where the source DVD is mounted
            cache=$2
            DVDMNT=$3
            isarg $1 "$2" cache
            isarg $1 $3
            [[ $4 == [01][01][01] ]] && cacher=${4%??} cachep=${4#?} cachep=${cachep%?} novobcopy=${4#??} && shift
            shift 2
            ;;
        -savecache) #[iso] [raid]
            # burn the content of the cache on a DVD or create only an iso image
            #-(two DVD or two iso images for raid; see the html documentation) 
            savecache[0]=1
            while : ; do
                case $2 in
                    iso|verify) savecache[0]=$2 ; shift ;;
                    force) savecache[1]=$2 ; shift ;;
                    raid) savecache[2]=$2 ; shift ;;
                    region) savecache[3]=$2 ; shift ;;
                    puos) savecache[4]=$2 ; shift ;;
                    backup) savecache[5]=$2 ; shift ;;
                    pause) savecache[6]=$2 ; shift ;;
                    doc|help) isarg $1 $2 cache ;;
                    *) break ;;
                esac
            done
            ;;
        -removecache)
            # remove the contents of the cache specified with -cachedvd or
            #--dvd-device
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 cache
            removecache=1
            ;;
        -audioonly) #<audio file> [["@:opt:txt"] [bg image]] [--]
            # make a video using <audio file> for the audio stream and a static
            # background for the video stream, opt can be: 0 [bg image scaled to
            # fit the screen], 1 (default) [bg image scaled keeping its aspect
            # ratio]; if provided, the string txt is written on the background
            #-image; -- indicates end of options
            if [[ ! -f $2 ]]; then
                [[ $2 = doc || $2 = help || ! $2 ]] && isarg $1 $2 || ! echo "**ERROR: [$PROGNAME] file '$2' not found" || exit 1
            fi
            audioonly=$2
            shift
            [[ ${2:0:2} = @: ]] && audioonlyopt=${2:2} audioonlytxt=${audioonlyopt#*:} audioonlyopt=${audioonlyopt%%:*} && shift
            if [[ ${2:0:1} != - && $# -gt 1 ]]; then
                if [[ -r $2 ]]; then
                    audioonlybg=$2
                    shift
                else
                    echo "**ERROR: [$PROGNAME] bg file '$2' argument of '$a $audioonly' not found"
                    exit 1
                fi
            fi
            [[ $2 = -- ]] && shift
            ;;
        -slidefps) #<n>
            # fps to use when creating video from pictures, default is 1; if
            # there is an audio file associated with a picture, the duration of
            #-the audio file is used
            isarg $1 "$2" images
            slidefps=$(awk -v a=$2 'BEGIN{printf("%.3f",1/a)}')
            shift
            ;;
        -slideaudio) #<audio file>
            # use the content of <audio file> as audio stream when creating video
            #-from pictures; it works correctly only if used with mf://singlepic
            slideaudio=$2
            if [[ ! -f $2 && $2 != /dev/null ]]; then
                [[ $2 = doc || $2 = help || ! $2 ]] && isarg $1 "$2" images || ! echo "**ERROR: [$PROGNAME] slide audio file '$2' not found" || exit 1
            fi
            shift
            ;;
        -norc)
            #-do not use the settings in the file $HOME/.encode2mpegrc
            [[ $2 = doc || $2 = help ]] && isarg $1 $2 rc
            ;;
        -debug)
            # make a more verbose log file and creates a debug file; if you are
            # submitting a bug report, use this option and compress and send the
            #-log file and the debug file together with your bugreport
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            echo "$2" | grep -q '^[0-9]*[0-9]$' && DEBUG=$2 && shift || DEBUG=3
            ;;
        -allow-unsupported) #
            # do not prompt the user to press return if an unsupported version of
            #-MPlayer is detected
            [[ $2 = doc || $2 = help ]] && isarg $1 $2
            unsupported=1
            DEBUG=$((DEBUG|2))
            ;;
        (-frames)
            frames=$2
            isarg $1 $2
            shift
            ;;
        (-channels)
            channels=$2
            isarg $1 $2
            shift
            ;;
        (-srate)
            MPLAYEROPT=( "${MPLAYEROPT[@]}" -srate $2 -af-adv force=1 )
            srate=$2
            isarg $1 $2
            shift
            ;;
        (-hr-edl-seek)
            MENCODEROPT=( "${MENCODEROPT[@]}" $1 )
            ;;
        (-force-avi-aspect)
            MENCODEROPT=( "${MENCODEROPT[@]}" $1 $2 )
            isarg $1 $2
            shift
            ;;
        (-vf)
            vf="$1 $2"
            MPLAYEROPT=( "${MPLAYEROPT[@]}" $vf )
            isarg $1 $2
            shift
            ;;
        (-af)
            af="-af $2"
            isarg $1 $2
            shift
            ;;
        (-dvd-device)
            dvddev=$2
            isarg $1 $2
            shift
            ;;
        (mf://*)
            MPLAYEROPT[${#MPLAYEROPT[*]}]=$1
            pictsrc=1
            a=$IFS
            IFS=,
            PICTSRC=( ${1#mf://} )
            IFS=$a
            srate=48000
            ;;
        (-sub)
            [[ ! -f $2 ]] && echo "**ERROR: [$PROGNAME] subtitle file '$2' not found" && exit 1
            MPLAYEROPT=( "${MPLAYEROPT[@]}" $1 "$2" )
            subrender=1
            shift
            ;;
        (-mpeg1|-mpeg2)
            frameformat=$(echo ${1:1} | tr '[:lower:]' '[:upper:]')
            ;;
        (-delay|-subdelay)
            MPLAYEROPT=( "${MPLAYEROPT[@]}" $1 $2 )
            isarg $1 ${2#-}
            shift
            ;;
        (-timelen)
            timelen=1
            ;;
        (-mpeg)
            mpeg=1
            : ${encode:=7:2:2}
            ;;
        (-ffourcc)
            fourcc=$2
            isarg $1 $2
            shift
            ;;
        (-noodml)
            noodml=1
            ;;
        (-rawsub)
            echo "$2" | grep -q '^[0-1]$' && rawsub=$2
            isarg $1 $2
            shift
            ;;
        (-aid)
            MPLAYEROPT=( "${MPLAYEROPT[@]}" $1 $2 )
            audioid=$2
            isarg $1 $2
            shift
            ;;
        (-ac|-afm)
            afm="$afm $1 $2"
            MPLAYEROPT=( "${MPLAYEROPT[@]}" $1 $2 )
            isarg $1 $2
            shift
            ;;
        (dvd://*)
            MPLAYEROPT[${#MPLAYEROPT[*]}]=$1
            dvdtrack=${1#dvd://}
            ;;
        (-chapter)
            MPLAYEROPT=( "${MPLAYEROPT[@]}" $1 $2 )
            if [[ $2 == *-* ]]; then 
                firstchap=${2%-*}
                lastchap=${2#*-}
            else
                firstchap=$2
            fi
            isarg $1 $2
            shift
            ;;
        (-burn)
            step=$MAXSTEP
            ;;
        (-nosub)
            unset addsub
            ;;
        (-noverify)
            verify=
            ;;
        (-testmca)
            [[ ! -f $2 ]] && echo "**ERROR: [$PROGNAME] file '$2' not found" && exit 1
            testmca=$2
            shift 2
            set -- " " -encode 0:3:1 -bframes 0 -mpeg "$@"
            ;;
        (-multisrc)
            while [[ ${2:0:1} != - && $# -gt 1 ]]; do
                MSRC[${#MSRC[*]}]=$2
                shift
            done
            ;;
        (-scache)
            [[ ! -d $2 ]] && echo "**ERROR: [$PROGNAME] directory '$2' not found" && exit 1
            a=$2
            shift 2
            set -- " " -dvd-device "$a" -cacheonly -verify $(echo $1 $2 $3 $4 | grep -q puos || echo -debug 0) -savecache "$@"
            ;;
        (-isoinfo)
            [[ ! -f $2 ]] && echo "**ERROR: [$PROGNAME] iso image '$2' not found" && exit 1
            if type isoinfo &>/dev/null ; then
                ! isoinfo -i "$2" >/dev/null && echo "**ERROR: [$PROGNAME] file '$2' is not an iso image" && exit 1
                ISOINFO=$(isoinfo -d -i "$2")
            else
                do_log "++ WARN: [$PROGNAME] isoinfo missing, ignoring option $1"
            fi
            shift
            ;;
        (-nomamenu)
            nomamenu=1
            ;;
        (-lavf)
            lavf=1
            ;;
        (-overburn)
            overburn=1
            ;;
        (-bit)
            if [[ $2 && -f $2 ]]; then
                src=$2
            elif [[ $output && -f $output.log ]]; then
                src=$output.log
            else
                [[ $2 ]] && echo "**ERROR: [bit] file '$2' not found" || echo "**ERROR: [bit] file '$output.log' not found"
                exit 1
            fi
            cat "$src"
            skip=0
            eval "$(tail -1 "$src" | tr '\015' '\012')"
            src=( $(sed '/^status_bit ()/,/esac/!d;/;;/!d;s/).*//' "$PROGFILE") )
            ((skip)) && echo -n "status bit: "
            while ((skip)); do
                ((skip&1)) && echo -n "${src[0]} "
                unset src[0]
                src=("${src[@]}")
                skip=$((skip>>1))
            done
            echo
            exit
            ;;
        (-extrachapter)
            extrachapter=1
            ;;
        (-addsdl)
            addsdl=( ${2//,/ } )
            isarg $1 ${2#-}
            shift
            ;;
        (-ftest)
            shift
            ftest=( "$@" )
            shift ${#ftest[*]}
            set -- " "
            ;;
        (-wide2std)
            echo "option ${1#-} is obsolete; use -mpegfixaspect instead" ; exit 1
            ;;
        (-fast)
            do_log "   INFO: [$PROGNAME] option $1 is the default; you do not need to use it"
            ;;
        *)
            if [[ ! $TOOL ]]; then
                [[ ${1:0:1} = - ]] && ! echo "${MOPT[@]}" | grep -q "\"${1#-}\"" && \
                  echo -e "Unknown option $1\nIf this is a valid MPlayer option add '-toolopts mplayer' in front of it" && exit 1
                MPLAYEROPT[${#MPLAYEROPT[*]}]=$1
            else
                case $TOOL in
                    yuvdenoise|y4mdenoise)
                        YUVDENOISE="$YUVDENOISE $1"
                        ;;
                    yuvscaler)
                        YUVSCALEROPT="$YUVSCALEROPT $1"
                        ;;
                    mpeg2enc)
                        MPEG2ENCOPT="$MPEG2ENCOPT $1"
                        ;;
                    mplex)
                        MPLEXOPT="$MPLEXOPT $1"
                        ;;
                    vcdimager)
                        VCDIMAGEROPT="$VCDIMAGEROPT $1"
                        ;;
                    cdrdao)
                        CDRDAOOPT="$CDRDAOOPT $1"
                        ;;
                    growisofs)
                        GROWISOFSOPT="$GROWISOFSOPT $1"
                        ;;
                    dvdauthor)
                        DVDAUTHOROPT="$DVDAUTHOROPT $1"
                        ;;
                    musicin)
                        MUSICINOPT="$MUSICINOPT $1"
                        ;;
                    *)
                        MPLAYEROPT[${#MPLAYEROPT[*]}]=$1
                        ;;
                esac
            fi
            ;;
    esac
    shift
done

[[ -s ~/.encode2mpegrc && ! $norc ]] && do_log "   INFO: [$PROGNAME] using .encode2mpegrc settings: '$(<~/.encode2mpegrc)'"
if [[ $subrender || $harddup ]]; then
    if [[ $vf ]]; then
        vf=$vf${subrender:+,expand=::::1}
        [[ $harddup ]] && ! echo $vf | grep -q harddup && vf=$vf,harddup
        for ((a=0;a<${#MPLAYEROPT[*]};a++)); do
            [[ ${MPLAYEROPT[a]} = -vf ]] && MPLAYEROPT[a+1]=${vf#-vf }
        done
    else
        vf="-vf ${subrender:+expand=::::1}${harddup:+${subrender:+,}harddup}"
        MPLAYEROPT=( "${MPLAYEROPT[@]}" $vf )
    fi
fi
[[ $frameformat == MPEG[12] && $step -gt 3 && ${#TITLESET[*]} -eq 0 ]] && step=3
trap 'rm -f "${CLEAN[@]}"' 0

###############################################################################
#### debug part
###############################################################################
if ((DEBUG)); then
    if ((DEBUG & 1)); then
        #### redirect stdout and stderr to the debug file
        exec 3>&1
        rm -f "$output".debug.fifo
        mkfifo "$output".debug.fifo
        tee "$output".debug <"$output".debug.fifo >&3 &
        PROCTEE=$!
        exec &>"$output".debug.fifo
        CLEAN[${#CLEAN[*]}]="$output".debug.fifo
    fi
    if ((DEBUG & 2)); then
        #### catch mplayer/mencoder errors
        mplayer () {
            command mplayer "$@"
            ret=$? ; (( ret )) && error_line "$FUNCNAME $*" || true
        }
        mencoder () {
            command mencoder "$@"
            ret=$? ; (( ret )) && error_line "$FUNCNAME $*" || true
        }
    fi
    ((DEBUG & 4)) && set -x
fi

###############################################################################
#### ERROR if some options conflict is detected part 1/2 #### TESTS ###########
###############################################################################
#### mplayer/mencoder
for a in mplayer mencoder ; do
    type -f $a &>/dev/null || ! echo "**ERROR: [$PROGNAME] $a missing, install $(echo ${a:0:2} | tr '[:lower:]' '[:upper:]')${a:2}" || exit 1
done
#### output stream name check
[[ ! $output && ${#ftest[*]} -eq 0 ]] && echo "**ERROR: [$PROGNAME] name of the output stream missing (-o name)" && exit 1
#### output write permission
if [[ ${output##*/} = "$output" ]]; then
    [[ ! -w . ]] && echo "**ERROR: [$PROGNAME] you need write permission in the current directory" && exit 1
else
    [[ ! -w ${output%/*} ]] && echo "**ERROR: [$PROGNAME] you need write permission in the directory '${output%/*}'" && exit 1
fi
#### -encode/abr
if [[ $encode != ${encode%,*} ]]; then
    echo "**ERROR: [$PROGNAME] wrong option '-encode $encode', use '-encode ${encode%,*} -abr ${encode#*,}' instead"
    exit 1
fi
#### unspecified video norm
[[ ! $videonorm && ( ! $encode || $encode != ?:0:? || $menu ) && $frameformat != MPEG[12] ]] && ((step>1&&!${#TITLESET[*]}&&!${#ftest[*]})) && \
  echo "**ERROR: [$PROGNAME] you must specify a video norm (-n n|p|s)" && exit 1
#### libfaac check
if [[ $encode == 8:?:? ]]; then
    ! mencoder -oac help 2>/dev/null | grep -q faac && echo "**ERROR: [$PROGNAME] missing libfaac support in mencoder [-encode 8:m:i]" && exit 1
    [[ $multiaudio ]] && echo "**ERROR: [$PROGNAME] -multiaudio does not work with -encode 8:m:i" && exit 1
    [[ ! $fast && $step -gt 1 && ${!audioformat} = copy ]] && echo "**ERROR: [$PROGNAME] -replex does not work with -encode 8:m:i" && exit 1
fi
#### MPEG-4/xvid/ffv1
[[ $vcodec = ffv1 && $step -gt 1 ]] && echo "**ERROR: [$PROGNAME] option -vcodec $vcodec requires -avionly" && exit 1
if [[ $vcodec = mpeg4 || $vcodec = xvid ]]; then
    [[ $multiaudio && $step -gt 1 ]] && echo "**ERROR: [$PROGNAME] -vcodec $vcodec and -multiaudio are not compatible" && exit 1
    [[ ! $fast ]] && echo "**ERROR: [$PROGNAME] -vcodec $vcodec and -replex are not compatible" && exit 1
fi
#### pictsrc
if [[ $pictsrc ]]; then
    [[ $slideaudio != /dev/null && $encode == 0:?:? && $step -gt 1 ]] && \
      echo "**ERROR: [$PROGNAME] -encode 0:m:i is not compatible with mf:// in MPEG Mode" && exit 1
    [[ ! $encode && $step -gt 1 && ${#TITLESET[*]} -eq 0 ]] && echo "**ERROR: [$PROGNAME] mf:// does not work in DIRECT Mode" && exit 1
    [[ $encode == 1:?:? && $step -gt 1 ]] && echo "**ERROR: [$PROGNAME] -encode 1:m:i does not work with mf:// in MPEG Mode" && exit 1
    [[ $multiaudio ]] && echo "**ERROR: [$PROGNAME] -multiaudio does not work with mf://" && exit 1
    [[ $encode == ?:0:? && $step -gt 1 ]] && echo "**ERROR: [$PROGNAME] -encode n:0:i works with mf:// only in AVI Mode" && exit 1
    [[ $audioonly ]] && echo "**ERROR: [$PROGNAME] -audioonly does not work with mf://" && exit 1
fi
#### -avionly/MPEG Mode conflict
[[ $mpeg && $step -eq 1 ]] && echo "**ERROR: [$PROGNAME] you can't use -avionly in MPEG Mode" && exit 1
#### -multiaudio/-aid conflict
[[ $audioid && $multiaudio ]] && echo "**ERROR: [$PROGNAME] -multiaudio and -aid are mutually exclusive" && exit 1
#### -acopy/-encode 0:m:i
[[ $audioformat = acopy && $encode && $encode != 0:?:? ]] && echo "**ERROR: [$PROGNAME] -acopy requires -encode 0:m:i" && exit 1
#### -titleset
if ((${#TITLESET[*]})); then
    [[ $encode ]] && a=${mpeg:+mpeg} && echo "**ERROR: [$PROGNAME] do not use -${a:-encode} together with -titleset" && exit 1
    for ((a=0;a<${#TITLESET[*]};a++)); do
        [[ ! -f "$(xmlunchar "$(grep '<dvdauthor' "${TITLESET[a]}.dvd.xml" | cut -f2 -d\")").dvd.xml" ]] && \
          echo "**ERROR: [$PROGNAME] you are not in the same directory from where the title '${TITLESET[a]}' has been made" && exit 1
    done
fi
#### -mpeg1/2-DIRECT Mode
if [[ $frameformat == MPEG[12] && ! $encode && $step -gt 1 && ${#TITLESET[*]} -eq 0 ]]; then
    echo "**ERROR: [$PROGNAME] do not use -mpeg${frameformat:4} In DIRECT Mode"
    exit 1
fi
#### -addsub copy
if [[ ${addsub[0]} = copy && $step -eq 1 && ! $encode ]]; then
    echo "**ERROR: [$PROGNAME] you need to encode a stream in order to use -addsub copy"
    exit 1
fi

###############################################################################
#### WARN if some options conflict is detected #### TESTS #####################
###############################################################################
#### missing toolame support
if [[ $encode == 7:?:? ]]; then
    if ! mencoder -oac help 2>/dev/null | grep -q t[wo]olame ; then
        encode=4:${encode#?:}
        do_log "++ WARN: [$PROGNAME] missing toolame support in mencoder, setting -encode $encode"
    else
        mencoder -oac help 2>/dev/null | grep -q toolame && TOOLAME=toolame || TOOLAME=twolame
    fi
fi
#### missing xvid support
if [[ $vcodec = xvid ]]; then
    if ! mencoder -ovc help 2>/dev/null | grep -q xvid ; then
        vcodec=mpeg4
        do_log "++ WARN: [$PROGNAME] missing xvid support in mencoder, setting -vcodec $vcodec"
    fi
fi
#### -setaspect/-mpegfixaspect
if [[ $zoom -ne 0 && $encode && $step -gt 1 ]]; then
    mpegaspect=1
    [[ $mpegfixaspect ]] && do_log "++ WARN: [$PROGNAME] using option -setaspect, option -mpegfixaspect ignored" && mpegfixaspect=
fi

###############################################################################
#### set default values for unspecified parameters
###############################################################################
if [[ ! $multiaudio ]]; then
    audiostream=1
else
    aid=($multiaudio)
    audiostream=${#aid[*]}
fi
###############################################################################
if [[ $encode ]]; then
    case ${encode%%:*} in
        0) [[ ! $pictsrc ]] && 
               AFMT=acopy ;;
        2|3|5) AFMT=mp3 ;;
        4|7)   AFMT=mp2 ;;
        6)     AFMT=ac3 ;;
        8)     AFMT=aac ;;
    esac
    [[ $AFMT ]] && eval : ${audioformat:-\${$AFMT:=copy\}}
    ((step>1)) && mpeg=1
fi
((${#TITLESET[*]})) && frameformat=DVD
: ${frameformat:=VCD}
: ${audioformat:=${AFMT:-mp2}}
: ${mp1:=mp2enc}
((${mpegchannels:-2}>2)) && : ${mp2:=musicin} || : ${mp2:=mp2enc}
: ${mp3:=lame}
: ${ac3:=mencoder}
: ${dts:=copy}
: ${aac:=faac}
case $audioformat in
    mp1)
        case ${mpegchannels:-2} in
            1) : ${abr:=192} ;;
            2) : ${abr:=384} ;;
        esac
        ;;
    mp2)
        case ${mpegchannels:-2} in
            1) : ${abr:=112} ;;
            2) : ${abr:=224} ;;
            [3-6]) : ${abr:=384} ;;
        esac
        ;;
    mp3)
        case ${mpegchannels:-2} in
            1) : ${abr:=64} ;;
            2) : ${abr:=128} ;;
        esac
        ;;
    ac3)
        case ${mpegchannels:-2} in
            1) : ${abr:=96} ;;
            2) : ${abr:=192} ;;
            3) : ${abr:=320} ;; # to verify
            4) : ${abr:=384} ;; # to verify
            5) : ${abr:=448} ;; # to verify
            6) : ${abr:=448} ;;
        esac
        ;;
    aac) : ${abr:=$((${mpegchannels:-2}*48))} ;;
    #### mplex fails with asr != 48000 for lpcm
    lpcm) : ${asr:=48000} ${abr:=$((asr*16*${mpegchannels:-2}/1024))} ;;
esac
if [[ $encode == 0:?:? && ${!audioformat} = copy ]]; then
    abr=0
    if [[ ! $multiaudio ]]; then
        get_abr
    else
        #### evaluate the average abr
        for ((i=0;i<audiostream;i++)); do
            get_abr -aid ${aid[i]}
        done
        abr=$((abr/audiostream))
    fi
fi
[[ $mpeg && $encode == ?:0:? && ${#ftest[*]} -eq 0 ]] && vbr=$(($(id_find ID_VIDEO_BITRATE "${MPLAYEROPT[@]}" ${dvddev:+-dvd-device "$dvddev"} "$@")/1000))
case $frameformat in
    DVD) : ${asr:=48000} ;;
    *)   : ${asr:=44100} ;;
esac
case $videonorm in
    p|s)
        : ${vfr:=3}
        ;;
    n)
        [[ $frameformat != VCD && $frameformat != MPEG1 && ! $vfr && $hispeed -eq 0 && ! $testmca ]] && vfr=1 && telecine=1
        : ${vfr:=4}
        ;;
esac
[[ $encode && $encode != ?:0:? ]] && : ${vfr:=2}
if [[ ! $ofps ]]; then
    case $vfr in
        1) ofps=24000/1001 ;;
        2) ofps=24 ;;
        3) ofps=25 ;;
        4) ofps=30000/1001 ;;
        5) ofps=30 ;;
        6) ofps=50 ;;
        7) ofps=60000/1001 ;;
        8) ofps=60 ;;
    esac
fi
if [[ $split && $split -eq 0 ]]; then
    [[ $mpeg ]] && split= || split=800
fi

###############################################################################
#### get MPlayer version
###############################################################################
mver=$(mencoder 2>/dev/null | awk '$1=="MEncoder"{print $2;exit}')

###############################################################################
#### threads check
###############################################################################
if [[ ! $cpu && -f /proc/cpuinfo ]]; then
    cpu=$(grep -c ^processor /proc/cpuinfo)
    #### if there are 2 logical cpu but 1 physical (hyperthreading)
    #### use only one thread. With kernel 2.4.x it is more efficent.
    ((cpu==2)) && [[ $(uname -r | cut -f 1-2 -d .) = 2.4 ]] && \
      [[ $(grep ^siblings /proc/cpuinfo | uniq | wc -l) -eq 1 ]] && \
      cpu=$((cpu/$(grep ^siblings /proc/cpuinfo | uniq | awk 'END{print $NF}')))
fi
((cpu<2)) && cpu=

###############################################################################
#### -ao pcm arguments
###############################################################################
PCMWAV=(pcm:waveheader:fast:file=%$((${#output}+4))%"$output".wav)
PCMTMP=(pcm:waveheader:fast:file=%$((${#output}+4))%"$output".tmp)
PCMNOWYUV=(pcm:nowaveheader:fast:file=/dev/fd/4)

###############################################################################
#### functions 2/3
###############################################################################
pr_date () {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')]"
}
###############################################################################
get_av_delay () {
    mplayer -nocache -frames 10 -mc 0 -ao null -vo null 2>/dev/null "$@" | tr '\015' '\012' | sed '/^A:/!d;s/.*A-V://;s/ ct:.*//' | \
      awk '{if ($1<2&&$1>-2){t+=$1;n+=1}}END{print int(-t*1000/n)}'
}
###############################################################################
verify_burn () {
    local MNTDIR M CNT c TOTAL a i t
    sleep 8
    if mount $dvdburndevice ; then
        vrfyumnt=$dvdburndevice
        MNTDIR=$(awk -v dev="$dvdburndevice" '$1==dev{print $2}' /etc/fstab)
        if [[ ! $MNTDIR || ! -d $MNTDIR ]]; then
            do_log "**ERROR: [verify] failed to find mountpoint for $dvdburndevice, skipping verify"
            umount $dvdburndevice 
            return
        fi
        echo "starting verify of $dvdburndevice mounted on $MNTDIR" >&2
        CLEAN[${#CLEAN[*]}]="$output".verify
        if [[ -d "$1" ]]; then
            CLEAN[${#CLEAN[*]}]="$output".counter
            [[ ${output:0:1} = / ]] && CNT="$output".counter || CNT="$PWD/$output.counter"
            c=7
            echo $c >"$CNT"
            ( TOTAL=$(($(mkisofs -print-size "$1" 2>/dev/null)*2048))
              cd "$1"
              a=( $(find . -type f -exec stat -c '%s' {} \;) )
              for ((i=1;i<${#a[*]};i++)) ; do
                  a[i]=$((a[i]+a[i-1]))
                  a[i-1]=$((a[i-1]*100/TOTAL))
              done
              a[i-1]=$((a[i-1]*100/TOTAL))
              [[ ${a[i-1]} = 99 ]] && a[i-1]=100
              t=$(date '+%j %H %M %S' | awk '{print $1*86400+$2*3600+$3*60+$4}')
              find . -type f -exec sh -c \
                'i=$(<"$3") ; m=$(eval echo \${$i}) ; i=$((i+1)) ; n=$(eval echo \${$i}) ; s="${1#./} [$m" ; ((m!=n)) && s="${s}-$n" ; \
                s="${s}% $((i-$5))/$4]" ; ((m)) && s="$s estimate finish: $(date "+%j %H %M %S" | \
                  awk -v t=$6 -v m=$m "{s=\$2*3600+\$3*60+\$4;a=(\$1*86400+s-t)*(100/m-1)+s;printf(\"%02d:%02d:%02d\",a/3600,a/60%60,a%60)}")" ; \
                echo -n "$s" ; echo $i >"$3" ; \
                [[ -f "$2/$1" ]] && cmp -s "$2/$1" "$1" && printf "\r%${#s}s\r" || echo "... ERROR"' \
                sh {} "$MNTDIR" "$CNT" ${#a[*]} $c $t 0 ${a[*]} \;
            ) | tee "$output".verify >&2
        else
            { for a ; do
                  echo -n "$a" ; [[ -f "$MNTDIR/${a##*/}" ]] && cmp -s "$MNTDIR/${a##*/}" "$a" && printf "\r%${#a}s\r" || echo "... ERROR"
              done
            } | tee "$output".verify >&2
        fi
        umount $dvdburndevice
        vrfyumnt=
        M=$(sed '/.*\r$/d;s/.*\r//;s/\(.*\)\.\.\. ERROR/**ERROR: [verify] \1/' "$output".verify)
        if [[ $M ]]; then
            do_log "$M"
            do_log "++ WARN: [verify] operation ended with error(s)"
        else
            do_log "   INFO: [verify] operation ended successfully"
        fi
    else
        do_log "++ WARN: [verify] failed to mount $dvdburndevice, skipping verify"
    fi
}
###############################################################################
dvd_image_size () {
    if [[ $1 -le 2295104 ]] ; then   # DVD+R
        echo "   INFO: [$2] "$3" ($(($1/512))MB) fits in a single layer DVD ($(((2295104-$1)/512))MB free)"
    elif [[ $1 -le 2297888 ]] ; then # DVD-R
        echo "++ WARN: [$2] "$3" ($(($1/512))MB) fits in a DVD-R, but is does not fit in a DVD+R"
    elif [[ $1 -le 4173825 ]] ; then # DVD+R DL
        echo "++ WARN: [$2] "$3" ($(($1/512))MB) fits only in a DVD+R DL ($(((4173825-$1)/512))MB free)"
    else
        echo "++ WARN: [$2] "$3" ($(($1/512))MB) does not fit in a DVD media"
    fi
}
###############################################################################
fixregion () {
    local a i
    a=$(od -t u -A none -j 35 -N 1 "$1")
    if ((a!=0&&a!=64)) ; then
        if [[ ! -w $1 ]]; then
            i=1
            rm -f "$output".r
            CLEAN[${#CLEAN[*]}]="$output".r
            touch -r "$1" "$output".r
            chmod --reference="$1" "$output".r
            chmod u+w "$1"
            [[ ! -w $1 ]] && do_log "++ WARN: [$2] cannot write to "${1##*/}", region unchanged" && return
        fi
        echo -n '@' | dd of="$1" bs=1 seek=35 conv=notrunc 2>/dev/null
        do_log "   INFO: [$2] set region(64): 1 2 3 4 5 6 8"
        ((i)) && chmod --reference="$output".r "$1" && touch -r "$output".r "$1" && rm -f "$output".r && unset CLEAN[${#CLEAN[*]}-1]
    fi
}
###############################################################################
if (($(echo -ne '\0\01' | od -t u2 -A none -j 0 -N 2)==256)); then
    readn () {
        local n
        n=$(od -t u$1 -A none -j $2 -N $1 "${3:-$rfile}")
        case $1 in
            4) echo $((((n&0xFF000000)/16777216)+((n&0xFF0000)/256)+((n&0xFF00)*256)+((n&0xFF)*16777216))) ;;
            2) echo $((((n&0xFF00)/256)+((n&0xFF)*256))) ;;
            1) echo $n ;;
        esac
    }
else
    readn () { echo $(od -t u$1 -A none -j $2 -N $1 "${3:-$rfile}") ; }
fi
readno () {
    echo $1 o $(readn $2 $3 "$4") p | dc
}
###############################################################################
scan_srpt () {
    local ADDRESS nSRPT a end
    ADDRESS=$1
    nSRPT=$(readn 2 $ADDRESS)
    end=$(readn 4 $((ADDRESS+4)))
    for ((a=0;a<nSRPT;a++)); do
        ((8+12*a>end)) && do_log "++ WARN: [Uops] SRPT offset ($((8+12*a))) beyond end ($end), skipping" && break
        n=$(readn 1 $((ADDRESS+8+12*a)))
        if ((n&3)); then
            ((PUOSCHECK)) && RCOD=1 && return || SCOD=1
            if ((PUOSSET)); then
                ((!ATTR)) && chmod u+w "$rfile" && ATTR=1
                echo -ne "\0$(printf "%o" $((n&0xFC)))" | dd of="$rfile" bs=1 seek=$((ADDRESS+8+12*a)) conv=notrunc 2>/dev/null
            fi
        fi
        ((n&3&&DEBUG&8||DEBUG&16)) && do_log "--DEBUG: [Uops] ${2}_SRPT[$((a+1))/$nSRPT]=$((n&3))"
    done
}
###############################################################################
check_pcg () {
    local ADDRESS n
    ADDRESS=$1
    n=$(readn 4 $((ADDRESS+8)))
    if ((n)); then
        ((PUOSCHECK)) && RCOD=1 && return || SCOD=1
        if ((PUOSSET)); then
            ((!ATTR)) && chmod u+w "$rfile" && ATTR=1
            echo -ne "\0\0\0\0" | dd of="$rfile" bs=1 seek=$((ADDRESS+8)) conv=notrunc 2>/dev/null
        fi
    fi
    ((n&&DEBUG&8||DEBUG&16)) && do_log "--DEBUG: [Uops] ${3}${2}_PCG${4}=$n"
}
###############################################################################
scan_pgc () {
    local ADDRESS nPGC PGC a n end
    ADDRESS=$1
    nPGC=$(readn 2 $ADDRESS)
    end=$(readn 4 $((ADDRESS+4)))
    for ((a=0;a<nPGC;a++)) ; do
        PGC=$(readn 4 $((ADDRESS+12+a*8)))
        ((PGC>end)) && do_log "++ WARN: [Uops] PGC offset ($PGC) beyond end offset ($end), skipping" && break
        check_pcg $((ADDRESS+PGC)) $2 "${2}_PCGI${3:+_UT}: ${3}" "[$((a+1))/$nPGC]"
        ((RCOD)) && return
    done
}
###############################################################################
scan_pgci_ut () {
    local ADDRESS nLU LU a end
    ADDRESS=$1
    nLU=$(readn 2 $ADDRESS)
    end=$(readn 4 $((ADDRESS+4)))
    for ((a=0;a<nLU;a++)) ; do
        LU=$(readn 4 $((ADDRESS+12+a*8)))
        ((LU>end)) && do_log "++ WARN: [Uops] ${2}_LU offset ($LU) beyond ${2}_PGCI_UT offset ($end), skipping" && break
        scan_pgc $((ADDRESS+LU)) $2 "${2}_LU[$((a+1))/$nLU] "
        ((RCOD)) && return
    done
}
###############################################################################
scan_vobuadmap () {
    local ADDRESS endVOBU_ADMAP VOB SIZE TOT VOBU i a n attr
    ADDRESS=$1
    endVOBU_ADMAP=$(readn 4 $ADDRESS)
    i=1
    case $2 in
        VMGM) VOB=${rfile%/*.IFO}/VIDEO_TS.VOB ;;
        VTSM) VOB=${rfile%/*.IFO}/VTS_${3}_0.VOB ;;
        VTS) VOB=${rfile%/*.IFO}/VTS_${3}_$i.VOB ;;
    esac
    TOT=0
    attr=0
    if [[ -f $VOB ]]; then
        SIZE=$(($(stat -c '%s' "$VOB")-1))
        touch -r "$VOB" "$output".vob
        chmod --reference="$VOB" "$output".vob
        for ((a=4;a<endVOBU_ADMAP;a+=4)); do
            VOBU=$(($(readn 4 $((ADDRESS+a)))*2048-TOT))
            if ((VOBU>SIZE)); then
                ((attr)) && chmod --reference="$output".vob "$VOB" && touch -r "$output".vob "$VOB"
                VOBU=$((VOBU-SIZE-1))
                TOT=$((TOT+SIZE+1))
                VOB=${rfile%/*.IFO}/VTS_${3}_$((++i)).VOB
                SIZE=$(($(stat -c '%s' "$VOB")-1))
                touch -r "$VOB" "$output".vob
                chmod --reference="$VOB" "$output".vob
                attr=0
            fi
            n=$(readn 4 $((VOBU+0x26)) "$VOB" )
            if ((n!=0x1BF)); then
                do_log "++ WARN: [Uops] VOBU[$((a/4))/$(((endVOBU_ADMAP+1)/4-1))]: not private stream 2"
                do_log "++ WARN: [Uops] wrong ${2}_VOBU_ADMAP for ${VOB##*/}, skipping"
                break
            else
                n=$(readn 1 $((VOBU+0x2C)) "$VOB" )
                if ((n)); then
                    do_log "++ WARN: [Uops] VOBU[$((a/4))/$(((endVOBU_ADMAP+1)/4-1))]: not PCI packet ($n)"
                    do_log "++ WARN: [Uops] wrong ${2}_VOBU_ADMAP for ${VOB##*/}, skipping"
                    break
                fi
            fi
            n=$(readn 4 $((VOBU+0x35)) "$VOB" )
            if ((n)); then
                ((PUOSCHECK)) && RCOD=1 && return || SCOD=1
                if ((PUOSSET)); then
                    ((!attr)) && chmod u+w "$VOB" && attr=1
                    echo -ne "\0\0\0\0" | dd of="$VOB" bs=1 seek=$((VOBU+0x35)) conv=notrunc 2>/dev/null
                fi
            fi
            if ((DEBUG&16)); then
                do_log "--DEBUG: [Uops] $2${3:+_$3}: ${2}_VOBU[$((a/4))/$(((endVOBU_ADMAP+1)/4-1))]=$n"
            elif ((DEBUG&8)); then
                ((n)) && do_log "--DEBUG: [Uops] ${2}_VOBU[$((a/4))/$(((endVOBU_ADMAP+1)/4-1))]=$n" || echo -n -e "$((a/4))\r"
            fi
        done
        ((attr)) && chmod --reference="$output".vob "$VOB" && touch -r "$output".vob "$VOB" && PUOSCL=1
    else
        do_log "++ WARN: [Uops] ${2}_VOBU_ADMAP set but no ${VOB##*/} found"
    fi
}
###############################################################################
puos () {
    local TT_SRPT FP_PGC VMGM_PCGI_UT VMGM_VOBU_ADMAP VTSM_PCGI_UT VTS_PCGI VTSM_VOBU_ADMAP VTS_VOBU_ADMAP i
    PUOSCHECK=$((!($2&6)))
    PUOSSET=$(($2&4))
    #PUOSSCAN=$((($2&6)==2))
    #PUOSFULL=$(($2&1))

    CLEAN[${#CLEAN[*]}]="$output".mod
    CLEAN[${#CLEAN[*]}]="$output".vob
    rfile="$1/VIDEO_TS.IFO"
    touch -r "$rfile" "$output".mod
    chmod --reference="$rfile" "$output".mod
    ATTR=0
    RCOD=0
    SCOD=0
    PUOSCL=0

    TT_SRPT=$(($(readn 4 0xC4)*2048))
    ((TT_SRPT)) && scan_srpt $TT_SRPT TT
    ((!TT_SRPT&&DEBUG&16)) && do_log "--DEBUG: [Uops] no TT_SRPT"
    ((RCOD)) && return $RCOD

    FP_PGC=$(readn 4 0x84)
    ((FP_PGC)) && check_pcg $FP_PGC FP
    ((!FP_PGC&&DEBUG&16)) && do_log "--DEBUG: [Uops] no FP_PGC"
    ((RCOD)) && return $RCOD

    VMGM_PCGI_UT=$(($(readn 4 0xC8)*2048))
    ((VMGM_PCGI_UT)) && scan_pgci_ut $VMGM_PCGI_UT VMGM
    ((!VMGM_PCGI_UT&&DEBUG&16)) && do_log "--DEBUG: [Uops] no VMGM_PCGI_UT"
    ((RCOD)) && return $RCOD

    VMGM_VOBU_ADMAP=$(($(readn 4 0xDC)*2048))
    ((VMGM_VOBU_ADMAP)) && scan_vobuadmap $VMGM_VOBU_ADMAP VMGM
    ((!VMGM_VOBU_ADMAP&&DEBUG&16)) && do_log "--DEBUG: [Uops] no VMGM_VOBU_ADMAP"
    ((RCOD)) && return $RCOD

    ((ATTR)) && chmod --reference="$output".mod "$rfile" && touch -r "$output".mod "$rfile" && PUOSCL=1

    for i in $(ls "$1"/VTS* | sed 's/_[0-9]\....$//;s/.*VTS_//' | uniq) ; do
        rfile="$1/VTS_${i}_0.IFO"
        touch -r "$rfile" "$output".mod
        chmod --reference="$rfile" "$output".mod
        ATTR=0
        ((DEBUG&24)) && do_log "--DEBUG: [Uops] TITLE ${i}"

        VTSM_PCGI_UT=$(($(readn 4 0xD0)*2048))
        ((VTSM_PCGI_UT)) && scan_pgci_ut $VTSM_PCGI_UT VTSM
        ((!VTSM_PCGI_UT&&DEBUG&16)) && do_log "--DEBUG: [Uops] no VTSM_PCGI_UT($1)"
        ((RCOD)) && return $RCOD
        VTS_PCGI=$(($(readn 4 0xCC)*2048))
        ((VTS_PCGI)) && scan_pgc $VTS_PCGI VTS
        ((!VTS_PCGI&&DEBUG&16)) && do_log "--DEBUG: [Uops] no VTS_PCGI($1)"
        ((RCOD)) && return $RCOD

        VTSM_VOBU_ADMAP=$(($(readn 4 0xDC)*2048))
        ((VTSM_VOBU_ADMAP)) && scan_vobuadmap $VTSM_VOBU_ADMAP VTSM $i
        ((!VTSM_VOBU_ADMAP&&DEBUG&16)) && do_log "--DEBUG: [Uops] no VTSM_VOBU_ADMAP($1)"
        ((RCOD)) && return $RCOD
        VTS_VOBU_ADMAP=$(($(readn 4 0xE4)*2048))
        ((VTS_VOBU_ADMAP&&$2&1)) && scan_vobuadmap $VTS_VOBU_ADMAP VTS $i
        ((!VTS_VOBU_ADMAP&&DEBUG&16)) && do_log "--DEBUG: [Uops] no VTS_VOBU_ADMAP($1)"
        ((RCOD)) && return $RCOD

        ((ATTR)) && chmod --reference="$output".mod "$rfile" && touch -r "$output".mod "$rfile" && PUOSCL=1
    done
    ((PUOSCL)) && do_log "   INFO: [$3] Prohibited user operations cleared"
    rm -f "$output".{mod,vob}
    unset CLEAN[${#CLEAN[*]}-1]
    unset CLEAN[${#CLEAN[*]}-1]
    return $SCOD
}

###############################################################################
#### cache the DVD
###############################################################################
[[ $cache && ! -d $cache ]] && do_log "++ WARN: [cachedvd] cache '$cache' does not exist, turning off cache support" && cache=
[[ $cache && ! -w $cache ]] && do_log "++ WARN: [cachedvd] cannot write to cache '$cache', turning off cache support" && cache=
if [[ $cache ]]; then
    for a in vobcopy rsync isoinfo ; do
        type $a &>/dev/null || ! do_log "++ WARN: [cachedvd] $a missing, turning off cache support" || cache=
    done
fi
if [[ $cache ]]; then
    #### vobcopy 0.5.13
    if (($(vobcopy -V | awk '{print $2}' | sed 's/\([^.]*\)\./(\1)*100+/;s/\([^.]*\)\./(\1)*100+/') <513)) ; then
        do_log "++ WARN: [cachedvd] you need vobcopy 0.5.13 or later, turning off cache support"
        cache=
    fi
fi
if [[ $cache && -d $DVDMNT/video_ts ]]; then
    do_log "++ WARN: [cachedvd] found directory video_ts instead of VIDEO_TS in $DVDMNT"
    do_log "++ WARN: [cachedvd] this should not happen, turning off cache support"
    cache=
fi
if [[ $cache ]]; then
    [[ -d $DVDMNT/VIDEO_TS ]] && a=/etc/mtab || a=/etc/fstab
    DVDDEV=$(awk '$2=="'"$DVDMNT"'"{m=$1}END{print m}' $a)
    [[ ! $DVDDEV ]] && do_log "++ WARN: [cachedvd] cannot find the device for $DVDMNT in $a, turning off cache support" && cache=
fi
DVDUMOUNT=
if [[ $cache ]]; then
    if [[ -d $DVDMNT/VIDEO_TS ]]; then
        i="-i $DVDMNT"
    else
        i=
        mount $DVDMNT
        if (($?)); then
            do_log "++ WARN: [cachedvd] error mounting $DVDMNT, turning off cache support"
            cache=
            umount $DVDMNT
        else
            trap 'umount $DVDMNT ; rm -f "${CLEAN[@]}"' 0
            DVDUMOUNT=1
            a=$(awk '$2=="'"$DVDMNT"'"{m=$1}END{print m}' /etc/mtab)
            [[ $a ]] && DVDDEV=$a
        fi
    fi
fi
[[ $cache && $DVDDEV && ! -r $DVDDEV ]] && do_log "++ WARN: [cachedvd] you need read access to $DVDDEV, turning off cache support" && cache=
if [[ $cache ]]; then
    if ! vobcopy -I $i &>/dev/null ; then
        echo "**ERROR: [cachedvd] aborting, vobcopy failed with the following message:"
        vobcopy -I $i
        exit 1
    fi
fi
if [[ $cache ]]; then
    [[ $i ]] && a=$(vobcopy -I $i 2>&1 | sed -n '/Device /s/.* //p') || a=$(vobcopy -I 2>&1 | sed -n '/[Pp]ath to dvd:/s/[^:]*: //p')
    [[ $DVDDEV != "$a" ]] && do_log "++ WARN: [cachedvd] vobcopy is reading the DVD from $a" && \
      do_log "++ WARN: [cachedvd] but I found $DVDDEV as the device for $DVDMNT, turning off cache support" && cache=
fi
if [[ $cache ]]; then
    DVDTITLE=$(vobcopy -I $i 2>&1| grep "DVD-name:")
    DVDTITLE=${DVDTITLE#*: }
    if [[ -d $cache/$DVDTITLE ]]; then
        #### check if the dvd is already cached
        F[0]="$cache/$DVDTITLE.ISOINFO"
        F[1]="$cache/$DVDTITLE/VIDEO_TS/VIDEO_TS.BUP"
        F[2]="$DVDMNT/VIDEO_TS/VIDEO_TS.BUP"
        F[3]="$cache/$DVDTITLE/VIDEO_TS/VTS_01_0.IFO"
        F[4]="$DVDMNT/VIDEO_TS/VTS_01_0.IFO"
        if [[ -f ${F[0]} && -f ${F[1]} && -f ${F[2]} && -f ${F[3]} && -f ${F[4]} ]] && cmp -s ${F[1]} ${F[2]} && cmp -s ${F[3]} ${F[4]} ; then
            do_log "   INFO: [cachedvd] $DVDTITLE already cached in '$cache'"
            dvddev=$cache/$DVDTITLE
        else
            echo "**ERROR: [cachedvd] in '$cache' there is already a directory called $DVDTITLE, cannot cache the dvd" && exit 1
        fi
    else
        #### cache the dvd
        STARTTIME=$(pr_time)
        LOG="### LOG: $output $(pr_date)"
        do_log "   INFO: [cachedvd] caching $DVDTITLE in '$cache'"
        pushd $cache >/dev/null
        if [[ $novobcopy = 0 ]]; then
            mkdir -p "$DVDTITLE"
            rsync -avWHP $DVDMNT/ "$DVDTITLE"
        else
            vobcopy -m $i
        fi
        isoinfo -d -i $DVDDEV >"$DVDTITLE".ISOINFO
        if [[ -d $DVDTITLE ]]; then
            cd "$DVDTITLE"
            #### set region free
            if [[ -f VIDEO_TS/VIDEO_TS.IFO ]]; then
                a=$(readn 1 35 VIDEO_TS/VIDEO_TS.IFO)
                b="   INFO: [cachedvd] dvd region($a): "
                for ((i=1; i<9;i++)) ; do
                    ! ((a%2)) && b="$b$i "
                    a=$((a/2))
                done
                do_log "$b"
                [[ ! $cacher || $cacher = 1 ]] && fixregion VIDEO_TS/VIDEO_TS.IFO cachedvd
                [[ ! $cachep || $cachep = 1 ]] && ! puos VIDEO_TS $(((DEBUG&24)>>3)) && puos VIDEO_TS 5 cachedvd
            fi
            find . -depth -exec chmod --reference=$DVDMNT/{} {} \; -exec touch -r $DVDMNT/{} {} \;
            #### add other non movie files
            rsync -avWHP --ignore-existing $DVDMNT/ .
            dvddev=$cache/$DVDTITLE
        else
            echo "**ERROR: [cachedvd] cannot find title '$DVDTITLE' in '$cache'"
            echo "**ERROR: [cachedvd] this should not happen, please submit a bugreport" && exit 1
        fi
        popd >/dev/null
    fi
    [[ $DVDUMOUNT ]] && trap 'rm -f "${CLEAN[@]}"' 0 && umount $DVDMNT
fi

###############################################################################
#### save the cache
###############################################################################
if [[ ${savecache[0]} ]]; then
    CACHE=
    if [[ $cache ]]; then
        if [[ -d $cache/$DVDTITLE && -f $cache/$DVDTITLE.ISOINFO ]]; then
            CACHE=$cache/$DVDTITLE
        else
            do_log "**ERROR: [savecache] cannot find cache $cache/$DVDTITLE, submit a bugreport"
        fi
    else
        if [[ $dvddev && -d $dvddev ]]; then
            if [[ -f $dvddev.ISOINFO || ${savecache[1]} = force || $ISOINFO ]]; then
                CACHE=$dvddev
            else
                do_log "++ WARN: [savecache] cannot find cache $dvddev, no cache saved"
            fi
        fi
    fi
    if [[ $CACHE ]]; then
        [[ $LOG ]] || ! STARTTIME=$(pr_time) || LOG="### LOG: $output $(pr_date)"
        if [[ -f $CACHE.ISOINFO || $ISOINFO ]]; then
            [[ $ISOINFO ]] || ISOINFO=$(<"$CACHE".ISOINFO)
            greparg () {
                echo "$ISOINFO" | sed "/^$1/!d;s/^$1 //;s/'/'\\\''/"
            }
            ISOFIELDS=(sysid        "System id:" \
                       V            "Volume id:" \
                       volset       "Volume set id:" \
                       P            "Publisher id:" \
                       p            "Data preparer id:" \
                       A            "Application id:" \
                       copyright    "Copyright File id:" \
                       abstract     "Abstract File id:" \
                       biblio       "Bibliographic File id:" \
                       volset-size  "Volume set size is:" \
                       volset-seqno "Volume set sequence number is:"
                       )
            ARG=
            for ((i=0;i<${#ISOFIELDS[*]};i+=2)) ; do
                ARG="$ARG -${ISOFIELDS[i]} '$(greparg "${ISOFIELDS[i+1]}")'"
            done
        else
            ((${#output} > 32)) && do_log "++ WARN: [savecache] iso volume label too long, using ${output:0:32}"
            ARG="-V '$(echo "${output:0:32}" | sed "s/'/'\\\''/g")' -A $PROGNAME-$VERSION"
        fi
        BAKCACHE=
        if [[ -f $CACHE/VIDEO_TS/VIDEO_TS.IFO ]]; then
            CODE=$(od -t u -A none -j 35 -N 1 "$CACHE/VIDEO_TS/VIDEO_TS.IFO" | tr -d ' ') || CODE=0
            if ((CODE!=64&&CODE!=0)); then
                    b="++ WARN: [savecache] region is $CODE ("
                    a=$CODE
                    for ((i=1; i<9;i++)) ; do
                        ! ((a%2)) && b="$b$i "
                        a=$((a/2))
                    done
                    b="${b% })"
                    do_log "$b"
                    echo -n "Press Return to proceed"
                    read
            fi
            ! puos "$CACHE/VIDEO_TS" $(((DEBUG&24)>>3)) && do_log "++ WARN: [savecache] found Prohibited user operations" && \
              echo -n "Press Return to proceed" && read
            if [[ ${savecache[5]} = backup && ( ${savecache[3]} = region || ${savecache[4]} = puos || ${savecache[6]} = pause ) && ! $removecache ]] ; then
                do_log "   INFO: [savecache] creating backup cache"
                mkdir -p "$output"
                chmod -R u+w "$output"
                rsync -aWP --delete "$CACHE"/ "$output"
                BAKCACHE=$CACHE
                CACHE=$output
                if [[ ${savecache[6]} = pause ]]; then
                    CLEAN[${#CLEAN[*]}]="$output".backup
                    touch -r "$output" "$output".backup
                    chmod --reference="$output" "$output".backup
                    chmod -R u+w "$output"
                    read -p "pause, press Enter to continue"
                    touch -r "$output".backup "$output"
                    chmod --reference="$output".backup "$output"
                fi
            fi
            [[ ${savecache[3]} = region ]] && fixregion "$CACHE/VIDEO_TS/VIDEO_TS.IFO" savecache
            [[ ${savecache[4]} = puos ]] && puos "$CACHE/VIDEO_TS" 5 savecache
        else
            do_log "++ WARN: [savecache] the cache content does not seem to be a valid DVD"
            echo -n "Press Return to proceed"
            read
        fi
        do_log "   INFO: [savecache] saving cache $CACHE"
        a=$(eval mkisofs -D -dvd-video $ARG -print-size "'$(echo "$CACHE" | sed "s/'/'\\\''/g")'" 2>/dev/null)
        if [[ ! $a ]]; then
            echo "**ERROR: [savecache] unknown cache size"
            echo "**ERROR: [savecache] mkisofs error:"
            eval mkisofs -D -dvd-video $ARG -print-size "'$(echo "$CACHE" | sed "s/'/'\\\''/g")'"
            echo "**ERROR: [savecache] submit a bug report"
            exit 1
        fi
        do_log "$(dvd_image_size $a savecache "cache")"
        if [[ ${savecache[2]} = raid ]]; then
            if [[ ! -b /dev/loop0 ]]; then
                do_log "++ WARN: [savecache] loop device /dev/loop0 not found, -savecache raid disabled" && unset savecache[2] && \
                  do_log "++ WARN: [savecache] submit a bug report" && sleep 2
            elif [[ ! -b /dev/md0 ]]; then
                do_log "++ WARN: [savecache] raid device /dev/md0 not found, -savecache raid disabled" && unset savecache[2] && \
                  do_log "++ WARN: [savecache] submit a bug report" && sleep 2
            elif [[ ! -f /proc/mdstat ]]; then
                do_log "++ WARN: [savecache] file /proc/mdstat not found, -savecache raid disabled" && unset savecache[2] && \
                  do_log "++ WARN: [savecache] do you have raid support in your kernel? if yes submit a bug report" && sleep 2
            fi
        fi
        if [[ ${savecache[2]} = raid ]]; then
            [[ $a -le 2297888 ]] && echo "**ERROR: [savecache] cache fits on a single layer DVD, do not use raid" && exit 1
            [[ $a -gt 4523008 ]] && echo "**ERROR: [savecache] cache does not fit on the raid device, submit a bug report" && exit 1
            do_log "   INFO: [savecache] creating two empty disk images for raid"
            dd if=/dev/zero of="${output}".disk0 obs=1 seek=4699717632 count=0 2>/dev/null
            dd if=/dev/zero of="${output}".disk1 obs=1 seek=4563402752 count=0 2>/dev/null
            do_log "   INFO: [savecache] $output.disk0 and $output.disk1 created"
            do_log "   INFO: [savecache] '-savecache raid' requires root password"
            su -c '
                type mdadm &>/dev/null || ! echo "**ERROR '\''mdadm'\'' not found, please install it" || exit 1
                SRC=$1
                ARG=$2
                CACHE=$3
                OUTPUT=$4
                shift 4
                [[ ${CACHE:0:1} != / ]] && CACHE="$SRC/$CACHE"
                [[ ${OUTPUT:0:1} != / ]] && OUTPUT="$SRC/$OUTPUT"
                unset LOOP
                MD=
                for a ; do
                    losetup $a &>/dev/null || LOOP[${#LOOP[@]}]=$a
                    ((${#LOOP[@]}==2)) && break
                done
                for ((a=0;a<10;a++)); do
                    grep -q "^md$a" /proc/mdstat || ! MD=/dev/md$a || break
                done
                echo "   INFO: using ${LOOP[*]} for raid $MD"
                losetup ${LOOP[0]} "$OUTPUT.disk0"
                losetup ${LOOP[1]} "$OUTPUT.disk1"
                mdadm -B $MD -l linear -n 2 ${LOOP[0]} ${LOOP[1]}
                eval mkisofs -D -dvd-video $ARG -o $MD "'\'"$(echo "\$CACHE" | sed "s/'/'\\\''/g")"\''"
                mdadm -S $MD
                grep -q "^${MD##*/}" /proc/mdstat && echo "**ERROR during deactivation of array $MD" && exit 1
                losetup -d ${LOOP[1]} || ! echo "**ERROR detaching ${LOOP[1]}" || exit 1
                losetup -d ${LOOP[0]} || ! echo "**ERROR detaching ${LOOP[0]}" || exit 1
            ' -l -s /bin/bash -- root bash "$PWD" "$ARG" "$CACHE" "$output" $(ls -l /dev/loop* | sort -k 6 -n | awk '{print $NF}')
            ret=$? ; (( ret )) && echo "**ERROR failure detected, exiting" && exit $ret
            do_log "   INFO: [savecache] disk images: $output.disk0 $output.disk1 filled"
            do_log "   INFO: [savecache] restoring normal user ID"
            if [[ ${savecache[0]} != iso ]]; then
                echo "please insert a dvd in your dvdwriter, press any key to start burning the first disk:"
                read -n 1 i
                growisofs -dvd-compat ${overburn:+-overburn} -Z $dvdburndevice="$output".disk0
                ret=$? ; (( ret )) && echo "**ERROR failure detected, exiting" && exit $ret
                echo "please insert a dvd in your dvdwriter, press any key to start burning the second disk:"
                read -n 1 i
                growisofs -dvd-compat ${overburn:+-overburn} -Z $dvdburndevice="$output".disk1
                ret=$? ; (( ret )) && echo "**ERROR failure detected, exiting" && exit $ret
            fi
        else
            trap '[[ $vrfyumnt ]] && sleep 4 && umount $vrfyumnt ; rm -f "${CLEAN[@]}"' 0
            if [[ ${savecache[0]} = iso ]]; then
                eval mkisofs -D -dvd-video $ARG -o "'$(echo "$output".cache.iso | sed "s/'/'\\\''/g")'" "'$(echo "$CACHE" | sed "s/'/'\\\''/g")'"
                ret=$? ; (( ret )) && exit $ret
            elif [[ ${savecache[0]} = verify ]]; then
                verify_burn "$CACHE"
            else
                echo "please insert a dvd in your dvdwriter, press any key to start burning:"
                read -n 1 i
                eval growisofs -dvd-compat ${overburn:+-overburn} -Z $dvdburndevice -D -dvd-video $ARG "'$(echo "$CACHE" | sed "s/'/'\\\''/g")'"
                ret=$? ; (( ret )) && echo "**ERROR failure detected, exiting" && exit $ret
                [[ $verify ]] && verify_burn "$CACHE"
            fi
            trap 'rm -f "${CLEAN[@]}"' 0
        fi
        if [[ $BAKCACHE ]]; then
            chmod -R u+w "$CACHE"
            rm -rf "$CACHE"
            CACHE=$BAKCACHE
            BAKCACHE=
        fi
    fi
fi

###############################################################################
#### -audioonly
###############################################################################
if [[ $audioonly ]] ; then
    MPLAYEROPT=( "${MPLAYEROPT[@]}" mf://"$output".test.png )
    pictsrc=1
    PICTSRC=( "$output".test.png )
    slideaudio=$audioonly
fi

[[ $dvddev ]] && MPLAYEROPT=( "${MPLAYEROPT[@]}" -dvd-device "$dvddev" )

###############################################################################
#### mplayer/mencoder/mjpegtools options
###############################################################################

#### mencoder output suffix
if [[ $encode ]]; then
    [[ $mpeg ]] && SUF=mpeg || SUF=avi
fi

#### MPLAYERINFO is used for [info]
MPLAYERINFO=( "${MPLAYEROPT[@]}" )

#### MPLAYERINFONOVF
MPLAYERINFONOVF=( "${MPLAYERINFO[@]}" )
for ((a=0;a<${#MPLAYERINFONOVF[*]};a++)); do
    while [[ ${MPLAYERINFONOVF[a]} = -vf ]]; do
        unset MPLAYERINFONOVF[a] MPLAYERINFONOVF[a+1]
        MPLAYERINFONOVF=( "${MPLAYERINFONOVF[@]}" )
    done
done

#### mf:// case
if [[ $pictsrc ]]; then
    if [[ $slideaudio && $slideaudio != /dev/null ]]; then
        [[ $(id_find ID_AUDIO_RATE "$slideaudio") != $asr ]] && SRATE="-srate $asr -af-adv force=1" || SRATE=
        CLEAN[${#CLEAN[*]}]="$output".wav
        mplayer "$slideaudio" $SRATE -vo null -vc dummy -ao "${PCMWAV[@]}" $afm ${mpegchannels:+-channels $mpegchannels -af channels=$mpegchannels}
        MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps 1/$(id_find ID_LENGTH "$output".wav) -audiofile "$output".wav )
    else
        if [[ $slideaudio == /dev/null ]]; then
            MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps $slidefps )
            encode=0:${encode#?:}
        else
            MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps $slidefps -audiofile /dev/zero -audio-demuxer 20 -rawaudio format=0x1:rate=48000 )
        fi
    fi
fi

#### MENCODERARG is used for mencoding, vobsub dumping
MENCODERARG=( "${MPLAYEROPT[@]}" ${frames:+-frames $frames} )

#### SUBDUMP is used by mplayer for stream dump
SUBDUMP=( "${MENCODERARG[@]}" )

#### MENCAUDIOOPT is used for audio dump, libavcodec audio, second and following wav audio stream
[[ $encode ]] && MENCAUDIOOPT=( "$output".$SUF ) || MENCAUDIOOPT=( "${MENCODERARG[@]}" )
MENCAUDIOOPT=( "${MENCAUDIOOPT[@]}" ${mpegchannels:+-channels $mpegchannels} )

#### MENCAUDIOINFO is used for identify in libavcodec audio
[[ $encode ]] && MENCAUDIOINFO=( "$output".$SUF ) || MENCAUDIOINFO=( "${MPLAYERINFO[@]}" )
MENCAUDIOINFO=( "${MENCAUDIOINFO[@]}" ${mpegchannels:+-channels $mpegchannels} )

#### MPLAYERYUVOPT is used to produce the mpeg2enc input stream and first wav audio stream in DIRECT Mode
MPLAYERYUVOPT=( "${MENCAUDIOOPT[@]}" -noframedrop -v -osdlevel 0 -vo yuv4mpeg${interlaced:+:interlaced}:file=/dev/fd/4 )
[[ ${!audioformat} = mencoder || ${!audioformat} = copy ]] && MPLAYERYUVOPT=( "${MPLAYERYUVOPT[@]}" -nosound -benchmark ) || \
  MPLAYERYUVOPT=( "${MPLAYERYUVOPT[@]}" -ao "${PCMWAV[@]}" )

if [[ ! $encode || $encode == 0:?:? ]];then
    AF=$af
    [[ $normalize ]] && AF=${AF:--af }${AF:+,}volnorm
else
    AF=
fi

#### CHAPTER
CHAPTEROPT=( "${MENCODERARG[@]}" )

MENCODERARG=( "${MENCODERARG[@]}" "${MENCODEROPT[@]}" ${ofps:+-ofps $ofps} )
if [[ $mpeg && $mpegchannels ]]; then
    MENCODERARG=( "${MENCODERARG[@]}" -channels $mpegchannels )
    af=$(echo "${af:--af }${af:+,}" | sed 's/channels=[^,]*,//')channels=$mpegchannels
    AF=$(echo "${AF:--af }${AF:+,}" | sed 's/channels=[^,]*,//')channels=$mpegchannels
elif [[ $channels ]]; then
    MENCODERARG=( "${MENCODERARG[@]}" -channels $channels )
    af=$(echo "${af:--af }${af:+,}" | sed 's/channels=[^,]*,//')channels=$channels
    AF=$(echo "${AF:--af }${AF:+,}" | sed 's/channels=[^,]*,//')channels=$channels
fi

[[ $frameformat == MPEG[12] ]] && GOPTABLE=([1]=48 48 50 60 60 100 120 120) GOP=${GOP:-${GOPTABLE[vfr]}}

YUVSCALEROPT="-v 1 -n $videonorm ${scale:+-O $frameformat} $YUVSCALEROPT"

MPEG2ENCOPT="${cpu:+-M $cpu }-v 1 -S ${split:-50000} -n $videonorm -F $vfr -s -r 16 ${telecine:+-p} $MPEG2ENCOPT"
case $vfr in
    1|2) MPEG2ENCOPT="-g 6 -G ${GOP:-12} $MPEG2ENCOPT" ;;
    3|6) MPEG2ENCOPT="-g 6 -G ${GOP:-15} $MPEG2ENCOPT" ;;
    4|5|7|8) MPEG2ENCOPT="-g 9 -G ${GOP:-18} $MPEG2ENCOPT" ;;
esac
[[ $frameformat = VCD ]] && MPEG2ENCOPT="-R 2 $MPEG2ENCOPT"
echo "$MPEG2ENCOPT" | grep -q -e '-K hi-res' && YUVSCALEROPT="-M BICUBIC $YUVSCALEROPT" && \
  MPEG2ENCOPT="-4 1 -2 1 $MPEG2ENCOPT" || MPEG2ENCOPT="-4 2 -2 1 $MPEG2ENCOPT"

echo "$CDRDAOOPT" | grep -q -e '--driver' || CDRDAOOPT="$CDRDAOOPT --driver generic-mmc"
echo "$CDRDAOOPT" | grep -q -e '--device' || CDRDAOOPT="$CDRDAOOPT --device $cdburndevice"

: ${GROWISOFSOPT:=-dvd-compat -Z $dvdburndevice -dvd-video}

case $frameformat in
    VCD) MPGRES=${MPGRES:-1} ;;
    SVCD)
        case $frameres in
            1) MPGRES=${MPGRES:-3} ;;
            2) MPGRES=${MPGRES:-1} ;;
        esac
        ;;
    DVD)
        case $frameres in
            1) MPGRES=${MPGRES:-7} ;;
            2) MPGRES=${MPGRES:-6} ;;
            3) MPGRES=${MPGRES:-3} ;;
            4) MPGRES=${MPGRES:-2} ;;
            5) MPGRES=${MPGRES:-1} ;;
        esac
        ;;
esac
case $MPGRES in
    1) H_RES=352 ; [[ $videonorm = n ]] && V_RES=240 || V_RES=288 ;;
    2) H_RES=352 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;;
    3) H_RES=480 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;;
    4) H_RES=528 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;;
    5) H_RES=544 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;;
    6) H_RES=704 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;;
    7) H_RES=720 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;;
esac
vbrbak=${vbr:-16000}
case $frameformat in
    MPEG1)
        : ${vbr:=16000}
        MPLEXOPT="-f 0 -V -b 2000 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT"
        MAXBR=100000
        ;;
    MPEG2)
        : ${vbr:=16000}
        MPLEXOPT="-f 3 -V -b 2000 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT"
        MAXBR=100000
        ;;
    VCD)
        : ${vbr:=1152}
        MPEG2ENCOPT="-f 2 -b $vbr -V 46 -B $(((abr*audiostream*101875-vbr*2819+3980000)/100000)) $MPEG2ENCOPT"
        MPLEXOPT="-f 2 -V -b 46 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT"
        VCDIMAGEROPT="-t vcd2 $VCDIMAGEROPT"
        H_STILL=704
        [[ $videonorm = n ]] && V_STILL=480 || V_STILL=576
        ((MPGRES!=1)) && YUVSCALEROPT="-O SIZE_${H_RES}x${V_RES} ${YUVSCALEROPT/ -O $frameformat}"
        MAXBR=1394
        ;;
    SVCD)
        : ${vbr:=2500}
        MPEG2ENCOPT="-f 5 -b $vbr -V 113 -B $(((abr*audiostream*101250+vbr*742+1665400)/100000)) $MPEG2ENCOPT"
        MPLEXOPT="-V -b 113 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT"
        if [[ $trick ]]; then
            MPLEXOPT="-f 2 $MPLEXOPT"
            VCDIMAGEROPT="-t vcd2 $VCDIMAGEROPT"
        else
            MPLEXOPT="-f 5 $MPLEXOPT"
            VCDIMAGEROPT="-t svcd $VCDIMAGEROPT"
        fi
        H_STILL=704
        [[ $videonorm = n ]] && V_STILL=480 || V_STILL=576
        ((frameres>1||MPGRES!=3)) && YUVSCALEROPT="-O SIZE_${H_RES}x${V_RES} ${YUVSCALEROPT/ -O $frameformat}"
        MAXBR=2778
        ;;
    DVD)
        : ${vbr:=7500}
        MPEG2ENCOPT="-f 8 -b $vbr -V 230 -B $(((abr*audiostream*101250+vbr*742+1665400)/100000)) $MPEG2ENCOPT"
        MPLEXOPT="-f 8 -V -b 230 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT"
        [[ ! $split ]] && MPLEXOPT="-M $MPLEXOPT"
        H_STILL=720
        [[ $videonorm = n ]] && V_STILL=480 || V_STILL=576
        ((frameres>1||MPGRES!=7)) && YUVSCALEROPT="-O SIZE_${H_RES}x${V_RES} ${YUVSCALEROPT/ -O $frameformat}"
        MAXBR=10080
        ;;
esac

###############################################################################
#### find the a/v delay; tested only with TS streams
###############################################################################
if [[ $autosync ]]; then
    autosync=$(get_av_delay "${MPLAYERINFO[@]}")
    MPLEXOPT="-O ${autosync}ms $MPLEXOPT"
fi

###############################################################################
#### mencoder audio/video/pass options
###############################################################################
if [[ $encode ]]; then
    #### CHECK -mc 0
    #### 1.0pre5 interlaced[ilme]/qpel conflict
    ####	 ildctcmp=2 not useful
    OPTIONS="-noskiplimit -sws $((hispeed?1:7))"
    if [[ ! $mpeg ]]; then
        OPTIONS="$OPTIONS -info comment=$PROGNAME-$VERSION ${noodml:+-noodml}"
        if [[ $encode == ?:0:? || $vcodec = xvid ]]; then
            OPTIONS="$OPTIONS ${fourcc:+-ffourcc $fourcc}"
        else
            [[ $vcodec && $vcodec != mpeg4 ]] || OPTIONS="$OPTIONS -ffourcc ${fourcc:-DX50}"
        fi
    fi
    if [[ $mpeg ]]; then
        # mencoder can put in the MPEG container:
        # video: mpeg1, mpeg2, mpeg4
        # audio: mp1, mp2, mp3, ac3, aac (not yet: lpcm, dts)
        [[ $encode != ?:0:? ]] && : ${mpegaspect:=2}
        #MUX="-mpegopts ${mpegaspect:+vaspect=${ASPECT[mpegaspect]}:}:vbitrate=${vbr}"
        MUX="-mpegopts tsaf:"
        if [[ $telecine ]]; then
            if [[ $vcodec = mpeg2video || ! $vcodec && $frameformat != VCD && $frameformat != MPEG1 ]]; then
                if [[ $vfr == [12] ]]; then
                    [[ $videonorm = n ]] && MUX2=":telecine" || MUX2=":film2pal"
                else
                    do_log "++ WARN: [$PROGNAME] telecine only works with 24000/1001 or 24 fps, disabling it"
                fi
            else
                do_log "++ WARN: [$PROGNAME] telecine only works for MPEG-2, disabling it"
            fi
        fi
        case $frameformat in
            MPEG1) MUX="${MUX}format=mpeg1"        LAVC="vcodec=${vcodec:-mpeg1video}:vrc_buf_size=16000" MUX="${MUX}:muxrate=$(((abr+vbr)*2))" ;;
            MPEG2) MUX="${MUX}format=mpeg2"        LAVC="vcodec=${vcodec:-mpeg2video}:vrc_buf_size=16000" MUX="${MUX}:muxrate=$(((abr+vbr)*2))" ;;
            VCD)   MUX="${MUX}format=xvcd"         LAVC="vcodec=${vcodec:-mpeg1video}${LAVC:-:vrc_buf_size=327:vrc_minrate=${vbr}:vrc_maxrate=${vbr}}" ;;
            SVCD) if [[ $trick ]]; then MUX="${MUX}format=xvcd" ; else 
                   MUX="${MUX}format=xsvcd" ; fi ; LAVC="vcodec=${vcodec:-mpeg2video}:vrc_buf_size=917" ;;
            DVD)   MUX="${MUX}format=dvd"          LAVC="vcodec=${vcodec:-mpeg2video}:vrc_buf_size=1835" ;;
        esac
        case $vfr in
            1|2) LAVC="$LAVC:keyint=$((hispeed?1:${GOP:-12}))" ;;
            3|6) LAVC="$LAVC:keyint=$((hispeed?1:${GOP:-15}))" ;;
            4|5|7|8) LAVC="$LAVC:keyint=$((hispeed?1:${GOP:-18}))" ;;
        esac
        [[ $frameformat = VCD && ! $bframes ]] && LAVC="$LAVC:vmax_b_frames=2"
        [[ $mpegmbr && $mpegmbr -lt $vbr ]] && mpegmbr=$vbr
        #### -a 1 is SAR=1 (do not scale), not DAR=1
        [[ $mpegaspect != 1 ]] && LAVC="${LAVC}:aspect=${ASPECT[mpegaspect]}"
        LAVC="${LAVC}${mpegmbr:+:vrc_maxrate=$mpegmbr}${inter_matrix:+:inter_matrix=${inter_matrix}}${intra_matrix:+:intra_matrix=${intra_matrix}}"
        if [[ $lavf && ( $frameformat = VCD || $frameformat = MPEG1 ) ]]; then
            OF="-of lavf"
            MUX="-lavfopts format=mpg:i_certify_that_my_video_stream_does_not_use_b_frames"
        else
            OF="-of mpeg"
        fi
        NOSKIP=-noskip
        if [[ $encode != ?:0:? ]]; then
            for ((a=0;a<${#MENCODERARG[*]};a++)); do
                while [[ ${MENCODERARG[a]} = -vf ]]; do
                    unset MENCODERARG[a] MENCODERARG[a+1]
                    MENCODERARG=( "${MENCODERARG[@]}" )
                done
            done
            MENCODERARG=( "${MENCODERARG[@]}" ${vf:--vf }${vf:+,}${scale:+scale=${H_RES}:${V_RES}${interlaced:+:1},}harddup )
        fi
        [[ $vcodec = xvid ]] && LAVC=$(echo $LAVC${cartoon:+:cartoon} | \
          sed 's/vcodec=[^:]*://;s/vrc_buf_size=/rc_buffer=/;s/keyint=/max_key_interval=/;s/:vrc_m[ia][nx]rate=[^:]*//g;s/vmax_b_f/max_bf/')
    else
        vbr=$vbrbak
        if [[ $vcodec = xvid ]]; then
            LAVC=autoaspect${cartoon:+:cartoon}
            if [[ ${PROFILE[8]} ]]; then
                LAVC="$LAVC:profile=${PROFILE[8]}"
                if [[ ${PROFILE[8]} = dxnport || ${PROFILE[8]} = dxnht ]]; then
                    awk -v a=$ofps 'BEGIN{if(a>25)exit 1}' && LAVC="${LAVC}pal" || LAVC="${LAVC}ntsc"
                fi
            fi
        else
            LAVC="vcodec=${vcodec:-mpeg4}:autoaspect"
            if [[ ${PROFILE[4]} ]]; then
                [[ ${PROFILE[4]} = vbr ]] && LAVC="$LAVC:vrc_maxrate=$vbr" || LAVC="$LAVC:vrc_maxrate=${PROFILE[4]}"
            fi
            [[ ${PROFILE[5]} ]] && LAVC="$LAVC:vrc_buf_size=${PROFILE[5]}"
        fi
        if [[ $lavf ]]; then
            OF="-of lavf"
            MUX="-lavfopts format=avi:i_certify_that_my_video_stream_does_not_use_b_frames"
        else
            OF=
            MUX=
        fi
        MUX2=
        NOSKIP=
    fi

    if [[ $vcodec = xvid ]]; then
        OVC="-ovc xvid -xvidencopts"
        BASIC="$LAVC:bitrate=$vbr${cpu:+:threads=$cpu}${bframes:+:max_bframes=$bframes}"
        ((hispeed)) && BASIC="$BASIC:me_quality=0" || BASIC="$BASIC:psnr"
        [[ ! $mpeg && $hispeed -eq 1 ]] && BASIC="$BASIC:max_key_interval=1"
        if ((step == 1)); then
            if [[ $inter_matrix ]]; then
                MATRIX=(${inter_matrix//,/ })
                CLEAN[${#CLEAN[*]}]="$output".interm
                { for ((a=0;a<${#MATRIX[*]};a++)) ; do
                      printf "%3s" ${MATRIX[a]}
                      ((! ((a+1)%8))) && echo
                  done
                } >"$output".interm
                BASIC="$BASIC:quant_inter_matrix=$output.interm"
            fi
            if [[ $intra_matrix ]]; then
                MATRIX=(${intra_matrix//,/ })
                CLEAN[${#CLEAN[*]}]="$output".intram
                { for ((a=0;a<${#MATRIX[*]};a++)) ; do
                      printf "%3s" ${MATRIX[a]}
                      ((! ((a+1)%8))) && echo
                  done
                } >"$output".intram
                BASIC="$BASIC:quant_intra_matrix=$output.intram"
            fi
            BASIC="$BASIC:quant_type=mpeg"
        fi
        [[ ! $mpeg && $hispeed -eq 0 ]] && BASIC="$BASIC${GOP:+:max_key_interval=$GOP}"
        [[ $mpeg && ( $frameformat = VCD || $frameformat = MPEG1 ) ]] || BASIC="$BASIC${interlaced:+:interlacing}"
        echo "$YUVSCALEROPT" | grep -q -e '-O MONOCHROME' && BASIC="$BASIC:grayscale"

        HQ="${BASIC}"
        ((hispeed)) || BASIC="$BASIC:me_quality=4"
        BASIC="$BASIC:notrellis:nochroma_me:nohq_ac:vhq=0:bvhq=0"
        BESTSIZE="${HQ}:vhq=4:lumi_mask"
        BESTQUALITY="${HQ}:vhq=4:chroma_opt"
    else
        OVC="-ovc lavc -lavcopts"
        BASIC="$LAVC:vstrict=0:vbitrate=$vbr${cpu:+:threads=$cpu}${bframes:+:vmax_b_frames=$bframes}${cartoon:+:precmp=2:cmp=2:subcmp=2:qns=2}"
        BASIC="$BASIC${cbr:+:vrc_minrate=$vbr:vrc_maxrate=$vbr}"
        [[ ! $mpeg ]] && BASIC="$BASIC${cbr:+:vrc_buf_size=16000}"
        ((hispeed)) && BASIC="$BASIC:vme=0" || BASIC="$BASIC:psnr"
        [[ ! $mpeg && $hispeed -eq 1 ]] && BASIC="$BASIC:keyint=1"
        (( step == 1 )) && BASIC="$BASIC${inter_matrix:+:inter_matrix=${inter_matrix}}${intra_matrix:+:intra_matrix=${intra_matrix}}"
        [[ $mpeg && ( $frameformat = VCD || $frameformat = MPEG1 ) ]] || BASIC="$BASIC${interlaced:+:ildct:ilme}"
        echo "$YUVSCALEROPT" | grep -q -e '-O MONOCHROME' && BASIC="$BASIC:gray"

        HQ="${BASIC}:mbd=2"

        if [[ $mpeg ]]; then
            #### dia=6 could be added
            BESTSIZE="${BASIC}:mbd=1:loop:mv0:trell"
            [[ $cartoon ]] || BESTSIZE="$BESTSIZE:vlelim=-4:vcelim=7:precmp=1:cmp=1:subcmp=1"
            [[ ! $bframes ]] && BESTSIZE="$BESTSIZE:vmax_b_frames=2"

            #### last_pred=1-2 could be added
            BESTQUALITY="${BASIC}:mbd=2:mv0"
            [[ $cartoon ]] || BESTQUALITY="$BESTQUALITY:precmp=6:cmp=6:subcmp=6"
            [[ $vbr -ge 3500 && $frameformat != VCD && $frameformat != MPEG1 && $vcodec != mpeg1video ]] && BESTQUALITY="$BESTQUALITY:dc=9"
        else
            #### removed qpel. (doubled encode time, bad ratio PSNR/file_size)
            BESTSIZE="${BASIC}:mbd=1:last_pred=5:aic:mv0:v4mv:preme=2"
            [[ $cartoon ]] || BESTSIZE="$BESTSIZE:vlelim=-4:vcelim=7"
            if [[ ! $bframes ]]; then
                [[ ${PROFILE[3]} ]] && BESTSIZE="$BESTSIZE:vmax_b_frames=${PROFILE[3]}" || BESTSIZE="$BESTSIZE:vmax_b_frames=2"
            fi
            #### 1.0pre5 interlaced ilme/qpel conflict
            [[ $interlaced ]] && BESTSIZE=${BESTSIZE/qpel:}

            BESTQUALITY="${BASIC}:mbd=2:trell:v4mv:mv0:aic:last_pred=5"
            [[ $cartoon ]] || BESTQUALITY="$BESTQUALITY:precmp=3:cmp=3:subcmp=3"
            if ((!hispeed)); then
                BASIC="$BASIC${GOP:+:keyint=$GOP}"
                HQ="$HQ:keyint=${GOP:-300}"
                BESTSIZE="$BESTSIZE:keyint=${GOP:-300}"
                BESTQUALITY="$BESTQUALITY${GOP:+:keyint=$GOP}"
            fi
        fi
        [[ $bframes && $bframes -gt 0 ]] && BESTQUALITY="$BESTQUALITY:bidir_refine=2"
    fi
    if ((cartoon == 2)); then
        for ((a=0;a<${#MENCODERARG[*]};a++)); do
            if [[ ${MENCODERARG[a]} = -vf ]]; then
                ! echo ${MENCODERARG[a+1]} | grep -q hqdn3d && MENCODERARG[a+1]=hqdn3d=5:5:5,${MENCODERARG[a+1]} || \
                  MENCODERARG[a+1]=$(echo ${MENCODERARG[a+1]} | sed 's/hqdn3d=[0-9]:[0-9]:[0-9]/hqdn3d/;s/hqdn3d/&=5:5:5/')
                break
            fi
        done
        ((a==${#MENCODERARG[*]})) && MENCODERARG=( "${MENCODERARG[@]}" -vf hqdn3d=5:5:5 )
        if [[ $vf ]]; then
            ! echo $vf | grep -q hqdn3d && vf="-vf hqdn3d=5:5:5,${vf#-vf }" || vf=$(echo $vf | sed 's/hqdn3d=[0-9]:[0-9]:[0-9]/hqdn3d/;s/hqdn3d/&=5:5:5/')
        else
            vf="-vf hqdn3d=5:5:5"
        fi
    fi

    case $encode in
        0:?:?) AUDIOPASS="-oac copy" ;;
        1:?:?) AUDIOPASS="-oac pcm" ;;
        2:?:?) AUDIOPASS="-oac mp3lame -lameopts ${acustom:-${abrset:+abr:br=}${abrset:-fast}}" ;;
        3:?:?) AUDIOPASS="-oac mp3lame -lameopts preset=${abrset:-standard}" ;;
        4:?:?) AUDIOPASS="-oac lavc -lavcopts acodec=mp2:abitrate=$abr" ;;
        5:?:?) AUDIOPASS="-oac lavc -lavcopts acodec=mp3:abitrate=$abr" ;;
        6:?:?) AUDIOPASS="-oac lavc -lavcopts acodec=ac3:abitrate=$abr" ;;
        7:?:?) AUDIOPASS="-oac $TOOLAME -${TOOLAME}opts br=$abr" ;;
        8:?:?) AUDIOPASS="-oac faac -faacopts ${acustom:-br=$abr}" ;;
    esac
    case $encode in
        ?:0:?) VIDEOPASS="$OF $MUX -ovc copy $NOSKIP" ; encode=${encode%%:*}:0:1 ; turbo=0 ;; # copy uses only one pass
        ?:1:?) VIDEOPASS="$OF $MUX$MUX2 $OVC ${BASIC}${vcustom:+:$vcustom}" ; : ${turbo:=0} ;;
        ?:2:?) VIDEOPASS="$OF $MUX$MUX2 $OVC ${HQ}"                         ; : ${turbo:=1} ;;
        ?:3:?) VIDEOPASS="$OF $MUX$MUX2 $OVC ${BESTSIZE}"                   ; : ${turbo:=1} ;;
        ?:4:?) VIDEOPASS="$OF $MUX$MUX2 $OVC ${BESTQUALITY}"                ; : ${turbo:=1} ;;
    esac
    ((turbo)) && turbo=:turbo || turbo=
    if [[ $vcodec != ffv1 ]]; then
        PASS=${encode##*:}
        pass=pass
        [[ $vcodec = xvid ]] && PASS=$((PASS>2?2:PASS)) || pass=v$pass
    else
        PASS=1
        VIDEOPASS="$OF $MUX$MUX2 $OVC $LAVC"
    fi
    [[ $normalize && $encode != 0:?:? ]] && af=${af:--af }${af:+,}volnorm
fi


###############################################################################
#### functions 3/3
###############################################################################
save_status () {
    ((skip)) && echo "skip=$skip" || echo
    (( ${#MPLEXSTREAM[*]} )) && declare -p MPLEXSTREAM
    [[ $LPCMPAR ]] && echo "LPCMPAR='$LPCMPAR'"
    [[ $SUBLANG ]] && echo "SUBLANG='$SUBLANG'"
}
status_bit () {
    local a
    #### if adding a new pattern, check skip_encode
    case $1 in
        avi) bit=0 ;;
        mpv) bit=1 ;;
        mpa) bit=2 ;;
        mpg) bit=3 ;;
        img) bit=4 ;;
        sub) bit=5 ;;
        ach) bit=6 ;;
        fno) bit=7 ;;
        ch0) bit=8 ;;
        sbm) bit=9 ;;
        spl) bit=10 ;;
        ocr) bit=11 ;;
    esac
    if [[ $2 = set ]]; then
        skip=$((skip|1<<bit))
    elif [[ $2 = clear ]]; then
        skip=$((skip&(65535^1<<bit)))
        if [[ $1 == mpv ]]; then
            for ((a=0;a<${#MPLEXSTREAM[*]};a++)); do
                [[ ${MPLEXSTREAM[a]} == *.mpv ]] && unset MPLEXSTREAM[a] && break
            done
            MPLEXSTREAM=( "${MPLEXSTREAM[@]}" )
        fi
        if [[ $1 == mpa ]]; then
            for ((a=0;a<${#MPLEXSTREAM[*]};a++)); do
                [[ ${MPLEXSTREAM[a]} == *.mpa || ${MPLEXSTREAM[a]} == *.mpa[0-9] || ${MPLEXSTREAM[a]} == *.mpa[0-9][0-9] || ${MPLEXSTREAM[a]} == *.lpcm ]] && unset MPLEXSTREAM[a]
            done
            MPLEXSTREAM=( "${MPLEXSTREAM[@]}" )
        fi
        [[ $1 == sbm ]] && SUBLANG=
    else
        return $(((skip&1<<bit) && 1))
    fi
}
###############################################################################
file_size () { #fsize,fint,ffrac,fpre
    local -a PRE=([1]=K M G T)
    local i=0
    fsize=$(stat -c '%s' "$1")
    fint=$fsize
    ffrac=0
    while ((fint>=1024)) ; do
        ((fint/1024 < 1024)) && ffrac=$((( fint+=51 )%1024))
        i=$((++i))
        fint=$((fint/1024))
    done
    ffrac=$((ffrac*10/1024))
    fpre=${PRE[i]}
}
###############################################################################
show_file_info () {
    file_size "$2"
    echo "   $1: $2 is $fsize bytes, $fint.$ffrac ${fpre}B" >>"$output".log
}
###############################################################################
show_finalvideo_info () {
    local codec TYPE i VIDEO OUT ASPECT CH FAAC SUBST
    SUBST=
    VIDEO="$(mplayer -nocache -frames 0 -vo null -nosound "$2" 2>/dev/null | grep "^VIDEO:")"
    if [[ ! $VIDEO ]]; then
        # MPEGs with MPEG-4 video do not show all the video informations in one line,
        # assebmling the informations (kbps is missing):
        OUT=$(mplayer -nocache -frames 1 -vo null -nosound -v "$2" 2>/dev/null)
        if echo "$OUT" | grep -q '^\[V].*fourcc:0x10000004' ; then
            VIDEO="VIDEO:  MPEG-4  $(echo "$OUT" | awk '$1=="VO:"&&$2=="[null]"{print $3}')"
            ASPECT=$(echo "$OUT" | awk '$1=="Movie-Aspect"{print $3}')
            case $ASPECT in
                undefined) VIDEO="$VIDEO  (aspect 1)" ;;
                1.33:1) VIDEO="$VIDEO  (aspect 2)" ;;
                1.78:1) VIDEO="$VIDEO  (aspect 3)" ;;
                2.21:1) VIDEO="$VIDEO  (aspect 4)" ;;
                *) VIDEO="$VIDEO  (aspect $ASPECT)" ;;
            esac
            VIDEO="$VIDEO  $(echo "$OUT" | awk '$1=="[V]"{print $5}')"
        fi
    fi
    do_log "   $1: $VIDEO"
    #### removed -vc dummy
    for i in $(mplayer -vo null -ao null -nocache -frames 1 -v "$2" 2>/dev/null | awk '/==> Found audio str/{print $NF}' | sort -n) ; do
        echo -n "   $1: AUDIO[$i]: " >>"$output".log
        codec=$(mplayer -ac mp3, -nocache -frames 0 -v -ao null -vo null "$2" -aid $i 2>/dev/null | \
          sed '/Selected audio codec:/!d;s/[^(]*(//;s/).*//;s/AAC.*/& AAC/;s/.* //')
        #### AAC info are insufficient/incorrect
        if [[ $codec = AAC ]]; then
            CH=$(mplayer -nocache -frames 0 -v -ao null -vo null "$2" -aid $i 2>/dev/null | awk '/FAAD: Negotiated samplerate:/{print $NF}')
            if type &>/dev/null faad ; then
                mplayer -dumpaudio -dumpfile "$output".audio -aid $i "$2" 2>/dev/null
                FAAC=$(faad -i "$output".audio 2>&1 | tail -2 | head -n 1)
                rm -f "$output".audio
                if [[ $FAAC = RAW ]]; then
                    SUBST="s/2 ch,/$CH ch, RAW,/;"
                else
                    #ADTS, 4.087 sec, 103 kbps, 44100 Hz
                    SUBST="s/AAC.*/AAC:$(echo "$FAAC" | sed 's/.*,\([^,]*Hz\).*/\1/'), "
                    SUBST="${SUBST}$CH ch, $(echo "$FAAC" | sed 's/,.*//'),"
                    SUBST="${SUBST}$(echo "$FAAC" | sed 's/.*,\([^,]*kbps\).*/\1/')"
                    SUBST="${SUBST}/;"
                fi
            else
                SUBST="s/2 ch,/$CH ch,/;"
            fi
        fi
        mplayer -ac mp3, -nocache -frames 0 -v -ao null -vo null "$2" -aid $i 2>/dev/null | sed '/^Opening audio decode/,/^AUDIO:/!d;s/\r//g' | \
          grep -e '^AC3:' -e '^MPEG' -e '^AUDIO:' | sed 's/AUDIO/'"$codec"'/;'"$SUBST"'q' >>"$output".log
    done
    TYPE=$1
    shift
    for i ; do
        show_file_info "$TYPE" "$i"
    done
}
###############################################################################
video_duration () {
    mencoder "$@" -ovc copy -nosound -o /dev/null -quiet 2>&1 | awk '/^Video stream:/{print $10+$10/$12}'
}
###############################################################################
findpng () {
    local src
    [[ ${output%/*} = "$output" ]] && src=. || src=${output%/*}
    find "$src" -maxdepth 1 -name "$(echo "${output##*/}" | sed 's/\\/\\\\/g')[0-9][0-9][0-9][0-9][0-9].png" -print0
}
###############################################################################
job_exit () {
    EXIT=$?
    if [[ $removecache ]]; then
        CACHE=
        if [[ $cache ]]; then
            if [[ -d $cache/$DVDTITLE && -f $cache/$DVDTITLE.ISOINFO ]]; then
                CACHE=$cache/$DVDTITLE
            else
                echo "**ERROR: [$PROGNAME] cannot find cache $cache/$DVDTITLE, submit a bugreport" >>"$output".log
            fi
        else
            if [[ $dvddev && -d $dvddev && -f $dvddev.ISOINFO ]]; then
                CACHE=$dvddev
            else
                echo "++ WARN: [$PROGNAME] cannot find cache $dvddev, no cache removed" >>"$output".log
            fi
        fi
        if [[ $CACHE ]]; then
            do_log "   INFO: [$PROGNAME] removing cache $CACHE"
            chmod -R u+w "$CACHE"
            rm -rf "$CACHE"{,.ISOINFO}
        fi
    fi
    if ((!${#TITLESET[*]})); then
        [[ $mpeg ]] || status_bit avi || [[ ! -f $output.avi ]] || show_finalvideo_info " AVI" "$output".avi
        status_bit mpg || [[ ! -f ${output}.mpg && ! -f ${output}01.mpg ]] || show_finalvideo_info  "MPEG" "${output}"?([0-9][0-9]).mpg
        [[ $usesbr ]] && ((DEBUG && usesbr>6)) && awk -v u=$usesbr -v f=$fsize \
          'BEGIN{b=u*1024*1024;printf("--DEBUG: [usesbr] target: %dMB (%d bytes), error: %f%%\n",u,b,(b-f)*100/b)}' >>"$output".log
        if ((timelen)); then
            do_log "--DEBUG:  source stream is $(video_duration $OPTIONS "${MENCODERARG[@]}") seconds"
            [[ $step -eq 1 ]] && do_log "--DEBUG: encoded stream is $(video_duration $OPTIONS "$output".avi) seconds" || \
              do_log "--DEBUG: encoded stream is $(video_duration $OPTIONS "$output"${split:+01}.mpg) seconds"
        fi
    fi
    [[ $LOGPROC ]] && wait $LOGPROC
    ((step==5)) && show_file_info " ISO" "$output".iso
    [[ $CACHE && ${savecache[0]} = iso && ${savecache[2]} != raid ]] && show_file_info " ISO" "$output".cache.iso
    sec=$(($(pr_time)-STARTTIME))
    echo " JOBEND: $output $(pr_date) ($((sec/3600))h$((sec/60%60))m$((sec%60))s)" >>"$output".log
    ((MENUERR)) && do_log "**ERROR: there has been $MENUERR failure(s) during menu creation"
    save_status | tr '\012' '\015' >>"$output".log
    printf "%$(save_status | awk '{if(m<length())m=length()}END{print m}')s\r" >>"$output".log
    [[ $bakiter ]] && iter=$bakiter
    if ((iter)); then
        CLEAN[${#CLEAN[*]}]="$output".log.log
        cat </dev/null >"$output".log.log
        for ((i=1;i<=iter;i++)); do
            awk 'NR!=1{print a}{a=$0}' <"$output"$(printf "%02d" $i).log >>"$output".log.log
            rm "$output"$(printf "%02d" $i).log
            ((i<iter)) && sed 's/[^ ]/*/g;q' "$output"$(printf "%02d" $((i+1))).log >>"$output".log.log
        done
        sed -n '/resuming from previous run/s/[^ ]/*/gp' "$output".log >>"$output".log.log
        sed '/resuming from previous run/,$!d' "$output".log >>"$output".log.log
        mv "$output".log.log "$output".log
        unset CLEAN[${#CLEAN[*]}-1]
    fi
    if [[ $bakiter = 0 ]]; then
        sed -n '/resuming from previous run/s/[^ ]/=/gp' "$output".log >>"$output".log.log
        sed '/resuming from previous run/,$!d;s/.*\r\( .*resuming\)/\1/' "$output".log >>"$output".log.log
        mv "$output".log.log "$output".log
    fi
    rm -f "${CLEAN[@]}" psnr_??????.log
    for ((i=0;;i++)); do
        eval [[ \${CLEAN$i[0]} ]] && eval rm -f "\"\${CLEAN$i[@]}\"" || break
    done
    if [[ $ocrterm = gnome-terminal && $step -eq 1 && ${#addsub[*]} -gt 0 ]]; then
        [[ -d ~/.gconf$AGTP/$PROGNAME ]] && rm -rf ~/.gconf$AGTP/$PROGNAME
        s=$(gconftool-2 -g $AGTG/profile_list)
        echo "$s" | grep -q $PROGNAME && gconftool-2 -s $AGTG/profile_list -t list --list-type string "${s/,$PROGNAME}"
    fi
    [[ $pngremove ]] && findpng | xargs -0 rm
    ((DEBUG)) && exec >&1- >&2- && exec >&3
    if [[ -f $output.yuvscaler.log || -f $output.mpeg2enc.log ]]; then
        [[ -f $output.yuvscaler.log ]] && cat "$output".yuvscaler.log
        [[ -f $output.mpeg2enc.log ]] && cat "$output".mpeg2enc.log
        echo -n "please remove: "
        [[ -f $output.yuvscaler.log ]] && echo -n "$output.yuvscaler.log "
        [[ -f $output.mpeg2enc.log ]] && echo -n "$output.mpeg2enc.log"
        echo
    else
        if ((!EXIT)) && [[ ! $quiet ]]; then
            if [[ $resume && $iter -eq 0 ]]; then
                n=$(awk '$0~/resuming from previous run/{n=NR}END{print n}' <"$output".log)
                sed "$n,\$!d" "$output".log
                WLIST=$(awk -v i=$n 'NR>i&&$0~/^++ WARN:/{print}' <"$output".log)
            else
                cat "$output".log
                WLIST=$(grep '^++ WARN:' "$output".log)
            fi
            [[ $WLIST ]] && echo "   Warnings summary:" && echo "$WLIST"
        fi
    fi
    ((DEBUG)) && rm -f "$output".debug.fifo && kill $PROCTEE
    [[ $removedir ]] && rm -r "$output".dir
    [[ $vrfyumnt ]] && umount $vrfyumnt
}
###############################################################################
filter_log () {
    rm -f "$output".fifo
    mkfifo "$output".fifo
    tee -a /dev/stderr <"$output".fifo | sed 's/'"${2:-^}"'//;/^$/d;s/.*\r//;s/....//g;s/^/   INFO: ['$1'] /' >>"$output".log &
    LOGPROC=$!
}
###############################################################################
filter_log2 () {
    rm -f "$output".fifo
    mkfifo "$output".fifo
    tee -a /dev/stderr <"$output".fifo | \
      awk -v i="$1" '{gsub(/.*\r/,"");
        if($0~/^(.. )?[A-Z][A-Z][A-Z][A-Z]:/){sub(/^(.. )?[A-Z][A-Z][A-Z][A-Z]: /,"&["i"] ");sub(/^[A-Z][A-Z][A-Z][A-Z]: /,"   &")} ;
        if($0~/^...[A-Z][A-Z][A-Z][A-Z]: /)print;else if($0!~/^$/)print "   INFO: ["i"] "$0}'  >>"$output".log &
    LOGPROC=$!
}
###############################################################################
dump_log () {
    rm -f "$output".fifo
    mkfifo "$output".fifo
    tee -a /dev/stderr <"$output".fifo >>"$output".log &
    LOGPROC=$!
}
###############################################################################
me_log () {
    rm -f "$output".fifo
    mkfifo "$output".fifo
    tee -a /dev/stderr <"$output".fifo | sed 's/.*\r//' | awk >>"$output".log -v m=${1:-mencoder} \
      '/PSNR|^M[EP][ln]|^There are |^audio stream:|^number of|^subtitle|^==> |^Recommended video bitrate/{sub(/^/,"   INFO: ["m"] "); print}' &
    LOGPROC=$!
}
###############################################################################
me_bit_log () {
    rm -f "$output".fifo
    mkfifo "$output".fifo
    tee -a /dev/stderr <"$output".fifo | sed 's/.*\r//;/^Recommended video bitrate/!d;s/^/   INFO: [mencoder] /' >>"$output".log &
    LOGPROC=$!
}
###############################################################################
check_abr () {
        # abr permitted:
        # ac3: ( 8000/11025/12000)  8 16 24 32 40 48 56 64 80 96 112 128 144 160
        # ac3: (16000/22050/24000)    16 24 32 40 48 56 64 80 96 112 128     160     192 224 256 288 320
        # ac3: (32000/44100/48000)          32 40 48 56 64 80 96 112 128     160     192 224 256     320     384     448 512 576 640
        # mp3: ( 8000/11025/12000)  8 16 24 32 40 48 56 64 80 96 112 128 144 160
        # mp3: (16000/22050/24000)  8 16 24 32 40 48 56 64 80 96 112 128 144 160
        # mp3: (32000/44100/48000)          32 40 48 56 64 80 96 112 128     160     192 224 256     320
        # mp2: ( 8000/11025/12000)
        # mp2: (16000/22050/24000)  8 16 24 32 40 48 56 64 80 96 112 128 144 160
        # mp2: (32000/44100/48000)          32    48 56 64 80 96 112 128     160     192 224 256     320     384
        # mp1: ( 8000/11025/12000)
        # mp1: (16000/22050/24000)          32    48 56 64 80 96 112 128 144 160 176 192 224 256
        # mp1: (32000/44100/48000)          32          64    96     128     160     192 224 256 288 320 352 384 416 448
    case $1 in
        ac3)
            case $2 in
                8000|11025|12000)
                    case $3 in
                        8|16|24|32|40|48|56|64|80|96|112|128|144|160) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                16000|22050|24000)
                    case $3 in
                        16|24|32|40|48|56|64|80|96|112|128|160|192|224|256|288|320) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                32000|44100|48000)
                    case $3 in
                        32|40|48|56|64|80|96|112|128|160|192|224|256|320|384|448|512|576|640) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                *) return 1 ;;
            esac
            ;;
        mp3)
            case $2 in
                8000|11025|12000|16000|22050|24000)
                    case $3 in
                        8|16|24|32|40|48|56|64|80|96|112|128|144|160) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                32000|44100|48000)
                    case $3 in
                        32|40|48|56|64|80|96|112|128|160|192|224|256|320) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                *) return 1 ;;
            esac
            ;;
        mp2)
            case $2 in
                16000|22050|24000)
                    case $3 in
                        8|16|24|32|40|48|56|64|80|96|112|128|144|160) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                32000|44100|48000)
                    case $3 in
                        32|48|56|64|80|96|112|128|160|192|224|256|320|384) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                *) return 1 ;;
            esac
            ;;
        mp1)
            case $2 in
                16000|22050|24000)
                    case $3 in
                        32|48|56|64|80|96|112|128|144|160|176|192|224|256) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                32000|44100|48000)
                    case $3 in
                        32|64|96|128|160|192|224|256|288|320|352|384|416|448) : ;;
                        *) return 1 ;;
                    esac
                    ;;
                *) return 1 ;;
            esac
            ;;
        *) return 1 ;;
    esac
}
###############################################################################
sec2time () { #### convert [+-]s[.ms] to [+-]h:m:s[.ms]
    local a b c d p
    [[ ${1%.*} = $1 ]] && a=$1 || d=${1#*.} a=${1%.*}
    [[ ${a:0:1} == [-+] ]] && p=${a:0:1} a=${a#?}
    a=$((10#$a+0))
    if ((a>59)); then
        b=$((a/60))
        a=$(printf "%02d" $((a%60)))
        ((b>59)) && c=$((b/60)) b=$(printf "%02d" $((b%60)))
    fi
    echo $p${c:+$c:}${b:+$b:}$a${d:+.$d}
}
###############################################################################
time2sec () { #### convert [+-]h:m:s[.ms] to [+-]s[.ms]
    local s t d p
    s=0
    [[ ${1%.*} = $1 ]] && t=$1 || d=${1#*.} t=${1%.*}
    [[ ${t:0:1} == [-+] ]] && p=${t:0:1} t=${t#?}
    while [[ $t != ${t#*:} ]]; do
        s=$(((s+10#${t%%:*})*60))
        t=${t#*:}
    done
    echo $p$((s+10#$t))${d:+.$d}
}
###############################################################################
sec2fulltime () { #### convert s[.ms] to hh:mm:ss:ms
    sec2time ${1%.*}.$(($([[ ${1#*.} = $1 ]];echo $?)?10#${1#*.}+0:0)) | \
      awk -F'[:.]' '{for(a=1;a<=4-NF;a++)printf("00:");for(a=1;a<=NF;a++){printf("%s%02d",s,$a);s=":"}}'
}
###############################################################################
debug_line () {
    echo "--DEBUG: [$PROGNAME] $2($1) $(eval echo $(sed -n $1p "$PROGFILE" | sed 's/ |.*//;s/.>.*//;s/</\\\</'))" >>"$output".log
}
###############################################################################
error_line () {
    echo "--DEBUG: [$PROGNAME] $1"
    echo "**ERROR: [$PROGNAME] there has been an error during the execution of the"
    echo "$(printf "%$((12+${#PROGNAME}))s")previous command line, this should not happen"
    echo "possible causes:"
    echo "  0) missing or misspelled input stream"
    echo "  1) the input stream is corrupted"
    echo "       -> try a different input stream"
    echo "  2) one of the options used has triggered a bug present only on your"
    echo "     combination of architecture/compiler/distribution"
    echo "       -> try to recompile MPlayer with a different compiler version or try"
    echo "          another distribution"
    echo "  3) disk full"
    ((SVN)) && echo "  4) one of the options used is not valid or is buggy for your SVN/unsupported" && echo "     version of MPlayer/MEncoder" && \
      echo "       -> check MPlayer's man page and/or try a supported release of MPlayer"
    echo
    echo "submit a bugreport if you think this is a bug in $PROGNAME"
    exec >&1- >&2-
    exit $ret
}
###############################################################################
check_mencoder_abr () {
    local codec lib ASR
    codec=([4]=mp2 mp3 ac3 mp2 aac)
    lib=([4]=libavcodec libavcodec libavcodec lib${TOOLAME} libfaac)
    ASR=${encode%%:*}
    check_abr ${codec[ASR]} $1 $2 || ! echo "**ERROR: [$PROGNAME] ${lib[ASR]} does not support $2 kbps / $1 Hz for ${codec[ASR]}" || exit 1
}
###############################################################################
is_film2pal () {
    local a
    a=$(mplayer -nocache "$@" -vo null -nosound -benchmark -frames 60 -noquiet 2>/dev/null | tr '\015' '\012' | tail | \
      awk -F/ '$1~/^V:/{s=$1;t=$2}END{match(s,/ [0-9]+$/);n=substr(s,RSTART+1);match(t,/[0-9]+ /);m=substr(t,RSTART,RLENGTH-1);r=n/m;if(r>1.02)print "24"}')
    [[ $a ]] && a=$(mplayer -nocache "$@" -vo null -nosound -benchmark -frames 1500 -noquiet 2>/dev/null | tr '\015' '\012' | tail | \
      awk -F/ '$1~/^V:/{s=$1;t=$2}END{match(s,/ [0-9]+$/);n=substr(s,RSTART+1);match(t,/[0-9]+ /);m=substr(t,RSTART,RLENGTH-1);r=n/m;
      if(r>1.042)print "24000/1001fps";if(r<1.042&&r>1.041)print "24fps"}')
    echo "$a"
}
###############################################################################
get_aspect () {
    mplayer -vc -mpegpes, -vo null -ao null -nocache -frames 4 "$@" 2>/dev/null | awk '/^Movie-Aspect is/{a=$3}END{sub(/:.*/,"",a);print a}'
}
###############################################################################
get_chapters () {
    mp_identify "$@" | awk '/^There are .* chapters in this DVD title/{print $3}'
}
###############################################################################
split_chapters () {
    #### split the chapterlist over the MPEGs in order to be used by dvdauthor
    #### make DVDAUTHORARG for dvdauthor command line
    #### make DVDTAUTHORARG for thumbs
    #### make DVDSUBAUTHORARG for animated thumbs
    local CHAPTERLIST imglen i mpg vobchapter t chaptime a nextvobsubchapter vobsubchapter TMP vobtchapter
    unset DVDCHAPTERS DVDMPEGS DVDSUBCHAPTERS DVDTCHAPTERS
    if (($#==2 && !TANIM)); then
        DVDCHAPTERS=("$1")
        DVDMPEGS=("$2")
        if ((${#thumboffset[*]})); then
            CHAPTERLIST=(${1//,/ })
            vobtchapter=
            #thumbmaxdur=$(video_duration $OPTIONS "$2")
            thumbmaxdur=$(id_find ID_LENGTH "$2")
            for ((a=0;a<${#CHAPTERLIST[*]};a++)); do
                vobtchapter=${vobtchapter:+$vobtchapter,}$(awk -v c=$(time2sec ${CHAPTERLIST[a]}) -v nc=$(time2sec ${CHAPTERLIST[a+1]:-$thumbmaxdur}) \
                  -v o=${thumboffset[a]:-0} -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log \
                  'BEGIN{if(o+c>=nc){printf "++ WARN: [menuthumboffset] skipping offset %d [%s]\n",'$((a+1))',o >>logfile;o=0};printf "%.3f",o+c}')
            done
            DVDTCHAPTERS=( "$vobtchapter" )
        else
            DVDTCHAPTERS=("$1")
        fi
    else
        if [[ ! $1 ]]; then
            shift
            DVDMPEGS=("$@")
        else
            CHAPTERLIST=(${1//,/ })
            shift
            imglen=0
            i=0
            for mpg ; do 
                vobchapter=
                vobtchapter=
                vobsubchapter=
                nextvobsubchapter=
                if ((i<${#CHAPTERLIST[*]})); then
                    t=$(video_duration $OPTIONS "$mpg")
                    chaptime=$(time2sec ${CHAPTERLIST[i]})
                    if [[ $nextvobsubchapter && $TANIM -gt 0 ]]; then
                        TMP=(${nextvobsubchapter//,/ })
                        nextvobsubchapter=
                        for ((a=0;a<${#TMP[*]};a++)); do
                            if awk -v c=${TMP[a]} -v t=$t 'BEGIN{if(c>t)exit 1}' ; then
                                vobsubchapter=${vobsubchapter:+$vobsubchapter,}${TMP[a]}
                            else
                                nextvobsubchapter=${nextvobsubchapter:+$nextvobsubchapter,}$(awk -v c=${TMP[a]} -v t=$t 'BEGIN{printf "%.3f",c-t}')
                            fi
                        done
                    fi
                    while awk -v c=$chaptime -v i=$imglen -v t=$t 'BEGIN{if(c+.0004>=i+t)exit 1}' ; do
                        vobchapter=${vobchapter:+$vobchapter,}$(awk -v a=$chaptime -v b=$imglen 'BEGIN{printf "%.3f",a-b}')
                        vobtchapter=${vobtchapter:+$vobtchapter,}$(awk -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log -v o=${thumboffset[i]:-0} \
                          -v c=$chaptime -v t=$t -v i=$imglen -v nc=$(time2sec ${CHAPTERLIST[i+1]:-0}) 'BEGIN{if(!nc)nc=i+t;if(o+c>=nc||o+c>=t+i)
                          {printf "++ WARN: [menuthumboffset] skipping offset %d [%s]\n",'$((i+1))',o >>logfile;o=0};printf "%.3f",c+o-i}')
                        if ((TANIM)); then
                            ((i<${#CHAPTERLIST[*]}-1)) && endSubChap=$(time2sec ${CHAPTERLIST[i+1]}) || \
                              endSubChap=$(awk -v i=$imglen -v t=$t 'BEGIN{printf("%.3f",i+t)}')
                            for ((a=0;a<TPART;a++)); do
                                if awk -v c=$chaptime -v e=$endSubChap -v p=$TPART -v a=$a -v i=$imglen -v t=$t 'BEGIN{if(c+a*(e-c)/p>i+t)exit 1}' ; then
                                    vobsubchapter=${vobsubchapter:+$vobsubchapter,}$(awk -v c=$chaptime -v e=$endSubChap -v p=$TPART -v a=$a -v i=$imglen \
                                      'BEGIN{printf "%.3f",c-i+a*(e-c)/p}')
                                else
                                    nextvobsubchapter=${nextvobsubchapter:+$nextvobsubchapter,}$(awk -v c=$chaptime -v e=$endSubChap -v p=$TPART -v a=$a \
                                      -v i=$imglen -v t=$t 'BEGIN{printf "%.3f",c-i-t+a*(e-c)/p}')
                                fi
                            done
                        fi
                        ((++i==${#CHAPTERLIST[*]})) && break
                        chaptime=$(time2sec ${CHAPTERLIST[i]})
                    done
                    imglen=$(awk -v i=$imglen -v t=$t 'BEGIN{printf("%.3f",i+t)}')
                fi
                DVDCHAPTERS[${#DVDCHAPTERS[*]}]=$vobchapter
                DVDTCHAPTERS[${#DVDTCHAPTERS[*]}]=$vobtchapter
                DVDMPEGS[${#DVDMPEGS[*]}]=$mpg
                ((TANIM)) && DVDSUBCHAPTERS[${#DVDSUBCHAPTERS[*]}]=$vobsubchapter
            done
        fi
    fi
    unset DVDAUTHORARG DVDSUBAUTHORARG DVDTAUTHORARG
    for ((a=0;a<${#DVDMPEGS[*]};a++)); do
        DVDAUTHORARG=( "${DVDAUTHORARG[@]}" ${DVDCHAPTERS[a]:+-c ${DVDCHAPTERS[a]}} "${DVDMPEGS[a]}" )
        DVDTAUTHORARG=( "${DVDTAUTHORARG[@]}" ${DVDTCHAPTERS[a]:+-c ${DVDTCHAPTERS[a]}} "${DVDMPEGS[a]}" )
        ((TANIM)) && DVDSUBAUTHORARG=( "${DVDSUBAUTHORARG[@]}" ${DVDSUBCHAPTERS[a]:+-c ${DVDSUBCHAPTERS[a]}} "${DVDMPEGS[a]}" )
    done
}
###############################################################################
burn_iso () {
    local ARG OPT
    ARG=()
    while (($#)) ; do
        file_size "$1"
        ((fsize>2147483646&&burniso==1)) && echo "**ERROR: [$PROGNAME] the size of file $1 is 2GB or bigger; use -burnudf instead of -burniso" && exit 1
        ARG[${#ARG[*]}]="/=$1"
        shift
    done
    if [[ $blank ]]; then
        OPT=( -Z $dvdburndevice -V "${output:0:32}" -A "$PROGNAME-$VERSION" )
    else
        OPT=( -M $dvdburndevice )
    fi
    [[ $burniso = 2 ]] && OPT=( "${OPT[@]}" -udf )
    if [[ ! $nowait ]]; then
        echo "please insert a dvd in your dvdwriter, press any key to start burning:"
        read -n 1 i
    fi
    ((DEBUG)) && debug_line $((LINENO+2)) growisofs
    filter_log growisofs '.*% done.*'
    growisofs ${overburn:+-overburn} "${OPT[@]}" -r -J -U -D -graft-points "${ARG[@]}" &>"$output".fifo
    ret=$? ; (( ret )) && exit $ret
}
###############################################################################
split_sub_opt () {
    echo "$1" | awk -v i=$2 -F: '{printf "%s",$i}'
}
###############################################################################
split_ocrsub_opt () {
    OCRSUBOPT=$(split_sub_opt "${ocropts}" $1)
    [[ $OCRSUBOPT ]] || ! OCRSUBOPT=${OCRDEF[$1*2-1]}
}
###############################################################################
split_txtsub_opt () {
    TXTSUBOPT=$(split_sub_opt "${txtsubopts[$1]}" $2)
    [[ $TXTSUBOPT ]]
}
###############################################################################
skip_encode () {
    for a in avi sub ocr mpv mpa mpg spl sbm ; do
        status_bit $a set
    done
}
###############################################################################
swap_lpcm_channels () {
    case $(id_find ID_AUDIO_NCH "$@") in
        6|5)
            case ${mpegchannels:-2} in
                4) echo "$(echo "${AF:--af }${AF:+,}" | sed 's/channels=[^,]*,//')channels=4:4:0:0:1:1:2:2:4:3" ;;
                3) echo "$(echo "${AF:--af }${AF:+,}" | sed 's/channels=[^,]*,//')channels=3:3:0:0:1:1:4:2" ;;
            esac
            ;;
        4)
            case ${mpegchannels:-2} in
                3) echo "$(echo "${AF:--af }${AF:+,}" | sed 's/channels=[^,]*,//')channels=3:3:0:0:1:1:3:2" ;;
            esac
            ;;
    esac
}
###############################################################################
fix_channel_order () {
   local ch
   [[ $mpeg && $mpegchannels ]] && ch=$mpegchannels
   [[ ! $mpeg && $channels ]] && ch=$channels
   case ${encode%%:*} in
       6)
           case $(id_find ID_AUDIO_CODEC "${MPLAYERINFO[@]}" $AID) in
               a52|dvdpcm)
                   #ch=$(mplayer -nocache -frames 0 -v -ao null -vo null "$@" 2>/dev/null | sed '/^Opening audio decode/,/^AUDIO:/!d;s/\r//g' | \
                   #  awk '$1=="AC3:"{c=$2;print int(c)+(c-int(c))*10}')
                   case ${ch:-2} in
                       6) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=6:6:0:0:4:1:1:2:2:3:3:4:5:5 ;;
                       5) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=5:5:0:0:4:1:1:2:2:3:3:4 ;;
                       3) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=3:3:0:0:2:1:1:2 ;;
                   esac
                   ;;
               faad)
                   case ${ch:-2} in
                       6) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=6:6:1:0:0:1:2:2:3:3:4:4:5:5 ;;
                       5) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=5:5:1:0:0:1:2:2:3:3:4:4 ;;
                       4) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=4:4:1:0:2:1:3:2:0:3 ;;
                       3) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=3:3:0:0:2:1:1:2 ;;
                   esac
                   ;;
           esac
           ;;
       8)
           case $(id_find ID_AUDIO_CODEC "${MPLAYERINFO[@]}" $AID) in
               a52|dvdpcm)
                   case ${ch:-2} in
                       6) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=6:6:0:1:1:2:2:3:3:4:4:0:5:5 ;;
                       5) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=5:5:0:1:1:2:2:3:3:4:4:0 ;;
                       4) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=4:4:0:1:1:2:2:3:3:0 ;;
                       3) F=$(echo "${F:--af }${F:+,}" | sed 's/channels=[^,]*,//')channels=3:3:0:1:1:2:2:0 ;; # guess
                   esac
                   ;;
           esac
           ;;
   esac 
}
###############################################################################
subcopy_id () {
    if [[ $vobsubsrc ]]; then
        addsub=( $(awk '/index:/{print $NF}' <"$vobsubsrc".idx | sort -n) )
    else
        addsub=( $(awk '/==> Found subtitle:/{print $NF}' <"$output".log | sort -n) )
        ((${#addsub[*]})) || addsub=( $(awk '/==> Found \(currently unsupported\) svcd subtitle:/{print $NF}' <"$output".log | sort -n) )
    fi
}
###############################################################################
dump_sub_stream () {
    CLEAN[${#CLEAN[*]}]="$output".dump
    if [[ $vobsubsrc ]]; then
        rm -f "$output".dump
        ln -s "$vobsubsrc".sub "$output".dump
    else
        if [[ $1 ]]; then
            # HASRAW
            mkfifo "$output".dump
            spuunmux -o "$output" -r -s 32 "$output".dump &
            command mplayer "${SUBDUMP[@]}" -dumpstream -dumpfile "$output".dump
            if (($?)) ; then
                do_log "++ WARN: [$PROGNAME] triggered a bug during subtitle demux. Using a workaround."
                stty sane
                rm "$output".dump
                mplayer "${SUBDUMP[@]}" -dumpstream -dumpfile "$output".dump
                spuunmux -o "$output" -r -s 32 "$output".dump
            fi
            rm "$output".dump
            mv "$output".spu "$output".dump
        else
            ((DEBUG)) && debug_line $((LINENO+1)) dumpstream
            mplayer "${SUBDUMP[@]}" -dumpstream -dumpfile "$output".dump
        fi
    fi
    CLEAN[${#CLEAN[*]}]="$output".rgb
    CLEAN[${#CLEAN[*]}]="$output"_pal.idx
    CLEAN[${#CLEAN[*]}]="$output"_pal.sub
    if [[ $vobsubsrc ]]; then
        ln -s "$vobsubsrc".idx "$output"_pal.idx
        touch "$output"_pal.sub
    else
        mencoder -ovc copy -o /dev/null -sid ${addsub[0]} "${MENCODERARG[@]}" -nosound -frames 0 -vobsubout "${output}"_pal
    fi
    grep "^palette:" "${output}"_pal.idx | cut -f 2 -d: | tr -d ' ' | tr ',' '\012' >"$output".rgb
    rm "${output}"_pal.{idx,sub}
    unset CLEAN[${#CLEAN[*]}-1]
    unset CLEAN[${#CLEAN[*]}-1]
}
###############################################################################
sublang () {
    local lang
    if [[ ${addsla[$1]} ]]; then
        lang=${addsla[$1]}
    else
        [[ ! $vobsubsrc ]] && lang=$(sed -n '/subtitle ( sid ):/!d;/sid ): '"${addsub[$1]} "'/s/.*language: //p' "$output".log) || \
          lang=$(sed -n '/^id/!d;s/\([0-9]\)[^0-9]*$/\1/;/^id.*'" ${addsub[$1]}\$"'/s/^id: \([^,]*\),.*/\1/p' "$vobsubsrc".idx)
    fi
    [[ ! $lang || $lang = unknown || $lang = xx ]] && lang=nolang
    echo $lang
}
###############################################################################
#### menu functions and variables
#### dvd menu are inspired by Wolfgang Wershofen's dvdwizard
###############################################################################
rgba () {
    ((iver>625)) && awk -v a=$1 -v b=$2 -v c=$3 -v d=$4 'BEGIN{printf("rgba(%s,%s,%s,%.3f)",a,b,c,1-d/255)}' || echo -n "rgba($1,$2,$3,$4)"
}
[[ $menu || ${#TITLESET[*]} -gt 0 ]] && iver=$(convert -version | awk '/^Version:/{gsub(/\./,"",$3); print $3}')
[[ $videonorm = n ]] && encFrameRate=29.97 || encFrameRate=25
offset=5
if [[ $frameformat = DVD ]]; then
    TOTOVER=2
else
    TANIM=0 # no animated thumbnail
    TOTOVER=0
fi
((TOTOVER&&MASP==2)) && MENU_H_RES_PS=1024 || MENU_H_RES_PS=768
MENU_H_RES=$((TOTOVER&&MASP?1024:MENU_H_RES_PS))
((TOTOVER&&MASP==2)) && MENU_V_RES_LB=768 || MENU_V_RES_LB=576
MENU_V_RES=576
TVOSX=$(((!MENUOS?76:0)+(TOTOVER&&MASP?(MENU_H_RES-MENU_H_RES_PS)/2:0)))
TVOSY=$((!MENUOS?56:0))
LEFTPANELW=150
TITLESIZE=48
MENUSIZE=20
HEADERSIZE=24
STEP=3
MENUSTEP=10
overlayc=( white red yellow )
overlayt=( $(rgba 255 255 255 48) $(rgba 255 0 0 150) $(rgba 255 255 0 150) )
MenuFr=1
gpp=6 #gallery per page ExtraMenu
((TSALL)) && TSETB=0
((!TANIM)) && TPART=1
((iver==557)) && ICOL="-colors 2" || ICOL=

languages=(-unknown nolang-unknown AA-Afar AB-Abkhazian AF-Afrikaans AM-Amharic AR-Arabic AS-Assamese AY-Aymara AZ-Azerbaijani BA-Bashkir BE-Byelorussian BG-Bulgarian BH-Bihari BI-Bislama BN-Bengali BO-Tibetan BR-Breton CA-Catalan CO-Corsican CS-Czech CY-Welsh DA-Dansk DE-Deutsch DZ-Bhutani EL-Greek EN-English EO-Esperanto ES-Espanol ET-Estonian EU-Basque FA-Persian FI-Suomi FJ-Fiji FO-Faroese FR-Francais FY-Frisian GA-Gaelic GD-ScotsGaelic GL-Galician GN-Guarani GU-Gujarati HA-Hausa HE-Hebrew HI-Hindi HR-Hrvatski HU-Magyar HY-Armenian IA-Interlingua ID-Indonesian IE-Interlingue IK-Inupiak IN-Indonesian IS-Islenska IT-Italiano IU-Inuktitut IW-Hebrew JA-Japanese JI-Yiddish JW-Javanese KA-Georgian KK-Kazakh KL-Greenlandic KM-Cambodian KN-Kannada KO-Korean KS-Kashmiri KU-Kurdish KY-Kirghiz LA-Latin LN-Lingala LO-Laothian LT-Lithuanian LV-LatvianLettish MG-Malagasy MI-Maori MK-Macedonian ML-Malayalam MN-Mongolian MO-Moldavian MR-Marathi MS-Malay MT-Maltese MY-Burmese NA-Nauru NE-Nepali NL-Nederlands NO-Norsk OC-Occitan OM-Oromo OR-Oriya PA-Punjabi PL-Polish PS-PashtoPushto PT-Portugues QU-Quechua RM-Rhaeto-Romance RN-Kirundi RO-Romanian RU-Russian RW-Kinyarwanda SA-Sanskrit SD-Sindhi SG-Sangho SH-Serbo-Croatian SI-Sinhalese SK-Slovak SL-Slovenian SM-Samoan SN-Shona SO-Somali SQ-Albanian SR-Serbian SS-Siswati ST-Sesotho SU-Sundanese SV-Svenska SW-Swahili TA-Tamil TE-Telugu TG-Tajik TH-Thai TI-Tigrinya TK-Turkmen TL-Tagalog TN-Setswana TO-Tonga TR-Turkish TS-Tsonga TT-Tatar TW-Twi UG-Uighur UK-Ukrainian UR-Urdu UZ-Uzbek VI-Vietnamese VO-Volapuk WO-Wolof XH-Xhosa YI-Yiddish YO-Yoruba ZA-Zhuang ZH-Chinese ZU-Zulu)
###############################################################################
Menu_Err () {
    do_log "**ERROR: failure during menu creation (FUNCTION: $1 LINE: $2)" >&2
    MENUERR=$((++MENUERR))
}
###############################################################################
Menu_Runfunc () { # function arguments
    if ((menufix)); then
        local s a
        a=0
        until s=$("$@" 2>/dev/null) ; do
            sleep 1
            ((++a>MAXFIX)) && do_log "**ERROR: [menufix] $FUNCNAME: too many failures for function $1" >&2 && break
        done
        echo "$s"
    else
        "$@"
    fi
}
###############################################################################
Menu_RunfuncPic () { # old|new file lineno function arguments
    local save pic line
    [[ $1 = old ]] && save=1 || save=0
    pic=$2
    line=$3
    shift 3
    if ((menufix)); then
        local a
        if ((save)); then
            a=0
            cp "$pic" "$output"_pic
            until identify &>/dev/null "$output"_pic ; do
                sleep 1
                cp "$pic" "$output"_pic
                ((++a>MAXFIX)) && do_log "**ERROR: [menufix] $FUNCNAME: source pic for function $1 line $2 already corrupted" && break
            done
            ((a&&a<MAXFIX+1)) && do_log "++ WARN: [menufix] $FUNCNAME: function $1 line $2: saved backup pic after $((a+1)) try"
        fi
        a=0
        until "$@" && identify &>/dev/null "$pic" ; do
            sleep 1
            ((++a>MAXFIX)) && do_log "**ERROR: [menufix] $FUNCNAME: too many failures for function $1 line $line" && break
            ((save)) && cp "$output"_pic "$pic"
        done
        ((a&&a<MAXFIX+1)) && do_log "++ WARN: [menufix] $FUNCNAME: success at line $line after $(($a+1)) try" || true
    else
        "$@"
    fi
}
###############################################################################
Menu_MakeSilence () { # outfile
    ####                 48kHz 2B 2ch      2s
    dd if=/dev/zero bs=$((48000*2*2)) count=2 2>/dev/null | \
      mplayer -demuxer 20 -rawaudio format=0x1:rate=48000 - -nocache -ao pcm:waveheader:file=/dev/fd/4 4>&1 >&2 | mp2enc -b 128 -r 48000 -o "$1"
}
###############################################################################
Menu_DrawArg1 () { # gravity X Y text
    local signX signY
    if ((iver<610)); then
        IMDraw1="-draw"
        IMDraw2="${1:+gravity $1} text $2,$3 '$(echo "$4" | sed "s/'/\\\'/g")'"
    else
        [[ ${2:0:1} == [0-9] ]] && signX=+ || signX=
        [[ ${3:0:1} == [0-9] ]] && signY=+ || signY=
        IMDraw1="${1:+-gravity $1} -annotate $signX$2$signY$3"
        IMDraw2="$4"
    fi
}
###############################################################################
Menu_DrawArg2 () { # gravity X1 Y1 X2 Y2 text
    Menu_DrawArg1 "$1" $4 $5 "$6"
    IMDraw3="$IMDraw1"
    IMDraw4="$IMDraw2"
    Menu_DrawArg1 "$1" $2 $3 "$6"
}
###############################################################################
Menu_MakeBg () { # outfile
    Menu_DrawArg1 southeast $((TVOSX+5)) $((TVOSY-(1-MENUOS)*MENUSIZE+(iver<600?3*MENUSIZE/2:0))) "$PROGNAME $VERSION"
    if [[ $menubg ]]; then
        #### use input picture
        if [[ $menubgopt = 1 ]]; then
            convert -geometry ${MENU_H_RES}x${MENU_V_RES} "$menubg" "$1"
            convert -size ${MENU_H_RES}x${MENU_V_RES} xc:black png:- | composite -compose Over -gravity center "$1" - "$1"
        else
            convert -scale ${MENU_H_RES}x${MENU_V_RES}! -pointsize $MENUSIZE -fill white $IMDraw1 "$IMDraw2" "$menubg" "$1"
        fi
    else
        #### create a background
        convert -size ${MENU_H_RES}x${MENU_V_RES} -depth 8 gradient:white-darkblue -pointsize $MENUSIZE -implode 3 -swirl $((5*270)) -implode 1 \
          -fill white $IMDraw1 "$IMDraw2" +shade 50x50 "$1"
          #-fill none -stroke green -draw "rectangle $TVOSX,$TVOSY $((MENU_H_RES-TVOSX)),$((MENU_V_RES-TVOSY))" \
    fi
}
###############################################################################
Menu_Getsize () { # pic [h|v]
    identify "$1" | awk -v i="$2" '{match($0,/ [0-9]+x[0-9]+/) ; s=substr($0,RSTART+1,RLENGTH-1) ;
      if (i=="h") s=substr(s,1,index(s,"x")-1) ; if (i=="v") s=substr(s,index(s,"x")+1) ; print s}'
}
Menu_Picsize () { # pic [h|v]
    Menu_Runfunc Menu_Getsize "$1" $2
}
###############################################################################
Menu_MakeThumb () { # thumbwidth nFrames
    # split_chapters must be called before Menu_MakeThumb
    local a b aspect thumbheight nChap VO FRAME ARG nFrames Z found choff
    dvddirdel -o "$output"
    ((TANIM)) && ARG=( "${DVDSUBAUTHORARG[@]}" ) || ARG=( "${DVDTAUTHORARG[@]}" )
    #### use dvdauthor to make an image with the chapters
    if ((TOTOVER)); then
        dvdauthor $DVDAUTHOROPT -o "$output" -t "${ARG[@]}" || Menu_Err $FUNCNAME $LINENO
    else
        #### for a VCD/SVCD the audio is usually wrong (44100kHz), filtering out the WARN messages
        mkdir "$output"
        #### n is the same when Menu_MakeVtsChapter is called
        if ((iter)); then
            for ((a=0;a<${#DVDMPEGS[*]};a++)); do
                "$PROGFILE" -norc -o "$output"/"${output##*/}"$(printf "%02d" $a) -mpeg -dvd "${DVDMPEGS[a]}" -encode 0:0:1 -mpegonly -noshowlog -nosplit
            done
            dvdauthor $DVDAUTHOROPT -o "$output" -t "$output"/"${output##*/}"*.mpg 2>&1 | \
              grep -v -e 'WARN: Discontinuity' -e '^WARN: Previous sector' -e '^WARN: Current sector' || Menu_Err $FUNCNAME $LINENO
        else
            "$PROGFILE" -norc -o "$output"/"${output##*/}" -mpeg -dvd "${DVDMPEGS[n]}" -encode 0:0:1 -mpegonly -noshowlog -nosplit
            dvdauthor $DVDAUTHOROPT -o "$output" -t -c ${DVDCHAPTERS[n]:-0} "$output"/"${output##*/}".mpg 2>&1 | \
              grep -v -e 'WARN: Discontinuity' -e '^WARN: Previous sector' -e '^WARN: Current sector' || Menu_Err $FUNCNAME $LINENO
        fi
        rm -r "$output"/"${output##*/}"*
    fi
    dvdauthor -o "$output" -T || Menu_Err $FUNCNAME $LINENO
    pushd "$output" >/dev/null
    aspect=$(get_aspect dvd://1 -dvd-device . )
    [[ ${aspect:0:9} = undefined ]] && aspect=$(awk -v a=$H_RES -v b=$V_RES 'BEGIN{printf("%f",a/b)}')
    thumbheight=$(awk -v a=$aspect -v b=$1 'BEGIN{printf("%.0f",b/a)}')
    nChap=$(get_chapters dvd://1 -dvd-device . )
    [[ ${thumboffset[0]} ]] && choff=$(echo $addchapter, | cut -f2 -d,) && \
      awk -v o=${thumboffset[0]} -v nc=$(time2sec ${choff:-$thumbmaxdur}) 'BEGIN{if(!o||o>=nc)exit 1}' && nChap=$((--nChap)) && choff=1 || choff=0
    case $TFMT in
        jpg) VO=jpeg ;;
        png) VO="${TFMT}:z=1" ;;
        pnm) VO="${TFMT}" TFMT=ppm ;;
        *) VO="${TFMT}" ;;
    esac
    #### extract all the thumbnails with mplayer
    for ((a=1;a<=nChap;a++)); do
        ((TMODE!=1 && !TKFRM && !TANIM)) && FRAME="framestep=I," || FRAME=
        ((TMODE==1 && !TANIM )) && nFrames=1 || nFrames=$2
        mplayer -nocache -benchmark -vo $VO -nosound -vf ${FRAME}scale=$1:$thumbheight -dvd-device . dvd://1 -chapter $((a+choff)) -frames $((nFrames+1))
        if ((TMODE==1||TANIM)); then
            found=$(ls 0000????.$TFMT | awk 'END{print NR}')
            if ((found<nFrames)); then
                for ((b=found+1;b<=nFrames;b++)); do
                    cp $(printf "%08d" $found).$TFMT $(printf "%08d" $b).$TFMT
                done
            fi
            for ((b=1;b<=nFrames;b++)); do
                mv $(printf "%08d" $b).$TFMT ../"${output##*/}".chap$(((a-1)/TPART+1)).frame$((b+((a-1)%TPART)*$2)).$TFMT #if TPART==1 chap$a.frame$b
            done
        else
            if ((TMODE)); then
                mv $(ls 00000???.$TFMT | tail -1) ../"${output##*/}".chap$a.frame1.$TFMT
            else
                if [[ $TFMT = ppm || $TFMT = tga ]]; then
                    gzip -1 00000???.$TFMT
                    gzip -dc $(ls -l 00000???.$TFMT.gz | awk '{if(m<$5){m=$5;f=$9}}END{print f}') >../"${output##*/}".chap$a.frame1.$TFMT
                else
                    mv $(ls -l 00000???.$TFMT | awk '{if(m<$5){m=$5;f=$9}}END{print f}') ../"${output##*/}".chap$a.frame1.$TFMT
                fi
            fi
            rm -f 00000???.$TFMT{,.gz}
        fi
    done
    popd >/dev/null
    ((!TOTOVER)) && dvddirdel -o "$output"
}
###############################################################################
Menu_Gettextsize () { # text pointsize h|v
    Menu_DrawArg1 center 0 0 "$1"
    convert -size ${MENU_H_RES}x${MENU_V_RES} xc:black -pointsize $2 -fill red -stroke white $IMDraw1 "$IMDraw2" -trim png:- | Menu_Picsize - $3
}
Menu_Titlesize () { # text pointsize h|v
    Menu_Runfunc Menu_Gettextsize "$1" $2 $3
}
###############################################################################
Menu_FormatTitle () { # title pointsize maxwidth maxheight
    local widthtitle titletxt a b TITLEWORDS
    TITLEWORDS=( $1 )
    widthtitle=$(Menu_Titlesize "${TITLEWORDS[*]}" $2 h)
    while ((widthtitle > $3)); do
        for ((a=0;a<${#TITLEWORDS[*]};a++)); do
            if (( $(Menu_Titlesize "$titletxt${TITLEWORDS[a]}" $2 h) > $3)); then
                if ((!a)); then
                    titletxt="$titletxt${TITLEWORDS[a++]}"
                    titletxt=${titletxt%?}
                    while (( $(Menu_Titlesize "$titletxt" $2 h) > $3)); do
                        titletxt=${titletxt%?}
                    done
                else
                    titletxt=${titletxt% }
                fi
                titletxt="${titletxt}\\n"
                for ((b=0;b<a;b++)) ; do
                    unset TITLEWORDS[b]
                done
                TITLEWORDS=( ${TITLEWORDS[*]} )
                break
            fi
            titletxt="$titletxt${TITLEWORDS[a]} "
        done
        (($(Menu_Titlesize "$titletxt${TITLEWORDS[*]}" $2 v) > $4)) && TITLEWORDS=() && break
        widthtitle=$(Menu_Titlesize "$titletxt${TITLEWORDS[*]}" $2 h)
    done
    echo "$titletxt${TITLEWORDS[*]}"
}
###############################################################################
Menu_MakeTitle () { # titletext outfile
    local txtformat
    txtformat=$(Menu_FormatTitle "$1" $TITLESIZE $((MENU_H_RES-2*TVOSX)) $((MENU_V_RES-2*TVOSY)))
    Menu_DrawArg1 north 0 $((TVOSY+(iver<600?TITLESIZE:0))) "$txtformat"
    mogrify -fill black -stroke white -pointsize $TITLESIZE $IMDraw1 "$IMDraw2" "$2"
}
###############################################################################
Menu_MakeSym () { # n widthlabel outputfile labelText [symbolLetter]
    local bgcolor subcolor DRAW DRAWS OPT1 OPT2 OPT3 OPT4 FILL X Y V H S T CHAN
    bgcolor=$(rgba 128 192 255 255)
    subcolor=white
    OPT1="-pointsize 34 -size 45x45"
    OPT2="-strokewidth 2 -fill $bgcolor"
    OPT3="-size $(($2+50))x45"
    OPT4="-pointsize $MENUSIZE -fill ${overlayc[$1]}"
    FILL="-fill ${overlayc[$1]}"
    ((iver>626)) && CHAN="-channel RGBA" || CHAN=
    case $5 in
        pl)
            DRAW="polygon 14,11 36,22 14,33"
            DRAWS="polygon 15,12 37,23 15,34"
            ;;
        up)
            DRAW="rectangle 21,33 23,11 polygon 23,12 26,18 18,18 21,12"
            DRAWS="rectangle 22,34 24,12 polygon 24,13 27,19 19,19 22,13"
            ;;
        st)
            DRAW="rectangle 15,29 29,15"
            DRAWS="rectangle 16,30 30,16"
            ;;
        re)
            FILL=
            DRAW="ellipse 22,22 10,8 -140,140 polygon 14,14 14,18 18,18"
            DRAWS="ellipse 23,23 10,8 -140,140 polygon 15,15 15,19 19,19"
            ;;
        pr)
            FILL=
            X=24 Y=22 V=7 H=6 S=6 T=4
            DRAW="line $((X+H-S)),$((Y-V)) $((X-S)),$Y line $((X+H-S)),$((Y+V)) $((X-S)),$Y"
            DRAW="$DRAW line $((X+H)),$((Y-V)) $X,$Y line $((X+H)),$((Y+V)) $X,$Y"
            DRAW="$DRAW line $((X-S-T)),$((Y-V)) $((X-S-T)),$((Y+V)) "
            X=25 Y=23
            DRAWS="line $((X+H-S)),$((Y-V)) $((X-S)),$Y line $((X+H-S)),$((Y+V)) $((X-S)),$Y"
            DRAWS="$DRAWS line $((X+H)),$((Y-V)) $X,$Y line $((X+H)),$((Y+V)) $X,$Y"
            DRAWS="$DRAWS line $((X-S-T)),$((Y-V)) $((X-S-T)),$((Y+V)) "
            ;;
        ne)
            FILL=
            X=20 Y=22 V=7 H=6 S=6 T=4
            DRAW="line $((X-H+S)),$((Y-V)) $((X+S)),$Y line $((X-H+S)),$((Y+V)) $((X+S)),$Y"
            DRAW="$DRAW line $((X-H)),$((Y-V)) $X,$Y line $((X-H)),$((Y+V)) $X,$Y"
            DRAW="$DRAW line $((X+S+T)),$((Y-V)) $((X+S+T)),$((Y+V)) "
            X=21 Y=23
            DRAWS="line $((X-H+S)),$((Y-V)) $((X+S)),$Y line $((X-H+S)),$((Y+V)) $((X+S)),$Y"
            DRAWS="$DRAWS line $((X-H)),$((Y-V)) $X,$Y line $((X-H)),$((Y+V)) $X,$Y"
            DRAWS="$DRAWS line $((X+S+T)),$((Y-V)) $((X+S+T)),$((Y+V)) "
            ;;
        *)
            DRAW="gravity center text 0,0 '$5'"
            DRAWS="gravity center text 1,1 '$5'"
            ;;
    esac
    Menu_DrawArg2 east 44 1 45 0 "$4"
    if (($1)); then
        convert +antialias $OPT3 xc:black -stroke red -fill red -draw "roundrectangle 0,0 $(($2+50)),45 10,10" -transparent black $CHAN \
          -fill ${overlayt[$1]} -opaque red "$3" || Menu_Err $FUNCNAME $LINENO
    else
        convert $OPT1 xc:$bgcolor $OPT2 -stroke black -draw "circle 23,23 23,5" -draw "$DRAWS" -stroke ${overlayc[$1]} \
          -draw "circle 22,22 22,4" $FILL -draw "$DRAW" -trim "$3" || Menu_Err $FUNCNAME $LINENO
        convert +antialias $OPT3 xc:$bgcolor $OPT4 -fill black $IMDraw1 "$IMDraw2" $OPT4 $IMDraw3 "$IMDraw4" png:- | \
          composite -compose over -gravity east "$3" - "$3" || Menu_Err $FUNCNAME $LINENO
    fi
}
###############################################################################
Menu_MakePicts () {
    local a b w WPICT BUTTONLIST buttonattr BUTTONFILES lbuttonattr LBUTTONLIST LBUTTONFILES LWPICT
    buttonattr=( pl "?" a s )
    BUTTONLIST=( Play )
    [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && BUTTONLIST=( "${BUTTONLIST[@]}" Chapters ) || BUTTONLIST=( "${BUTTONLIST[@]}" "" )
    [[ $multiaudio && $TOTOVER -gt 0 ]] && BUTTONLIST=( "${BUTTONLIST[@]}" Audio ) || BUTTONLIST=( "${BUTTONLIST[@]}" "" )
    (( ${#addsub[*]}+${#txtsub[*]} && TOTOVER )) && BUTTONLIST=( "${BUTTONLIST[@]}" Subtitles ) || BUTTONLIST=( "${BUTTONLIST[@]}" "" )
    if ((TOTOVER)); then
        lbuttonattr=( re )
        LBUTTONLIST=( Return )
        ((${#MEXTRATXT[*]})) && LBUTTONLIST[${#LBUTTONLIST[*]}]=Extra lbuttonattr[${#lbuttonattr[*]}]=x
        ((dvdtitle)) && LBUTTONLIST[${#LBUTTONLIST[*]}]=Up lbuttonattr[${#lbuttonattr[*]}]=up
    else
        buttonattr=( pr ne "" re )
        BUTTONLIST[3]=Return
        if [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]]; then
            :
        elif [[ $multiaudio ]]; then
            BUTTONLIST[1]=Audio
        elif ((${#addsub[*]}+${#txtsub[*]})); then
            BUTTONLIST[1]=Subtitles
        else
            BUTTONLIST[1]=Info
        fi
    fi
    WPICT=0
    for a in ${BUTTONLIST[*]} ; do
        w=$(Menu_Titlesize "$a" $MENUSIZE h)
        ((WPICT<w)) && WPICT=$w
    done
    if ((TOTOVER)); then
        LWPICT=0
        for a in ${LBUTTONLIST[*]} ; do
            w=$(Menu_Titlesize "$a" $MENUSIZE h)
            ((LWPICT<w)) && LWPICT=$w
        done
    fi
    CLEAN[${#CLEAN[*]}]="$output".empty.png
    convert -size 45x45 xc:none "$output".empty.png || Menu_Err $FUNCNAME $LINENO
    for ((a=0;a<=TOTOVER;a++)); do
        BUTTONFILES=()
        for ((b=0;b<4;b++)); do
            if [[ ${BUTTONLIST[b]} ]]; then
                CLEAN[${#CLEAN[*]}]="$output".${BUTTONLIST[b]}$a.png
                Menu_MakeSym $a $WPICT "$output".${BUTTONLIST[b]}$a.png ${BUTTONLIST[b]} "${buttonattr[b]}"
                BUTTONFILES[${#BUTTONFILES[*]}]="$output".${BUTTONLIST[b]}$a.png
            else
                BUTTONFILES[${#BUTTONFILES[*]}]="$output".empty.png
            fi
        done
        montage -compose copy -background none -geometry $(Menu_Picsize "$output".${BUTTONLIST[0]}$a.png)+5+$STEP -tile 1x4 "${BUTTONFILES[@]}" \
          "$output".bar$a.png || Menu_Err $FUNCNAME $LINENO
        if ((TOTOVER)); then
            LBUTTONFILES=()
            for ((b=${#LBUTTONLIST[*]}-1;b>=0;b--)); do
                CLEAN[${#CLEAN[*]}]="$output".${LBUTTONLIST[b]}$a.png
                Menu_MakeSym $a $LWPICT "$output".${LBUTTONLIST[b]}$a.png ${LBUTTONLIST[b]} "${lbuttonattr[b]}"
                LBUTTONFILES[${#LBUTTONFILES[*]}]="$output".${LBUTTONLIST[b]}$a.png
            done
            montage -compose copy -background none -geometry $(Menu_Picsize "$output".${LBUTTONLIST[0]}$a.png)+5+$STEP -tile 1x${#LBUTTONLIST[*]} \
              "${LBUTTONFILES[@]}" "$output".lbar$a.png || Menu_Err $FUNCNAME $LINENO
            for ((b=0;b<${#LBUTTONLIST[*]};b++)); do
                unset CLEAN[${#CLEAN[*]}-1] && rm "$output".${LBUTTONLIST[b]}$a.png
            done
        fi
        for ((b=3;b>=0;b--)); do
            [[ ${BUTTONLIST[b]} ]] && unset CLEAN[${#CLEAN[*]}-1] && rm "$output".${BUTTONLIST[b]}$a.png
        done
    done
    unset CLEAN[${#CLEAN[*]}-1] && rm "$output".empty.png
}
###############################################################################
Menu_MakeTile () { #height title titlepic bgpic
    local h tileX tileY tbarX tbarY state title barX barY a yOffset lbarX lbarY W
    CLEAN[${#CLEAN[*]}]="$output".tile.png
    #### title thumb
    W=$(($1*(12+(TOTOVER&&MASP==2?4:0))/9))
    convert -size ${W}x$1 xc:$(rgba 255 255 255 48) "$output".tile.png || Menu_Err $FUNCNAME $LINENO
    if ((VTSMBG)); then
        convert -trim -geometry ${W}x "$3" png:- | \
          composite -compose copy -gravity center - "$output".tile.png "$output".tile.png || Menu_Err $FUNCNAME $LINENO
    fi
    tileX=$(($(Menu_Picsize "$output".tile.png h)+40))
    tileY=$(($(Menu_Picsize "$output".tile.png v)+40))
    tbarX=$(($W-30))
    tbarY=$((HEADERSIZE*3/2))
    title=$(Menu_FormatTitle "$2" $HEADERSIZE $((tbarX-20)) $tbarY)
    barX=$(Menu_Picsize "$output".bar0.png h)
    barY=$(Menu_Picsize "$output".bar0.png v)
    if ((TOTOVER)); then
        lbarX=$(Menu_Picsize "$output".lbar0.png h)
        lbarY=$(Menu_Picsize "$output".lbar0.png v)
    fi
    yOffset=$((HEADERSIZE/4+(iver<600?HEADERSIZE:0)))
    for ((a=0;a<=TOTOVER;a++)); do
        CLEAN[${#CLEAN[*]}]="$output".panel$a.png
    done
    #### put on the thumb: the rectangles, titletext, left and right buttons
    Menu_DrawArg2 northwest 16 $((yOffset+1)) 15 $yOffset "$title"
    if ((TOTOVER)); then
        convert -size ${tileX}x${tileY} xc:$(rgba 255 255 255 48) png:- | \
          composite -compose copy -gravity center "$output".tile.png - png:- | \
          convert -fill $(rgba 128 192 255 96) \
          -draw "roundrectangle $offset,$offset $((tbarX+offset)),$((tbarY+offset)) 10,10" \
          -draw "roundrectangle $((tileX-barX-offset)),$((tileY-barY-10-offset)) $((tileX-offset)),$((tileY-offset)) 10,10" \
          -draw "roundrectangle $((offset)),$((tileY-lbarY-10-offset)) $((lbarX+offset)),$((tileY-offset)) 10,10" \
          -fill black -pointsize $HEADERSIZE $IMDraw1 "$IMDraw2" -fill white $IMDraw3 "$IMDraw4" - png:- | \
          composite -compose atop -gravity southeast -geometry +5+10 "$output".bar0.png - png:- | \
          composite -compose atop -gravity southwest -geometry +5+10 "$output".lbar0.png - "$output".panel0.png || Menu_Err $FUNCNAME $LINENO
    else
        convert -size ${tileX}x${tileY} xc:$(rgba 255 255 255 48) png:- | \
          composite -compose copy -gravity center "$output".tile.png - png:- | \
          convert -fill $(rgba 128 192 255 96) \
          -draw "roundrectangle $offset,$offset $((tbarX+offset)),$((tbarY+offset)) 10,10" \
          -draw "roundrectangle $((tileX-barX-offset)),$((tileY-barY-10-offset)) $((tileX-offset)),$((tileY-offset)) 10,10" \
          -fill black -pointsize $HEADERSIZE $IMDraw1 "$IMDraw2" -fill white $IMDraw3 "$IMDraw4" - png:- | \
          composite -compose atop -gravity southeast -geometry +5+10 "$output".bar0.png - "$output".panel0.png || Menu_Err $FUNCNAME $LINENO
    fi
    #### put on the overlay left and right buttons
    for ((a=1;a<=TOTOVER;a++)); do
        convert +antialias -size ${tileX}x${tileY} xc:none png:- | \
          composite -compose copy -gravity southeast -geometry +5+10 "$output".bar$a.png - png:- | \
          composite -compose copy -gravity southwest -geometry +5+10 "$output".lbar$a.png - "$output".panel$a.png || Menu_Err $FUNCNAME $LINENO
    done
    #### put on the background the decorated thumb
    convert -size $((tileX+20))x$((tileY+20)) xc:$(rgba 255 255 255 48) png:- | \
      composite -compose copy -gravity center "$output".panel0.png - png:- | \
      composite -compose over -gravity south -geometry +0+$((TVOSY+3*MENUSIZE/2 )) - "$4" "$output".bg0.png || Menu_Err $FUNCNAME $LINENO
    #### put on the overlay background the overlay thumb
    for ((a=1;a<=TOTOVER;a++)); do
        convert -size ${MENU_H_RES}x${MENU_V_RES} xc:none png:- | \
          composite -compose copy -gravity south -geometry +0+$((TVOSY+3*MENUSIZE/2+10)) "$output".panel$a.png - "$output".bg$a.png || \
          Menu_Err $FUNCNAME $LINENO
        if ((MASP==1)); then
            convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".bg$a.png "$output".bg$((a+3)).png || Menu_Err $FUNCNAME $LINENO
        elif ((MASP==2)); then
            Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".bg$a.png "$output".bg$((a+3)).png || Menu_Err $FUNCNAME $LINENO
        fi
    done
    for ((a=0;a<=TOTOVER;a++)); do
        rm "$output".panel$a.png
        unset CLEAN[${#CLEAN[*]}-1]
    done
    rm "$output".tile.png && unset CLEAN[${#CLEAN[*]}-1]
}
###############################################################################
Menu_DrawText () { # size x y text pic
    Menu_DrawArg2 "" $(($2+1)) $(($3+1)) $2 $3 "$4"
    mogrify -pointsize $1 -fill black $IMDraw1 "$IMDraw2" -fill 'rgb(128,128,196)' $IMDraw3 "$IMDraw4" "$5"
}
###############################################################################
Menu_DrawRect () { # color x y pic
    local polyX1 polyY1 polyX2 polyY3
    polyX1=$2
    polyX2=$((polyX1+(MENUSIZE-5)))
    polyY1=$(($3-(MENUSIZE-5)))
    polyY3=$(($3-3))
    mogrify -fill "$1" -draw "rectangle $polyX1,$polyY1 $polyX2,$polyY3" "$4"
}
###############################################################################
Menu_DrawPolyLine () { # color x y pic [linelenght]
    local polyX1 polyY1 polyX2 polyY2 polyX3 polyY3 lineX1 lineY lineX2
    lineX1=$2
    lineX2=$((lineX1+${5:-120}))
    polyX1=$lineX1
    polyX2=$((lineX1+(MENUSIZE-5)))
    polyX3=$lineX1
    lineY=$(($3+3))
    polyY1=$(($lineY-MENUSIZE))
    polyY3=$(($lineY-4))
    polyY2=$(($lineY-MENUSIZE/2-2))
    mogrify +antialias -fill "$1" -draw "polygon $polyX1,$polyY1 $polyX2,$polyY2 $polyX3,$polyY3" -draw "line $lineX1,$lineY $lineX2,$lineY" "$4"
}
###############################################################################
Menu_MontageThumbs () { # patchsize tilesize outputpic picList
    local patchsize tilesize outfile ret
    patchsize=$1
    tilesize=$2
    outfile=$3
    shift 3
    ret=0
    montage -background transparent -geometry $patchsize -gravity North -tile $tilesize "$@" "$outfile" || ret=$?
    convert -size $((MENU_H_RES-2*TVOSX))x$((MENU_V_RES-2*TVOSY)) xc:transparent png:- | \
      composite -compose Over -gravity NorthEast "$outfile" - "$outfile" || ret=$?
    return $ret
}
###############################################################################
Menu_SmallButton () { # pointsize bgcolor text file l|r nlayer
    local X X1 X2 Y Y1 Y2 SPACE CHAN
    ((iver>626)) && CHAN="-channel RGBA" || CHAN=
    Y1=$((MENU_V_RES-TVOSY-2*$1))
    Y2=$((Y1+5*$1/4))
    Y=$((MENU_V_RES-TVOSY-$1))
    if [[ $5 = l ]]; then
        X1=$TVOSX
        X2=$((TVOSX+$(Menu_Titlesize "${3:0:1} ${3:1:$((${#3}-2))} ${3:$((${#3}-1)):1}" $1 h)))
        SPACE=" "
    else
        X1=$((MENU_H_RES-TVOSX-$(Menu_Titlesize "n$3n" $1 h)))
        X2=$((MENU_H_RES-TVOSX))
        SPACE="  "
    fi
    X=$X1
    if (($6)); then
        mogrify -fill red -draw "rectangle $X1,$Y1 $X2,$Y2" $CHAN -fill $2 -opaque red "$4" || Menu_Err $FUNCNAME $LINENO
    else
        mogrify -fill $2 -draw "rectangle $X1,$Y1 $X2,$Y2" "$4" || Menu_Err $FUNCNAME $LINENO
        Menu_DrawText $1 $X $Y "$SPACE$3" "$4" || Menu_Err $FUNCNAME $LINENO
    fi
}
###############################################################################
Menu_ArrowButton () { # size color file l|r
    local X X1 X2 Y Y1 Y2 Y3 Y4 S
    S=$1
    [[ $4 = l ]] && X=$((TVOSX+S/2)) X1=$((X+S)) X2=$((X+2*S)) || X=$((MENU_H_RES-TVOSX-S/2)) X1=$((X-S)) X2=$((X-2*S))
    Y=$((MENU_V_RES-TVOSY-2*$1))
    Y1=$((Y+S/2)) Y2=$((Y+S/4))
    Y3=$((Y-S/2)) Y4=$((Y-S/4))
    mogrify +antialias -fill $2 -draw "polygon $X,$Y $X1,$Y1 $X1,$Y2 $X2,$Y2 $X2,$Y4 $X1,$Y4 $X1,$Y3" "$3" || Menu_Err $FUNCNAME $LINENO
}
###############################################################################
Menu_UpArrowButton () { # size color file l|r
    local X X1 X2 X3 X4 Y Y1 Y2 S
    S=$1
    [[ $4 = l ]] && X=$((TVOSX+3*S/4)) X1=$((X+3*S/4)) X2=$((X+3*S/2)) X3=$((X+S/4)) X4=$((X+5*S/4)) || \
      X=$((MENU_H_RES-TVOSX-3*S/4)) X1=$((X-3*S/4)) X2=$((X-3*S/2)) X3=$((X-S/4)) X4=$((X-5*S/4))
    Y=$((MENU_V_RES-TVOSY-2*$1))
    Y1=$((Y-S/2))
    Y2=$((Y+S/2))
    mogrify +antialias -fill $2 -draw "polygon $X,$Y $X1,$Y1 $X2,$Y $X4,$Y $X4,$Y2 $X3,$Y2 $X3,$Y" "$3" || Menu_Err $FUNCNAME $LINENO
}
###############################################################################
Menu_MakeButtonXml () { # spumask1 spumask2 outwidth [spumask0]
    echo '<subpictures>'
    echo '  <stream>'
    echo '    <spu start="0" highlight="'"$(xmlchar "$1")"'" select="'"$(xmlchar "$2")"'" force="yes"'
    [[ $4 ]] && echo -n '      ' &&
          echo 'image="'"$(xmlchar "$4")"'"'
    echo '      autoorder="columns" autooutline="infer" outlinewidth="'$3'"'
    echo '      >'
    echo '    </spu>'
    echo '  </stream>'
    echo '</subpictures>'
}
###############################################################################
Menu_MakeMpeg () { # imagein nframes encFrameRate audioin mpegout spumask1 spumask2 outwidth [spumask0] [aspect] [spumask4] [spumask5] [spumask3]
    local p
    Menu_MakeButtonXml "$6" "$7" $8 "$9" >"$output".spu.xml
    [[ $3 = 23.976 || $3 = 24.000 ]] && p="-p" || p=
    if [[ ${11} ]]; then
        Menu_MakeButtonXml "${11}" "${12}" $8 "${13}" >"$output".spu1.xml
        png2yuv -j "$1" -f $3 -b 1 -n $2 -I p | mpeg2enc -a ${10:-2} -n $videonorm $p -f 8 -o /dev/fd/4 4>&1 >&2 | \
          mplex -f 8 -o /dev/stdout /dev/stdin "$4" | spumux -v4 "$output".spu.xml | spumux -s 1 -v4 "$output".spu1.xml > "$5" || Menu_Err $FUNCNAME $LINENO
    else
        png2yuv -j "$1" -f $3 -b 1 -n $2 -I p | mpeg2enc -a ${10:-2} -n $videonorm $p -f 8 -o /dev/fd/4 4>&1 >&2 | \
          mplex -f 8 -o /dev/stdout /dev/stdin "$4" | spumux -v4 "$output".spu.xml > "$5" || Menu_Err $FUNCNAME $LINENO
    fi
}
###############################################################################
Menu_MakeStillMpeg () { # imagein mpegout
    local OPT
    [[ $frameformat = VCD ]] && OPT=6 || OPT=7
    png2yuv -j "$1" -f $encFrameRate -b 1 -n 1 -I p | mpeg2enc -a 2 -n $videonorm -f $OPT -T 120 -o /dev/fd/4 4>&1 >&2 | \
      mplex -f $OPT -o "$2" /dev/stdin || Menu_Err $FUNCNAME $LINENO
}
###############################################################################
Menu_MakeInfo () {
    local W X Y LABEL SF EXTRAARG
    EXTRAARG=()
    CLEAN[${#CLEAN[*]}]="$output".info0.png
    convert -size ${MENU_H_RES}x${MENU_V_RES} -depth 8 gradient:white-darkblue -implode 3 -swirl $((5*270)) -implode 1 "$output".info0.png || \
      Menu_Err $FUNCNAME $LINENO
    ((TOTOVER&&MASP==2)) && SF=sourceforge || SF=sf
    Menu_MakeTitle "created with:\n\n$PROGNAME\nv. $VERSION\n$(date '+%Y-%m-%d')\n\nhttp://encode2mpeg.$SF.net" "$output".info0.png || \
      Menu_Err $FUNCNAME $LINENO
    for ((i=1;i<=TOTOVER;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".info$i.png
        ((MASP)) && CLEAN[${#CLEAN[*]}]="$output".info$((i+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
        convert -size ${MENU_H_RES}x${MENU_V_RES} xc:transparent "$output".info$i.png || Menu_Err $FUNCNAME $LINENO
    done
    ((TOTOVER)) && LABEL=back || LABEL="next >>|"
    W=$(Menu_Titlesize "$LABEL" $MENUSIZE h)
    X=$(((MENU_H_RES-W)/2))
    Y=$((MENU_V_RES-TVOSY-MENUOS*MENUSIZE))
    Menu_DrawText $MENUSIZE $X $Y "$LABEL" "$output".info0.png || Menu_Err $FUNCNAME $LINENO
    mogrify -geometry ${H_STILL}x${V_STILL}! "$output".info0.png || Menu_Err $FUNCNAME $LINENO
    for ((m=1;m<=TOTOVER;m++)); do
        Menu_DrawPolyLine "${overlayc[m]}" $((X-MENUSIZE)) $Y "$output".info$m.png $((W+MENUSIZE)) || Menu_Err $FUNCNAME $LINENO
        if ((MASP==1)); then
            convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".info$m.png "$output".info$((m+3)).png || Menu_Err $FUNCNAME $LINENO
        elif ((MASP==2)); then
            Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".info$m.png "$output".info$((m+3)).png 1 || Menu_Err $FUNCNAME $LINENO
        fi
    done
    [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".info.mpeg
    if ((TOTOVER)); then
        mogrify +antialias $ICOL -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".info[12].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
        Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".info0.png $MenuFr $encFrameRate "$output".menu.mp2 "$output".info.mpeg "$output".info1.png \
          "$output".info2.png 4 "" $((3-!MASP)) "${EXTRAARG[@]}"
    else
        Menu_MakeStillMpeg "$(echo "$output" | sed 's/%/%%/g')".info0.png "$output".info.mpeg
        echo '    <segment-item src="'"$(xmlchar "$output")".info.mpeg'" id="vts-info" />' >>"$output".segment.xml
        { echo '    <playlist id="play-info">'
          echo '      <prev ref="play-root"/>'
          echo '      <next ref="play-root"/>'
          echo '      <return ref="play-root"/>'
          echo '      <wait>-1</wait>'
          echo '      <play-item ref="vts-info"/>'
          echo '    </playlist>'
        } >>"$output".selection.xml
    fi
}
###############################################################################
Menu_MakeVmgm () { # xmloutput
    local title TXTLIN TXTS rectW rectH rectX bgbutton tpp pagecount entry n bnum JUMP PRESET m TR i rectY a rectPS EXTRAARG CHAN
    EXTRAARG=()
    xmlfile=$1
    do_log "   INFO: [menu] creating VMGM menu"
    title=("${TITLESET[@]}")
    TXTLIN=2
    TXTS=$HEADERSIZE
    rectW=$((315*(12+(MASP==2?4:0))/9))
    #rectH=$((TXTLIN*TXTS+(TXTLIN-1)*TXTS/4+2*TXTS/2))
    rectX=$(((MENU_H_RES-rectW)/2))
    bgbutton=($(rgba 255 255 255 96) $(rgba 0 255 100 150) $(rgba 255 255 0 150))
    tpp=4
    pagecount=$(((${#title[*]}-1)/tpp+1))
    entry=('entry="title"')
    ((iver>626)) && CHAN="-channel RGBA" || CHAN=
    for ((i=0;i<=2;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".vmgm$i.png
        ((MASP&&i)) && CLEAN[${#CLEAN[*]}]="$output".vmgm$((i+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
    done
    for ((n=1;n<=pagecount;n++)); do
        bnum=1
        { echo     '      <pgc '"${entry[n-1]}"' pause="0">'
          if ((MASP)); then
              echo '        <subpicture>'
              echo '          <stream mode="widescreen" id="0"/>'
              ((MASP==1)) && s=panscan || s=letterbox
              echo '          <stream mode="'$s'" id="1"/>'
              echo '        </subpicture>'
          fi
          # jump to the correct menu
          if ((n<pagecount)); then
              JUMP="if (g3 gt $((tpp*n))) jump menu $((n+1));"
              if ((TSALL)); then
                  JUMP="$JUMP if (g5 eq 1) {"
                  for ((a=(n-1)*tpp+1;a<=n*tpp;a++)); do
                      JUMP="$JUMP if (g3 eq $a) jump title $a;"
                  done
                  JUMP="$JUMP }"
              fi
          else
              JUMP="if (g3 gt ${#title[*]}) {g3=1; g5=$((TSALL==2)); jump menu 1;}"
              if ((TSALL)); then
                  JUMP="$JUMP if (g5 eq 1) {"
                  for ((a=(n-1)*tpp+1;a<=${#title[*]};a++)); do
                      JUMP="$JUMP if (g3 eq $a) jump title $a;"
                  done
                  JUMP="$JUMP }"
              fi
          fi
          JUMP="$JUMP button=(((g3-1)%$tpp)+1+$((pagecount>TSETB)))*1024; "
          echo     '        <pre> { '"$JUMP"'} </pre>'
          echo     '        <vob file="'"$(xmlchar "$output.vmgm$n.mpeg")"'" pause="inf"/>'
          ((pagecount>TSETB&&n==1)) && echo -n '        ' && 
                      echo '<button name="'$((bnum++))'"> { '"$(((TSALL)) && echo "g5=1; g3=1; jump title 1;" || echo "exit;")"' } </button>'
          ((pagecount>TSETB&&n>1)) && echo -n '        ' && 
                      echo '<button name="'$((bnum++))'"> { g3='$(((n-1)*tpp))'; jump menu '$((n-1))'; } </button>'
        } >>"$xmlfile"
        convert -scale ${MENU_H_RES}x${MENU_V_RES}! "$output".bg.png "$output".vmgm0.png || Menu_Err $FUNCNAME $LINENO
        if ((BGTITLE%2)); then
            Menu_MakeTitle "$output" "$output".vmgm0.png || Menu_Err $FUNCNAME $LINENO
        fi
        convert -size ${MENU_H_RES}x${MENU_V_RES} xc:transparent "$output".vmgm1.png || Menu_Err $FUNCNAME $LINENO
        cp "$output".vmgm1.png "$output".vmgm2.png

        for ((i=0;i<tpp;i++)); do
            (((n-1)*tpp+i<${#title[*]})) || break
            echo '        <button name="'$((bnum++))'"> { g3='$((i+1+(n-1)*tpp))'; g1=0 ; jump titleset '$((i+1+(n-1)*tpp))' menu entry root; } </button>' \
              >>"$xmlfile"
            rectY=$((MENU_V_RES-TVOSY+(i-tpp)*(TXTLIN*TXTS+(TXTLIN-1)*TXTS/4+3*TXTS/4)))
            title[i+(n-1)*tpp]=$(Menu_FormatTitle "${title[i+(n-1)*tpp]}" $TXTS $rectW $((5*TXTLIN*TXTS/4+3*TXTS/4)))
            mogrify -fill ${bgbutton[0]} -draw "rectangle $rectX,$rectY $((rectX+rectW)),$((rectY+$(Menu_Titlesize "b\ng" $TXTS v)+TXTS/4))" \
              "$output".vmgm0.png || Menu_Err $FUNCNAME $LINENO
            Menu_DrawText $TXTS $((rectX+(rectW-$(Menu_Titlesize "${title[i+(n-1)*tpp]}" $TXTS h))/2)) $((rectY+TXTS)) "${title[i+(n-1)*tpp]}" \
              "$output".vmgm0.png || Menu_Err $FUNCNAME $LINENO
            for ((m=1;m<3;m++)); do
                mogrify -fill red -draw "rectangle $rectX,$rectY $((rectX+rectW)),$((rectY+$(Menu_Titlesize "b\ng" $TXTS v)+TXTS/4))" $CHAN \
                  -fill ${bgbutton[m]} -opaque red "$output".vmgm$m.png || Menu_Err $FUNCNAME $LINENO
            done
        done
        if ((pagecount>TSETB)); then
            for ((m=0;m<3;m++)); do
                ((n==1)) && Menu_SmallButton $TXTS ${bgbutton[m]} "$(((TSALL)) && echo "play all" || echo exit)" "$output".vmgm$m.png l $m
                ((n>1)) && Menu_SmallButton $TXTS ${bgbutton[m]} back "$output".vmgm$m.png l $m
                ((n<pagecount)) && Menu_SmallButton $TXTS ${bgbutton[m]} next "$output".vmgm$m.png r $m
                ((n==pagecount)) && Menu_SmallButton $TXTS ${bgbutton[m]} info "$output".vmgm$m.png r $m
            done
        fi
        for ((m=1;m<3*(MASP!=0);m++)); do
            if ((MASP==1)); then
                convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".vmgm$m.png "$output".vmgm$((m+3)).png || \
                  Menu_Err $FUNCNAME $LINENO
            else
                Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".vmgm$m.png "$output".vmgm$((m+3)).png || Menu_Err $FUNCNAME $LINENO
            fi
        done

        { ((pagecount>TSETB&&n<pagecount)) && echo -n '        ' && 
                      echo '<button name="'$((bnum++))'"> { g3='$((1+n*tpp))'; jump menu '$((n+1))'; } </button>'
          ((pagecount>TSETB&&n==pagecount)) && echo -n '        ' && 
                      echo '<button name="'$((bnum++))'"> { jump menu '$((n+1))'; } </button>'
          echo     '      </pgc>'
        } >>"$xmlfile"
        if ((pagecount>TSETB&&n==pagecount)); then
            Menu_MakeInfo
            { echo     '      <pgc pause="0">'
              if ((MASP)); then
                  echo '        <subpicture>'
                  echo '          <stream mode="widescreen" id="0"/>'
                  ((MASP==1)) && s=panscan || s=letterbox
                  echo '          <stream mode="'$s'" id="1"/>'
                  echo '        </subpicture>'
              fi
              echo     '        <vob file="'"$(xmlchar "$output.info.mpeg")"'" pause="inf"/>'
              echo     '        <button name="1"> { jump menu '$n'; } </button>'
              echo     '      </pgc>'
            } >>"$xmlfile"
        fi
        mogrify -geometry ${H_STILL}x${V_STILL}! "$output".vmgm0.png || Menu_Err $FUNCNAME $LINENO
        mogrify +antialias -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".vmgm[12].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
        [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vmgm$n.mpeg
        Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".vmgm0.png $MenuFr $encFrameRate "$output".menu.mp2 "$output".vmgm$n.mpeg "$output".vmgm1.png \
          "$output".vmgm2.png 2 "" $((3-!MASP)) "${EXTRAARG[@]}"
    done
}
###############################################################################
Menu_MakeVtsRoot () {
    local TITLE EXTRAARG
    EXTRAARG=()
    do_log "   INFO: [menu] creating VTSM root menu"
    CLEAN[${#CLEAN[*]}]="$output".vmgm.png
    convert -scale ${MENU_H_RES}x${MENU_V_RES}! "$output".bg.png "$output".vmgm.png || Menu_Err $FUNCNAME $LINENO
    if ((BGTITLE%2)); then
        Menu_MakeTitle "$output" "$output".vmgm.png || Menu_Err $FUNCNAME $LINENO
    fi
    for ((a=0;a<=TOTOVER;a++)); do CLEAN[${#CLEAN[*]}]="$output".bar$a.png ; CLEAN[${#CLEAN[*]}]="$output".lbar$a.png ; done
    Menu_MakePicts
    for ((a=0;a<=TOTOVER;a++)); do 
        CLEAN[${#CLEAN[*]}]="$output".bg$a.png
        ((MASP&&a)) && CLEAN[${#CLEAN[*]}]="$output".bg$((a+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
    done
    ((BGTITLE/2)) && TITLE="$output" || TITLE="Select an option:"
    case $VTSMBG in
        1)
            CLEAN[${#CLEAN[*]}]="$output".vtsthumb.png
            convert -charcoal 0.2 "$output".vmgm.png "$output".vtsthumb.png || Menu_Err $FUNCNAME $LINENO
            ;;
        2)
            [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] || VTSMBG=0
            ;;
        3)
            if [[ $menuvtsbg ]]; then
                cp "$menuvtsbg" "$output".vtsthumb.png
            else
                [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] || VTSMBG=0
            fi
            ;;
    esac
    Menu_MakeTile 225 "$TITLE" "$output".vtsthumb.png "$output".vmgm.png
    mogrify -geometry ${H_STILL}x${V_STILL}! "$output".bg0.png || Menu_Err $FUNCNAME $LINENO
    [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vtsroot.mpeg
    if ((TOTOVER)); then
        mogrify +antialias -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".bg[12].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
        Menu_MakeMpeg "$(echo "$output" | sed 's/%/%%/g')".bg0.png $MenuFr $encFrameRate "$output".menu.mp2 "$output".vtsroot.mpeg "$output".bg1.png \
          "$output".bg2.png 2 "" $((3-!MASP)) "${EXTRAARG[@]}"
    else
        Menu_MakeStillMpeg "$(echo "$output" | sed 's/%/%%/g')".bg0.png "$output".vtsroot.mpeg
        echo '    <segment-item src="'"$(xmlchar "$output")".vtsroot.mpeg'" id="vtsroot" />' >>"$output".segment.xml
    fi
}
###############################################################################
Menu_MakeFrame () { # thumbsize pointsize offset index srcpic destpic
    convert -size $1 xc:transparent -pointsize $2 \
      -fill $(rgba 255 255 255 128) -draw "gravity SouthEast text 12,$(($3+2)) '$4'" \
      -fill $(rgba 0 0 0 128) -draw "gravity SouthEast text 10,$3 '$4'" \
      +antialias -fill green  -draw "gravity SouthEast text 11,$(($3+1)) '$4'" -transparent green png:- | \
      composite -compose Over -gravity Center - "$5" "$6"
}
###############################################################################
Menu_MakeBorderFrame () { # thumbsize pointsize pic
    convert -size $1 xc:transparent -pointsize $2 png:- | \
      composite -compose Over -gravity North "$3" - png:- | \
      convert -bordercolor transparent -border ${bs}x${bs} -border ${bgap}x${bgap} - "$3"
}
###############################################################################
Menu_ComposeFrame () { # size srcpic destpic [shift]
    if [[ $4 ]]; then
        convert -size $1 xc:transparent png:- | composite -compose copy -gravity Center -geometry +0+$4 "$2" - png:- | \
          composite -compose Over -gravity Center "$2" - "$3"
    else
        convert -size $1 xc:transparent png:- | composite -compose copy -gravity Center "$2" - "$3"
    fi
}
###############################################################################
Menu_MakeVtsExtra () { # xmloutput
    local xmlfile TXTLIN TXTS r rectW rectX bgbutton pagecount n bnum i rectY m emcnt gmax s o OPTIONS EXTRAARG
    EXTRAARG=()

    xmlfile=$1
    do_log "   INFO: [menu] creating VTSM extra menu"
    CLEAN[${#CLEAN[*]}]="$output".extra.png
    for ((i=0;i<=2;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".extra$i.png
        ((MASP)) && CLEAN[${#CLEAN[*]}]="$output".extra$(((i+1)%3+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
    done
    TXTLIN=2
    TXTS=$HEADERSIZE
    r=5
    rectW=$((315*(12+(MASP==2?4:0))/9-6*r))
    rectX=$(((MENU_H_RES-rectW)/2))
    bgbutton=($(rgba 255 255 255 96) 'rgb(0,255,100)' yellow)
    pagecount=$(((${#MEXTRATXT[*]}-1)/gpp+1))
    for ((n=1;n<=pagecount;n++)); do
        bnum=1
        { echo     '      <pgc pause="0">'
          if ((MASP)); then
              echo '        <subpicture>'
              echo '          <stream mode="widescreen" id="0"/>'
              ((MASP==1)) && s=panscan || s=letterbox
              echo '          <stream mode="'$s'" id="1"/>'
              echo '        </subpicture>'
          fi
          echo     '        <pre> { button=((g6/2-1)%'$gpp'+2)*1024; }</pre>'
          echo     '        <vob file="'"$(xmlchar "$output.vtsextra$n.mpeg")"'" pause="inf"/>'
          ((n==1)) && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { jump menu 1; } </button>'
          ((n>1)) && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { jump menu '$n'; } </button>'
        } >>"$xmlfile"
        convert -scale ${MENU_H_RES}x${MENU_V_RES}! "$output".bg.png "$output".extra.png || Menu_Err $FUNCNAME $LINENO
        convert -size ${MENU_H_RES}x${MENU_V_RES} xc:transparent "$output".extra0.png || Menu_Err $FUNCNAME $LINENO
        cp "$output".extra0.png "$output".extra1.png
        cp "$output".extra0.png "$output".extra2.png
        for ((i=0;i<gpp;i++)); do
            (((n-1)*gpp+i<${#MEXTRATXT[*]})) || break
            echo   '        <button name="'$((bnum++))'"> { if (g6 ne '$((((n-1)*gpp+i+1)*2))') g6=g6|1; g6='$((((n-1)*gpp+i+1)*2))'+(g6 and 1); if ((g6 and 1) gt 0) jump menu '$((pagecount+2+${MEXTRAIND[(n-1)*gpp+i]}))'; else jump menu '$((pagecount+2+${MEXTRAIND[(n-1)*gpp+i+1]}-1))'; } </button>' >>"$xmlfile"
            rectY=$((MENU_V_RES-TVOSY+(i-gpp)*(TXTLIN*TXTS+(TXTLIN-1)*TXTS/4+3*TXTS/4)))
            MEXTRATXT[i+(n-1)*gpp]=$(Menu_FormatTitle "${MEXTRATXT[i+(n-1)*gpp]}" $TXTS $rectW $((5*TXTLIN*TXTS/4+3*TXTS/4)))
            Menu_DrawText $TXTS $((rectX+2*r)) $((rectY+TXTS)) "${MEXTRATXT[i+(n-1)*gpp]}" "$output".extra.png || Menu_Err $FUNCNAME $LINENO
            #mogrify -fill none -stroke green -draw "rectangle $(((MENU_H_RES-rectW-6*r)/2)),$rectY \
            #  $(((MENU_H_RES+rectW+6*r)/2)),$((rectY+$(Menu_Titlesize "b\ng" $TXTS v)+TXTS/4))" "$output".extra.png
            for ((m=0;m<3;m++)); do
                mogrify -fill ${bgbutton[m]} -draw "rectangle $((rectX-2*r)),$((rectY+2*r)) $((rectX+0/2)),$((rectY+4*r))" "$output".extra$m.png || \
                  Menu_Err $FUNCNAME $LINENO
                if ((MASP==1)); then
                    convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".extra$m.png "$output".extra$((m+3)).png || \
                      Menu_Err $FUNCNAME $LINENO
                elif ((MASP==2)); then
                    Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".extra$m.png "$output".extra$((m+3)).png || Menu_Err $FUNCNAME $LINENO
                fi
            done
        done
        for ((m=0;m<3;m++)); do
            ((n==1)) && Menu_UpArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png l
            ((n>1)) && Menu_ArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png l
            ((n<pagecount)) && Menu_ArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png r
            ((n>1&&n==pagecount)) && Menu_UpArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png r
            if ((MASP==1)); then
                convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".extra$m.png "$output".extra$((m+3)).png || \
                  Menu_Err $FUNCNAME $LINENO
            elif ((MASP==2)); then
                Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".extra$m.png "$output".extra$((m+3)).png || Menu_Err $FUNCNAME $LINENO
            fi
        done
        { ((n<pagecount)) && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { jump menu '$((n+2))'; } </button>'
          ((n>1&&n==pagecount)) && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { jump menu 1; } </button>'
          echo     '      </pgc>'
        } >>"$xmlfile"
        mogrify -geometry ${H_STILL}x${V_STILL}! "$output".extra.png || Menu_Err $FUNCNAME $LINENO
        mogrify +antialias -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".extra[012].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
        [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vtsextra$n.mpeg
        Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".extra.png $MenuFr $encFrameRate "$output".menu.mp2 "$output".vtsextra$n.mpeg \
          "$output".extra1.png "$output".extra2.png 2 "$output".extra0.png $((3-!MASP)) "${EXTRAARG[@]}"
    done
    emcnt=1
    for ((n=1;n<=${#MEXTRATXT[*]};n++)); do
        s=$(echo ${MEXTRAARG[${MEXTRAIND[n-1]}]##*.} | tr '[:upper:]' '[:lower:]')
        o=$(split_sub_opt "${MEXTRAOPT[n-1]}" 1)
        [[ $o ]] || o=1
        [[ $o = 1 ]] || o=
        if [[ ${MEXTRAARG[${MEXTRAIND[n-1]}]:0:5} = mf:// || $s = mpg || $s = mpeg || $s = vob ]]; then
            if [[ ${MEXTRAARG[${MEXTRAIND[n-1]}]:0:5} = mf:// ]]; then
                [[ $o ]] && OPTIONS=-mpegfixaspect
                o=$(split_sub_opt "${MEXTRAOPT[n-1]}" 2)
                OPTIONS="$OPTIONS${o:+ -slidefps $o}"
                o=$(split_sub_opt "${MEXTRAOPT[n-1]}" 3)
                OPTIONS="$OPTIONS${o:+ -vc $o}"
                OPTIONS="$OPTIONS -mpegonly -dvd -nosplit -noshowlog"
                # there should be no need to change -abr 64 -encode 4:1:1
                OPTIONS="-abr 64 -encode 4:1:1 -bframes 2 -n $videonorm -slidefps 4 $OPTIONS"
            else
                if [[ $o ]]; then
                    OPTIONS="-mpegonly -nosplit -noshowlog -dvd2dvd -nosub -mc 0"
                else
                    echo       "      <!-- addtitleset $(split_sub_opt "${MEXTRAOPT[n-1]}" 2)-$(split_sub_opt "${MEXTRAOPT[n-1]}" 3) //-->" >>"$xmlfile"
                    OPTIONS=
                fi
            fi
            if [[ $OPTIONS ]]; then
                "$PROGFILE" -norc -o "$output".vtse_$emcnt "${MEXTRAARG[${MEXTRAIND[n-1]}]}" $OPTIONS -a $((3-!MASP))
                ret=$? ; (( ret )) && echo "**ERROR: [$PROGNAME] failed to execute '-menuextra ${MEXTRATXT[n-1]} ${MEXTRAARG[${MEXTRAIND[n-1]}]}'" && \
                  exit $ret
                rm -f "$output".vtse_$emcnt.mpeg
                mv "$output".vtse_$emcnt.mpg "$output".vtse_$emcnt.mpeg
            else
                rm -f "$output".vtse_$emcnt.mpeg
                ln -s "${MEXTRAARG[${MEXTRAIND[n-1]}]}" "$output".vtse_$emcnt.mpeg
                touch "$output".vtse_$emcnt.log
            fi
            [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vtse_$emcnt.mpeg
            { echo '      <pgc pause="0">'
              echo '        <vob file="'"$(xmlchar "$output.vtse_$emcnt.mpeg")"'" pause="0"/>'
              echo '        <post> { '"$(((n==${#MEXTRATXT[*]})) && echo 'g6=3; jump menu 2' || \
                echo "if ((g6 and 1) gt 0 ) g6=(g6/2+1)*2+1; else g6=(g6/2-1)*2; jump menu $((n/gpp+2))")"'; }</post>'
              echo '      </pgc>'
            } >>"$xmlfile"
            rm "$output".vtse_$((emcnt++)).log
        else
            gmax=$((${MEXTRAIND[n]}-${MEXTRAIND[n-1]}))
            for ((i=1;i<=gmax;i++)); do
                CLEAN[${#CLEAN[*]}]="$output".vtse_$emcnt.png
                if [[ $o ]]; then
                    convert -geometry ${MENU_H_RES}x${MENU_V_RES} "${MEXTRAARG[${MEXTRAIND[n-1]}+i-1]}" "$output".vtse_$emcnt.png || \
                      Menu_Err $FUNCNAME $LINENO
                    convert -size ${MENU_H_RES}x${MENU_V_RES} xc:black png:- | \
                      composite -compose Over -gravity center "$output".vtse_$emcnt.png - "$output".vtse_$emcnt.png || Menu_Err $FUNCNAME $LINENO
                    mogrify -geometry ${H_STILL}x${V_STILL}! "$output".vtse_$emcnt.png || Menu_Err $FUNCNAME $LINENO
                else
                    convert -scale ${H_STILL}x${V_STILL}! "${MEXTRAARG[${MEXTRAIND[n-1]}+i-1]}" "$output".vtse_$emcnt.png || Menu_Err $FUNCNAME $LINENO
                fi
                { echo     '      <pgc pause="0">'
                  if ((MASP)); then
                      echo '        <subpicture>'
                      echo '          <stream mode="widescreen" id="0"/>'
                      ((MASP==1)) && s=panscan || s=letterbox
                      echo '          <stream mode="'$s'" id="1"/>'
                      echo '        </subpicture>'
                  fi
                  echo     '        <pre> { button=(g6%2+1)*1024; }</pre>'
                  echo     '        <vob file="'"$(xmlchar "$output.vtse_$emcnt.mpeg")"'" pause="inf"/>'
                  ((i==1)) && echo -n '        ' && \
                              echo '<button name="1"> { g6=(g6/2-1)*2; jump menu '$((((n>1?n:2)-2)/gpp+2))'; } </button>'
                  ((i>1)) && echo -n '        ' && \
                              echo '<button name="1"> { g6=g6 and 65534; jump menu '$((emcnt+pagecount))'; } </button>'
                  ((i<gmax)) && echo -n '        ' && \
                              echo '<button name="2"> { g6=g6|1; jump menu '$((emcnt+pagecount+2))'; } </button>'
                  ((i==gmax)) && echo -n '        ' && \
                              echo '<button name="2"> { g6='"$(((n==${#MEXTRATXT[*]})) && echo '3; jump menu 2' || echo "(g6/2+1)*2+1; jump menu $((n/gpp+2))")"'; } </button>'
                  echo     '      </pgc>'
                } >>"$xmlfile"
                if ((i<3||i==gmax)); then
                    convert -size ${MENU_H_RES}x${MENU_V_RES} xc:transparent "$output".extra0.png || Menu_Err $FUNCNAME $LINENO
                    cp "$output".extra0.png "$output".extra1.png
                    cp "$output".extra0.png "$output".extra2.png
                    for ((m=0;m<3;m++)); do
                        ((i==1)) && Menu_UpArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png l
                        ((i>1)) && Menu_ArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png l
                        ((i<gmax)) && Menu_ArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png r
                        ((i==gmax)) && Menu_UpArrowButton $TXTS ${bgbutton[m]} "$output".extra$m.png r
                        if ((MASP==1)); then
                            convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".extra$m.png "$output".extra$((m+3)).png || \
                              Menu_Err $FUNCNAME $LINENO
                        elif ((MASP==2)); then
                            Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".extra$m.png "$output".extra$((m+3)).png || \
                              Menu_Err $FUNCNAME $LINENO
                        fi
                    done
                    mogrify +antialias -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".extra[012].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
                fi
                [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vtse_$emcnt.mpeg
                rm -f "$output".vtse_$emcnt.mpeg
                Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".vtse_$emcnt.png $MenuFr $encFrameRate "$output".menu.mp2 \
                  "$output".vtse_$((emcnt++)).mpeg "$output".extra1.png "$output".extra2.png 2 "$output".extra0.png $((3-!MASP)) "${EXTRAARG[@]}"
            done
        fi
    done
}
###############################################################################
Menu_MakeVtsChapter () { # cpr xmloutput
    local EXTRAARG
    EXTRAARG=()
    do_log "   INFO: [menu] creating VTSM chapter menu"
    #### make the MPEG for the chapter vts submenu
    local cpr xmlfile bs bgap w chapFPS totframes h TXTS TXTLIN TXTY cpc cpm thumbsize patchsize tilesize numChapters yOffset i m menucount entry INFO PREV
    local btext mnum bnum maskList0 maskList1 maskList2 PAUSE chapButton currChap rows b a rectX rectY DrectX DrectY chaptertext picList rmList OPT1 OPT2
    local NEXT extrapages

    cpr=$1
    xmlfile=$2
    bs=3
    bgap=8
    w=$(((MENU_H_RES-TVOSX*2-LEFTPANELW)/$1-(2*bs+2*bgap)))
    chapFPS=$(mplayer -nocache -frames 0 -vo null -nosound "${DVDMPEGS[0]}" 2>/dev/null | awk '/^VIDEO:/{for(a=1;a<=NF;a++)if($a=="fps")print $(a-1)}')
    if [[ $chapFPS = 29.970 || $chapFPS = 30.000 ]]; then
        a=$(mplayer -nocache -quiet "${DVDMPEGS[0]}" -vo null -nosound -benchmark -frames 60 2>/dev/null | awk '/^demux_mpg:/{print $2}')
        [[ $a = 24fps || $a = 24000/1001fps ]] && chapFPS=$(awk -v a=$chapFPS 'BEGIN{printf("%.3f",a*4/5)}')
    elif [[ $chapFPS = 25.000 ]]; then
        a=$(is_film2pal "${DVDMPEGS[0]}")
        if [[ $a ]]; then
            [[ $a = 24fps ]] && chapFPS=24.000 || chapFPS=23.976
        fi
    fi
    Menu_MakeThumb $w $(awk -v a=$chapFPS -v b=$((TANIM?TPARTSEC:TSECS)) -v g=$((((TMODE!=1 && !TKFRM && !TANIM))?${GOP:-0}:1)) \
      'BEGIN{printf("%.0f",a*b/(g?g:int(a/2)+(int(a+.5)%24?3:0)))}')
    #### use the first chapter thumbnail as vts thumb
    ((VTSMBG/2)) && CLEAN[${#CLEAN[*]}]="$output".vtsthumb.png && convert "$output".chap1.frame1.$TFMT "$output".vtsthumb.png
    ((TANIM)) && totframes=$(awk -v a=$chapFPS -v b=$TPARTSEC -v c=$TPART 'BEGIN{printf("%.0f",int(a+.5)*b*c)}') || totframes=1
    h=$(Menu_Picsize "$output".chap1.frame1.$TFMT v)
    TXTS=$(((11+TFONTSIZE)*MENUSIZE/20))
    if ((${#CHAPTERTEXT[*]})); then
        TXTLIN=$TLINES
        TXTY=$((TXTLIN*TXTS+(TXTLIN-1)*TXTS/4+2*TXTS/2-20))
    else
        TXTLIN=0
        TXTY=0
    fi
    cpc=$(((MENU_V_RES-TVOSY*2)/(h+2*bs+2*bgap+TXTY)))
    cpm=$((cpr*cpc))
    thumbsize=${w}x${h}
    patchsize=$((w+2*bs+2*bgap))x$((h+2*bs+2*bgap+TXTY))
    tilesize=${cpr}x${cpc}
    numChapters=$(ls "$output".chap*.frame1.$TFMT | awk 'END{printf NR}')

    CLEAN[${#CLEAN[*]}]="$output".vtsbg.png
    #### draw the left panel
    convert -scale ${MENU_H_RES}x${MENU_V_RES}! -fill $(rgba 255 255 255 96) \
      -draw "rectangle $TVOSX,$TVOSY $((TVOSX+LEFTPANELW)),$((MENU_V_RES-TVOSY))" "$output".bg.png "$output".vtsbg.png || Menu_Err $FUNCNAME $LINENO

    CLEAN[${#CLEAN[*]}]="$output".empty_button.png
    convert -size $patchsize xc:transparent "$output".empty_button.png || Menu_Err $FUNCNAME $LINENO
    for ((i=0;i<=TOTOVER;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".bmask$i.png
        convert +antialias -size $thumbsize xc:green -bordercolor "${overlayc[i]}" -border ${bs}x${bs} \
          -bordercolor green -border ${bgap}x${bgap} -transparent green "$output".bmask$i.png || Menu_Err $FUNCNAME $LINENO
    done

    yOffset=$((MENUSIZE/4+(iver<600?5*MENUSIZE/4:0)))
    for ((i=1;i<=$numChapters;i++)); do
        for ((m=1;m<=totframes;m++)); do
            echo -en "  Processing chapter $i/$numChapters frame $m/$totframes   \r"
            #### put the chapter number on the thumbnail
            Menu_RunfuncPic old "$output".chap$i.frame$m.$TFMT $LINENO Menu_MakeFrame $thumbsize $MENUSIZE $yOffset $((i+FirstChap-1)) \
              "$output".chap$i.frame$m.$TFMT "$output".chap$i.frame$m.png || Menu_Err $FUNCNAME $LINENO
            [[ $TFMT != png ]] && rm "$output".chap$i.frame$m.$TFMT
            #### add the border to the thumbnail
            if ((${#CHAPTERTEXT[*]})); then
                Menu_RunfuncPic old "$output".chap$i.frame$m.png $LINENO Menu_MakeBorderFrame $thumbsize $MENUSIZE "$output".chap$i.frame$m.png || \
                  Menu_Err $FUNCNAME $LINENO # IM5
            else
                Menu_RunfuncPic old "$output".chap$i.frame$m.png $LINENO mogrify -bordercolor transparent -border ${bs}x${bs} -border ${bgap}x${bgap} \
                  "$output".chap$i.frame$m.png || Menu_Err $FUNCNAME $LINENO # IM5
            fi
        done
    done
    echo
    menucount=$(((numChapters-1)/cpm+1))
    entry=('entry="ptt"')
    if ((TOTOVER)); then
        btext=(Return Main-Menu)
        (( ${#addsub[*]}+${#txtsub[*]} )) && btext[${#btext[*]}]=Subtitles
        [[ $multiaudio ]] && btext[${#btext[*]}]=Audio
    else
        if [[ $multiaudio ]]; then
            btext=("Audio  <--")
        elif ((${#addsub[*]}+${#txtsub[*]})); then
            btext=("Subs    <--")
        else
            btext=("Info    <--")
        fi
        btext=("${btext[@]}" "Next   >>|" "Prev   |<<")
    fi
    CLEAN[${#CLEAN[*]}]="$output".thumbs.png
    for ((i=0;i<=TOTOVER;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".buttons$i.png
        CLEAN[${#CLEAN[*]}]="$output".vtsm_mask$i.png
        ((MASP&&i)) && CLEAN[${#CLEAN[*]}]="$output".vtsm_mask$((i+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
    done
    if [[ $multiaudio ]]; then
        INFO=play-audio
    elif ((${#addsub[*]}+${#txtsub[*]})); then
        INFO=play-subtitle
    else
        INFO=play-info
    fi
    ((${#MEXTRATXT[*]})) && extrapages=$(((${#MEXTRATXT[*]}-1)/gpp+1+${MEXTRAIND[${#MEXTRAIND[*]}-1]})) || extrapages=0
    for ((mnum=1;mnum<=menucount;mnum++)); do
        bnum=1
        maskList0=()
        maskList1=()
        maskList2=()
        { echo     '      <pgc '"${entry[mnum-1]}"' pause="0">'
          if ((MASP&&TOTOVER)); then
              echo '        <subpicture>'
              echo '          <stream mode="widescreen" id="0"/>'
              ((MASP==1)) && s=panscan || s=letterbox
              echo '          <stream mode="'$s'" id="1"/>'
              echo '        </subpicture>'
          fi
          echo     '        <pre> { if (g1 lt 9) g1=1; if (g2 lt 1024) button=1024; else button=g2; } </pre>'
          ((TANIM)) && PAUSE=0 || PAUSE=inf
          echo     '        <vob file="'"$(xmlchar "$output.vts$mnum.mpeg")"'" pause="'$PAUSE'"/>'
          for ((i=1;i<=menucount;i++)); do
              # the first chapter menu is menu 2+extrapages, menu 1 is the root menu
              ((i!=mnum)) && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { g2=button; jump menu '$((i+1+extrapages))'; } </button>'
          done
          [[ $multiaudio ]] && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { g2=button; jump menu entry audio; } </button>'
          (( ${#addsub[*]}+${#txtsub[*]} )) && echo -n '        ' && \
                      echo '<button name="'$((bnum++))'"> { g2=button; jump menu entry subtitle; } </button>'
          echo     '        <button name="'$((bnum++))'"> { g2=button; jump menu entry root; } </button>'
          echo     '        <button name="'$((bnum++))'"> { g2=button; if (g1 lt 9) jump menu entry root; if (g1 eq 9) resume; } </button>'
          chapButton=$bnum
          for ((m=1;m<=cpm;m++)); do
              currChap=$((m+(mnum-1)*cpm))
              if ((currChap<=numChapters)); then
                  maskList0[${#maskList0[*]}]="$output".bmask0.png
                  maskList1[${#maskList1[*]}]="$output".bmask1.png
                  maskList2[${#maskList2[*]}]="$output".bmask2.png
                  bnum=$((++bnum))
              else
                  maskList0[${#maskList0[*]}]="$output".empty_button.png
                  maskList1[${#maskList1[*]}]="$output".empty_button.png
                  maskList2[${#maskList2[*]}]="$output".empty_button.png
              fi
          done
          rows=$(((bnum-chapButton-1)/cpr+1))
          for ((b=0;b<cpr;b++)); do
              for ((a=0;a<rows;a++)); do
                  ((chapButton<bnum)) || break 2
                  currChap=$((1+(mnum-1)*cpm+b+a*cpr))
                  ((currChap>numChapters)) && continue
                  echo '        <button name="'$((chapButton++))'"> { g2=button; jump title 1 chapter '$currChap'; } </button>'
              done
          done
          ((TANIM)) && echo -n '        ' && \
                          echo '<post> jump menu '$((mnum+1+extrapages))'; </post>'
                          #echo '<post> jump cell 1; </post>'
          echo     '      </pgc>'
        } >>"$xmlfile"

        #### put all the thumbnails of the page together
        Menu_RunfuncPic new "$output".buttons0.png $LINENO Menu_MontageThumbs $patchsize $tilesize "$output".buttons0.png "${maskList0[@]}" || \
          Menu_Err $FUNCNAME $LINENO
        a=$(Menu_Titlesize "from $((FirstChap-1+(menucount-1)*cpm+1)) to $((FirstChap-1+numChapters))" $MENUSIZE h)
        if ((TOTOVER)); then
            #### put all the thumbnails buttons of the page together
            Menu_RunfuncPic new "$output".buttons1.png $LINENO Menu_MontageThumbs $patchsize $tilesize "$output".buttons1.png "${maskList1[@]}" || \
              Menu_Err $FUNCNAME $LINENO
            Menu_RunfuncPic new "$output".buttons2.png $LINENO Menu_MontageThumbs $patchsize $tilesize "$output".buttons2.png "${maskList2[@]}" || \
              Menu_Err $FUNCNAME $LINENO
            for ((i=1;i<=2;i++)); do
                for ((m=1;m<=menucount;m++)); do
                    if ((m!=mnum)); then
                        #### other pages selection overlay button
                        Menu_RunfuncPic old "$output".buttons$i.png $LINENO Menu_DrawPolyLine "${overlayc[i]}" $offset \
                          $((offset+5*HEADERSIZE/4+MENUSIZE+(m-1)*(MENUSIZE+10))) "$output".buttons$i.png $((MENUSIZE+a)) || Menu_Err $FUNCNAME $LINENO
                    fi
                done
                for ((m=0;m<${#btext[*]};m++)); do
                    #### lower left menu selection overlay button
                    Menu_RunfuncPic old "$output".buttons$i.png $LINENO Menu_DrawPolyLine "${overlayc[i]}" $offset \
                      $((MENU_V_RES-2*TVOSY-offset-m*(MENUSIZE+MENUSTEP))) "$output".buttons$i.png || Menu_Err $FUNCNAME $LINENO
                done
                #### put all the overlay buttons on the center mask
                Menu_RunfuncPic new "$output".vtsm_mask$i.png $LINENO Menu_ComposeFrame ${MENU_H_RES}x${MENU_V_RES} "$output".buttons$i.png \
                  "$output".vtsm_mask$i.png || Menu_Err $FUNCNAME $LINENO
                Menu_RunfuncPic old "$output".vtsm_mask$i.png $LINENO mogrify -colors 3 "$output".vtsm_mask$i.png || Menu_Err $FUNCNAME $LINENO
                if ((MASP==1)); then
                    Menu_RunfuncPic new "$output".vtsm_mask$((i+3)).png $LINENO convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 \
                      "$output".vtsm_mask$i.png "$output".vtsm_mask$((i+3)).png || Menu_Err $FUNCNAME $LINENO
                elif ((MASP==2)); then
                    Menu_RunfuncPic new "$output".vtsm_mask$((i+3)).png $LINENO Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} \
                      "$output".vtsm_mask$i.png "$output".vtsm_mask$((i+3)).png 1 || Menu_Err $FUNCNAME $LINENO
                fi
            done
        fi
        cp "$output".vtsbg.png "$output".vtsm_mask0.png
        if ((${#CHAPTERTEXT[*]})); then
            #### put the text under the thumbnails
            for ((m=0;m<cpm;m++)); do
                (((mnum-1)*cpm+m<numChapters)) || break
                #### draw the background rectangle
                if ((TFONTBG)); then
                    rectX=$((TVOSX+LEFTPANELW+bgap+(m%cpr)*(w+2*bs+2*bgap)))
                    rectY=$((TVOSY+h+TXTS/4+bs+bgap+(m/cpr)*(h+TXTY+2*bs+2*bgap)))
                    Menu_RunfuncPic old "$output".vtsm_mask0.png $LINENO mogrify -fill $(rgba 255 255 255 96) \
                      -draw "rectangle $rectX,$rectY $((rectX+w+2*bs)),$((rectY+TXTY+20-TXTS/4))" "$output".vtsm_mask0.png || Menu_Err $FUNCNAME $LINENO
                    [[ ${CHAPTERTEXT[(mnum-1)*cpm+m]} ]] || continue
                    chaptertext=$(Menu_FormatTitle "${CHAPTERTEXT[(mnum-1)*cpm+m]}" $TXTS $w $((5*TXTLIN*TXTS/4+3*TXTS/4)))
                else
                    [[ ${CHAPTERTEXT[(mnum-1)*cpm+m]} ]] || continue
                    chaptertext=$(Menu_FormatTitle "${CHAPTERTEXT[(mnum-1)*cpm+m]}" $TXTS $w $((5*TXTLIN*TXTS/4+3*TXTS/4)))
                    rectX=$((TVOSX+LEFTPANELW+bgap+(m%cpr)*(w+2*bs+2*bgap)))
                    rectY=$((TVOSY+h+TXTS/4+bs+bgap+(m/cpr)*(h+TXTY+2*bs+2*bgap)))
                    DrectX=$((rectX+$(Menu_Titlesize "$chaptertext" $TXTS h)+2*bs))
                    DrectY=$((rectY+$(Menu_Titlesize "$chaptertext" $TXTS v)+TXTS/4))
                    Menu_RunfuncPic old "$output".vtsm_mask0.png $LINENO mogrify -fill $(rgba 255 255 255 96) \
                      -draw "rectangle $rectX,$rectY $DrectX,$DrectY" "$output".vtsm_mask0.png || Menu_Err $FUNCNAME $LINENO
                fi
                #### draw the text on the background rectangle
                Menu_RunfuncPic old "$output".vtsm_mask0.png $LINENO Menu_DrawText $TXTS $((TVOSX+LEFTPANELW+bs+bgap+(m%cpr)*(w+2*bs+2*bgap))) \
                  $((TVOSY+h+TXTS+2*bs+bgap+(m/cpr)*(h+TXTY+2*bs+2*bgap))) "$chaptertext" "$output".vtsm_mask0.png || Menu_Err $FUNCNAME $LINENO
            done
        fi
        #### put the thumbnails together
        for ((i=1;i<=totframes;i++)); do
            echo -en "  Processing menu page $mnum/$menucount frame $i/$totframes   \r"
            picList=()
            rmList=()
            for ((m=1;m<=cpm;m++)); do
                currChap=$((m+(mnum-1)*cpm))
                if ((currChap<=numChapters)); then
                    picList[${#picList[*]}]="$output".chap$currChap.frame$i.png
                    rmList[${#rmList[*]}]="$output".chap$currChap.frame$i.png
                else
                    picList[${#picList[*]}]="$output".empty_button.png
                fi
            done
            Menu_RunfuncPic new "$output".thumbs.png $LINENO Menu_MontageThumbs $patchsize $tilesize "$output".thumbs.png "${picList[@]}" || \
              Menu_Err $FUNCNAME $LINENO # IM5
            rm "${rmList[@]}"
            #### text on the left panel
            Menu_RunfuncPic old "$output".thumbs.png $LINENO Menu_DrawText $HEADERSIZE $offset $((3*HEADERSIZE/4+offset)) "Chapters:" \
              "$output".thumbs.png || Menu_Err $FUNCNAME $LINENO # IM5
            ####i=0
            Menu_RunfuncPic old "$output".thumbs.png $LINENO composite -compose Over "$output".buttons0.png "$output".thumbs.png "$output".thumbs.png || \
              Menu_Err $FUNCNAME $LINENO # IM5
            for ((m=1;m<=menucount;m++)); do
                #### text on the left panel
                Menu_RunfuncPic old "$output".thumbs.png $LINENO Menu_DrawText $MENUSIZE $((MENUSIZE+offset)) \
                  $((offset+5*HEADERSIZE/4+MENUSIZE+(m-1)*(MENUSIZE+10))) \
                  "from $((FirstChap-1+(m-1)*cpm+1)) to $((FirstChap-1+(m*cpm<numChapters?m*cpm:numChapters)))" \
                  "$output".thumbs.png || Menu_Err $FUNCNAME $LINENO # IM5
                if ((m==mnum)); then
                    #### current page rectangle
                    Menu_RunfuncPic old "$output".thumbs.png $LINENO Menu_DrawRect "${overlayc[2]}" $offset \
                      $((offset+5*HEADERSIZE/4+MENUSIZE+(m-1)*(MENUSIZE+10))) "$output".thumbs.png || Menu_Err $FUNCNAME $LINENO # IM5
                fi
            done
            for ((m=0;m<${#btext[*]};m++)); do
                #### for CD menu do not write the last entry on the last page
                ((!TOTOVER&&!m&&mnum==menucount)) && continue
                #### text on the left panel (menu)
                Menu_RunfuncPic old "$output".thumbs.png $LINENO Menu_DrawText $MENUSIZE $((MENUSIZE+offset)) \
                  $((MENU_V_RES-2*TVOSY-offset-m*(MENUSIZE+MENUSTEP))) "${btext[m]}" "$output".thumbs.png || Menu_Err $FUNCNAME $LINENO # IM5
            done
            ((mnum==1)) && eval "CLEAN$(((i-1)/1000))[(i-1)%1000]=\"$(echo "$output" | sed 's/"/\\"/g')\".vtsm_thumbs$i.png"
            Menu_RunfuncPic new "$output".vtsm_thumbs$i.png $LINENO composite -compose Over -gravity Center "$output".thumbs.png "$output".vtsm_mask0.png \
              "$output".vtsm_thumbs$i.png || Menu_Err $FUNCNAME $LINENO # IM5
            Menu_RunfuncPic old "$output".vtsm_thumbs$i.png $LINENO mogrify -geometry ${H_STILL}x${V_STILL}! "$output".vtsm_thumbs$i.png # IM5
        done
        echo
        ((TANIM)) && OPT1="%d" OPT2="$totframes $chapFPS" || OPT1=1 OPT2="$MenuFr $encFrameRate"
        [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vts$mnum.mpeg
        if ((TOTOVER)); then
            mogrify +antialias $ICOL -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".vtsm_mask[12].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
            Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".vtsm_thumbs${OPT1}.png $OPT2 "$output".menu.mp2 "$output".vts$mnum.mpeg \
              "$output".vtsm_mask1.png "$output".vtsm_mask2.png 4 "" $((3-!MASP)) "${EXTRAARG[@]}"
        else
            Menu_MakeStillMpeg "$(echo "$output"| sed 's/%/%%/g')".vtsm_thumbs${OPT1}.png "$output".vts$mnum.mpeg
            echo '    <segment-item src="'"$(xmlchar "$output")".vts$mnum.mpeg'" id="vts-'$(printf "%02d" $mnum)'" />' >>"$output".segment.xml
            { echo '    <selection id="play-ptt-'$(printf "%02d" $mnum)'">'
              echo '      <bsn>'$((FirstChap+(mnum-1)*cpm))'</bsn>'
              ((mnum==1)) && PREV=play-root || PREV="play-ptt-$(printf "%02d" $((mnum-1)))"
              echo '      <prev ref="'"$PREV"'"/>'
              ((mnum<menucount)) && NEXT="play-ptt-$(printf "%02d" $((mnum+1)))" || NEXT=$INFO
              echo '      <next ref="'"$NEXT"'"/>'
              echo '      <return ref="'"$INFO"'"/>'
              echo '      <timeout ref="play-ptt-'$(printf "%02d" $mnum)'"/>'
              echo '      <wait>60</wait>'
              echo '      <loop jump-timing="immediate">1</loop>'
              echo '      <play-item ref="vts-'$(printf "%02d" $mnum)'"/>'
              for ((m=1;m<=cpm;m++)); do
                  currChap=$((m+(mnum-1)*cpm))
                  if ((currChap<=numChapters)); then
                      echo '      <select ref="selection-'$(printf "%02d" $currChap)'"/>'
                  else
                      break
                  fi
              done
              echo '    </selection>'
            } >>"$output".selection.xml
        fi
    done
    FirstChap=$((currChap+FirstChap-1-$(awk -v c=${DVDCHAPTERS[n]:-1} 'BEGIN{if(c==0)print 0; else print 1}')))
}
###############################################################################
Menu_MakeVtsAudio () { # xmloutput
    local EXTRAARG
    EXTRAARG=()
    do_log "   INFO: [menu] creating VTSM audio menu"
    local xmlfile bnum m i WLABEL ALANG langtext audiotxt audioId codec w btext RESUME AUDIOACTION PREV NEXT
    xmlfile=$1

    RESUME="if (g1 eq 0) jump menu entry root; if (g1 eq 1) jump menu entry ptt; if (g1 eq 9) resume;"
    #AUDIOACTION="jump menu entry audio;"
    AUDIOACTION="$RESUME"
    { echo     '      <pgc entry="audio" pause="0">'
      if ((MASP&&TOTOVER)); then
          echo '        <subpicture>'
          echo '          <stream mode="widescreen" id="0"/>'
          ((MASP==1)) && s=panscan || s=letterbox
          echo '          <stream mode="'$s'" id="1"/>'
          echo '        </subpicture>'
      fi
      echo     '        <pre> { button=(audio+1)*1024; }</pre>'
      echo     '        <vob file="'"$(xmlchar "$output.vtsaudio.mpeg")"'" pause="inf"/>'
      bnum=1
      for ((m=0;m<audiostream;m++)); do
          echo '        <button name="'$((bnum++))'"> { audio='$m' ; '"$AUDIOACTION"' } </button>'
      done
      [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && echo -n '        ' && \
                  echo '<button name="'$((bnum++))'"> jump menu entry ptt; </button>'
      (( ${#addsub[*]}+${#txtsub[*]} )) && echo -n '        ' && \
                  echo '<button name="'$((bnum++))'"> jump menu entry subtitle; </button>'
      echo     '        <button name="'$((bnum++))'"> jump menu entry root; </button>'
      echo     '        <button name="'$((bnum++))'"> { '"$RESUME"' } </button>'
      echo     '      </pgc>'
    } >>"$xmlfile"

    for ((i=0;i<=TOTOVER;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".vtsm_audio$i.png
        ((MASP&&i)) && CLEAN[${#CLEAN[*]}]="$output".vtsm_audio$((i+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
    done
    convert -size $((MENU_H_RES-TVOSX*2))x$((MENU_V_RES-TVOSY*2)) xc:none "$output".vtsm_audio0.png || Menu_Err $FUNCNAME $LINENO
    ((TOTOVER)) && LABEL="Select Audio Track:" || LABEL="Audio Track:"
    Menu_DrawText $HEADERSIZE $((offset+8)) $((offset+HEADERSIZE+0)) "$LABEL" "$output".vtsm_audio0.png || Menu_Err $FUNCNAME $LINENO
    WLABEL=$(Menu_Titlesize "Select Audio Track:" $HEADERSIZE h)
    ALANG=( ${dvdaudiolang//,/ } )
    if [[ $audioformat != acopy ]]; then
        case ${mpegchannels:-2} in
            1) langtext=mono ;;
            2) langtext=stereo ;;
            *) langtext="$mpegchannels channels"
        esac
        langtext="($audioformat $langtext)"
    fi
    for ((m=0;m<audiostream;m++)); do
        if [[ ${AUDIOTEXT[m]} ]]; then
            audiotxt=$(Menu_FormatTitle "${AUDIOTEXT[m]}" $MENUSIZE $((MENU_H_RES-2*TVOSX-2*MENUSIZE)) $MENUSIZE)
        else
            ALANG[m]=$(echo ${languages[*]} | tr ' ' '\012' | grep -i "^${ALANG[m]}-" | cut -f2- -d-)
            if [[ $audioformat = acopy ]]; then
                audioId=( $multiaudio )
                codec=$(mplayer -ac mp3, -nocache -frames 0 -v -ao null -vo null "${MPLAYERINFO[@]}" -aid ${audioId[m]} 2>/dev/null | \
                  sed '/Selected audio codec:/!d;s/[^(]*(//;s/).*//;s/.* //')
                langtext="($(mplayer -ac mp3, -nocache -frames 0 -v -ao null -vo null "${MPLAYERINFO[@]}" -aid ${audioId[m]} 2>/dev/null | \
                  sed '/^Opening audio deco/,/^AUDIO:/!d;s/\r//g' | grep -e '^AC3:' -e '^MPEG' -e '^AUDIO:' | \
                  sed 's/AUDIO/'"$codec"'/;s/(.*//;s/AC3:/ac3/;s/LPCM[^,]*,/lpcm/;s/DTS[^,]*,/dts/;s/MPEG .\.., Layer /mp/;s/III/3/;s/II/2/;s/I/1/;s/,.*kbit / /;s/,.*//;q'))"
                #AC3: 5.1 (3f+2r+lfe)  48000 Hz  448.0 kbit/s
                #LPCM: 48000 Hz, 2 ch, 16 bit (0x20), ratio: 192000->192000 (1536.0 kbit)
                #DTS: 48000 Hz, 2 ch, 16 bit (0x10), ratio: 96000->192000 (768.0 kbit)
                #MPEG 1.0, Layer II, 48000 Hz 224 kbit Stereo, BPF: 672
                #1.0pre7
                #LPCM: 48000 Hz, 2 ch, s16be, 1536.0 kbit/100.00% (ratio: 192000->192000)
            fi
            audiotxt="${ALANG[m]} $langtext"
        fi
        Menu_DrawText $MENUSIZE $((MENUSIZE+offset)) $((offset+HEADERSIZE+(MENUSIZE+10)+m*(MENUSIZE+10))) "$audiotxt" "$output".vtsm_audio0.png || \
          Menu_Err $FUNCNAME $LINENO
        w=$(Menu_Titlesize "$audiotxt" $MENUSIZE h)
        ((WLABEL<w+MENUSIZE)) && WLABEL=$((w+MENUSIZE))
    done

    if ((TOTOVER)); then
        btext=(Return Main-Menu)
        (( ${#addsub[*]}+${#txtsub[*]} )) && btext[${#btext[*]}]=Subtitles
        [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && btext[${#btext[*]}]=Chapters
    else
        btext=("" "Next   >>|" "Prev   |<<")
    fi
    for ((m=0;m<${#btext[*]};m++)); do
        Menu_DrawText $MENUSIZE $((MENUSIZE+offset)) $((MENU_V_RES-2*TVOSY-offset-m*(MENUSIZE+MENUSTEP))) "${btext[m]}" "$output".vtsm_audio0.png || \
          Menu_Err $FUNCNAME $LINENO
    done

    for ((i=1;i<=TOTOVER;i++)); do
        convert -size $((MENU_H_RES-TVOSX*2))x$((MENU_V_RES-TVOSY*2)) xc:none "$output".vtsm_audio$i.png || Menu_Err $FUNCNAME $LINENO
        for ((m=1;m<=audiostream;m++)); do
            Menu_DrawPolyLine "${overlayc[i]}" $offset $((offset+HEADERSIZE+(MENUSIZE+10)+(m-1)*(MENUSIZE+10))) "$output".vtsm_audio$i.png \
              $((WLABEL+MENUSIZE-MENUSIZE)) || Menu_Err $FUNCNAME $LINENO
        done
        for ((m=0;m<${#btext[*]};m++)); do
            Menu_DrawPolyLine "${overlayc[i]}" $offset $((MENU_V_RES-2*TVOSY-offset-m*(MENUSIZE+MENUSTEP))) "$output".vtsm_audio$i.png || \
              Menu_Err $FUNCNAME $LINENO
        done
        Menu_ComposeFrame ${MENU_H_RES}x${MENU_V_RES} "$output".vtsm_audio$i.png "$output".vtsm_audio$i.png || Menu_Err $FUNCNAME $LINENO
        if ((MASP==1)); then
            convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".vtsm_audio$i.png "$output".vtsm_audio$((i+3)).png || \
              Menu_Err $FUNCNAME $LINENO
        elif ((MASP==2)); then
            Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".vtsm_audio$i.png "$output".vtsm_audio$((i+3)).png 1 || Menu_Err $FUNCNAME $LINENO
        fi
    done

    CLEAN[${#CLEAN[*]}]="$output".vtsaudiobg.png
    convert -scale ${MENU_H_RES}x${MENU_V_RES}! \
      -fill $(rgba 255 255 255 96) -draw "rectangle $TVOSX,$TVOSY $((TVOSX+LEFTPANELW)),$((MENU_V_RES-TVOSY))" -fill $(rgba 128 192 255 128) \
      -draw "roundrectangle $((TVOSX+2)),$((TVOSY+2)) $((TVOSX+WLABEL+(MENUSIZE<HEADERSIZE?HEADERSIZE:MENUSIZE)/2+offset)),$((TVOSY+offset+HEADERSIZE+MENUSIZE+audiostream*(MENUSIZE+10))) 10,10" \
      "$output".bg.png "$output".vtsaudiobg.png || Menu_Err $FUNCNAME $LINENO

    composite -compose Over -gravity Center "$output".vtsm_audio0.png "$output".vtsaudiobg.png "$output".vtsm_audio0.png || Menu_Err $FUNCNAME $LINENO
    rm "$output".vtsaudiobg.png && unset CLEAN[${#CLEAN[*]}-1]
    mogrify -geometry ${H_STILL}x${V_STILL}! "$output".vtsm_audio0.png || Menu_Err $FUNCNAME $LINENO
    [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vtsaudio.mpeg
    if ((TOTOVER)); then
        mogrify +antialias $ICOL -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".vtsm_audio[12].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
        Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".vtsm_audio0.png $MenuFr $encFrameRate "$output".menu.mp2 "$output".vtsaudio.mpeg \
          "$output".vtsm_audio1.png "$output".vtsm_audio2.png 4 "" $((3-!MASP)) "${EXTRAARG[@]}"
    else
        Menu_MakeStillMpeg "$(echo "$output"| sed 's/%/%%/g')".vtsm_audio0.png "$output".vtsaudio.mpeg
        echo '    <segment-item src="'"$(xmlchar "$output")".vtsaudio.mpeg'" id="vts-audio" />' >>"$output".segment.xml
        { echo '    <playlist id="play-audio">'
          [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && PREV=play-ptt-01 || PREV=play-root
          echo '      <prev ref="'"$PREV"'"/>'
          ((${#addsub[*]}+${#txtsub[*]})) && NEXT=play-subtitle || NEXT=play-info
          echo '      <next ref="'"$NEXT"'"/>'
          echo '      <return ref="play-root"/>'
          echo '      <wait>-1</wait>'
          echo '      <play-item ref="vts-audio"/>'
          echo '    </playlist>'
        } >>"$output".selection.xml
    fi
}
###############################################################################
Menu_MakeVtsSub () { # xmloutput
    local EXTRAARG
    EXTRAARG=()
    do_log "   INFO: [menu] creating VTSM subtitle menu"
    local xmlfile k bnum m i subtxt WLABEL subwidth DVDSUBLANG w RESUME SUBACTION PREV spusub
    xmlfile=$1

    RESUME="if (g1 eq 0) jump menu entry root; if (g1 eq 1) jump menu entry ptt; if (g1 eq 9) resume;"
    SUBACTION="g4=1; jump menu entry subtitle;"
    ((dvdsub)) && spusub=$((dvdsub+${#txtsub[*]})) || spusub=$((${#addsub[*]}+${#txtsub[*]}))
    k=1
    [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && k=$((++k))
    [[ $multiaudio ]] && k=$((++k))
    ((spusub<32)) && k=$((++k))
    { echo     '      <pgc entry="subtitle" pause="0">'
      if ((MASP&&TOTOVER)); then
          echo '        <subpicture>'
          echo '          <stream mode="widescreen" id="0"/>'
          ((MASP==1)) && s=panscan || s=letterbox
          echo '          <stream mode="'$s'" id="1"/>'
          echo '        </subpicture>'
      fi
      echo     '        <pre> { if ( g4 eq 1 ) { g4=0; '"$RESUME"' } button=((subtitle/64)*(subtitle-'$((63-k))')+(1-(subtitle/64))*'$((spusub+1+k))')*1024; }</pre>'
      echo     '        <vob file="'"$(xmlchar "$output.vtssub.mpeg")"'" pause="inf"/>'
      bnum=1
      [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && echo -n '        ' && \
                  echo '<button name="'$((bnum++))'"> jump menu entry ptt; </button>'
      [[ $multiaudio ]] && echo -n '        ' && \
                  echo '<button name="'$((bnum++))'"> jump menu entry audio; </button>'
      echo     '        <button name="'$((bnum++))'"> jump menu entry root; </button>'
      ((spusub<32)) && echo -n '        ' && \
                  echo '<button name="'$((bnum++))'"> { '"$RESUME"' } </button>'
      for ((m=0;m<spusub;m++)); do
          echo '        <button name="'$((bnum++))'"> { subtitle='$((m+64))' ; '"$SUBACTION"' } </button>'
      done
      echo     '        <button name="'$((bnum++))'"> { subtitle=subtitle-(64*(subtitle/64)) ; '"$SUBACTION"' } </button>'
      echo     '      </pgc>'
    } >>"$xmlfile"

    for ((i=0;i<=TOTOVER;i++)); do
        CLEAN[${#CLEAN[*]}]="$output".vtsm_sub$i.png
        ((MASP&&i)) && CLEAN[${#CLEAN[*]}]="$output".vtsm_sub$((i+3)).png && EXTRAARG=( "${EXTRAARG[@]}" "${CLEAN[${#CLEAN[*]}-1]}" )
    done
    subtxt=Subtitle
    ((spusub>1)) && subtxt="${subtxt}s"
    subtxt="${subtxt}:"
    convert -size $((MENU_H_RES-TVOSX*2))x$((MENU_V_RES-TVOSY*2)) xc:none "$output".vtsm_sub0.png || Menu_Err $FUNCNAME $LINENO
    Menu_DrawText $HEADERSIZE $((offset+8)) $((offset+HEADERSIZE)) "$subtxt" "$output".vtsm_sub0.png || Menu_Err $FUNCNAME $LINENO
    ((TOTOVER)) && WLABEL=$(Menu_Titlesize "None" $MENUSIZE h) || WLABEL=0
    ((MENUOS)) && lpc=19 || lpc=15
    subwidth=$(((MENU_H_RES-TVOSX*2-LEFTPANELW)/(spusub/lpc+1)))
    DVDSUBLANG=( ${SUBLANG//,/ } )
    for ((m=0;m<spusub;m++)); do
        [[ ${SUBTEXT[m]} ]] && subtxt=$(Menu_FormatTitle "${SUBTEXT[m]}" $MENUSIZE $((subwidth-2*MENUSIZE)) $MENUSIZE) || \
          subtxt=$(echo ${languages[*]} | tr ' ' '\012' | grep -i "^${DVDSUBLANG[m]}-" | cut -f2- -d-)
        Menu_DrawText $MENUSIZE $((MENUSIZE+offset+LEFTPANELW+(m/lpc)*subwidth)) $((offset+MENUSIZE+(m%lpc)*(MENUSIZE+MENUSTEP))) "$subtxt" \
          "$output".vtsm_sub0.png || Menu_Err $FUNCNAME $LINENO
        w=$(Menu_Titlesize "$subtxt" $MENUSIZE h)
        ((WLABEL<w+MENUSIZE/2)) && WLABEL=$((w+MENUSIZE/2))
    done
    if ((TOTOVER)); then
        Menu_DrawText $MENUSIZE $((MENUSIZE+offset+LEFTPANELW+(m/lpc)*subwidth)) $((offset+MENUSIZE+(m%lpc)*(MENUSIZE+MENUSTEP))) "None" \
          "$output".vtsm_sub0.png || Menu_Err $FUNCNAME $LINENO
    fi

    if ((TOTOVER)); then
        ((spusub<32)) && btext=(Return Main-Menu) || btext=(Main-Menu) 
        [[ $multiaudio ]] && btext[${#btext[*]}]=Audio
        [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && btext[${#btext[*]}]=Chapters
    else
        btext=("" "Next   >>|" "Prev   |<<")
    fi
    for ((m=0;m<${#btext[*]};m++)); do
        Menu_DrawText $MENUSIZE $((MENUSIZE+offset)) $((MENU_V_RES-2*TVOSY-offset-m*(MENUSIZE+MENUSTEP))) "${btext[m]}" "$output".vtsm_sub0.png || \
          Menu_Err $FUNCNAME $LINENO
    done

    for ((i=1;i<=TOTOVER;i++)); do
        convert -size $((MENU_H_RES-TVOSX*2))x$((MENU_V_RES-TVOSY*2)) xc:none "$output".vtsm_sub$i.png || Menu_Err $FUNCNAME $LINENO
        for ((m=0;m<=spusub;m++)); do
            Menu_DrawPolyLine "${overlayc[i]}" $((offset+LEFTPANELW+(m/lpc)*subwidth)) $((offset+MENUSIZE+(m%lpc)*(MENUSIZE+MENUSTEP))) \
              "$output".vtsm_sub$i.png $((WLABEL+MENUSIZE)) || Menu_Err $FUNCNAME $LINENO
        done
        for ((m=0;m<${#btext[*]};m++)); do
            Menu_DrawPolyLine "${overlayc[i]}" $offset $((MENU_V_RES-2*TVOSY-offset-m*(MENUSIZE+MENUSTEP))) "$output".vtsm_sub$i.png || \
              Menu_Err $FUNCNAME $LINENO
        done
        Menu_ComposeFrame ${MENU_H_RES}x${MENU_V_RES} "$output".vtsm_sub$i.png "$output".vtsm_sub$i.png || Menu_Err $FUNCNAME $LINENO
        if ((MASP==1)); then
            convert -gravity center -shave $(((MENU_H_RES-MENU_H_RES_PS)/2))x0 "$output".vtsm_sub$i.png "$output".vtsm_sub$((i+3)).png || \
              Menu_Err $FUNCNAME $LINENO
        elif ((MASP==2)); then
            Menu_ComposeFrame ${MENU_H_RES_PS}x${MENU_V_RES_LB} "$output".vtsm_sub$i.png "$output".vtsm_sub$((i+3)).png 1 || Menu_Err $FUNCNAME $LINENO
        fi
    done

    CLEAN[${#CLEAN[*]}]="$output".vtssubbg.png
    convert -scale ${MENU_H_RES}x${MENU_V_RES}! \
      -fill $(rgba 255 255 255 96) -draw "rectangle $TVOSX,$TVOSY $((TVOSX+LEFTPANELW)),$((MENU_V_RES-TVOSY))" -fill $(rgba 128 192 255 128) \
      -draw "roundrectangle $((TVOSX+LEFTPANELW+2)),$((TVOSY+2)) $((TVOSX+LEFTPANELW+WLABEL+3*MENUSIZE/2+(spusub/lpc)*subwidth)),$((TVOSY+2+(spusub<lpc?spusub+(TOTOVER?1:0):lpc)*(MENUSIZE+MENUSTEP))) 10,10" \
      "$output".bg.png "$output".vtssubbg.png || Menu_Err $FUNCNAME $LINENO

    composite -compose Over -gravity Center "$output".vtsm_sub0.png "$output".vtssubbg.png "$output".vtsm_sub0.png || Menu_Err $FUNCNAME $LINENO
    rm "$output".vtssubbg.png && unset CLEAN[${#CLEAN[*]}-1]
    mogrify -geometry ${H_STILL}x${V_STILL}! "$output".vtsm_sub0.png || Menu_Err $FUNCNAME $LINENO
    [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".vtssub.mpeg
    if ((TOTOVER)); then
        mogrify +antialias $ICOL -filter Point -geometry ${H_STILL}x${V_STILL}! "$output".vtsm_sub[12].png "${EXTRAARG[@]}" || Menu_Err $FUNCNAME $LINENO
        Menu_MakeMpeg "$(echo "$output"| sed 's/%/%%/g')".vtsm_sub0.png $MenuFr $encFrameRate "$output".menu.mp2 "$output".vtssub.mpeg \
          "$output".vtsm_sub1.png "$output".vtsm_sub2.png 4 "" $((3-!MASP)) "${EXTRAARG[@]}"
    else
        Menu_MakeStillMpeg "$(echo "$output"| sed 's/%/%%/g')".vtsm_sub0.png "$output".vtssub.mpeg
        echo '    <segment-item src="'"$(xmlchar "$output")".vtssub.mpeg'" id="vts-sub" />' >>"$output".segment.xml
        { echo '    <playlist id="play-subtitle">'
          if [[ $multiaudio ]]; then
              PREV=play-audio
          elif [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]]; then
              PREV=play-ptt-01
          else
              PREV=play-root
          fi
          echo '      <prev ref="'"$PREV"'"/>'
          echo '      <next ref="play-info"/>'
          echo '      <return ref="play-root"/>'
          echo '      <wait>-1</wait>'
          echo '      <play-item ref="vts-sub"/>'
          echo '    </playlist>'
        } >>"$output".selection.xml
    fi
}
###############################################################################
Menu_ProcessTitle () {
    local titleset n srcline audiolang sublang a m
    titleset=$(grep -c '<!-- addtitleset .* \/\/-->' "$output".dvd.xml)
    ((titleset)) || return
    rm -f "$output".tmp.xml
    CLEAN[${#CLEAN[*]}]="$output".tmp.xml
    #### make a new titleset section for every addtitleset
    for ((n=1;n<=titleset;n++)); do
        #### find the line with addtitleset
        srcline=$(awk -v i=$n '/<!-- addtitleset .* \/\/-->/{l+=1;if(l==i){print NR;exit}}' <"$output".dvd.xml)
        #### retrive the lang information
        audiolang=$(sed $srcline'!d;s/.*addtitleset //;s/ \/\/-->//' "$output".dvd.xml)
        sublang=${audiolang#*-}
        audiolang=${audiolang%-*}
        #### create the new titleset description
        { echo '  <titleset>'
          echo '    <menus>'
          echo '      <pgc entry="root" pause="0">'
          echo '        <pre> if (g7 eq 0) jump title 1; else jump titleset 1 menu; </pre>'
          echo '      </pgc>'
          echo '    </menus>'
          echo '    <titles>'
          if [[ $audiolang ]]; then
              for a in ${audiolang/,/ } ; do
                  echo '      <audio lang="'$a'" />'
              done
          fi
          if [[ $sublang ]]; then
              for a in ${sublang/,/ } ; do
                  echo '      <subpicture lang="'$a'" />'
              done
          fi
          #### copy pgc line
          sed -n "$((srcline+1))p" "$output".dvd.xml
          #### make pre line with menu number to jump
          sed -n "$((srcline+3))s/.*jump menu \([^;]*\).*/        <pre> g7=\1; <\/pre>/p" "$output".dvd.xml
          #### copy vob post /pgc lines
          sed -n "$((srcline+2)),$((srcline+4))p" "$output".dvd.xml
          echo '    </titles>'
          echo '  </titleset>'
        } >>"$output".tmp.xml
    done
    #### remove /dvdauthor
    sed -i '$d' "$output".dvd.xml
    #### add titleset section and modify post line
    sed '/<post>/s/jump menu [^;]*/call menu/' "$output".tmp.xml >>"$output".dvd.xml
    m=2
    #### for every titleset section added
    for a in $(awk '/<titleset>/{i+=1;if(i>1)print NR}' <"$output".dvd.xml)  ; do
        #### find the original vob line in the first titleset
        n=$(cat -n "$output".dvd.xml | grep -e "$(sed $a',/<\/titleset>/!d;/vob file/!d' "$output".dvd.xml)" | awk '{print $1;exit}')
        #### replace vob and post lines with a single pre line
        sed -i $n's@<.*>@<pre> jump titleset '$((m++))' menu; </pre>@;'$((n+1))'d' "$output".dvd.xml
    done
    #### find the last root menu to jump
    m=$(sed '/g7=/!d;s/.*g7=//;s/[^0-9].*//' "$output".dvd.xml | sort -n | tail -1)
    #### in every root menu where to jump
    for ((a=1;a<m;a++)) ; do
        #### find the pre line in the root menu a, add if command at the beginning
        sed -i $(awk -v t=$a '/<titleset>/{i+=1}/pre/{if(i==1){m+=1;if(m==t){print NR;exit}}}' \
          <"$output".dvd.xml)'s/{ /&if (g7 gt '$a') jump menu '$((a+1))'; else g7=0; /' "$output".dvd.xml
    done
    #### find the pre line in the root menu m, add if command at the beginning
    sed -i $(awk -v t=$a '/<titleset>/{i+=1}/pre/{if(i==1){m+=1;if(m==t){print NR;exit}}}' \
      <"$output".dvd.xml)'s/{ /&g7=0; /;/<!-- addtitleset .* \/\/-->/d' "$output".dvd.xml
    #### add /dvdauthor
    echo '</dvdauthor>' >>"$output".dvd.xml
}
#### end menu functions

#### test
if ((${#ftest[*]})); then
    "${ftest[@]}"
    exit
fi


###############################################################################
#### ERROR if some options conflict is detected part 2/2 #### TESTS ###########
###############################################################################
#### libavcodec codec/asr/abr
#### libtoolame asr/abr
#### libmp3lame asr
#### no check is done on the other channel in case of multiaudio
if [[ $encode == [2-8]:?:? ]]; then
    if [[ $srate ]]; then
        r=$srate
    else
        [[ $audioonly ]] && r=$asr s=asr || r=$(id_find ID_AUDIO_RATE "${MPLAYERINFO[@]}") s=srate
        if [[ ! $r ]]; then
            do_log "++ WARN: [$PROGNAME] failure to detect the audio sample rate of the input stream"
            [[ ! $multiaudio && ! $audioid ]] && do_log "++ WARN: [$PROGNAME] if your source video does not have audio use -encode 0:${encode#*:}" || \
              do_log "++ WARN: [$PROGNAME] probably is incorrect the audio stream selected with -${audioid:+aid}${multiaudio:+multiaudio}"
        fi
        if [[ $mpeg && ! $usespeed ]]; then
            case $frameformat in
                *VCD) ((r != 44100)) && do_log "++ WARN: [$PROGNAME] $frameformat standard requires 44100kHz audio, add -$s 44100" ;;
                DVD)  ((r != 48000)) && do_log "++ WARN: [$PROGNAME] $frameformat standard requires 48000kHz audio, add -$s 48000" ;;
            esac
        fi
    fi
    if [[ $encode == [4-7]:?:? ]]; then
        check_mencoder_abr "$r" ${AUDIOPASS##*=}
    elif [[ $encode == 8:?:? ]]; then
        case $r in
            8000|11025|12000|16000|22050|24000|32000|44100|48000|64000|88200|96000) : ;;
            *) echo "**ERROR: [$PROGNAME] libfaac does not support $r Hz sample rate" ; exit 1 ;;
        esac
    else
        case $r in
            8000|11025|12000|16000|22050|24000|32000|44100|48000) : ;;
            *) echo "**ERROR: [$PROGNAME] libmp3lame does not support $r Hz sample rate" ; exit 1 ;;
        esac
    fi
fi
if ((step>1)); then
    if [[ ${!audioformat} = mencoder ]]; then
        check_abr $audioformat $asr $abr || ! echo "**ERROR: [$PROGNAME] libavcodec does not support $abr kbps / $asr Hz for $audioformat" || exit 1
    fi
    if [[ ${!audioformat} = mp2enc || ${!audioformat} = musicin || ${!audioformat} = mctoolame ]]; then
        case $asr in
            16000|22050|24000) 
                echo -n "**ERROR: [$PROGNAME] ${!audioformat} does not support $asr Hz"
                if [[ ${!audioformat} = mp2enc ]]; then
                    [[ $audioformat = mp2 ]] && echo -n ", use toolame or mencoder instead" || echo -n ", use encode instead. See the README"
                fi
                echo
                exit 1
                ;;
        esac
    fi
    if [[ ${!audioformat} = mp2enc || ${!audioformat} = encode || ${!audioformat} == *lame ]]; then
        check_abr $audioformat $asr $abr || ! echo "**ERROR: [$PROGNAME] ${!audioformat} does not support $abr kbps / $asr Hz for $audioformat" || exit 1
    fi
fi
#### copy of non-MPEG audio in a VCD
if [[ $step -gt 1 && ( $frameformat = VCD || $frameformat = MPEG1 ) && $encode == 0:?:? && ( $mpeg || ${!audioformat} = copy ) && ! $testmca && ! $pictsrc ]]; then
    a=$(id_find ID_AUDIO_CODEC "${MPLAYERINFO[@]}")
    [[ $a != mp3 ]] && echo "**ERROR: [$PROGNAME] you cannot copy $a audio in a $frameformat" && exit 1
fi
#### mpegchannels > 2 only with ac3 and aac
[[ $mpeg && ${mpegchannels:-2} -gt 2 && $encode == [2-57]:?:? ]] && CODEC=([2]=mp3 mp3 mp2 mp3 [7]=mp2) && \
  echo "**ERROR: [$PROGNAME] audio codec ${CODEC[${encode%%:*}]} selected with -encode $encode do not support more than 2 audio channels" && exit 1
#### avimerge-non mp3/ac3
if [[ $multiaudio && $encode == [1,4,7]:?:? && ! $mpeg ]]; then
    echo "**ERROR: [$PROGNAME] avimerge works only with mp3 and ac3 audio" && exit 1
fi
#### -profile/-avionly
((${#PROFILE[*]}&&step!=1)) && echo "**ERROR: [$PROGNAME] -profile requires -avionly" && exit 1
#### -audioonly/DIRECT Mode
if [[ $audioonly ]]; then
    if [[ ! $encode && $step -gt 1 && ${#TITLESET[*]} -eq 0 ]]; then
        echo "**ERROR: [$PROGNAME] -audioonly does not work in DIRECT Mode"
        rm -f "$output".wav
        exit 1
    fi
    for a in identify convert ; do
        ! type $a &>/dev/null && echo "**ERROR: [$PROGNAME] $a(ImageMagick) missing, it is required by -audioonly" && rm -f "$output".wav && exit 1
    done
fi
#### -multisrc check
if [[ $mpeg && ${#MSRC[*]} -gt 0 ]]; then
    ((${#MSRC[*]} != audiostream)) && echo "**ERROR: [$PROGNAME] -multisrc (${#MSRC[*]}) and -multiaudio ($audiostream) inconsistence" && exit 1
    ((${#encsid[*]})) && echo "**ERROR: [$PROGNAME] -multisrc and -encsid cannot be used together" && exit 1
    for ((i=0;i<${#MENCODERARG[*]};i++)) ; do
        [[ ${MENCODERARG[i]} = "${MSRC[0]}" ]] && break
    done
    ((i==${#MENCODERARG[*]})) && echo "**ERROR: [$PROGNAME] -multisrc inconsistence" && exit 1
fi
#### -addchapter
if [[ $addchapter && $addchapter != copy && $addchapter != *-* ]]; then
    echo $addchapter | awk -F, '{for(a=1;a<=NF;a++)if($a=="")exit 1}' || ! echo "**ERROR: [$PROGNAME] wrong argument of -addchapter (empty field)" || exit 1
    ( IFS=, ; for a in $addchapter ; do echo $(time2sec $a) ; done ) | awk 'BEGIN{m=-1}{if(m<$1)m=$1;else exit 1}' || \
      ! echo "**ERROR: [$PROGNAME] wrong argument of -addchapter (fields not in ascending order)" || exit 1
fi

###############################################################################
#### ERROR if some required tools are missing #### TESTS ######################
###############################################################################
#### avimerge
if [[ $encode && $multiaudio && ! $mpeg ]]; then
    type avimerge &>/dev/null || ! echo "**ERROR: [$PROGNAME] -encode and -multiaudio requires avimerge(transcode)" || exit 1
fi
#### avisplit
if [[ $encode && $avisplit ]]; then
    type avisplit &>/dev/null || ! echo "**ERROR: [$PROGNAME] -avisplit requires avisplit(transcode)" || exit 1
fi
#### mjpegtools
if [[ $step -gt 1 ]]; then
    list="yuvscaler mpeg2enc"
    [[ $step -gt 2 ]] && list="$list mplex"
    for a in $list ; do
        type $a &>/dev/null || ! echo "**ERROR: [$PROGNAME] $a(mjpegtools) missing" || exit 1
    done
fi
#### mp1
if [[ $audioformat = mp1 ]]; then
    type encode &>/dev/null || type mp2enc &>/dev/null || \
      ! echo "**ERROR: [$PROGNAME] mp2enc or encode missing, cannot create mp1 audio. See the README" || exit 1
fi
#### vcdimager
if [[ $step -gt 3 && $frameformat == *VCD ]]; then
    if ! type vcdimager &>/dev/null ; then
        type vcdxbuild &>/dev/null || ! echo "**ERROR: [$PROGNAME] vcdxbuild missing, cannot create S/VCD image" || exit 1
        type vcdxgen &>/dev/null || ! echo "**ERROR: [$PROGNAME] vcdxgen missing, cannot create S/VCD image" || exit 1
    fi
    if ! type vcdxbuild &>/dev/null || ! type vcdxgen &>/dev/null ; then
        vcdxgen () { : ; }
        type vcdimager &>/dev/null || ! echo "**ERROR: [$PROGNAME] vcdimager missing, cannot create S/VCD image" || exit 1
        cdi=
    fi
fi
#### dvdauthor
if [[ $step -gt 3 && $frameformat = DVD ]]; then
    type dvdauthor &>/dev/null || ! echo "**ERROR: [$PROGNAME] dvdauthor missing, cannot create DVD filesystem" || exit 1
    (( $(dvdauthor 2>&1 | sed 's/[^0-9]*//;s/[^0-9]*$//;s/\([0-9.]*\).*/\1/;s/\([^.]*\)\./(\1)*100+/;s/\([^.]*\)\./(\1)*100+/;q') <612 )) && \
      do_log "**ERROR: [$PROGNAME] you need dvdauthor 0.6.14 or later." && exit 1
fi
#### cdrdao
if [[ $step -gt 4 && $frameformat == *VCD ]]; then
    type cdrdao &>/dev/null || ! echo "**ERROR: [$PROGNAME] cdrdao missing, cannot burn S/VCD" || exit 1
fi
#### growisofs and mkisofs
if [[ $step -gt 4 && $frameformat = DVD || $burniso ]]; then
    type growisofs &>/dev/null || ! echo "**ERROR: [$PROGNAME] growisofs missing, cannot burn DVD" || exit 1
    type mkisofs &>/dev/null || ! echo "**ERROR: [$PROGNAME] mkisofs missing, cannot create the DVD iso image" || exit 1
fi
#### ttf font
if ((${#txtsub[*]}&&step>1)); then
    [[ ! -d ~/.spumux ]] && echo "**ERROR: [$PROGNAME] the directory $HOME/.spumux, required by the option -txtsub, does not exist" && exit 1
    [[ ! -f ~/.spumux/arial.ttf ]] && echo "**ERROR: [$PROGNAME] option -txtsub requires the font $HOME/.spumux/arial.ttf" && exit 1
fi
#### mp2 multichannel audio
if [[ $audioformat = mp2 ]]; then 
    [[ ${mpegchannels:-2} -gt 2 && $mp2 != musicin && $mp2 != mctoolame ]] && \
       echo "**ERROR: [$PROGNAME] the mp2 encoder selected ($mp2) does not support $mpegchannels audio channels, select an appropriate encoder or reduce the number of channels" && exit 1
    [[ ( $mp2 = musicin || $mp2 = mctoolame ) && ${mpegchannels:-2} -le 2 ]] && \
      echo "**ERROR: [$PROGNAME] the mp2 encoder selected ($mp2) can be used only with -mpegchannels <3-6>" && exit 1
    if [[ $mp2 = musicin || $mp2 = mctoolame ]]; then 
        for a in $mp2 musicout pcm2aiff ; do
            type $a &>/dev/null || ! echo "**ERROR: [$PROGNAME] $a missing, cannot use mp2 multichannel audio encoder $mp2" || exit 1
        done
    fi
fi
#### identify
[[ $pictsrc ]] && ! type identify &>/dev/null && echo "**ERROR: [$PROGNAME] identify(ImageMagick) missing, cannot make movie from image files" && exit 1
#### -menu/ImageMagick
[[ $menu ]] && ((iver<554||iver>607&&iver<613||iver==617)) && \
  echo "**ERROR: [$PROGNAME] option -menu requires ImageMagick 5.5.4-6.0.7 or 6.1.3-6.1.6 or 6.1.8-6.3.x" && exit 1
 
###############################################################################
#### set cleanup
###############################################################################
trap 'job_exit' 0
CLEAN[${#CLEAN[*]}]="$output".fifo

###############################################################################
#### resume or start a new log file
###############################################################################	
skip=0
LG=1
[[ -f $output.log ]] || resume=
if [[ ! $resume ]] ; then
    #### start the log file
    { if [[ $LOG ]]; then
          echo "$LOG"
      else
          STARTTIME=$(pr_time)
          echo "### LOG: $output $(pr_date)" 
      fi
      echo -n "   INFO: [$PROGNAME] version $VERSION running in "
      if ((${#TITLESET[*]})); then
          echo -n "Titleset Mode"
      elif ((!step)); then
          echo -n "Cache Mode"
      elif [[ $mpeg ]]; then
          [[ $testmca ]] && echo -n "Testmca Mode" || echo -n "MPEG Mode"
      elif [[ $encode ]]; then
          echo -n "AVI Mode"
      elif ((step>1)); then
          echo -n "DIRECT Mode"
      else
          [[ $ocr ]] && echo -n "Ocr Mode" || echo -n "Vobsub Mode"
      fi
      [[ $burniso ]] && echo -n " + BurnIso"
      [[ $verify ]] && echo -n " + Verify"
      echo "${cpu:+ (cpu=$cpu)}"
      echo "   INFO: [$PROGNAME] command line: '${CMD[@]}'"
    } >"$output".log
else
    #### resume from a previous run
    eval "$(tail -1 "$output".log | tr '\015' '\012')"
    a="   INFO: [$PROGNAME] resuming from previous run $(pr_date)"
    echo "$a" | sed 's/[^ ]/=/g' >>"$output".log
    do_log "$a"
    ((!iter)) && STARTTIME=$(pr_time)
    { echo -n "   INFO: [$PROGNAME] "
      [[ $iter -eq 0 || $bakiter ]] && echo -n "resume "
      echo "command line: '${CMD[@]}'"
    } | tee -a "$output".log
    for a in $clear ; do
        [[ $iter -gt 0 && $a != img ]] && continue
        status_bit $a clear
    done
fi

###############################################################################
#### -audioonly
###############################################################################
if [[ $audioonly ]] ; then
    CLEAN[${#CLEAN[*]}]="$output".test.png
    if [[ $audioonlybg ]];then
        if [[ $audioonlyopt = 0 ]]; then
            convert -scale ${ARES[${mpegaspect:-2}]}x${ARES[1]}! "$audioonlybg" "$output".test.png || Menu_Err -audioonly $LINENO
        else
            convert -geometry ${ARES[${mpegaspect:-2}]}x${ARES[1]} "$audioonlybg" "$output".test.png || Menu_Err -audioonly $LINENO
            convert -size ${ARES[${mpegaspect:-2}]}x${ARES[1]} xc:black png:- | \
              composite -compose Over -gravity center "$output".test.png - "$output".test.png || Menu_Err -audioonly $LINENO
        fi
        if [[ $audioonlytxt ]];then
            Menu_MakeTitle "$audioonlytxt" "$output".test.png || Menu_Err -audioonly $LINENO
        fi
    else
        convert -size ${ARES[${mpegaspect:-2}]}x${ARES[1]} -depth 8 gradient:white-darkblue -implode 3 -swirl $((5*270)) -implode 1 "$output".test.png || \
          Menu_Err -audioonly $LINENO
        Menu_MakeTitle "${audioonlytxt:-\n\nAudio\n\nOnly\n\nhttp://encode2mpeg.sf.net}" "$output".test.png || Menu_Err -audioonly $LINENO
    fi
fi

###############################################################################
#### WARNING if some requested tools are missing and can be replaced #### TESTS
###############################################################################
#### WARN
if [[ $WARN ]]; then
    echo -e "$WARN" >>"$output".log
fi
#### mjpegtools 1.8.0
if ((step >1 && $(yuvscaler </dev/null 2>&1 | awk '{print $4 $5;exit}' | sed 's/[^0-9]*\([0-9.]*\).*/\1/;s/\([^.]*\)\./(\1)*100+/;s/\([^.]*\)\./(\1)*100+/') <10800)) ; then
    do_log "++ WARN: [$PROGNAME] you need mjpegtools 1.8.0 or later"
fi
#### yuvdenoise
if [[ $YUVDENOISE ]]; then
    type ${YUVDENOISE%% *} &>/dev/null || ! do_log "++ WARN: [$PROGNAME] ${YUVDENOISE%% *} missing, denoising disabled" || YUVDENOISE=
fi
#### encode
if [[ ${!audioformat} = encode ]]; then
    type encode &>/dev/null || ! do_log "++ WARN: [$PROGNAME] encode missing, using mp2enc instead. See the README" || eval ${audioformat}=mp2enc
fi
#### toolame
if [[ ${!audioformat} = toolame ]]; then
    type toolame &>/dev/null || ! do_log "++ WARN: [$PROGNAME] toolame missing, using mp2enc instead" || eval ${audioformat}=mp2enc
fi
#### mp2enc
if [[ ${!audioformat} = mp2enc && $audioformat = mp2 ]]; then
    type mp2enc &>/dev/null || ! do_log "++ WARN: [$PROGNAME] mp2enc missing, using libavcodec instead" || eval ${audioformat}=mencoder
fi
#### lame
if [[ ${!audioformat} = lame ]]; then
    type lame &>/dev/null || ! do_log "++ WARN: [$PROGNAME] lame missing, using libavcodec" || eval ${audioformat}=mencoder
fi
#### avimerge
if [[ $encode && $multiaudio && ! $mpeg ]]; then
    (( $(avimerge | awk '{print $3;exit}'| sed 's/[^0-9]*//;s/\([0-9.]*\).*/\1/;s/\([^.]*\)\./(\1)*100+/;s/\([^.]*\)\./(\1)*100+/') <613 )) && \
      do_log "++ WARN: [$PROGNAME] you need avimerge 0.6.13 or later" && echo -n "Press return to proceed" && read && \
      MENCODERARG[${#MENCODERARG[*]}]=-noodml
fi
#### usesbr and multiaudio
if [[ $usesbr && $multiaudio ]]; then
    ((usesbr<=6)) && \
      do_log "++ WARN: [$PROGNAME] -multiaudio selected but -usesbr does not specify the file size in MB, the length of the output file will be bigger"
fi 
#### volume and audio copy
if [[ $volume ]]; then
    [[ $encode == 0:?:? && ( ${!audioformat} = copy || $step -eq 1 || $mpeg ) || ${!audioformat} = copy && ! $encode ]] && \
      do_log "++ WARN: [$PROGNAME] you cannot modify the volume of the output audio stream if you are making a copy the input audio stream"
fi
#### cpu and bframes
if [[ $cpu && $bframes ]]; then
    ((bframes)) && do_log "++ WARN: [$PROGNAME] with bframes>0 the encoding will be faster with cpu=1"
fi
#### vcdxbuild
if [[ $addchapter && $frameformat == *VCD ]] ; then
    ! type vcdxbuild &>/dev/null || ! type -f vcdxgen &>/dev/null && \
      do_log "++ WARN: [$PROGNAME] vcdxbuild or vcdxgen missing, disabling -addchapter for $frameformat" && addchapter=
fi
#### cdi
if [[ $cdi && $frameformat = VCD ]]; then
    if [[ ! -d $cdi ]]; then
        do_log "++ WARN: [$PROGNAME] path to CD-i application files ($cdi) does not exist, CD-i compatibility disabled"
        cdi=
    else
        [[ ! -f $cdi/CDI_IMAG.RTF || ! -f $cdi/CDI_TEXT.FNT || ! -f $cdi/CDI_VCD.APP ]] && \
          do_log "++ WARN: [$PROGNAME] some or all the CD-i application files not found in $cdi, CD-i compatibility disabled" && cdi=
    fi
fi
#### spumux/spuunmux
if ((${#addsub[*]}+${#txtsub[*]}&&step>1)) && [[ $frameformat != VCD && $frameformat != MPEG[12] ]] || ((${#addsub[*]}&&step==1)); then
    if ! type spuunmux &>/dev/null || ! type spumux &>/dev/null ; then
        ((${#addsub[*]})) && do_log "++ WARN: [$PROGNAME] spuunmux or spumux missing, -addsub disabled" && unset addsub
        ((${#txtsub[*]})) && do_log "++ WARN: [$PROGNAME] spuunmux or spumux missing, -txtsub disabled" && unset txtsub
    else
        (( $(spuunmux -V 2>&1 | sed 's/[^0-9]*//;s/[^0-9]*$//;s/\([0-9.]*\).*/\1/;s/\([^.]*\)\./(\1)*100+/;s/\([^.]*\)\./(\1)*100+/;q') <612 )) && \
          do_log "++ WARN: [$PROGNAME] you need spumux/spuunmux(dvdauthor) 0.6.14 or later"
    fi
fi
#### ImageMagick/png2yuv
if [[ $menu ]]; then
    for a in identify convert mogrify composite montage ; do
        type $a &>/dev/null || ! echo "++ WARN: [$PROGNAME] $a(ImageMagick) missing, disabling menu" || menu=
    done
    type png2yuv &>/dev/null || ! echo "++ WARN: [$PROGNAME] png2yuv(mjpegtools) missing, disabling menu" || menu=
fi
#### rotate
if [[ $rotate && ! ( $mpeg || $step -eq 1 ) ]]; then
    do_log "++ WARN: [$PROGNAME] -rotate is only allowed in AVI Mode or MPEG Mode, disabling it" && rotate=
fi
#### crop/autocrop
if [[ ( $autocrop || $crop ) && ! $encode && $step -gt 1 && ${#TITLESET[*]} -eq 0 ]]; then
    [[ $autocrop ]] && do_log "++ WARN: [$PROGNAME] -autocrop does not work in DIRECT Mode, disabling it" && autocrop=
    [[ $crop ]] && do_log "++ WARN: [$PROGNAME] -crop does not work in DIRECT Mode, disabling it" && crop=
fi
#### burniso
if [[ $burniso && $step -ge $MAXSTEP ]]; then
    do_log "++ WARN: [$PROGNAME] a standard $frameformat will be burned, disabling -burniso" && burniso=
fi
#### vcdxrip
if [[ $verify && $step -eq $MAXSTEP && $frameformat == *VCD ]]; then
    type vcdxrip &>/dev/null || ! do_log "++ WARN: [$PROGNAME] vcdxrip missing, disabling -verify" || verify=
fi
#### -profile
[[ ${PROFILE[1]} ]] && ((${PROFILE[1]}<zoom||-1*${PROFILE[1]}>zoom)) && \
  do_log "++ WARN: [profile] output width [$((zoom>0?zoom:-1*zoom))] exceed maximum [${PROFILE[1]}] allowed for profile ${PROFILE[0]}"
[[ ${PROFILE[6]} ]] && VBRTXT=( [2]=default [6]=maximum ) || VBRTXT=( [2]=maximum )
for a in 6 2 ; do
    [[ ${PROFILE[a]} ]] && ((vbr>${PROFILE[a]})) && \
      do_log "++ WARN: [profile] output vbitrate [$vbr] exceed ${VBRTXT[a]} [${PROFILE[a]}] allowed for profile ${PROFILE[0]}" && break
done
[[ ${PROFILE[3]} && $bframes ]] && ((bframes>${PROFILE[3]})) && \
  do_log "++ WARN: [profile] output bframes [$bframes] exceed maximum [${PROFILE[3]}] allowed for profile ${PROFILE[0]}"
[[ ${PROFILE[7]} ]] && awk 'BEGIN{a='$ofps';b='${PROFILE[7]}';if(a<=b)exit 1}' && \
  do_log "++ WARN: [profile] output fps [$ofps] exceed maximum [${PROFILE[7]}] allowed for profile ${PROFILE[0]}"
#### overscan > 0 in AVI Mode
((step==1&&overscan<0)) && do_log "++ WARN: [$PROGNAME] in AVI Mode -overscan argument can only be positive; using -overscan ${overscan##-}" && \
  overscan=${overscan##-}
#### -usespeed
if [[ $usespeed && ( $encode == 0:?:? || $encode == ?:0:? ) ]]; then 
    do_log "++ WARN: [$PROGNAME] -usespeed may not work if you do not encode both audio and video." && echo -n "Press return to proceed" && read
fi
#### total br
[[ $encode != ?:0:? ]] && ((step>1&&abr*audiostream*1024/1000+vbr>MAXBR)) && \
  do_log "++ WARN: [$PROGNAME] total video+audio bitrate ($vbr+$((abr*audiostream*1024/1000))kbps) exceed $frameformat specifications (${MAXBR}kbps)"
#### -slideaudio/single picture
if [[ $slideaudio && $slideaudio != /dev/null && $pictsrc ]]; then
    ((${#PICTSRC[*]}!=1||$(ls "${PICTSRC[0]}" | wc -l)!=1)) && \
      do_log "++ WARN: [$PROGNAME] you should use only one source image if you use the option -slideaudio"
fi
#### pictsrc/aspect
[[ $pictsrc && $frameformat == MPEG[12] && ! $MPGRES && $mpegaspect -ne 1 ]] && do_log "++ WARN: [$PROGNAME] unscaled source picture, you should use -a 1"
#### last 2 digit
[[ $step -gt 3 && ${output: -2} == [0-9][0-9] ]] && do_log "++ WARN: [$PROGNAME] the last two characters of -o argument ($output) should not be digits"
#### -ocr
if [[ $ocr ]]; then
    ocr=
    split_ocrsub_opt 1 && s=selected || s=default
    case $OCRSUBOPT in
        [aA][uU][tT][oO]) : ;;
        tesseract|gocr|ocrad|ocradi)
            type ${OCRSUBOPT%i} &>/dev/null && ocr=$OCRSUBOPT || do_log "++ WARN: [$PROGNAME] $s ocr engine '${OCRSUBOPT%i}' not found, using builtin list"
            ;;
        *) do_log "++ WARN: [$PROGNAME] unsupported ocr engine '${OCRSUBOPT%i}', using builtin list" ;;
    esac
    if [[ ! $ocr ]]; then
        for a in tesseract gocr ocrad ; do
            type $a &>/dev/null && ocr=$a && break
        done
        [[ ! $ocr ]] && do_log "++ WARN: [$PROGNAME] no ocr engine found, disabling -ocr"
    fi
    if [[ $ocr ]]; then
        [[ $step -eq 1 && ${#addsub[*]} -eq 0 ]] && do_log "++ WARN: [ocr] no subtitle selected with -addsub"
        split_ocrsub_opt 6
        if [[ $OCRSUBOPT == [Oo][Nn] || $OCRSUBOPT -eq 1 || $OCRSUBOPT == [yY][eE][sS] ]]; then
            if [[ $DISPLAY ]]; then
                split_ocrsub_opt 7
                if [[ $OCRSUBOPT != [aA][uU][tT][oO] ]]; then
                    if type $OCRSUBOPT &>/dev/null; then
                        if [[ $OCRSUBOPT = konsole || $OCRSUBOPT = gnome-terminal ]]; then
                            ocrterm=$OCRSUBOPT
                        else
                            $OCRSUBOPT -help 2>&1 | grep -q -e -pixmap && ocrterm=$OCRSUBOPT || \
                              do_log "++ WARN: [ocr] terminal $OCRSUBOPT does not support backgroundPixmap, using builtin list"
                        fi
                    else
                        do_log "++ WARN: [ocr] terminal $OCRSUBOPT not found, using builtin list"
                    fi
                fi
                if [[ ! $ocrterm ]]; then
                    for a in urxvt rxvt Eterm aterm ; do
                        type $a &>/dev/null && $a -help 2>&1 | grep -q -e -pixmap && ocrterm=$a && break
                    done
                fi
                if [[ ! $ocrterm ]]; then
                    for a in konsole gnome-terminal ; do
                        type $a &>/dev/null && ocrterm=$a && break
                    done
                fi
                split_ocrsub_opt 6
                if [[ ! $ocrterm ]]; then
                    if ! type urxvt &>/dev/null && ! type rxvt &>/dev/null && ! type Eterm &>/dev/null && ! type aterm &>/dev/null && \
                      ! type konsole &>/dev/null && ! type gnome-terminal &>/dev/null; then
                        do_log "++ WARN: [ocr] none of urxvt, rxvt, Eterm, aterm, konsole and gnome-terminal found, disabling -ocropts :::::$OCRSUBOPT"
                    else
                        for a in urxvt rxvt Eterm aterm ; do
                            type $a &>/dev/null && ! $a -help 2>&1 | grep -q -e -pixmap && \
                              do_log "++ WARN: [ocr] $a compiled without backgroundPixmap support, disabling -ocropts :::::$OCRSUBOPT"
                        done
                    fi
                fi
                ! type convert &>/dev/null && do_log "++ WARN: [ocr] convert(ImageMagick) missing, disabling -ocropts :::::$OCRSUBOPT" && ocrterm=
            else
                do_log "++ WARN: [ocr] environment variable DISPLAY not set, disabling -ocropts :::::$OCRSUBOPT"
            fi
            if [[ $ocrterm ]]; then
                ocrtpre=
                ocrE=
                case $ocrterm in
                    *rxvt) ocrtopt=( -fg black -pixmap "$output".xpm\;1x1+0+0 -title ) ;;
                    Eterm) ocrtopt=( -f black -b white --background-pixmap "$output".xpm@=+0+0 --title ) ocrtpre=- ;;
                    aterm) ocrtopt=( $(aterm -help 2>&1 | awk '$1=="Usage"{if($2!="v1.00.00")print "-bgtype notile";exit}') \
                                     -txttype invert -pixmap "$output".xpm -title ) ;;
                    konsole) 
                        ocrtopt=( -schema $PROGNAME -T )
                        [[ -d ~/.kde/share/apps/konsole ]] || mkdir -p ~/.kde/share/apps/konsole
                        CLEAN[${#CLEAN[*]}]=~/.kde/share/apps/konsole/$PROGNAME.schema
                        { echo "title $PROGNAME"
                          echo -n "image tile "
                          [[ ${output:0:1} = / ]] && echo "$output.xpm" || echo "$PWD/$output.xpm"
                          echo "color 0 0 0 0 0 0"
                          echo "color 1 255 255 255 1 0"
                        } >~/.kde/share/apps/konsole/$PROGNAME.schema
                        ;;
                    gnome-terminal) 
                        ocrtopt=( --window-with-profile=$PROGNAME --disable-factory -t ) ocrtpre=- ocrE=x
                        AGTP=/apps/gnome-terminal/profiles
                        AGTG=/apps/gnome-terminal/global
                        mkdir -p ~/.gconf$AGTP/$PROGNAME
                        s=$(gconftool-2 -g $AGTG/profile_list)
                        echo "$s" | grep -q $PROGNAME || gconftool-2 -s $AGTG/profile_list -t list --list-type string "${s%]},$PROGNAME]"
                        gconftool-2 -s $AGTP/$PROGNAME/visible_name -t string $PROGNAME
                        gconftool-2 -s $AGTP/$PROGNAME/background_type -t string image
                        gconftool-2 -s $AGTP/$PROGNAME/background_image -t string "$output.xpm"
                        gconftool-2 -s $AGTP/$PROGNAME/foreground_color -t string "#000000"
                        gconftool-2 -s $AGTP/$PROGNAME/background_color -t string "#FFFFFF"
                        ;;
                esac
                split_ocrsub_opt 8
                [[ $OCRSUBOPT != default ]] && ocrtopt=( $ocrtpre-geometry $OCRSUBOPT "${ocrtopt[@]}" )
            else
                split_ocrsub_opt 6 && ocropts=$(echo $ocropts | cut -f1-5 -d:):0:$(echo $ocropts | cut -f7- -d:) || \
                  ocropts=$(echo $ocropts | awk -F: -v i=6 '{for(a=1;a<i;a++)printf($a":");printf("0");for(a=i+1;a<=NF;a++)printf(":"$a)}')
            fi
        fi
    fi
fi
#### -menuthumboffset
if [[ $menu && ${#thumboffset[*]} -gt 0 && ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]]; then
    [[ $frameformat != DVD ]] && do_log "++ WARN: [$PROGNAME] -menuthumboffset works only for DVD, ignoring it" && thumboffset=()
    ((TANIM)) && do_log "++ WARN: [$PROGNAME] -menuthumboffset does not work with animated thumbnails, ignoring it" && thumboffset=()
fi
#### -menuextra
if [[ $menu && ${#MEXTRATXT[*]} -gt 0 ]]; then
    check_mfaspect () {
        local o
        o=$(split_sub_opt "${MEXTRAOPT[$1]}" 1)
        if [[ ! $o || $o -eq 1 ]]; then
            ( IFS=,
              m=0
              for b in ${MEXTRAARG[${MEXTRAIND[$1]}]#mf://} ; do
                  as=$(Menu_Picsize "$b" | awk -Fx '{printf("%.3f\n",$1/$2)}')
                  t=$(identify "$b" | awk '{print $2}')
                  ((!m)) && AS=$as F=$b T=$t m=$((++m)) && continue
                  [[ $as != $AS ]] && do_log "++ WARN: [$PROGNAME] aspect of -menuextra ${MEXTRATXT[a]} argument $b ($as) is different from $F ($AS)"
                  [[ $t != $T ]] && do_log "++ WARN: [$PROGNAME] image type of -menuextra ${MEXTRATXT[a]} argument $b ($t) is different from $F ($T): it may cause a failure"
              done 
            )
        fi
    }
    for ((a=0;a<${#MEXTRATXT[*]};a++)); do
        k=$((${MEXTRAIND[a+1]}-${MEXTRAIND[a]}))
        if ((k>1)); then
            s=$(echo ${MEXTRAARG[${MEXTRAIND[a]}]##*.} | tr '[:upper:]' '[:lower:]')
            if [[ ${MEXTRAARG[${MEXTRAIND[a]}]:0:5} = mf:// || $s = mpg || $s = mpeg || $s = vob ]]; then
               [[ ${MEXTRAARG[${MEXTRAIND[a]}]:0:5} = mf:// ]] && check_mfaspect $a
                for ((m=1;m<k;m++)); do
                    do_log "++ WARN: [$PROGNAME] -menuextra ${MEXTRATXT[a]} accepts only one argument of type ${MEXTRAARG[${MEXTRAIND[a]}]}, ignoring ${MEXTRAARG[${MEXTRAIND[a]}+m]}"
                    unset MEXTRAARG[${MEXTRAIND[a]}+m]
                done
                for ((m=a;m<${#MEXTRATXT[*]};m++)); do
                    MEXTRAIND[m+1]=$((${MEXTRAIND[m+1]}-(k-1)))
                done
                MEXTRAARG=( "${MEXTRAARG[@]}" )
            else
                for ((b=1;b<k;b++)); do
                    s=$(echo ${MEXTRAARG[${MEXTRAIND[a]}+b]##*.} | tr '[:upper:]' '[:lower:]')
                    if [[ ${MEXTRAARG[${MEXTRAIND[a]}+b]:0:5} = mf:// || $s = mpg || $s = mpeg || $s = vob ]]; then
                        do_log "++ WARN: [$PROGNAME] -menuextra ${MEXTRATXT[a]} accepts after argument of type ${MEXTRAARG[${MEXTRAIND[a]}]} only arguments of the same type, ignoring ${MEXTRAARG[${MEXTRAIND[a]}+b]}"
                        for ((m=a;m<${#MEXTRATXT[*]};m++)); do
                            MEXTRAIND[m+1]=$((${MEXTRAIND[m+1]}-1))
                        done
                        unset MEXTRAARG[${MEXTRAIND[a]}+b]
                        MEXTRAARG=( "${MEXTRAARG[@]}" )
                        k=$((--k))
                        b=$((--b))
                    fi
                done
            fi
        else
            [[ ${MEXTRAARG[${MEXTRAIND[a]}]:0:5} = mf:// ]] && check_mfaspect $a
        fi
    done
fi

###############################################################################
#### dump some info in the log file
###############################################################################
logvar () {
    local i
    echo -n "$1"
    for ((i=0;i<${#VARS[*]};i++)) ; do
        echo -n "${VARS[i]}:${!VARS[i]} "
    done
}
{ VARS=(frameformat ${split:+split} vfr vbr abr asr ${mpegchannels:+mpegchannels} ${GOP:+GOP} audioformat) # audioformat must be the last
  VARS[${#VARS[*]}]=${!VARS[${#VARS[*]}-1]}
  [[ $volume && ! $encode ]] && VARS[${#VARS[*]}]=volume
  logvar "   MPEG: "
  echo -n "${multiaudio:+multiaudio:${multiaudio// /,} }"
  echo -n "mpegencoder:$([ $mpeg ] && echo mencoder || echo mpeg2enc)"
  [[ $mpegaspect ]] && echo -n " aspect:${ASPECT[mpegaspect]}"
  [[ $cdi && $frameformat = VCD ]] && echo -n " CD-i"
  [[ $telecine ]] && echo -n " telecine"
  echo
  if [[ $encode ]]; then
      VARS=(encode ${vcodec:+vcodec} ${volume:+volume} ${usesbr:+usesbr} ${avisplit:+avisplit} ${channels:+channels} ${cartoon:+cartoon} AUDIOPASS VIDEOPASS PASS)
      logvar "   $([ $mpeg ] && echo MPEG || echo \ AVI): "
      if ((PASS>1)); then
          [[ $turbo ]] && echo -n "TURBO:on " || echo -n "TURBO:off "
      fi
      txt=
      [[ $(echo $encode | cut -f 2 -d:) = 1 && $vcustom ]] && txt="video"
      [[ ${encode%%:*} == [28] && $acustom ]] && txt=${txt:+${txt} and} && txt="$txt audio"
      txt=${txt:+(custom ${txt} options)}
      echo $txt
  fi
  VARS=(${ocr:+ocr})
  if ((${#VARS[*]})); then
      logvar "    SUB: "
      echo
  fi
  [[ ! $resume ]] && { [[ $audioonly ]] && mp_identify "$audioonly" || mp_identify "${MPLAYERINFO[@]}" -frames 1 ; } | \
    grep '^ID_' | uniq | sed -n 'G;s/\n/&&/;/^\([ -~]*\n\).*\n\1/d;s/\n//;h;s/^/   INFO: [identify] /;P'
  VARS=(${encode:+MENCODERARG} MPLAYERYUVOPT)
  for ((i=0;i<${#VARS[*]};i++)) ; do
      s="INFO: \[${VARS[i]}] \${${VARS[i]}[*]}"
      eval echo "\ \ \ $s"
  done
  VARS=(${YUVDENOISE:+YUVDENOISE} YUVSCALEROPT MPEG2ENCOPT MPLEXOPT VCDIMAGEROPT CDRDAOOPT ${DVDAUTHOROPT:+DVDAUTHOROPT} GROWISOFSOPT)
  for ((i=0;i<${#VARS[*]};i++)) ; do
      echo "   INFO: [${VARS[i]}] ${!VARS[i]}"
  done
  if ((DEBUG)); then
      VARS=(MPLAYERINFO SUBDUMP MENCAUDIOOPT MENCAUDIOINFO CHAPTEROPT)
      for ((i=0;i<${#VARS[*]};i++)) ; do
          s="--DEBUG: \[${VARS[i]}] \${${VARS[i]}[*]}"
          eval echo "$s"
      done
  fi
  [[ ${PROFILE[0]} ]] && echo "   INFO: [profile] using profile: ${PROFILE[0]}"
} >>"$output".log
h_res=$(grep ID_VIDEO_WIDTH "$output".log | tail -1 | cut -f2 -d=)
v_res=$(grep ID_VIDEO_HEIGHT "$output".log | tail -1 | cut -f2 -d=)
if [[ $pictsrc ]]; then
    ((!h_res)) && h_res=$(Menu_Picsize "${PICTSRC[0]}" h)
    ((!v_res)) && v_res=$(Menu_Picsize "${PICTSRC[0]}" v)
fi
[[ $mpeg && $encode == ?:0:? ]] && H_RES=$h_res && V_RES=$v_res

###############################################################################
#### -titleset
###############################################################################
if ((${#TITLESET[*]})); then
    ((step <4)) && do_log "++ WARN: [$PROGNAME] -titleset selected, assuming -imageonly" && step=4
    skip_encode
fi

###############################################################################
#### -testmca
###############################################################################
if [[ $testmca ]] && status_bit avi ; then
    for a in identify convert mogrify ; do
        type $a &>/dev/null || ! echo "**ERROR: [$PROGNAME] $a(ImageMagick) missing, it is required by -testmca" || exit 1
    done
    [[ $vcodec = mpeg4 || $vcodec = xvid ]] && echo "**ERROR: [$PROGNAME] options -testmca and -vcodec $vcodec are not compatible" && exit 1
    do_log "$(mp_identify "$testmca" | sed -n '/^ID_/s/^/   INFO: [identify] /p' | uniq)"
    CLEAN[${#CLEAN[*]}]="$output".test.png
    convert -size ${ARES[${mpegaspect:-2}]}x${ARES[1]} -depth 8 gradient:white-darkblue -implode 3 -swirl $((5*270)) -implode 1 "$output".test.png || \
      Menu_Err -testmca $LINENO
    Menu_MakeTitle "\n\nTesting\n\nMPEG Multichannel Audio\n\nhttp://encode2mpeg.sf.net" "$output".test.png || Menu_Err -testmca $LINENO
    [[ $H_RES && $V_RES ]] && ! mogrify -geometry ${H_RES}x${V_RES}! "$output".test.png && Menu_Err -testmca $LINENO
    # make the MPEG from a single picture
    mencoder $VIDEOPASS -o "$output".mpg "${MENCODERARG[@]}" $AUDIOPASS mf://"$output".test.png -fps 1/$(grep ID_LENGTH "$output".log | tail -1 |cut -f2 -d=)
    mplayer "$output".mpg -dumpvideo -dumpfile /dev/fd/4 4>&1 >&2 | mplex $MPLEXOPT -o "$output".test.png /dev/stdin "$testmca" && \
      mv "$output".test.png "$output".mpg
    skip_encode
    [[ ! $fast ]] && for a in mpv mpa mpg ; do status_bit $a clear ; done && mv "$output".mpg "$output".$SUF
fi

###############################################################################
#### -cacheonly? then exit
###############################################################################
if ((!step)); then
    exit
fi

###############################################################################
#### put the volume in DB
###############################################################################
if [[ $volume ]]; then
    volume=$(awk -v a=$volume 'BEGIN{if(a>0) print 20*log(a)/log(10) ; else print 0}')
    af=${af:--af }${af:+,}volume=$volume
    [[ ! $encode || $encode == 0:?:? ]] && AF=${AF:--af }${AF:+,}volume=$volume
fi

###############################################################################
#### warn for old/svn version
###############################################################################
WTEXT="you need MPlayer 1.0rc1 or a later stable relase, $PROGNAME can fail\\nPress return to proceed"
if [[ ${mver:0:5} = 1.0rc ]] ; then
    [[ ${mver:5:1} -ge 1 ]] || ! echo -en "WARNING $WTEXT" || read
else
    if [[ $unsupported ]]; then
        do_log "++ WARN: [$PROGNAME] you are using an unsupported version of MPlayer,"
        do_log "++ WARN: [$PROGNAME] you may experience problems using some options"
    else
        echo -en "WARNING you have an unsupported version of MPlayer [$mver]\n$WTEXT" && read
    fi
    SVN=1
fi

###############################################################################
#### warn if ifps != ofps in DIRECT Mode
###############################################################################
if [[ ! $encode && ! $usespeed && $step -gt 1 && ${#TITLESET[*]} -eq 0 ]]; then
    FPS=($(grep ID_VIDEO_FPS "$output".log | cut -f2 -d=) [1]=23.976 24.000 25.000 29.970 30.000 50.000 59.940 60.000)
    if [[ ${FPS[0]} = ${FPS[4]} || ${FPS[0]} = ${FPS[5]} ]]; then
        FPS[9]=$(mplayer -nocache -quiet "${MPLAYERINFO[@]}" -vo null -nosound -benchmark -frames 60 2>/dev/null | awk '/^demux_mpg:/{print $2}')
        if [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps ]]; then
            [[ ${FPS[0]} = ${FPS[4]} ]] && FPS[0]="${FPS[1]}(${FPS[4]} 3:2 pulldown)" || FPS[0]="${FPS[2]}(${FPS[5]} 3:2 pulldown)"
        fi
    elif [[ ${FPS[0]} = ${FPS[3]} ]]; then
        FPS[9]=$(is_film2pal "${MPLAYERINFO[@]}")
        if [[ ${FPS[9]} ]]; then
            [[ ${FPS[9]} = 24fps ]] && FPS[0]="${FPS[2]}" || FPS[0]="${FPS[1]}"
            FPS[0]="${FPS[0]}(${FPS[3]} film2pal)"
        fi
    fi
    [[ ${FPS[0]%%(*} != ${FPS[vfr]} ]] && echo "WARNING DIRECT Mode: ifps=${FPS[0]}, ofps=${FPS[vfr]} [vfr=$vfr]" && \
      echo -ne "most probably audio/video will be out of sync unless you use -usespeed. Press return to proceed" && read
fi

###############################################################################
#### telecined (NTSC/PAL) MPEG copy/speed encoding change
###############################################################################
if [[ $mpeg && ( $encode == ?:0:? || $usespeed ) || $usespeed && ! $encode && $step -gt 1 ]]; then
    FPS=($(grep ID_VIDEO_FPS "$output".log | cut -f2 -d=) [1]=23.976 24.000 25.000 29.970 30.000 50.000 59.940 60.000)
    for ((i=1;i<9;i++)); do
        a=$(awk -v a=${FPS[0]} -v b=${FPS[i]} 'BEGIN{if (sqrt((a-b)*(a-b))<.02) print b}')
        if [[ $a ]]; then
            if [[ ${FPS[0]} != ${FPS[i]} ]]; then
                do_log "++ WARN: [$PROGNAME] input video frame rate is not exactly ${FPS[i]}fps"
                FPS[0]=${FPS[i]}
            fi
            FPS[10]=$i
            break
        fi
    done
    [[ $usespeed && $i -eq 9 ]] && do_log "++ WARN: [$PROGNAME] input video frame rate is not a valid NTSC/PAL value; disabling -usespeed" && usespeed=
    
    if [[ ${FPS[0]} = ${FPS[4]} || ${FPS[0]} = ${FPS[5]} ]]; then
        FPS[9]=$(mplayer -nocache -quiet "${MPLAYERINFO[@]}" -vo null -nosound -benchmark -frames 60 2>/dev/null | awk '/^demux_mpg:/{print $2}')
        [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps ]] && FPS[10]=$((FPS[10]-3))
    elif [[ ${FPS[0]} = ${FPS[3]} ]]; then
        FPS[9]=$(is_film2pal "${MPLAYERINFO[@]}")
        if [[ ${FPS[9]} ]]; then
            [[ ${FPS[9]} = 24fps ]] && FPS[10]=2 || FPS[10]=1
        fi
    fi
    if [[ $usespeed ]]; then
        if ((vfr!=${FPS[10]})); then
            NSPEEDCOEF=([1]=1001 1001 5 1001 1001 5 1001 25 1250 5 25 2500 5 1200 6 2 2400 12 1001 1001 2 1001 5 2000 2 1200 6 1001 )
            MSPEEDCOEF=([1]=1000  960 4  800  480 2  400 24 1001 4 12 1001 2 1001 5 1 1001  5 1000  200 1  500 3 1001 1 1001 5 1000 )
            DCOEF=([1]=-2 3 7 10 12 13 13)
            if ((vfr>${FPS[10]})); then
                #### black magic here ;-)
                n=$((vfr+${FPS[10]}+${DCOEF[${FPS[10]}]}))
                a=${NSPEEDCOEF[n]}/${MSPEEDCOEF[n]}
            else
                n=$((vfr+${FPS[10]}+${DCOEF[vfr]}))
                a=${MSPEEDCOEF[n]}/${NSPEEDCOEF[n]}
            fi
            MENCODERARG=( -speed $a -srate $asr -af-adv force=1 "${MENCODERARG[@]}" )
            MPLAYERYUVOPT=("${MPLAYERYUVOPT[@]}" -speed $a )
            do_log "   INFO: [usespeed] using speed factor $a"
        fi
    elif [[ ${FPS[0]} = ${FPS[4]} || ${FPS[0]} = ${FPS[5]} || ${FPS[0]} = ${FPS[3]} ]]; then
        if [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps || $telesrc ]]; then
            { echo -n "   INFO: [$PROGNAME] "
              [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps ]] && echo -n "detected" || echo -n "user selected"
              [[ ${FPS[0]} = ${FPS[3]} ]] && echo -n " PAL" || echo -n " NTSC"
              echo " telecined source" 
            } | tee -a "$output".log
            [[ ${FPS[10]} = 1 ]] && MENCODERARG=( "${MENCODERARG[@]}" -ofps 24000/1001 -mc 0 ) || MENCODERARG=( "${MENCODERARG[@]}" -ofps 24 -mc 0 )
        fi
    fi
fi

###############################################################################
#### autocrop
###############################################################################
if [[ $autocrop ]]; then
    a=0
    [[ $dvdtrack ]] && a=$(get_chapters "${MPLAYERINFO[@]}" )
    rm -f "$output".crp
    CLEAN[${#CLEAN[*]}]="$output".crp
    if [[ $dvdtrack && $a -gt 1 ]]; then
        b=1
        CRPOPT=-chapter
    else
        a=10
        b=$(awk -v a=$a '$3~/ID_LENGTH/{printf("%d",substr($3,index($3,"=")+1)/(a+1)+.5)}' <"$output".log)
        CRPOPT=-ss
    fi
    for ((c=1;c<=a;c++)); do
        echo -en "\rautocrop: $c of $a"
        mplayer ${vf:--vf }${vf:+,}cropdetect -nocache -quiet "${MPLAYERINFONOVF[@]}" -vo null -nosound -benchmark -frames 100 $CRPOPT $((c*b)) 2>/dev/null|\
          sed '/^\[CROP]/!d;s/.*crop=//;s/:/ /g;s/)\.//' >>"$output".crp
    done
    crop=$(awk '$1>m1{m1=$1;m3=$3} $2>m2{m2=$2;m4=$4} END{print m1":"m2":"m3":"m4}' <"$output".crp)
fi
###############################################################################
#### calculate the scaling options according to setaspect
#### crop,rotate and overscan
###############################################################################
if ((zoom)); then
    if ((zoom>2)); then
        CW=$zoom && CH=$CW
    elif ((zoom<-2)); then
        CW=$((-1*zoom)) && CH=$CW
    else
        CW=$h_res
        CH=$v_res
    fi
    if [[ $crop ]]; then
        cw=${crop%%:*}	#1
        ch=${crop#*:}
        ch=${ch%%:*}	#2
        sw=${crop%:*}
        sw=${sw##*:}	#3
        sh=${crop##*:}	#4
    else
        cw=$h_res
        ch=$v_res
        sw=0
        sh=0
    fi
    a=$(get_aspect "${MPLAYERINFO[@]}")
    [[ ${a:0:9} = undefined ]] && a=$(awk -v a=$h_res -v b=$v_res 'BEGIN{printf("%f",a/b)}')
    vfilter=$(awk -v w=$h_res -v h=$v_res -v a=$a -v cw=$cw -v ch=$ch -v sw=$sw -v sh=$sh -v CW=$CW -v CH=$CH -v zoom=$zoom -v i=${interlaced:-0} -v r=$rotate -v o=$overscan -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log 'BEGIN{
      ko=(1-o/100)
      if(a==1.78||a==1.74)a=16/9
      if(a==1.33||a==1.30)a=4/3
      ratio=w/h
      ep=sqrt((ratio-a)*(ratio-a))
      if (ep/a<0.01) {
        a=ratio+ep
      }
      if(((zoom==1||zoom==-1)&&ratio<a)||((zoom==2||zoom==-2)&&ratio>a)){
        CH=ch/ko
      }
      if(((zoom==1||zoom==-1)&&ratio>a)||((zoom==2||zoom==-2)&&ratio<a)){
        CW=cw/ko
      }
      if((zoom>2||zoom<-2)&&ratio>a){
        CH=CW/a
      }
      if((zoom==1||zoom==-1)?ratio<a:ratio>a){
        ECH=CH
        ECW=2*int((ECH*h/ch)/2+0.50)
        ECW=2*int(ECW*a/2+0.50)
        ECW=2*int((ECW*cw/w)/2+0.50)

        CH=2*int(ECH*ko/2+0.50)
        H=2*int((CH*h/ch)/2+0.50)
        W=2*int(H*a/2+0.50)
        CW=2*int((W*cw/w)/2+0.50)
      }else{
        ECW=CW
        ECH=2*int((ECW*w/cw)/2+0.50)
        ECH=2*int(ECH/(a*2)+0.50)
        ECH=2*int((ECH*ch/h)/2+0.50)

        CW=2*int(ECW*ko/2+0.50)
        W=2*int((CW*w/cw)/2+0.50)
        H=2*int(W/(a*2)+0.50)
        CH=2*int((H*ch/h)/2+0.50)
      }
      SW=2*int((W*sw/w)/2+0.50)
      SH=2*int((H*sh/h)/2+0.50)
      E=int(ECW/16+.99)*16
      F=int(ECH/16+.99)*16

      printf("   INFO: [setaspect] initial resolution: %dx%d aspect: %f",w,h,a) >>logfile
      if(cw==w&&ch==h&&sw==0&&sh==0)print >>logfile ; else printf(" crop: %d:%d:%d:%d\n",cw,ch,sw,sh) >>logfile
      printf("   INFO: [setaspect] final resolution: %dx%d",(zoom>0)?E:ECW,(zoom>0)?F:ECH) >>logfile
      if(cw==w&&ch==h&&sw==0&&sh==0)print >>logfile ; else printf(" aspect: %f\n",(zoom>0)?E/F:ECW/ECH) >>logfile
      printf("   INFO: [setaspect] ") >>logfile
      printf("-vf scale=%d:%d",W,H) | "tee -a '\''"logfile"'\''"
      if(i==1)printf(":1") | "tee -a '\''"logfile"'\''"
      if(cw==w&&ch==h&&sw==0&&sh==0);else printf(",crop=%d:%d:%d:%d",CW,CH,SW,SH) | "tee -a '\''"logfile"'\''"
      if((E>CW||F>CH)&&(zoom>0))printf(",expand=%d:%d",CW-E,CH-F) | "tee -a '\''"logfile"'\''" ;
        else printf(",expand=%d:%d",ECW,ECH) | "tee -a '\''"logfile"'\''"
      if(r!="")printf(",rotate=%d",r) | "tee -a '\''"logfile"'\''"
      print >>logfile
    }')
    for ((a=0;a<${#MENCODERARG[*]};a++)); do
        while [[ ${MENCODERARG[a]} = -vf ]]; do
            unset MENCODERARG[a] MENCODERARG[a+1]
            MENCODERARG=( "${MENCODERARG[@]}" )
        done
    done
    MENCODERARG=( "${MENCODERARG[@]}" ${vf:--vf }${vf:+,}${vfilter#-vf }${mpeg:+,harddup} )
fi
###############################################################################
#### crop/rotate/overscan only
###############################################################################
if [[ $step -eq 1 && $zoom -eq 0 && ( $crop || $rotate || $overscan -ne 0 ) ]]; then
    if ((overscan)); then
        [[ $crop ]] && cw=${crop%%:*} ch=${crop#*:} ch=${ch%%:*} || cw=$h_res ch=$v_res
        vfilter=$(awk -v w=$cw -v h=$ch -v o=$overscan 'BEGIN{
          ko=(1+o/100)
          EH=h*ko
          EW=w*ko
          EW=int(EW/16+.99)*16
          EH=int(EH/16+.99)*16
          printf("expand=%s:%s",EW,EH)
        }')
    else
        vfilter=
    fi
    vfilter=${crop:+crop=$crop}${vfilter:+${crop:+,}$vfilter}
    for ((a=0;a<${#MENCODERARG[*]};a++)); do
        while [[ ${MENCODERARG[a]} = -vf ]]; do
            unset MENCODERARG[a] MENCODERARG[a+1]
            MENCODERARG=( "${MENCODERARG[@]}" )
        done
    done
    MENCODERARG=( "${MENCODERARG[@]}" ${vf:--vf }${vf:+,}$vfilter${rotate:+${vfilter:+,}rotate=$rotate} )
fi
###############################################################################
#### scale and expand/crop to adapt the aspect ratio
#### added rotation and overscan
###############################################################################
if [[ $mpegfixaspect && $step -gt 1 ]]; then
    a=$(get_aspect "${MPLAYERINFO[@]}")
    [[ ${a:0:9} = undefined ]] && a=$(awk -v a=$h_res -v b=$v_res 'BEGIN{printf("%f",a/b)}')
    [[ $mpegaspect = 1 ]] && b=$(awk -v a=$H_RES -v b=$V_RES 'BEGIN{printf("%f",a/b)}') || b=${ASPECT[${mpegaspect:-2}]}
    vfilter=$(awk -v a=$a -v A=$b -v W=$H_RES -v H=$V_RES -v pad=$mpegfixaspect -v i=${interlaced:-0} -v r=$rotate -v o=$overscan -v w=$h_res -v h=$v_res -v crop=$crop -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log 'BEGIN{
      ko=(1-o/100)
      if(a==1.78||a==1.74)a=16/9
      if(a==1.33||a==1.30)a=4/3
      if(A=="4/3")A=4/3
      if(A=="16/9")A=16/9
      if(crop!=""){
          tmp=crop
          cw=substr(tmp,1,index(tmp,":")-1)
          sub(/[^:]*:/,"",tmp)
          ch=substr(tmp,1,index(tmp,":")-1)
          a=cw*h*a/(ch*w)
      }
      if(r!=""){
        A=1/A
        tmp=W
        W=H
        H=tmp
      }
      if(a>A&&pad==0||a<A&&pad==1){
        Eh=A*H/a
        Ew=W
      }else{
        Ew=W*a/A
        Eh=H
      }
      Ew=2*int(Ew*ko/2+0.50)
      Eh=2*int(Eh*ko/2+0.50)
      printf("   INFO: [mpegfixaspect] ") >>logfile
      printf("-vf ") | "tee -a '\''"logfile"'\''"
      if(crop!="")printf("crop=%s,",crop) | "tee -a '\''"logfile"'\''"
      printf("scale=%d:%d",Ew,Eh) | "tee -a '\''"logfile"'\''"
      if(i==1)printf(":1") | "tee -a '\''"logfile"'\''"
      if(pad==0)printf(",expand=%d:%d",W,H) | "tee -a '\''"logfile"'\''" ;else printf(",crop=%d:%d",W,H) | "tee -a '\''"logfile"'\''"
      if(r!="")printf(",rotate=%d",r) | "tee -a '\''"logfile"'\''"
      if(o!=0) printf(" [overscan=%d]",o) >>logfile
      printf("\n") >>logfile
    }')
    if [[ $mpeg ]]; then
        for ((a=0;a<${#MENCODERARG[*]};a++)); do
            if [[ ${MENCODERARG[a]} = -vf ]]; then
                MENCODERARG[a+1]=$(echo ${MENCODERARG[a+1]} | sed 's/scale=[^,]*,//;s/^/'"${vfilter#-vf }"',/')
            fi
        done
    else
        vfilter=${vfilter#-vf scale=}
        YUVSCALEROPT="$(echo $YUVSCALEROPT | sed 's/ -O '$frameformat'//;s/-O SIZE_[^ ]* //')"
        YUVSCALEROPT="-M RATIO_${h_res}_${vfilter%%:*}_${v_res}_$(echo $vfilter | sed 's/[^:]*://;s/,.*//') -O SIZE_${H_RES}x${V_RES} $YUVSCALEROPT"
    fi
fi

###############################################################################
#### warn for aspect ratio
###############################################################################
if [[ ( $mpeg && $encode != ?:0:? || ! $mpeg && $step -gt 1 ) && ! $mpegfixaspect && ${#TITLESET[*]} -eq 0 && ! $testmca && ! $pictsrc ]]; then
    a=$(get_aspect "${MPLAYERINFO[@]}")
    [[ ${mpegaspect:-2} = 2 && $a != 1.33 && $a != 1.30 || ${mpegaspect:-2} = 3 && $a != 1.78 && $a != 1.74 || ${mpegaspect:-2} = 4 && $a != 2.21 ]] && \
      do_log "++ WARN: [$PROGNAME] selected aspect ratio [${ASPECT[${mpegaspect:-2}]}] and source aspect ratio [$a] are different"
fi

###############################################################################
#### dvd vobsub
###############################################################################
#### function to select the vobsub to extract
next_vobsub_idx () {
    if ((${#SID[*]})); then
        if ((idx < ${#encsid[*]})); then
            SID=(-sid ${encsid[idx]} -vobsuboutindex ${encsdx[idx]} ${encsla:+-vobsuboutid ${encsla[idx]}} -vobsubout "$output")
            do_log "   INFO: [$PROGNAME] dumping subtitle ${encsid[idx]} to vobsub ${encsdx[idx]}${encsla:+ (${encsla[idx]})}"
            idx=$((idx+1))
        else
            unset SID
        fi
    fi
}
#### turn on vobsub extraction if encsid is given
if (( ${#encsid[*]} )) ; then
    (( ${#encsdx[*]} )) || encsdx=( ${encsid[*]} )
    idx=0
    SID=(0000)
    next_vobsub_idx
else
    unset SID
fi
status_bit sub || unset SID

###############################################################################
#### test condition "extra"
###############################################################################
IDACOD=$(grep "ID_AUDIO_CODEC" "$output".log | tail -1 | cut -f2 -d=)
[[ $IDACOD = hwdts ]] && echo "**ERROR: [$PROGNAME] dts audio support missing in MPlayer" && \
  echo "**ERROR: add dts support (libdts-0.0.2.tar.gz) or select a non dts stream" && \
  echo "**ERROR: example:  -aid 128 (ac3), -aid 160 (lpcm), -aid 0 (mpeg)" && exit 1
[[ $IDACOD = faad && $encode == 0:?:? ]] && AUDIOPASS="$AUDIOPASS -fafmttag 0x706D -mc 0"
[[ $mpeg && ! $pictsrc && ( $encode == 1:?:? || $multiaudio || $encode == 0:?:? && $IDACOD != mp3 && $IDACOD != a52 && $IDACOD != faad ) ]] && extra=1 || \
  extra=

CLEAN[${#CLEAN[*]}]="$output".tmp

###############################################################################
#### AVI/MPEG section
###############################################################################
if [[ $encode ]]; then
    #### AVI $output.avi or $output.mpeg
    ####     ${output}_${b}_${aid[b]}.audio
    ####     ${output}_frameno.avi
    ####     ${output}_audio_frameno.avi
    if status_bit avi ; then
        find_sbr () {
            local kv k ka
            wait $LOGPROC
            [[ $mpeg ]] && kv=9888 k=33 ka=1015 || kv=10000 k=0 ka=1011
            if ((usesbr<=6)); then
                sbr=$(awk '/for '"${SBR[usesbr-1]}"'MB CD/{print $NF}' <"$output".log)
                [[ $sbr ]] && ((sbr<vbr)) && VIDEOPASS=${VIDEOPASS/vbitrate=$vbr:/vbitrate=$sbr:} && \
                  do_log "   INFO: [mencoder] using vbitrate=$sbr"
            else
                #### usesbr is in MB
                #### remind: 650-800,650-1400,800-1400
                sbr[0]=650
                sbr[1]=1400
                sbr[2]=$(awk '/for '"${SBR[0]}"'MB CD/{print $NF}' <"$output".log)
                sbr[3]=$(awk '/for '"${SBR[4]}"'MB CD/{print $NF}' <"$output".log)
                [[ ${sbr[2]} && ${sbr[3]} ]] && \
                  sbr[4]=$(((((usesbr*kv/10000-k)-(audiosize*ka/1000))*(sbr[3]-sbr[2])+sbr[1]*sbr[2]-sbr[0]*sbr[3])/(sbr[1]-sbr[0])))
                [[ ${sbr[4]} ]] && ((sbr[4]<vbr && sbr[4]>0)) && VIDEOPASS=${VIDEOPASS/vbitrate=$vbr:/vbitrate=${sbr[4]}:} && \
                  do_log "   INFO: [mencoder] using vbitrate=${sbr[4]}"
            fi
        }
        AID=
        [[ $extra && ${!audioformat} = copy ]] && rm -f "$output".mpa* "$output".lpcm "${output}"_[0-9].lpcm "${output}"_[0-9][0-9].lpcm
        #### if multiaudio, encode all the audio streams except the first
        if [[ $multiaudio ]]; then
            #### ach ${output}_${b}_${aid[b]}.audio
            if status_bit ach ; then
                for ((b=1; b<${#aid[*]} ; b++)) ; do
                    rm -f frameno.avi
                    do_log "   INFO: [$PROGNAME] dumping -aid ${aid[b]}"
                    [[ $encode == 0:?:? && ${aid[b]} -ge 160 && ${aid[b]} -le 191 ]] && BAKAUDIOPASS=$AUDIOPASS && \
                      AUDIOPASS="-oac pcm -channels $(id_find ID_AUDIO_NCH "${MPLAYERINFO[@]}")"

                    if [[ $mpeg ]]; then
                        if ((${#MSRC[*]})); then
                            BAKMARG=("${MENCODERARG[@]}")
                            for ((i=0;i<${#MENCODERARG[*]};i++)) ; do
                                [[ ${MENCODERARG[i]} = ${MSRC[0]} ]] && MENCODERARG[i]=${MSRC[b]} && break
                            done
                        fi
                        if [[ ${!audioformat} = copy ]]; then
                            if [[ $encode == 0:?:? && ${aid[b]} -ge 160 && ${aid[b]} -le 191 ]]; then
                                DDOPT=( of="${output}"${b:+_$b}.lpcm conv=swab )
                                LPCMPAR="${LPCMPAR:+$LPCMPAR,}$(id_find ID_AUDIO_RATE "${MPLAYERINFO[@]}" -aid ${aid[b]})"
                                LPCMPAR="$LPCMPAR:$(id_find ID_AUDIO_NCH "${MPLAYERINFO[@]}" -aid ${aid[b]}):16"
                            else
                                DDOPT=( of="${output}".mpa$b )
                            fi
                            RAWAUDIO=( -of rawaudio -o /dev/fd/4 )
                            MPLEXSTREAM[${#MPLEXSTREAM[*]}]=${DDOPT[0]#of=}
                        else
                            RAWAUDIO=( -o /dev/fd/4 )
                            DDOPT=( of="${output}"_${b}_${aid[b]}.avi )
                        fi
                    else
                        RAWAUDIO=( -of rawaudio -o /dev/fd/4 )
                        DDOPT=( of="${output}"_${b}_${aid[b]}.audio )
                    fi
                    [[ $encode == 0:?:? ]] && F= || F=$af
                    [[ $mpeg && ${mpegchannels:-2} -gt 2 || ! $mpeg && ${channels:-2} -gt 2 ]] && fix_channel_order "${MPLAYERINFO[@]}" $AID
                    ((DEBUG)) && debug_line $((LINENO+1)) "multiaudio: aid=${aid[b]}"
                    mencoder $OPTIONS -ovc frameno "${RAWAUDIO[@]}" "${SID[@]}" "${MENCODERARG[@]}" -aid ${aid[b]} $AUDIOPASS $F 4>&1 >&2 | \
                      dd "${DDOPT[@]}" 2>/dev/null
                    [[ $mpeg ]] && ((${#MSRC[*]})) && MENCODERARG=("${BAKMARG[@]}")
                    [[ $encode == 0:?:? && ${aid[b]} -ge 160 && ${aid[b]} -le 191 ]] && AUDIOPASS=$BAKAUDIOPASS
                    next_vobsub_idx
                    file_size "${DDOPT[0]#of=}"
                    audiosize=$((audiosize+fsize/1024/1024))
                done
                [[ $keep ]] && status_bit ach set
            else
                [[ ! $keep ]] && status_bit ach clear
            fi
            #rm -f frameno.avi
            AID="-aid ${aid[0]}"
        fi
        if [[ ! $extra ]]; then
            RAWVIDEO=( -o "$output".$SUF )
        else
            #### process the audio stream 0
            if status_bit ch0 ; then
                rm -f frameno.avi
                do_log "   INFO: [$PROGNAME] (MPEG container) dumping first audio stream $AID"
                [[ $encode == 0:?:? && ( $multiaudio && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 || ! $multiaudio && $IDACOD = dvdpcm ) ]] && \
                  BAKAUDIOPASS=$AUDIOPASS && AUDIOPASS="-oac pcm -channels $(id_find ID_AUDIO_NCH "${MPLAYERINFO[@]}")"
                if [[ ${!audioformat} = copy ]]; then
                    [[ $multiaudio ]] && b=0 || b=
                    if [[ $encode == 0:?:? && ( $multiaudio && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 || ! $multiaudio && $IDACOD = dvdpcm ) ]]; then
                        if [[ $multiaudio ]]; then
                            LPCMPAR="$(id_find ID_AUDIO_RATE "${MPLAYERINFO[@]}" $AID):$(id_find ID_AUDIO_NCH "${MPLAYERINFO[@]}" $AID):16${LPCMPAR:+,$LPCMPAR}"
                        else
                            LPCMPAR="${LPCMPAR:+$LPCMPAR,}$(grep ID_AUDIO_RATE "$output".log | tail -1 | cut -f2 -d=)"
                            LPCMPAR="${LPCMPAR}:$(grep ID_AUDIO_NCH "$output".log | tail -1 | cut -f2 -d=):16"
                        fi
                        DDOPT=( of="${output}"${b:+_$b}.lpcm conv=swab )
                    else
                        DDOPT=( of="${output}".mpa$b )
                    fi
                    RAWAUDIO=( -of rawaudio -o /dev/fd/4 )
                    MPLEXSTREAM=( "${DDOPT[0]#of=}" "${MPLEXSTREAM[@]}" )
                else
                    RAWAUDIO=( -o /dev/fd/4 )
                    DDOPT=( of="${output}"_frameno.avi )
                fi
                [[ $encode == 0:?:? ]] && F= || F=$af
                [[ ${mpegchannels:-2} -gt 2 ]] && fix_channel_order "${MPLAYERINFO[@]}" $AID
                if [[ $usesbr ]]; then
                    ((DEBUG)) && debug_line $((LINENO+2)) "usesbr "
                    me_bit_log
                    mencoder $OPTIONS -ovc frameno -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F &>"$output".fifo
                    find_sbr
                    next_vobsub_idx
                fi
                ((DEBUG)) && debug_line $((LINENO+1))
                mencoder $OPTIONS -ovc frameno "${RAWAUDIO[@]}" "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F 4>&1 >&2 | dd "${DDOPT[@]}" 2>/dev/null
                next_vobsub_idx
                [[ $encode == 0:?:? && ( $multiaudio && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 || ! $multiaudio && $IDACOD = dvdpcm ) ]] && \
                  AUDIOPASS=$BAKAUDIOPASS
                [[ $keep ]] && status_bit ch0 set
            else
                [[ ! $keep ]] && status_bit ch0 clear
            fi
            BAKAUDIOPASS=$AUDIOPASS
            BAKAF=$af
            AUDIOPASS="-srate 16000 -af-adv force=2 -channels 1 -oac lavc -lavcopts acodec=mp2:abitrate="
            af="-af channels=1"
            if [[ $telecine ]] && ((vfr==1||vfr==2)); then
                AUDIOPASS="${AUDIOPASS}64"
                RAWVIDEO=( -o "$output".$SUF )
            else
                AUDIOPASS="${AUDIOPASS}8"
                RAWVIDEO=( -of rawvideo -o "$output".mpv )
                MPLEXSTREAM=( "${RAWVIDEO[${#RAWVIDEO[*]}-1]}" "${MPLEXSTREAM[@]}" )
                rm -f "$output".mpv
            fi
        fi
        if [[ $fixasync && ! $mpeg && $encode != 0:?:? ]]; then
            BAKAUDIOPASS=$AUDIOPASS
            AUDIOPASS="-oac pcm"
        fi
        #### start mencoder
        PLOG=( -passlogfile "$output".avi2pass.log )
        MSG="-msglevel demuxer=6:demux=6"
        rm -f frameno.avi
        [[ $encode == 0:?:? && ! $extra ]] && F= || F=$af
        [[ ! $extra && ${mpegchannels:-2} -gt 2 || ! $mpeg && ${channels:-2} -gt 2 ]] && fix_channel_order "${MPLAYERINFO[@]}" $AID
        if [[ $usesbr && ! $extra ]]; then
            ((DEBUG)) && debug_line $((LINENO+2)) "usesbr "
            me_bit_log
            mencoder         $OPTIONS -ovc frameno         -o /dev/null       "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F       &>"$output".fifo
            find_sbr
            next_vobsub_idx
        fi
        if ((PASS==1)); then
            ((DEBUG)) && debug_line $((LINENO+2)) "PASS 1/$PASS"
            me_log
            mencoder         $OPTIONS $VIDEOPASS           "${RAWVIDEO[@]}"   "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F $MSG >"$output".fifo
            next_vobsub_idx
        else
            #### N pass
            CLEAN[${#CLEAN[*]}]="$output".avi2pass.log
            if [[ $keep ]]; then
                NULL=( "${RAWVIDEO[@]}" )
                NULL[${#NULL[*]}-1]="${RAWVIDEO[${#RAWVIDEO[*]}-1]}"_pass1
            else
                rm -f "${RAWVIDEO[${#RAWVIDEO[*]}-1]}"_pass1
                NULL=( -o /dev/null )
            fi
            ((DEBUG)) && debug_line $((LINENO+1)) "PASS 1/$PASS"
            mencoder         $OPTIONS ${VIDEOPASS}:$pass=1$turbo "${NULL[@]}" "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F "${PLOG[@]}"
            next_vobsub_idx
            if ((PASS==2)); then
                ((DEBUG)) && debug_line $((LINENO+2)) "PASS 2/$PASS"
                me_log
                mencoder     $OPTIONS ${VIDEOPASS}:$pass=2 "${RAWVIDEO[@]}"   "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F "${PLOG[@]}" $MSG \
                  >"$output".fifo
                next_vobsub_idx
            else
                for ((a=2;a<PASS;a++)); do
                    [[ $keep ]] && NULL[${#NULL[*]}-1]="${RAWVIDEO[${#RAWVIDEO[*]}-1]}"_pass$a || rm -f "${RAWVIDEO[${#RAWVIDEO[*]}-1]}"_pass$a
                    ((DEBUG)) && debug_line $((LINENO+1)) "PASS $a/$PASS"
                    mencoder $OPTIONS ${VIDEOPASS}:$pass=3 "${NULL[@]}"       "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F "${PLOG[@]}"
                    next_vobsub_idx
                done
                ((DEBUG)) && debug_line $((LINENO+2)) "PASS $PASS/$PASS"
                me_log
                mencoder     $OPTIONS ${VIDEOPASS}:$pass=3 "${RAWVIDEO[@]}"   "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $F "${PLOG[@]}" $MSG \
                  >"$output".fifo
                next_vobsub_idx
            fi
        fi
        if [[ $fixasync && ! $mpeg && $encode != 0:?:? ]]; then
            AUDIOPASS=$BAKAUDIOPASS
            ((DEBUG)) && debug_line $((LINENO+1)) "PASS audiosync"
            mencoder $OPTIONS -ovc copy -mc 0 -noskip -o "$output".tmp "$output".$SUF $AUDIOPASS
            mv "$output".tmp "$output".$SUF
        fi
        #### fix seek in the AVI file
        if [[ $fixavi && ! $mpeg ]]; then
            do_log "   INFO: [fixavi] fixing index in the AVI stream"
            ((DEBUG)) && debug_line $((LINENO+1)) fixavi
            mencoder     $OPTIONS $OF $MUX -oac copy -ovc copy -forceidx -o "$output".tmp "$output".$SUF # -forceidx is better than -noidx
            mv "$output".tmp "$output".$SUF
        fi
        #### restore the AUDIOPASS
        [[ $extra ]] && AUDIOPASS=$BAKAUDIOPASS af=$BAKAF
        #### merge the AVI with the others audio tracks
        if [[ $multiaudio && ! $mpeg ]]; then
            CLEAN[${#CLEAN[*]}]="$output".comm
            echo -en >"$output".comm "ICMT $PROGNAME-$VERSION\nISRC "
            mplayer "$output".avi 2>/dev/null -vo null -vc dummy -nosound -frames 0 | sed -n '/^ Software:/s/ Software: //p' >>"$output".comm
            for ((b=1; b<${#aid[*]} ; b++)) ; do
                do_log "   INFO: [avimerge] merging aid ${aid[b]}"
                mv "$output".$SUF "$output".tmp
                rm -f "${output}"_0_*.$SUF
                [[ $keep ]] && ln "$output".tmp "${output}"_0_${aid[0]}.$SUF && do_log "   INFO: [keep] ${output}_0_${aid[0]}.$SUF"
                ((DEBUG)) && debug_line $((LINENO+2)) "avimerge aid=${aid[b]}"
                filter_log avimerge
                avimerge -o "$output".$SUF -f "$output".comm -i "$output".tmp -p "${output}"_${b}_${aid[b]}.audio -a $((b+1)) >"$output".fifo
                rm -f "${keep:-${output}_${b}_${aid[b]}.audio}" "$output".tmp
                [[ $keep ]] && do_log "   INFO: [keep] ${output}_${b}_${aid[b]}.audio"
            done
        fi
        #### -avisplit ?
        if [[ $avisplit && $step -eq 1 ]]; then
            rm -f "$output"-[0-9][0-9][0-9][0-9].$SUF
            [[ $encode == [147]:?:? ]] && do_log "++ WARN: [$PROGNAME] avisplit works correctly only with mp3/ac3 audio"
            ((DEBUG)) && debug_line $((LINENO+2)) avisplit
            filter_log avisplit '\r$'
            avisplit -i "$output".$SUF -s $avisplit -o "$output" >"$output".fifo 2>&1
        fi
        #### check if the ofps is the optimum
        if [[ $step -eq 1 && ! $pictsrc ]]; then
            INFPS=$(grep ID_VIDEO_FPS "$output".log | tail -1 | cut -f2 -d=)
            if [[ $INFPS = 29.970 || $INFPS = 30.000 ]]; then
                M=$(mplayer -nocache -quiet "${MPLAYERINFO[@]}" -vo null -nosound -benchmark -frames 60 2>/dev/null | awk '/^demux_mpg:/{print $2}')
                if [[ $M = 24fps || $M = 24000/1001fps ]]; then
                    [[ $INFPS = 29.970 ]] && INFPS=23.976 || INFPS=24.000
                fi
            elif [[ $INFPS = 25.000 ]]; then
                M=$(is_film2pal "${MPLAYERINFO[@]}")
                if [[ $M ]]; then
                    [[ $M = 24fps ]] && INFPS=24.000 || INFPS=23.976
                fi
            fi
            OFPS=$(id_find ID_VIDEO_FPS "$output".$SUF)
            if [[ $INFPS != $OFPS ]]; then
                M=
                case $INFPS in
                    23.976) M="-vfr 1" ;;
                    24.000) M="-vfr 2" ;;
                    25.000) M="-vfr 3" ;;
                    29.970) M="-vfr 4" ;;
                    30.000) M="-vfr 5" ;;
                    50.000) M="-vfr 6" ;;
                    59.940) M="-vfr 7" ;;
                    60.000) M="-vfr 8" ;;
                esac
                [[ $M ]] || M="-ofps ${INFPS%.000}"
                if awk -v a=$INFPS  'BEGIN{if(a>100)exit 1}' ; then
                    { echo -n "   INFO: [$PROGNAME] $M may avoid "
                      awk -v a=$INFPS -v b=$OFPS 'BEGIN{if(a<b)print "duplicate frames" ; else print "skipping frames"}'
                    } | tee -a "$output".log
                fi
            fi
        fi
        status_bit avi set
    fi
fi

###############################################################################
#### if there are still vobsub to dump, do it now
###############################################################################
while ((${#SID[*]})) ; do
    ((DEBUG)) && debug_line $((LINENO+1)) vobsub
    mencoder -ovc copy -o /dev/null $AID "${SID[@]}" "${MENCODERARG[@]}" -nosound
    next_vobsub_idx
done
if status_bit sub ; then
    if [[ -f $output.sub && -f $output.idx && ${#encsid[*]} -gt 0 ]]; then
        #### reset the subtitles with the wrong timestamp
        awk -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log '{
          if($1=="id:")id=" ("$0")"
          if($1=="timestamp:"){
            n=$2;
            sub(/,/,"",n);
            # convert the timestamp in seconds
            m=3600*substr(n,1,index(n,":")-1);
            sub(/[0-9]*:/,"",n);
            m=m+60*substr(n,1,index(n,":")-1);
            sub(/[0-9]*:/,"",n);
            m=m+substr(n,1,index(n,":")-1);
            sub(/[0-9]*:/,"",n);
            m=m+n/1000;
            # .002 is already ok
            if(m+.004<t){
              printf("++ WARN: [encsid] reset bad timestamp sequence: %s %s%s\n",gensub(/[^ ]* /,"",1,gensub(/,.*/,"",1,p)),substr($2,1,length($2)-1),id) >>logfile ;
              id="";
              p=gensub(/ [^ ]* /," 00:00:00:000, ",1,p)" #"p}
            t=m}
          else t=0;
          if(NR>1)print p;
          p=$0
          }
          END{print p}' <"$output".idx >"$output".idx.idx && mv "$output".idx.idx "$output".idx
        #### split the subtitles
        if [[ $encode && $avisplit && $step -eq 1 ]]; then
            imglen=
            rm -f "$output"-[0-9][0-9][0-9][0-9].{sub,idx}
            for a in "$output"-*.$SUF ; do
                t=$(video_duration $OPTIONS "$a")
                cp "$output".sub "${a%$SUF}"sub
                cp "$output".idx "${a%$SUF}"idx
                [[ $imglen ]] && sed -i '/^id:/s/.*/&\ndelay: -'"$(sec2fulltime $imglen)"'/' "${a%$SUF}"idx 
                imglen=$(awk -v i=${imglen:-0} -v t=$t 'BEGIN{printf("%.3f",i+t)}')
            done
        fi
        status_bit sub set
    fi
fi

###############################################################################
#### create the vobsub rar archive
###############################################################################
if [[ -f $output.sub && -f $output.idx && ${#encsid[*]} -gt 0 ]]; then
    if type rar &>/dev/null ; then
        rver=$(rar | awk '$1=="RAR"{print $2;exit}')
        if [[ ${rver%%.*} -le 2 ]] ; then
            rm -f "$output".rar
            [[ -d $output ]] && mv "$output" "$output".$$
            echo "$output" | grep -q '\.' && RSUF=.rar || RSUF=
            ((DEBUG)) && debug_line $((LINENO+2)) rar
            filter_log rar
            rar -s -m5 -mde a "$output"$RSUF "$output".idx "$output".sub >"$output".fifo
            [[ -d $output.$$ ]] && mv "$output".$$ "$output"
            rm "$output".{idx,sub}
            #status_bit rar set
            if [[ $encode && $avisplit && $step -eq 1 ]]; then
                for a in "$output"-*.$SUF ; do
                    rm -f "${a%$SUF}"rar
                    ((DEBUG)) && debug_line $((LINENO+2)) rar
                    filter_log rar
                    rar -s -m5 -mde a "${a%.avi}"$RSUF "${a%$SUF}"idx "${a%$SUF}"sub >"$output".fifo
                    rm "${a%$SUF}"{idx,sub}
                done
            fi
        else
            do_log "++ WARN: [$PROGNAME] you need rar 2.x, you have $rver, vobsub left uncompressed"
        fi
    else
        do_log "++ WARN: [$PROGNAME] rar missing, vobsub left uncompressed"
    fi
fi

###############################################################################
#### convert a SPU or Vobsub subtitle to text subtitle
###############################################################################
if [[ $ocr && $step -eq 1 && ${#addsub[*]} -gt 0 ]] && status_bit ocr ; then
    [[ ${addsub[0]} = copy ]] && subcopy_id
    dump_sub_stream "$(spuunmux 2>&1 | grep -e '-r')"
    CLEAN[${#CLEAN[*]}]="$output".xml
    CLEAN[${#CLEAN[*]}]="$output".tess.txt
    rm -f "$output".tess.txt
    case $ocr in
        tesseract)
            CLEAN[${#CLEAN[*]}]="$output".tif
            OCR () {
                convert +compress +matte "$1" "$output".tif
                tesseract "$output".tif "$output".tess 2>/dev/null
            }
            ;;
        gocr)
            OCR () {
                convert "$1" pbm:- | gocr -i - >"$output".tess.txt
            }
            ;;
        ocrad)
            OCR () {
                convert "$1" pbm:- | ocrad >"$output".tess.txt
            }
            ;;
        ocradi)
            OCR () {
                convert "$1" pbm:- | ocrad -i >"$output".tess.txt
            }
            ;;
        *) ;;
    esac
    u2d () {
        if type unix2dos &>/dev/null ; then
            unix2dos -o "$1"
        else
            sed -i 's/$/\r/' "$1"
        fi 
    }
    if ((DEBUG)); then
        { for ((n=0;n<${#OCRDEF[*]}/2;n++)); do
            echo -n "--DEBUG: [ocr] ${OCRDEF[2*n]}="
            split_ocrsub_opt $((n+1)) && echo -n "$OCRSUBOPT "
            echo "[${OCRDEF[2*n+1]}]"
          done
          echo "$(declare -f OCR | sed '1,2d;$d;s/^ */--DEBUG: [OCR] /')"
        } | tee -a "$output".log
    fi
    split_ocrsub_opt 5
    OCRSUFFIX=$OCRSUBOPT
    split_ocrsub_opt 2
    OCRSUFFIX="$OCRSUBOPT.$OCRSUFFIX"
    split_ocrsub_opt 4
    [[ $OCRSUBOPT == [Oo][Nn] || $OCRSUBOPT -eq 1 || $OCRSUBOPT == [yY][eE][sS] ]] && OCRSUFFIX="$OCRSUFFIX;1"
    split_ocrsub_opt 6
    [[ $OCRSUBOPT == [Oo][Nn] || $OCRSUBOPT -eq 1 || $OCRSUBOPT == [yY][eE][sS] ]] && CLEAN[${#CLEAN[*]}]="$output".xpm ocredit=1 || ocredit=
    split_ocrsub_opt 9
    [[ $OCRSUBOPT == [Oo][Nn] || $OCRSUBOPT -eq 1 || $OCRSUBOPT == [yY][eE][sS] ]] && TRIM=-trim || TRIM=
    split_ocrsub_opt 3
    [[ $encode && $avisplit ]] && \
      rm -f "$output"-[0-9][0-9][0-9][0-9].$(echo "$OCRSUFFIX" | sed 's/%%/\r/g;s/%o/'${ocr%i}'/g;s/%i/*/g;s/%l/*/g' | tr '\015' '%')
    for ((l=0;l<${#addsub[*]};l++)); do
        srtlang=$(sublang $l)
        [[ $srtlang = nolang ]] && srtlang=xx
        ocrsuffix=$(echo "$OCRSUFFIX" | sed 's/%%/\r/g;s/%o/'${ocr%i}'/g;s/%i/'$l'/g;s/%l/'$srtlang'/g' | tr '\015' '%')
        do_log "   INFO: [ocr(${ocr}${ocrterm:+,$ocrterm})] converting subtitle ${addsub[l]} to $output.$ocrsuffix"
        rm -f "$output".$ocrsuffix "$output".xml
        pngremove=1
        spuunmux -o "$output" -s ${addsub[l]} -p "$output".rgb "$output".dump
        BURNLIST[${#BURNLIST[*]}]="$output".$ocrsuffix
        n=1
        s=$IFS
        IFS='"'
        while read -a a ; do
            for ((i=0;i<${#a[*]};i++)); do
                if [[ ${a[i]} == *"<spu image=" ]]; then
                    ((DEBUG)) && echo -ne "$n\r"
                    subimg=$(xmlunchar "${a[i+1]}")
                    substart=
                    subend=
                    for ((m=i+2;m<${#a[*]};m++)); do
                        if [[ ${a[m]} == *"start=" ]]; then
                            substart=${a[m+1]/./,}
                            m=$((++m))
                        elif [[ ${a[m]} == *"end=" ]]; then
                            subend=${a[m+1]/./,}
                            m=$((++m))
                        fi
                    done
                    if [[ -f $subimg ]]; then
                        OCR "$subimg"
                        if [[ $ocredit ]]; then
                            m=$(($(wc -l <"$output".tess.txt)))
                            convert $TRIM -bordercolor white -border 0x$(((m>0?m:1)*16)) "$subimg" "$output".xpm
                            ( IFS=$s ; $ocrterm "${ocrtopt[@]}" "$subimg" -${ocrE:-e} vi "$output".tess.txt )
                        fi
                        { echo $((n++))
                          echo "$substart --> $subend"
                          { cat "$output".tess.txt ; echo ; } | cat -s
                        } >>"$output".$ocrsuffix
                    fi
                    break
                fi
            done
        done <"$output".xml
        IFS=$s
        findpng | xargs -0 rm
        pngremove=
        #### split the subtitles
        if [[ $encode && $avisplit ]]; then
            imglen=
            for a in "$output"-*.$SUF ; do
                t=$(video_duration $OPTIONS "$a")
                r=0
                while read -r i ; do
                    if echo "$i" | grep -q '[0-9] --> [0-9]' ; then
                        if awk -v a=${imglen:-0} -v b=$(time2sec $(echo "${i//,/.}" | awk '{print $1}')) 'BEGIN{if(b>=a)exit 1}' ; then
                            r=0
                        elif awk -v a=${imglen:-0} -v b=$(time2sec $(echo "${i//,/.}" | awk '{print $1}')) -v t=$t 'BEGIN{if(b<=t+a)exit 1}' ; then
                            r=0
                            break
                        else
                            ((!r)) && r=$p
                            p=$((p-r+1))
                        fi
                        if [[ $imglen && $r -gt 0 ]]; then
                            n=$(sec2fulltime $(awk -v a=$imglen -v b=$(time2sec $(echo "${i//,/.}" | awk '{print $1}')) 'BEGIN{printf("%.2f",b-a)}'))
                            m=$(sec2fulltime $(awk -v a=$imglen -v b=$(time2sec $(echo "${i//,/.}" | awk '{print $3}')) 'BEGIN{printf("%.2f",b-a)}'))
                            i=$(echo "$n --> $m" | sed 's/:\([0-9]* .*\):/,\1,/')
                        fi
                    fi
                    ((r)) && echo "$p" >>"${a%$SUF}"$ocrsuffix
                    p=$i
                done <"$output".$ocrsuffix
                ((r)) && echo "$p" >>"${a%$SUF}"$ocrsuffix
                imglen=$(awk -v i=${imglen:-0} -v t=$t 'BEGIN{printf("%.3f",i+t)}')
                [[ $OCRSUBOPT == [dD][oO][sS] ]] && u2d "${a%$SUF}"$ocrsuffix
            done
        fi
        [[ $OCRSUBOPT == [dD][oO][sS] ]] && u2d "$output".$ocrsuffix
    done
    status_bit ocr set
fi

###############################################################################
#### -avionly? then exit
###############################################################################
if ((step <2)); then
    [[ $encode ]] && BURNLIST=( "$output".$SUF "${BURNLIST[@]}" )
    #### convert a text subtitles
    SUBOPTDEF=( dumpsrtsub dumpsub.srt srt dumpmicrodvdsub dumpsub.txt sub dumpsami dumpsub.smi smi dumpjacosub dumpsub.jss jss dumpmpsub dump.mpsub mpsub )
    #		1			   2				   3			    4				5
    for ((i=0;i<${#txtsub[*]};i++)); do
        split_txtsub_opt $i 3 && [[ $TXTSUBOPT == [dD][oO][sS] ]] && \
          if ! type unix2dos &>/dev/null ; then do_log "++ WARN: [txtsub] unix2dos not found, using sed instead" ; break ; else break ; fi
    done
    for ((i=0;i<${#txtsub[*]};i++)); do
        DUMPSUBOPT=
        #### subtitle format
        split_txtsub_opt $i 1 || TXTSUBOPT=${AVISUBDEF[1]}
        TXTSUBOPT=$(echo $TXTSUBOPT | tr '[:upper:]' '[:lower:]')
        case $TXTSUBOPT in
            subviewer) n=1 ;;
            microdvd) n=2 ;; 
            sami) n=3 ;;
            jacosub) n=4 ;;
            mpsub) n=5 ;;
            *) n=1 ; do_log "++ WARN: [txtsub] unknown subtitle format '$TXTSUBOPT', using default: ${AVISUBDEF[1]}" ;;
        esac
        rm -rf "$output".dir
        SUBLIST=( "${output##*/}" )
        t=
        #### split subtitles also for AVI created with avisplit
        if [[ $encode && $avisplit ]]; then
            for a in "$output"-*.$SUF ; do
                a=${a%.$SUF}
                SUBLIST=( "${SUBLIST[@]}" "${a##*/}" )
            done
        fi
        for ((a=0;a<${#SUBLIST[*]};a++)); do
            DUMPSUBOPT="-${SUBOPTDEF[(n-1)*3]} -vo null -frames 1 -nocache -quiet -noass"
            #### subtitle delay
            split_txtsub_opt $i 5
            [[ $TXTSUBOPT || $t ]] && DUMPSUBOPT="$DUMPSUBOPT -subdelay $(awk -v a=${TXTSUBOPT:-0} -v b=${t:-0} 'BEGIN{printf("%.3f",a+b)}')"
            #### subtitle fps
            split_txtsub_opt $i 6 && DUMPSUBOPT="$DUMPSUBOPT -subfps $TXTSUBOPT"
            removedir=1
            mkdir "$output".dir
            pushd "$output".dir >/dev/null
            ((a)) && t=$(awk -v a=$(video_duration ../"${SUBLIST[a]}.$SUF") -v b=${t:-0} 'BEGIN{printf("%.3f",a+b)}')
            [[ ${txtsub[i]:0:1} = / ]] && p= || p=../
            if [[ $encode ]]; then
                avi="$output".$SUF
                [[ ${output:0:1} = / ]] || avi="../$avi"
                mplayer -sub "$p${txtsub[i]}" $DUMPSUBOPT "$avi"    -nosound -benchmark                       &>/dev/null
            else
                [[ $ofps ]] || ( pushd >/dev/null ; do_log "++ WARN: [txtsub] if you are not encoding, you must use option -ofps: assuming 25 fps" )
                mplayer -sub "$p${txtsub[i]}" $DUMPSUBOPT /dev/null -demuxer 26 -rawvideo cif:fps=${ofps:-25} &>/dev/null
            fi
            #### subtitle name extension
            split_txtsub_opt $i 2
            SUBEXT="$TXTSUBOPT"
            #### subtitle name suffix
            split_txtsub_opt $i 7 && SUBEXT="$SUBEXT.$TXTSUBOPT" || SUBEXT="$SUBEXT.${SUBOPTDEF[(n-1)*3+2]}"
            #### subtitle name version number
            split_txtsub_opt $i 4 && [[ $TXTSUBOPT == [oO][nN] || $TXTSUBOPT -eq 1 ]] && SUBEXT="$SUBEXT;1"
            #### subtitle unix/dos format
            split_txtsub_opt $i 3
            if [[ $TXTSUBOPT == [dD][oO][sS] ]]; then
                if type unix2dos &>/dev/null ; then
                    unix2dos -n ${SUBOPTDEF[(n-1)*3+1]} ../"${SUBLIST[a]}$SUBEXT"
                else
                    sed 's/$/\r/' ${SUBOPTDEF[(n-1)*3+1]} > ../"${SUBLIST[a]}$SUBEXT"
                fi 
            else
                mv ${SUBOPTDEF[(n-1)*3+1]} ../"${SUBLIST[a]}$SUBEXT"
            fi
            popd >/dev/null
            rm -rf "$output".dir
            removedir=
        done
        BURNLIST[${#BURNLIST[*]}]="${SUBLIST[0]}$SUBEXT"
        { echo "   INFO: [txtsub] converting subtitle ${txtsub[i]}"
          if ((DEBUG)); then
              for ((n=0;n<${#AVISUBDEF[*]}/2;n++)); do
                  echo -n "--DEBUG: [txtsub] ${AVISUBDEF[2*n]}="
                  split_txtsub_opt $i $((n+1)) && echo -n "$TXTSUBOPT "
                  echo "[${AVISUBDEF[2*n+1]}]"
              done
          fi
        } | tee -a "$output".log
    done
    #### burn the AVI stream and the subtitles
    if [[ $burniso ]]; then
        burn_iso "${BURNLIST[@]}"
        [[ $verify ]] && verify_burn "${BURNLIST[@]}" || true
    fi
    exit
fi

###############################################################################
#### if fast mode skip multiplexing
###############################################################################
if [[ $mpeg && $fast ]]; then
    if status_bit mpg ; then
        if [[ ! $extra ]]; then
            rm -f "$output".mpg "${output}"[0-9][0-9].mpg
            status_bit mpv set
            status_bit mpa set
            status_bit mpg set
            mv "$output".$SUF "$output".mpg
        else
            do_log "   INFO: [$PROGNAME] it is necessary to multiplex the streams with mplex"
            fast=
        fi
    fi
fi

###############################################################################
#### mplex does not work with MPEG-4
###############################################################################
[[ ! $fast && ( $vcodec = mpeg4 || $vcodec = xvid ) ]] && echo "**ERROR: [$PROGNAME] mplex does not multiplex $vcodec video" && exit 1

###############################################################################
#### create the MPEG video elementary stream and dump the first audio track in a wav file
###############################################################################
[[ $extra && ( ! $telecine || $vfr -ne 1 && $vfr -ne 2 ) ]] && status_bit mpv set
if status_bit mpv ; then
    rm -f "$output".mpv
    if [[ ! $mpeg ]]; then
        [[ $multiaudio && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 || ! $multiaudio && $IDACOD = dvdpcm ]] && \
          AFILTER=$AF
        if ((DEBUG)); then
            debug_line $((LINENO+7)) stream.yuv
            [[ $YUVDENOISE ]] && debug_line $((LINENO+7)) ${YUVDENOISE%% *}
            debug_line $((LINENO+7)) yuvscaler
            debug_line $((LINENO+7)) mpeg2enc
        fi
        : ${YUVDENOISE:=cat -}
        me_log mplayer
        mplayer ${multiaudio:+-aid ${aid[0]}} "${MPLAYERYUVOPT[@]}" $AFILTER 4>&1 >"$output".fifo | \
          $YUVDENOISE 2>>"$output".log | \
          yuvscaler $YUVSCALEROPT 2>"$output".yuvscaler.log | \
          mpeg2enc $MPEG2ENCOPT -o "$output".mpv 2>"$output".mpeg2enc.log
    else
        do_log "   INFO: [$PROGNAME] encoded to $frameformat video with mencoder"
        ((DEBUG)) && debug_line $((LINENO+1)) mpeg2mpv
        mplayer -dumpvideo -dumpfile "$output".mpv "$output".$SUF
    fi
    ret=$? ; (( ret )) && sleep 2 && exit $ret

    if [[ ! $mpeg ]]; then
        sed -n '1,/Frame number 0$/p' "$output".yuvscaler.log >>"$output".log
        sed '1,/ GOP start /!d;1,/ NEW GOP INIT /!d' "$output".mpeg2enc.log >>"$output".log
        CLEAN[${#CLEAN[*]}]="$output".yuvscaler.log
        CLEAN[${#CLEAN[*]}]="$output".mpeg2enc.log
    fi

    CLEAN[${#CLEAN[*]}]="$output".wav

    MPLEXSTREAM[${#MPLEXSTREAM[*]}]="$output".mpv
    status_bit mpv set
fi

###############################################################################
#### create the MPEG audio elementary stream
###############################################################################
if [[ $extra && ${!audioformat} = copy ]]; then
    status_bit mpa set
    if [[ ! $fast && $telecine && ( $vfr -eq 1 || $vfr -eq 2 ) ]]; then
        [[ ! $keep ]] && rm "$output".$SUF || do_log "   INFO: [keep] $output.$SUF"
    fi
fi
if status_bit mpa ; then
    #### function to select the source audio stream
    set_src () {
        local CH
        [[ $2 = ch ]] && CH="${mpegchannels:+-channels $mpegchannels}"
        if [[ $mpeg && $i -gt 0 ]]; then
            STRSRC=( "${output}"_${i}_${aid[i]}.avi $CH )
        else
            if [[ $extra ]]; then
                STRSRC=( "${output}"_frameno.avi $CH )
            else
                [[ $1 = INFO ]] && STRSRC=( "${MENCAUDIOINFO[@]}" ) || STRSRC=( "${MENCAUDIOOPT[@]}" )
                STRSRC=( "${STRSRC[@]}" ${multiaudio:+-aid ${aid[i]}} )
            fi
        fi
    }
    #### function to create the audio stream with libavcodec
    libavcodec_audio () {
        local rate AFILTER
        set_src INFO
        [[ $(id_find ID_AUDIO_RATE "${STRSRC[@]}") != $asr ]] && rate="-srate $asr -af-adv force=1"
        rm -f frameno.avi
        set_src OPT ch
        #### mplayer executed in swap_lpcm_channels will use STRSRC that will never get assigned MENCAUDIOOPT if source is lpcm
        [[ $multiaudio && ( $i -gt 0 && ${aid[i]} -ge 160 && ${aid[i]} -le 191 || $i -eq 0 && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 ) || ! $multiaudio && $IDACOD = dvdpcm ]] && \
          AFILTER=$(swap_lpcm_channels "${STRSRC[@]}") || AFILTER=$AF
        [[ $1 ]] && AFILTER=$(echo "${AFILTER:--af }${AFILTER:+,}" | sed 's/channels=[^,]*,//')channels=$1
        ((DEBUG)) && debug_line $((LINENO+1)) "libavcodec($audioformat)"
        mencoder -o "$output".mpa -of rawaudio -ovc frameno -oac lavc -lavcopts acodec=$audioformat:abitrate=$abr $rate "${STRSRC[@]}" $AFILTER $afm \
          "${EXTWAV[@]}" 
    }
    #### function dump_audio [audio codec] [MPEG layer]
    dump_audio () {
        local VAR1 VAR2
        set_src INFO
        if [[ $# -gt 0 ]]; then
            VAR1=$(id_find ID_AUDIO_CODEC "${STRSRC[@]}")
            [[ $VAR1 != $1 ]] && return 1
            if [[ $# -gt 1 ]]; then
                VAR2=$(mplayer -ao null -vo null -nocache -ac mp3, "${STRSRC[@]}" -v -frames 0 2>/dev/null | sed '/MPEG.*Layer/!d;s/.*Layer *//;s/,.*//')
                [[ $VAR2 != $2 ]] && return 1
            fi
        fi
        set_src OPT
        ((DEBUG)) && debug_line $((LINENO+1)) "dumpaudio $1 $2 ${multiaudio:+aid=${aid[i]}}"
        mplayer -dumpaudio -dumpfile "$output".mpa "${STRSRC[@]}"
    }
    #### function to set MPEGTABLES
    set_mpegtables () {
        if [[ ! $MPEGTABLES ]]; then
            MPEGTABLES=$(type -p $1)
            export MPEGTABLES=${MPEGTABLES%/*}/$2
            [[ -d $MPEGTABLES ]] || do_log "++ WARN: [$PROGNAME] MPEGTABLES $MPEGTABLES does not exist"
        fi
    }
    #### function to swap the pcm audio streams
    swap_pcm_channels () {
        local n
        for ((n=0;n<${#CHANSWAP[*]};n++)); do
            if (($#)); then
                mplayer -ao pcm:nowaveheader:fast:file=%$((${#output}+6+${#CHANLIST[n]}))%"$output"__${CHANLIST[n]}.pcm "$output"_${CHANSWAP[n]}.pcm \
                  -channels 1 -demuxer 20 -rawaudio format=0x1:channels=1:rate=$mcrate "$@"
            else
                mv "$output"_${CHANSWAP[n]}.pcm "$output"__${CHANLIST[n]}.pcm
            fi
        done
        for ((n=0;n<${#CHANSWAP[*]};n++)); do
            mv "$output"__${CHANLIST[n]}.pcm "$output"_${CHANLIST[n]}.pcm
        done
    }
    #### function to convert a multichannel mp2 audio stream to single channel pcm files 
    mc2pcm () {
        set_mpegtables musicout tablesmc
        rm -f "$output"_*.pcm
        mv "$output".mpa "$output".mpg
        CLEAN[${#CLEAN[*]}]="$output"_lfe.dec
        CLEAN[${#CLEAN[*]}]="$output".dec
        mcrate=$(musicout "$output" | tee /dev/stderr | awk '$3~/sfrq=/{printf("%d\n",substr($3,6)*1000)}')
        [[ ! -s "$output".dec ]] && rm "$output".dec && unset CLEAN[${#CLEAN[*]}-1] CLEAN[${#CLEAN[*]}-2] && return 1
        rm "$output".mpg
        mv "$output".dec "$output".aiff && CLEAN[${#CLEAN[*]}-1]="$output".aiff
        pcm2aiff "$output" -a
        rm "$output".aiff && unset CLEAN[${#CLEAN[*]}-1]
        case $(($(ls "$output"_*.pcm | wc -l))) in
            5) CHANLIST=(l r ls rs c) ; CHANSWAP=(r c rs l ls) ;;
            4) CHANLIST=(l r ls c) ; CHANSWAP=(r c l ls) ;;
            3) CHANLIST=(l r c) ; CHANSWAP=(r c l) ;;
            2) CHANLIST=(l r) ; CHANSWAP=() ;;
        esac
        swap_pcm_channels $SRATE
        #for ((n=0;n<${#CHANLIST[*]};n++)); do
        #    mplayer -ao pcm:fast:file=%$((${#output}+5+${#CHANLIST[n]}))%"$output"_${CHANLIST[n]}.wav "$output"_${CHANLIST[n]}.pcm -channels 1 -demuxer 20 \
        #      -rawaudio format=0x1:channels=1:rate=$mcrate
        #done
        echo -n "   INFO: [$PROGNAME] input audio stream: mp2 ${#CHANLIST[*]}." | tee -a "$output".log
        if [[ -f ${output}_lfe.dec ]]; then
            do_log "1"
            mv "$output"_lfe.dec "$output"_lfe.aiff && CLEAN[${#CLEAN[*]}-1]="$output"_lfe.aiff
            type sox &>/dev/null || ! echo "**ERROR: sox missing, cannot process lfe channel" || exit 1
            pcm2aiff "$output"_lfe -a
            rm "$output"_lfe.aiff && CLEAN[${#CLEAN[*]}-1]="$output"_lfe_l.pcm
            sox -t raw -c 1 -r $((mcrate/96)) -w -s "$output"_lfe_l.pcm -t wav -r 8000 "$output"_lfe_8k.wav resample -ql
            rm "$output"_lfe_l.pcm && CLEAN[${#CLEAN[*]}-1]="$output"_lfe_8k.wav
            #mplayer -ao pcm:fast:file=%$((${#output}+8))%"$output"_lfe.wav "$output"_lfe_8k.wav -srate $mcrate -af-adv force=1 -channels 1
            mplayer -ao pcm:nowaveheader:fast:file=%$((${#output}+8))%"$output"_lfe.pcm "$output"_lfe_8k.wav -srate $mcrate -af-adv force=1 -channels 1
            rm "$output"_lfe_8k.wav && unset CLEAN[${#CLEAN[*]}-1]
        else
            unset CLEAN[${#CLEAN[*]}-1]
            do_log "0"
            [[ ${chconf} == ??1 ]] && echo "**ERROR: LFE channel missing in the input mp2 audio stream" && exit 1
            ((${#CHANLIST[*]}>2))
        fi
    }
    #### function 
    set_clean_pcm () {
        local n
        for ((n=0;n<${#CH6LIST[*]};n++)) ; do
            CLEAN[${#CLEAN[*]}]="$output"_${CH6LIST[n]}.pcm
        done
    }
    #### function 
    unset_clean_pcm () {
        local n
        for ((n=0;n<${#CH6LIST[*]};n++)) ; do
            rm -f "$output"_${CH6LIST[n]}.pcm
            unset CLEAN[${#CLEAN[*]}-1]
        done
    }
    #### function to convert a multichannel mp2 audio stream to a multichannel wav files 
    mc2wav () {
        local EXT CHLIST n
        for n in musicout pcm2aiff ; do
            type $n &>/dev/null || ! echo "**ERROR: [$PROGNAME] $n missing, cannot process mp2 multichannel audio input stream" || exit 1
        done
        set_clean_pcm
        if mc2pcm ; then
            case ${mpegchannels:-2} in
                6) EXT=(l r ls rs c lfe) ;;
                5) EXT=(l r ls rs c) ;;
                4) EXT=(l r ls c) ;;
                3) EXT=(l r c) ;;
            esac
            type ch_wave &>/dev/null || ! echo "**ERROR: ch_wave missing, cannot convert MPEG Multichannel Audio to $audioformat" || exit 1
            CHLIST=()
            for ((n=0;n<${#EXT[*]};n++)); do
                CHLIST=("${CHLIST[@]}" "$output"_${EXT[n]}.pcm)
            done
            CLEAN[${#CLEAN[*]}]="$output"_mc.wav
            ch_wave "${CHLIST[@]}" -itype raw -n 1 -f $mcrate -ibo LSB -istype short -pc FIRST -o "$output"_mc.wav
            EXTWAV=(-audiofile "$output"_mc.wav)
        fi
        unset_clean_pcm
    }
    #### end functions
    rm -f "$output".mpa* "$output".lpcm "${output}"_[0-9].lpcm "${output}"_[0-9][0-9].lpcm
    #### loop for all the audio id specified
    for ((i=0;i<audiostream;i++)) ; do
        if [[ ${!audioformat} != mencoder && ${!audioformat} != copy ]]; then
            if [[ $i -gt 0 || $mpeg ]]; then
                #### dump to wav
                set_src OPT ch
                [[ $multiaudio && ( $i -gt 0 && ${aid[i]} -ge 160 && ${aid[i]} -le 191 || $i -eq 0 && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 ) || ! $multiaudio && $IDACOD = dvdpcm ]] && \
                  AFILTER=$(swap_lpcm_channels "${STRSRC[@]}") || AFILTER=$AF
                ((DEBUG)) && debug_line $((LINENO+1)) "$output".wav
                mplayer "${STRSRC[@]}" -vo null -vc dummy -ao "${PCMWAV[@]}" $AFILTER $afm
            fi
        fi

        #### encode to mp1/mp2/mp3/ac3/dts/lpcm
        do_log "   INFO: [$PROGNAME] encoding to $audioformat audio with ${!audioformat}"
        case $audioformat in
            mp1)
                case $mp1 in
                    mp2enc)
                        ((mpegchannels==1)) && M=-m || M=
                        ((DEBUG)) && debug_line $((LINENO+2)) mp2enc
                        dump_log
                        mp2enc -b $abr -r $asr -l 1 -o "$output".mpa $M <"$output".wav 2>"$output".fifo
                        [[ ! -f $output.mpa ]] && exit 1
                        ;;
                    encode)
                        [[ $(id_find ID_AUDIO_RATE "$output".wav) != $asr ]] && SRATE="-srate $asr -af-adv force=1" || SRATE=
                        mplayer -ao "${PCMNOWYUV[@]}" $SRATE "$output".wav ${mpegchannels:+-channels $mpegchannels} 4>&1 >&2 | \
                          dd of="$output".mpa conv=swab 2>/dev/null
                        mv "$output".mpa "$output".wav
                        set_mpegtables encode tables
                        ((mpegchannels==1)) && M="-m m" || M=
                        ((DEBUG)) && debug_line $((LINENO+2)) encode
                        filter_log encode
                        encode -l 1 -b $abr -s $(awk -v f=$asr 'BEGIN{printf("%.3f",f/1000)}') $M "$output".wav "$output".mpa >"$output".fifo
                        [[ ! -f $output.mpa ]] && exit 1
                        ;;
                    copy)
                        dump_audio mp3 I || ! echo "**ERROR: audio stream is not $audioformat, copy aborted" || exit 1
                        ;;
                esac
                ;;
            mp2)
                case $mp2 in
                    mp2enc)
                        ((mpegchannels==1)) && M=-m || M=
                        ((DEBUG)) && debug_line $((LINENO+2)) mp2enc
                        dump_log
                        mp2enc -b $abr -r $asr -o "$output".mpa $M <"$output".wav 2>"$output".fifo
                        [[ ! -f $output.mpa ]] && exit 1
                        ;;
                    toolame)
                        [[ $(id_find ID_AUDIO_RATE "$output".wav) != $asr ]] && SRATE="-srate $asr -af-adv force=1" || SRATE=
                        if [[ $SRATE ]]; then
                            mplayer -ao "${PCMTMP[@]}" $SRATE "$output".wav ${mpegchannels:+-channels $mpegchannels}
                            mv "$output".tmp "$output".wav
                        fi
                        ((mpegchannels==1)) && M="-m m" || M=
                        ((DEBUG)) && debug_line $((LINENO+2)) toolame
                        filter_log toolame
                        toolame -b $abr $M "$output".wav 2>"$output".fifo
                        mv "$output".mp2 "$output".mpa
                        ;;
                    mencoder)
                        libavcodec_audio
                        ;;
                    copy)
                        dump_audio mp3 II || ! echo "**ERROR: audio stream is not $audioformat, copy aborted" || exit 1
                        ;;
                    musicin|mctoolame)
                        set_clean_pcm
                        [[ $(id_find ID_AUDIO_RATE "$output".wav) != $asr ]] && SRATE="-srate $asr -af-adv force=1" || SRATE=
                        if dump_audio mp3 II ; then
                            mc2pcm || ! echo "**ERROR: input mp2 audio stream is not multichannel, do not use $mp2 encoder" || exit 1
                        else
                            set_src INFO
                            case $(id_find ID_AUDIO_CODEC "${STRSRC[@]}") in
                                faad)
                                    case ${mpegchannels:-2} in
                                        6|5) CHANLIST=(c l r ls rs lfe) ;;
                                        4) CHANLIST=(c l r ls) ;;
                                        3) CHANLIST=(c l r) ;;
                                    esac
                                    ;;
                                *) #a52)
                                    case ${mpegchannels:-2} in
                                        6|5) CHANLIST=(l r ls rs c lfe) ;;
                                        4) CHANLIST=(l r ls c) ;;
                                        3) CHANLIST=(l r c) ;;
                                    esac
                                    ;;
                            esac
                            for ((n=0;n<${mpegchannels:-2};n++)) ; do
                                mplayer "$output".wav $SRATE ${mpegchannels:+-channels $mpegchannels} -af channels=1:1:$n:0 -nocache \
                                  -ao pcm:nowaveheader:fast:file=%$((${#output}+5+${#CHANLIST[n]}))%"$output"_${CHANLIST[n]}.pcm
                            done
                        fi
                        case ${mpegchannels:-2} in
                            6)  CHANLIST=(l r ls rs c lfe) ; CHANSWAP=(l r lfe ls c rs) ; chconf="-L" ;;
                            5)
                                CHANLIST=(l r ls rs c)
                                case $chconf in
                                    320|"") CHANSWAP=() ; chconf= ;;
                                    311) CHANSWAP=(l r lfe ls c) ; chconf="-C 310 -L" ;;
                                    221) CHANSWAP=(l r c ls lfe) ; chconf="-C 220 -L" ;;
                                esac
                                ;;
                            4)
                                CHANLIST=(l r ls c)
                                case $chconf in
                                    310|"") CHANSWAP=() ; chconf= ;;
                                    220) CHANSWAP=() ; chconf="-C 220" ;;
                                    211) CHANSWAP=(l r c lfe) ; chconf="-C 210 -L" ;;
                                  # 301) CHANSWAP=(l r lfe c) ; chconf="-C 300 -L" ;;
                                esac
                                ;;
                            3)
                                CHANLIST=(l r c)
                                case $chconf in
                                    210|"") CHANSWAP=() ; chconf= ;;
                                  # 300) CHANSWAP=() ; chconf="-C 300" ;;
                                    201) CHANSWAP=(l r lfe) ; chconf="-C 200 -L" ;;
                                esac
                                ;;
                        esac
                        swap_pcm_channels
                        pcm2aiff "$output" -c$((${mpegchannels:-2}-1)) -r$((asr/4000%5-1)) # 32000=2,44100=0,48000=1
                        unset_clean_pcm
                        CLEAN[${#CLEAN[*]}]="$output".aiff
                        [[ $mp2 = musicin ]] && set_mpegtables musicin tablesmc
                        ((DEBUG)) && debug_line $((LINENO+2)) $mp2
                        filter_log $mp2
                        $mp2 -r $(awk -v f=$asr 'BEGIN{printf("%.4f",f/1000+.0001)}') -m s -n s $chconf -b $abr -B $abr $MUSICINOPT "$output".aiff \
                          >"$output".fifo
                        rm "$output".aiff && unset CLEAN[${#CLEAN[*]}-1]
                        [[ $mp2 = musicin ]] && mv "$output".aiff.mpg "$output".mpa || mv "$output".aiff.mp2 "$output".mpa
                        ;;
                esac
                ;;
            mp3)
                case $mp3 in
                    lame)
                        ((mpegchannels==1)) && M="-m m" || M=
                        ((DEBUG)) && debug_line $((LINENO+2)) lame
                        filter_log lame
                        lame -b $abr --resample $asr $M - "$output".mpa <"$output".wav 2>"$output".fifo
                        ;;
                    mencoder)
                        libavcodec_audio
                        ;;
                    copy)
                        dump_audio mp3 III || ! echo "**ERROR: audio stream is not $audioformat, copy aborted" || exit 1
                        ;;
                esac
                ;;
            ac3)
                case $ac3 in
                    mencoder)
                        [[ ${mpegchannels:-2} -gt 2 ]] && dump_audio mp3 II && SRATE= && mc2wav
                        s=
                        set_src INFO
                        case $(id_find ID_AUDIO_CODEC "${STRSRC[@]}") in
                            faad)
                                case ${mpegchannels:-2} in
                                    6) s=6:6:1:0:0:1:2:2:3:3:4:4:5:5 ;;
                                    5) s=5:5:1:0:0:1:2:2:3:3:4:4 ;;
                                    4) s=4:4:1:0:2:1:3:2:0:3 ;;
                                    3) s=3:3:0:0:2:1:1:2 ;;
                                esac
                                ;;
                            *) #a52)
                                case ${mpegchannels:-2} in
                                    6) s=6:6:0:0:4:1:1:2:2:3:3:4:5:5 ;; # LIST=(l r ls rs c lfe) SWAP=(l c r ls rs lfe)
                                    5) s=5:5:0:0:4:1:1:2:2:3:3:4 ;;     # LIST=(l r ls rs c)     SWAP=(l c r ls rs)
                                    4) : ;;                             # LIST=(l r ls c)        SWAP=()
                                    3) s=3:3:0:0:2:1:1:2 ;;             # LIST=(l r c)           SWAP=(l c r)
                                esac
                                ;;
                        esac
                        libavcodec_audio $s
                        [[ ${EXTWAV[0]} = -audiofile ]] && rm "$output"_mc.wav && unset CLEAN[${#CLEAN[*]}-1]
                        EXTWAV=()
                        ;;
                    copy)
                        dump_audio a52 || ! echo "**ERROR: audio stream is not $audioformat, copy aborted" || exit 1
                        ;;
                esac
                ;;
            aac)
                case $aac in
                    copy)
                        dump_audio faad || ! echo "**ERROR: audio stream is not $audioformat, copy aborted" || exit 1
                        ;;
                esac
                ;;
            dts)
                case $dts in
                    copy)
                        dump_audio ffdts || ! echo "**ERROR: audio stream is not $audioformat, copy aborted" || exit 1
                        ;;
                esac
                ;;
            lpcm)
                if [[ ${mpegchannels:-2} -gt 2 ]] && dump_audio mp3 II ; then
                    SRATE=
                    mc2wav
                    ((${#EXTWAV[*]})) && mv "$output"_mc.wav "$output".wav && unset CLEAN[${#CLEAN[*]}-1]
                    EXTWAV=()
                fi
                LPCMPAR="${LPCMPAR:+$LPCMPAR,}"
                SRATE=$(id_find ID_AUDIO_RATE "$output".wav)
                [[ $SRATE != $asr ]] && SRATE="-srate $asr -af-adv force=1" LPCMPAR="${LPCMPAR}$asr" || LPCMPAR="${LPCMPAR}$SRATE" SRATE=
                LPCMPAR="$LPCMPAR:$(id_find ID_AUDIO_NCH $SRATE "$output".wav):16"
                AFILTER=$AF
                set_src INFO
                case $(id_find ID_AUDIO_CODEC "${STRSRC[@]}") in
                    faad)
                        case ${mpegchannels:-2} in
                            6) AFILTER=$(echo "${AFILTER:--af }${AFILTER:+,}" | sed 's/channels=[^,]*,//')channels=6:6:1:0:2:1:3:2:4:3:0:4:5:5 ;;
                            5) AFILTER=$(echo "${AFILTER:--af }${AFILTER:+,}" | sed 's/channels=[^,]*,//')channels=5:5:1:0:2:1:3:2:4:3:0:4 ;;
                            4) AFILTER=$(echo "${AFILTER:--af }${AFILTER:+,}" | sed 's/channels=[^,]*,//')channels=4:4:1:0:2:1:3:2:0:3 ;;
                            3) AFILTER=$(echo "${AFILTER:--af }${AFILTER:+,}" | sed 's/channels=[^,]*,//')channels=3:3:1:0:2:1:0:2 ;;
                        esac
                        ;;
                esac
                ((DEBUG)) && debug_line $((LINENO+1)) lpcm
                mplayer -ao "${PCMNOWYUV[@]}" $SRATE "$output".wav ${mpegchannels:+-channels $mpegchannels} $AFILTER 4>&1 >&2 | \
                  dd of="$output".mpa conv=swab 2>/dev/null
                ;;
            acopy)
                if [[ $multiaudio && ( $i -gt 0 && ${aid[i]} -ge 160 && ${aid[i]} -le 191 || $i -eq 0 && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 ) || ! $multiaudio && $IDACOD = dvdpcm ]]; then
                    # since 0.6.0 this if clause is never executed, but I will leave the code around for some time
                    set_src OPT # OPT is never set for lpcm
                    LPCMPAR="${LPCMPAR:+$LPCMPAR,}$(id_find ID_AUDIO_RATE "${STRSRC[@]}")"
                    a=$(id_find ID_AUDIO_NCH "${STRSRC[@]}")
                    LPCMPAR="$LPCMPAR:$a:16"
                    ((DEBUG)) && debug_line $((LINENO+1)) lpcm
                    mplayer -vo null -vc dummy -ao "${PCMNOWYUV[@]}" "${STRSRC[@]}" -channels $a -af channels=$a 4>&1 >&2 | \
                      dd of="$output".mpa conv=swab 2>/dev/null
                else
                    dump_audio
                    case $IDACOD in
                        mp3|a52|ffdts) : ;;
                        *) do_log "**ERROR: mplex cannot multiplex audio codec $IDACOD" ;;
                    esac
                fi
                ;;
        esac
        rm -f "$output".wav
        if ((audiostream >1)); then
            if [[ $audioformat = lpcm || $audioformat = acopy && ( $i -gt 0 && ${aid[i]} -ge 160 && ${aid[i]} -le 191 || $i -eq 0 && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 ) ]]; then
                audiofile="${output}_$i.lpcm"
            else
                audiofile="$output".mpa$i
            fi
            mv "$output".mpa "$audiofile"
            MPLEXSTREAM[${#MPLEXSTREAM[*]}]="$audiofile"
        fi
    done

    if ((audiostream==1)); then
        if [[ $audioformat = lpcm || $audioformat = acopy && ( $multiaudio && ${multiaudio%% *} -ge 160 && ${multiaudio%% *} -le 191 || ! $multiaudio && $IDACOD = dvdpcm ) ]]; then
            audiofile="$output".lpcm
            mv "$output".mpa "$audiofile"
        else
            audiofile="$output".mpa
        fi
        MPLEXSTREAM[${#MPLEXSTREAM[*]}]="$audiofile"
    fi
    if [[ $extra ]]; then
        [[ $keep ]] && do_log "   INFO: [keep] ${output}_frameno.avi" || rm "${output}"_frameno.avi
        if [[ $multiaudio ]]; then
            for ((i=1;i<audiostream;i++)) ; do
                [[ $keep ]] && do_log "   INFO: [keep] ${output}_${i}_${aid[i]}.avi" || rm "${output}"_${i}_${aid[i]}.avi
            done
        fi
    fi
    status_bit mpa set
    if [[ $mpeg && ! $fast && ! $extra ]]; then
        [[ ! $keep ]] && rm "$output".$SUF || do_log "   INFO: [keep] $output.$SUF"
    fi
fi

###############################################################################
#### -streamonly? then exit
###############################################################################
if ((step <3)); then
    exit
fi

###############################################################################
#### multiplex all the elementary streams
###############################################################################
if status_bit mpg ; then
    rm -f "$output".mpg "${output}"[0-9][0-9].mpg
    [[ $split && $mpeg ]] && ((DEBUG&32)) && MPLEXOPT="-M -S $split $MPLEXOPT"
    ((DEBUG)) && debug_line $((LINENO+2)) mplex
    dump_log
    mplex $MPLEXOPT ${LPCMPAR:+-L $LPCMPAR} "${MPLEXSTREAM[@]}" -o "$(echo "$output"| sed 's/%/%%/g')"${split:+%02d}.mpg 2>"$output".fifo
    ret=$? ; (( ret )) && exit $ret
    [[ ! $keep ]] && rm "${MPLEXSTREAM[@]}" || do_log "   INFO: [keep] ${MPLEXSTREAM[*]}"
    status_bit mpg set
    [[ $split && $mpeg ]] && ((DEBUG&32)) && status_bit spl set
fi

###############################################################################
#### split the MPEG stream (for MPEG Mode)
###############################################################################
if status_bit spl ; then
    #### split for MPEG Mode (MPEG-4 codec not supported)
    #### mencoder does not support split as it does mpeg2enc/mplex
    #### this solution is slow, but it seems quite accurate
    if [[ $mpeg && $split && $vcodec != mpeg4 && $vcodec != xvid ]]; then
        [[ ! $fast ]] && mv "$output"01.mpg "$output".mpg
        file_size "$output".mpg
        if ((split*1024*1024<fsize)); then
            chunks=$((fsize/(split*1024*1024)+1))
            #### if mplex has created more than one MPEG file split only the first
            if [[ -f "$output"02.mpg ]]; then
                mpg=( "$output"[0-9][0-9].mpg )
                for ((i=${#mpg[*]};i>0;i--)) ; do
                    mv "${mpg[i-1]}" "$output"$(printf "%02d" $((chunks+i))).mpg
                done
                unset mpg
            fi
            CLEAN[${#CLEAN[*]}]="$output".framelist
            mplayer "$output".mpg -vf framestep=I -vo null -nosound -benchmark 2>/dev/null | tr '\015' '\012' | \
              awk '{if($1=="I!")print t,substr(f,index(f,"/")+1);t=$2;if($3~/\/$/)f=$3$4;else f=$3}' >"$output".framelist
            m=0
            if [[ $multiaudio ]]; then
                a=$(mplayer -vo null -ao null -frames 1 -v "$output".mpg 2>/dev/null | awk '/==> Found audio str/{print $NF}' | sort -n | \
                  tr '\012' ',' | sed 's/,$/\n/')
            fi
            for ((i=0;i<chunks;i++)); do
                if ((i<chunks-1)); then
                    n=$(mplayer "$output".mpg  -vf framestep=I -vo null -nosound -benchmark 2>/dev/null -sb $(((i+1)*split*1024*1024)) -frames 2 | \
                      tr '\015' '\012' | awk '{if($1=="I!"){print t;exit};t=$2}')
                    n=$(awk '/^'"$n"'/{print $2-1;exit}' <"$output".framelist) #should be -2
                else
                    n=
                fi
                ((DEBUG)) && debug_line $((LINENO+1)) "mpeg_split $((i+1))/$chunks"
                "$PROGFILE" -norc "$output".mpg -o "$output"$(printf "%02d" $((i+1))) -mpegonly -mpeg -encode 0:0:1 -$(echo $frameformat| tr '[:upper:]' '[:lower:]') -nosplit -noshowlog -sb $((i*split*1024*1024)) ${n:+-frames $((n-m))} -a ${mpegaspect:-2} ${multiaudio:+-multiaudio $a} -mc 0
                rm "$output"$(printf "%02d" $((i+1))).log
                m=$n
            done
            rm "$output".mpg
        else
            mv "$output".mpg "$output"01.mpg
        fi
        status_bit spl set
    fi
fi

############################################################################### 
#### get Video Title Set number for souce title
###############################################################################
if [[ $dvdtrack && ( ! $VIDEOATTR && $step -gt 3 && $encode == ?:0:? || ${addsub[0]} = copy && $dvdsub -eq 0 ) ]]; then
    if [[ $dvddev && -d $dvddev ]]; then
        rfile="$dvddev/VIDEO_TS/VIDEO_TS.IFO"
        [[ -f $rfile ]] || rfile=
        vtsaddr=0
    else
        rfile=${dvddev:-/dev/dvd}
        vtsaddr=$(isoinfo -i "$rfile" -l | awk '/VIDEO_TS.IFO/{for(a=1;a<=NF;a++)if($a=="["){print $(a+1);exit}}')
    fi
    if [[ $rfile ]]; then
        s=$(readn 4 $((vtsaddr*2048+0xC4)))
        #(( dvdtrack > $(readn 2 $(((vtsaddr+s)*2048))) )) && do_log "++ WARN: [$PROGNAME] wrong track number"
        n=$(readn 1 $(((vtsaddr+s)*2048+8+6+12*(dvdtrack-1))))
        if [[ $dvddev && -d $dvddev ]]; then
            rfile="$dvddev/VIDEO_TS/VTS_$(printf "%02d" $n)_0.IFO"
            [[ -f $rfile ]] || rfile=
        else
            vtsaddr=$(isoinfo -i "$rfile" -l | awk '/VTS_'$(printf "%02d" $n)'_0.IFO/{for(a=1;a<=NF;a++)if($a=="["){print $(a+1);exit}}')
        fi
    fi
fi

############################################################################### 
#### get video attributes
###############################################################################
if [[ ! $VIDEOATTR && $dvdtrack && $step -gt 3 && $encode == ?:0:? ]]; then
    if [[ $rfile ]]; then
        videoattr=$(readn 2 $((vtsaddr*2048+0x200)))
        if ((videoattr&0x0C00)); then
            if ((videoattr&0x0300)); then
                ((videoattr&0x0200)) && VIDEOATTR=nopanscan || VIDEOATTR=noletterbox
            fi
        else
            ((videoattr&0x0004)) && VIDEOATTR=crop
        fi
    fi
fi

###############################################################################
#### find all the subtitle id to copy
###############################################################################
if [[ ${addsub[0]} = copy ]]; then
    subcopy_id
    if [[ $dvdtrack && $dvdsub -eq 0 ]]; then
        dvdsub=$(awk '/number of subtitles on disk:/{print $NF}' <"$output".log)
        [[ ! $dvdsub ]] && dvdsub=0
        if ((dvdsub&&dvdsub<${#addsub[*]})); then
            if [[ $rfile ]]; then
                videoattr=$(readn 2 $((vtsaddr*2048+0x200)))
                if ((videoattr&0x0C00)); then
                    if ((videoattr&0x0300)); then
                        ((videoattr&0x0200)) && IFOVATTR=nopanscan || IFOVATTR=noletterbox
                    else
                        IFOVATTR=16:9
                    fi
                else
                    ((videoattr&0x0004)) && IFOVATTR=crop || IFOVATTR=4:3
                fi
                nsub=$(readn 2 $((vtsaddr*2048+0x254)))
                ((dvdsub!=nsub)) && do_log "++ WARN: [subcopy] subtitle number mismatch, MPlayer: $dvdsub, IFO: $nsub; submit a bug report"
                subaddr=$(readn 4 $((vtsaddr*2048+0xCC)))
                subaddr=$(((vtsaddr+subaddr)*2048+$(readn 4 $(((vtsaddr+subaddr)*2048+12)))))
                SUBSTREAMATTR=()
                for ((n=0;n<dvdsub;n++)); do
                    subid=$(readn 4 $((subaddr+0x1C+n*4)))
                    ((subid&0x80000000)) || do_log "++ WARN: [subcopy] wrong IFO: subtitle $n does not have MSB set [0x$(printf "%08x" $subid)]"
                    case $IFOVATTR in
                        4:3)
                            SUBSTREAMATTR[n]=normal,$(((subid&0x1F000000)>>24))
                            ;;
                        crop)
                            SUBSTREAMATTR[n]=normal,$(((subid&0x1F000000)>>24)),widescreen,$(((subid&0x1F0000)>>16))
                            ;;
                        16:9)
                            SUBSTREAMATTR[n]=widescreen,$(((subid&0x1F0000)>>16)),letterbox,$(((subid&0x1F00)>>8)),panscan,$((subid&0x1F))
                            ;;
                        nopanscan)
                            SUBSTREAMATTR[n]=widescreen,$(((subid&0x1F0000)>>16)),letterbox,$(((subid&0x1F00)>>8))
                            ;;
                        noletterbox)
                            SUBSTREAMATTR[n]=widescreen,$(((subid&0x1F0000)>>16)),panscan,$((subid&0x1F))
                            ;;
                    esac
                done
                for ((n=dvdsub;n<32;n++)); do
                    subid=$(readn 4 $((subaddr+0x1C+n*4)))
                    ((subid&0x80000000)) && do_log "++ WARN: [subcopy] wrong IFO: subtitle $n has MSB set [0x$(printf "%08x" $subid)] but the number of subtitles is $dvdsub"
                done
            fi
        fi
    fi
fi

###############################################################################
#### multiplex the subtitles
###############################################################################
if status_bit sbm && [[ $frameformat != VCD && $frameformat != MPEG[12] ]]; then
    #### mux the subtitles from a DVD or SVCD or Vobsub
    if ((${#addsub[*]})); then
        spuunmux 2>&1 | grep -q -e '-r' && HASRAW=1 || HASRAW=
        (( $(ls -d "${output}"?([0-9][0-9]).mpg | awk 'END{print NR}') >1 )) && ONEMPG= || ONEMPG=1
        [[ $vobsubsrc || "$(awk '/==> Found subtitle:/{print $NF}' <"$output".log)" ]] && subformat=DVD SUBW=720 || subformat=SVCD SUBW=704
        v_scal=100
        if [[ $vobsubsrc ]]; then
            SUBH=$(grep size: "$vobsubsrc".idx | cut -f2 -dx)
            SUBH=${SUBH//[^0-9]}
            if [[ $videonorm ]]; then
                if [[ $videonorm = n ]]; then
                    [[ $SUBH = 576 ]] && v_scal=83.3
                else
                    [[ $SUBH = 480 ]] && v_scal=120
                fi
            else
                if [[ $SUBH = 480 ]]; then
                    ((v_res==288||v_res==576)) && v_scal=120
                else
                    ((v_res==240||v_res==480)) && v_scal=83.3
                fi
            fi
        else
            if [[ $videonorm ]]; then
                if [[ $videonorm = n ]]; then
                    ((v_res==288||v_res==576)) && v_scal=83.3
                else
                    ((v_res==240||v_res==480)) && v_scal=120
                fi
            fi
        fi
        if [[ $frameformat != $subformat ]]; then
            [[ $frameformat = SVCD ]] && h_scal=97.8 || h_scal=102.3
        else
            h_scal=100
        fi
        dump_sub_stream $HASRAW
        ((!${#addsdx[*]})) && addsdx=( ${addsub[@]} )
        rawshift=
        if [[ ! $HASRAW || $subformat != $frameformat || $rawsub && $rawsub -eq 0 || ! $ONEMPG || $vobsubsrc ]]; then
            SUBDECODE=1
            [[ $rawsub && $rawsub -eq 1 ]] && do_log "   WARN: [$PROGNAME] -rawsub 1 is not compatible with the current set of options"
        elif [[ $v_scal != 100 ]]; then
            if [[ $rawsub && $rawsub -eq 1 ]]; then
                SUBDECODE=0
                if [[ $videonorm ]]; then
                    if [[ $videonorm = n ]]; then
                        ((v_res==288||v_res==576)) && rawshift=-n
                    else
                        ((v_res==240||v_res==480)) && rawshift=-f
                    fi
                fi
            else
                SUBDECODE=1
            fi
        else
            SUBDECODE=0
        fi
        if ((SUBDECODE)); then
            do_log "   INFO: [$PROGNAME] Decoding and reencoding the subtitles"
            CLEAN[${#CLEAN[*]}]="$output".xml
            CLEAN[${#CLEAN[*]}]="$output".XML
        else
            do_log "   INFO: [$PROGNAME] Demuxing and muxing the subtitles in raw mode"
            CLEAN[${#CLEAN[*]}]="$output".spu
        fi
        [[ $HASRAW ]] && [[ ! $vobsubsrc && ( $v_res -eq 480 || $v_res -eq 240 ) || $vobsubsrc && $SUBH -eq 480 ]] && subdemuxopt=-n || subdemuxopt=-f
        [[ $HASRAW && $frameformat == DVD ]] && submuxopt=-d || submuxopt=
        for ((i=0;i<${#addsub[*]};i++)); do
            do_log "   INFO: [addsub] processing subtitle ${addsub[i]}"
            if ((SUBDECODE)); then
                pngremove=1
                ((DEBUG)) && debug_line $((LINENO+2)) "spuunmux sid=${addsub[i]}"
                #### added -f/-n, in this way the scaling with mogrify looks better
                spuunmux $subdemuxopt -o "$output" -s ${addsub[i]} -p "$output".rgb "$output".dump
                #### need to cut if the source is NTSC
                if [[ ! $HASRAW ]] && [[ ! $vobsubsrc && ( $v_res -eq 480 || $v_res -eq 240 ) || $vobsubsrc && $SUBH -eq 480 ]]; then
                    if type mogrify &>/dev/null ; then
                        findpng | xargs -0 mogrify -crop ${SUBW}x480+0+0
                    else
                        do_log "++ WARN: [$PROGNAME] mogrify[ImageMagick] missing, cannot crop subtitle ${addsub[i]}"
                    fi
                fi
                #### scale the subtitles
                if [[ $v_scal != 100 || $h_scal != 100 ]]; then
                    if type mogrify &>/dev/null ; then
                        #((DEBUG)) && debug_line $((LINENO+1)) "mogrify"
                        findpng | xargs -0 mogrify -antialias -filter Point -geometry ${h_scal}%x${v_scal}%
                    else
                        do_log "++ WARN: [$PROGNAME] mogrify[ImageMagick] missing, subtitle ${addsub[i]} left unscaled"
                    fi
                fi
                [[ ${addsdl[i]} ]] && imglen=$(time2sec ${addsdl[i]}) || imglen=0
                for mpg in "${output}"?([0-9][0-9]).mpg; do 
                    if [[ ! $ONEMPG || $imglen != 0 ]]; then
                        t=$(video_duration $OPTIONS "$mpg")
                        rm -f "$output".XML
                        while read -a a ; do
                            if [[ ${a[2]%=*} = start ]]; then
                                subtime=${a[2]#*\"}
                                subtime=$(time2sec ${subtime%\"*})
                                if awk -v s=$subtime -v i=$imglen -v t=$t 'BEGIN{if(s<i||s>i+t)exit 1}'; then
                                    subtime=$(awk -v a=$imglen -v b=$subtime 'BEGIN{printf("%.2f",b-a)}')
                                    a[2]=$(echo ${a[2]} | sed 's/\(start="\)[^"]*\("\)/\1'$(sec2time $subtime)'\2/')
                                    if [[ ${a[3]%=*} = end ]]; then
                                        subtime=${a[3]#*\"}
                                        subtime=$(time2sec ${subtime%\"*})
                                        subtime=$(awk -v a=$imglen -v b=$subtime 'BEGIN{printf "%.2f",b-a}')
                                        a[3]=$(echo ${a[3]} | sed 's/\(end="\)[^"]*\("\)/\1'$(sec2time $subtime)'\2/')
                                    fi
                                    echo "${a[@]}" >>"$output".XML
                                fi
                            else
                                echo "${a[@]}" >>"$output".XML
                            fi
                        done < "$output".xml
                        imglen=$(awk -v i=$imglen -v t=$t 'BEGIN{printf("%.3f",i+t)}')
                    else
                        cp "$output".xml "$output".XML
                    fi
                    ((DEBUG)) && debug_line $((LINENO+1)) "spumux sid=${addsdx[i]}"
                    spumux $submuxopt -m $frameformat -s ${addsdx[i]} "$output".XML <"$mpg" >"${mpg%mpg}"mux
                    ret=$? ; (( ret )) && exit $ret
                    mv "${mpg%mpg}"mux "$mpg"
                done
                findpng | xargs -0 rm
                pngremove=
            else
                ((DEBUG)) && debug_line $((LINENO+1)) "spuunmux sid=${addsub[i]}"
                spuunmux $rawshift -r -o "$output" -s ${addsub[i]} -p "$output".rgb -v 1 "$output".dump
                for mpg in "${output}"?([0-9][0-9]).mpg; do 
                    ((DEBUG)) && debug_line $((LINENO+1)) "spumux sid=${addsdx[i]}"
                    spumux -r -m $frameformat -s ${addsdx[i]} "$output".spu <"$mpg" >"${mpg%mpg}"mux
                    ret=$? ; (( ret )) && exit $ret
                    mv "${mpg%mpg}"mux "$mpg"
                done
                rm "${output}".spu
            fi
            #### subtitles langauges codes
            SUBLANG=${SUBLANG:+$SUBLANG,}$(sublang $i)
            ((DEBUG)) && do_log "--DEBUG: [addsub] added subtitle ( sid ): ${addsdx[i]}, language: ${SUBLANG##*,}"
        done
        rm "$output".dump
    fi
    #### mux the text subtitles, supported format (tested only few of them):
    #### MicroDVD (.txt), SubRip (.sub), SubViewer (.srt), Sami (.smi), VPlayer, RT (.rt)
    #### SSA (.ssa,.ass), AQTitle (.aqt), JACOsub (.js,.jss), PJS, MPsub (.mpsub)
    # if -split is used, the subtitles are added only to the first MPEG;
    # this normally is not a problem for DVD because you do not need -split in order to make a DVD
    # for SVCD this could be a problem, but so far nobody seems to use SVCD subtitles
    ((${#txtsub[*]})) && CLEAN[${#CLEAN[*]}]="$output".txtsub.xml
    for ((i=0;i<${#txtsub[*]};i++)); do
        split_txtsub_opt $i 2 && CLEAN[${#CLEAN[*]}]="$output".mpsub && break
    done
    for ((i=0;i<${#txtsub[*]};i++)); do
        #### subtitle lang id
        split_txtsub_opt $i 1 && SUBLANG=${SUBLANG:+$SUBLANG,}$TXTSUBOPT || SUBLANG=${SUBLANG:+$SUBLANG,}${TXTSUBDEF[1]}
        if split_txtsub_opt $i 2 || split_txtsub_opt $i 8 ; then
            DUMPSUBOPT=
            #### subtitle delay
            split_txtsub_opt $i 2 && DUMPSUBOPT="$DUMPSUBOPT -subdelay $TXTSUBOPT"
            #### subtitle fps
            split_txtsub_opt $i 8 && DUMPSUBOPT="$DUMPSUBOPT -subfps $TXTSUBOPT"
            rm -rf  "$output".dir
            removedir=1
            mkdir "$output".dir
            pushd "$output".dir >/dev/null
            mpg="$output"${split:+01}.mpg
            [[ ${output:0:1} = / ]] || mpg="../$mpg"
            [[ ${txtsub[i]:0:1} = / ]] && p= || p=../
            mplayer -dumpsrtsub -sub "$p${txtsub[i]}" $DUMPSUBOPT "$mpg" -vo null -nosound -benchmark -frames 1 -nocache -quiet &>/dev/null
            mv dumpsub.srt ../"${output##*/}".mpsub
            popd >/dev/null
            rm -rf  "$output".dir
            removedir=
            txtsub[i]="$output".mpsub
        fi
        { echo "   INFO: [txtsub] adding subtitle ${txtsub[i]}"
          if ((DEBUG)); then
              echo "--DEBUG: [txtsub] sid: $((i+${#addsub[*]}))"
              for ((n=0;n<${#TXTSUBDEF[*]}/2;n++)); do
                  echo -n "--DEBUG: [txtsub] ${TXTSUBDEF[2*n]}="
                  split_txtsub_opt $i $((n+1)) && echo -n "$TXTSUBOPT "
                  echo "[${TXTSUBDEF[2*n+1]}]"
              done
          fi
        } | tee -a "$output".log
        { echo '<subpictures>'
          echo '  <stream>'
          echo '    <textsub filename="'"$(xmlchar "${txtsub[i]}")"'"'
          echo '      horizontal-alignment="center"'
          split_txtsub_opt $i 3 && if [[ -f ~/.spumux/$TXTSUBOPT ]]; then
               echo -n '      ' && \
                echo 'font="'"$TXTSUBOPT"'"'
              else
                  do_log "++ WARN: [txtsub] font $HOME/.spumux/$TXTSUBOPT for subtitle ${txtsub[i]} not found, using default font" >&2
              fi
          split_txtsub_opt $i 4 && echo -n '      ' && \
                echo 'fontsize="'"$TXTSUBOPT"'"'
          split_txtsub_opt $i 5 && echo -n '      ' && \
                echo 'bottom-margin="'"$TXTSUBOPT"'"'
          split_txtsub_opt $i 6 && echo -n '      ' && \
                echo 'characterset="'"$TXTSUBOPT"'"'
          split_txtsub_opt $i 7 || TXTSUBOPT=0
          echo -n '      ' && [[ $frameformat = SVCD ]] && \
                echo 'movie-width="704"' || \
                echo 'movie-width="720"'
          echo -n '      ' && ((V_RES==480||V_RES==240)) && \
                echo 'movie-height="'$((480-TXTSUBOPT))'"' || \
                echo 'movie-height="'$((576-TXTSUBOPT))'"'
          echo '    />'
          echo '  </stream>'
          echo '</subpictures>'
        } >"$output".txtsub.xml
        mpg="$output"${split:+01}.mpg
        ((DEBUG)) && debug_line $((LINENO+1)) "spumux sid=$((i+${#addsub[*]}))"
        spumux -m $frameformat -s $((i+${#addsub[*]})) "$output".txtsub.xml <"$mpg" >"${mpg%mpg}mux"
        ret=$? ; (( ret )) && exit $ret
        mv "${mpg%mpg}mux" "$mpg"
    done
    [[ $frameformat = SVCD ]] && ((${#addsub[*]}+${#txtsub[*]}>4)) && \
      do_log "++ WARN: [$PROGNAME] maximum 4 subtitles are permitted by the SVCD standard"
    ((${#addsub[*]}+${#txtsub[*]})) && status_bit sbm set
fi

###############################################################################
#### -mpegonly? then exit
###############################################################################
if ((step <4)); then
    if [[ $burniso ]]; then
        burn_iso "$output"?([0-9][0-9]).mpg
        [[ $verify ]] && verify_burn "$output"?([0-9][0-9]).mpg || true
    fi
    exit
fi

###############################################################################
#### create the S/VCD binary image or the DVD filesystem
###############################################################################
if [[ -h $output ]]; then
    slink=-f
    do_log "   INFO: [$PROGNAME] output '$output' is a symbolic link, adding option -f to mkisofs"
else
    slink=
fi
if status_bit img ; then
    if ((iter)); then
        if [[ $addchapter = copy && $frameformat == *VCD || $menu && $frameformat = DVD && ${#thumboffset[*]} -gt 0 ]]; then
            [[ $addchapter = copy && $frameformat == *VCD ]] && singletrack=1
            addchapter=
            i=0
            for mpg in "$output"?([0-9][0-9]).mpg ; do
                addchapter="${addchapter}${addchapter:+,}$i"
                i=$(awk -v t=$(video_duration $OPTIONS "$mpg") -v i=$i 'BEGIN{printf "%.3f",t+i}')
            done
        else
            addchapter=
        fi
    fi
    if [[ $addchapter ]]; then
        ((extrachapter)) && [[ $frameformat != DVD ]] && extrachapter=0
        if [[ $addchapter = copy ]]; then
            #### retreive the chapters from the DVD
            if [[ ! $resume ]]; then
                i=1
                while ! grep -q 'chapters in this DVD title' "$output".log ; do
                    ((i==5)) && break
                    sleep $((i++))
                done
            fi
            maxchapter=$(awk '/chapters in this DVD title/{print $5}' <"$output".log)
            if [[ $maxchapter ]]; then
                addchapter=0
                abslen=0
                for ((a=${firstchap:-1};a<${lastchap:-$maxchapter};a++)); do
                    chaplen=$(video_duration $OPTIONS "${CHAPTEROPT[@]}" -chapter $a-$a )
                    abslen=$(awk -v abslen=$abslen -v chaplen=$chaplen 'BEGIN{printf "%.3f",abslen+chaplen}')
                    addchapter="$addchapter,$abslen"
                done
                if ((extrachapter)); then
                    chaplen=$(video_duration $OPTIONS "${CHAPTEROPT[@]}" -chapter $a-$a )
                    abslen=$(awk -v abslen=$abslen -v chaplen=$chaplen 'BEGIN{printf "%.3f",abslen+chaplen}')
                    if awk -v c=$chaplen 'BEGIN{if(c<5)exit 1}' ; then
                        addchapter="$addchapter,$(awk -v abslen=$abslen 'BEGIN{printf "%.3f",abslen-1}')"
                    else
                        extrachapter=0
                    fi
                fi
                do_log "   INFO: [addchapter] ${firstchap:-1}-$((${lastchap:-$maxchapter}+extrachapter)) TIME=$addchapter (from DVD)"
            else
                addchapter=
            fi
        else
            #### use the chapters list from the command line
            if echo $addchapter | grep -q -e '-'; then
                abslen=0
                for mpg in "$output"?([0-9][0-9]).mpg ; do
                    abslen=$(awk -v abslen=$abslen -v n=$(id_find ID_LENGTH "$mpg") 'BEGIN{printf "%.3f",abslen+n}')
                done
                addchapter=$(awk -v step=$(time2sec ${addchapter%%-*}) -v end=$(time2sec ${addchapter##*-}) -v max=$abslen \
                  'BEGIN{printf("0");end=end<max?end:max;for(a=step;a<=end;a+=step)printf(",%g",a);print}')
                ((extrachapter)) && addchapter="$addchapter,$(awk -v abslen=$abslen 'BEGIN{printf "%.3f",abslen-1}')"
            else
                awk -v c=${addchapter%%,*} 'BEGIN{if(!c)exit 1}' && addchapter=0,$addchapter
            fi
            maxchapter=$(echo $addchapter | awk -F, '{print NF}')
            do_log "   INFO: [addchapter] ${firstchap:-1}-${lastchap:-$maxchapter} TIME=$addchapter (from command line)"
        fi
    fi
    if ((${#thumboffset[*]})); then
        for ((a=0;a<${#thumboffset[*]};a++)); do
            thumboffset[a]=$(time2sec ${thumboffset[a]})
        done
    fi

    FirstChap=1
    case $frameformat in
        *VCD)
            rm -f "${output}"?([0-9][0-9]).cue "${output}"?([0-9][0-9]).bin
            MPGSOURCE=( "$output"?([0-9][0-9]).mpg )
            if ((iter)); then
                MPGNAME=( "$output".mpg )
                MPGITERSRC=( "$output"?([0-9][0-9]).mpg )
                if [[ $singletrack ]]; then
                    grep -q multiaudio "$output"[0-9][0-9].log && do_log "++ WARN: [$PROGNAME] found multiaudio MPEG, using only one audio stream"
                    CLEAN[${#CLEAN[*]}]="$output".mpeg
                    mencoder -oac copy -ovc copy -of mpeg -o "$output".mpeg -noskip -mpegopts tsaf:format=x$(echo $frameformat| tr '[:upper:]' '[:lower:]') \
                      ${telecine:+-ofps 24000/1001} -mc 0 "$output"[0-9][0-9].mpg
                    bakiter=$iter
                    iter=0
                    MPGSOURCE=( "$output".mpeg )
                fi
            else
                MPGNAME=( "$output"?([0-9][0-9]).mpg )
            fi
            split_chapters "$addchapter" "${MPGSOURCE[@]}"
            if [[ $menu ]]; then
                CLEAN[${#CLEAN[*]}]="$output".bg.png
                Menu_MakeBg "$output".bg.png || Menu_Err Menu_MakeBg $LINENO
            fi
            [[ $nomamenu && $multiaudio ]] && ( set -- $multiaudio ; (($#==1)) ) && multiaudio=
            [[ $frameformat = VCD ]] && unset addsub txtsub
            for ((n=0;n<${#MPGNAME[*]};n++)) ; do 
                #### create the menus
                if [[ $menu ]]; then
                    rm -f "$output".se{lection,gment}.xml
                    CLEAN[${#CLEAN[*]}]="$output".selection.xml
                    CLEAN[${#CLEAN[*]}]="$output".segment.xml
                    [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && Menu_MakeVtsChapter $TCPR /dev/null
                    if [[ $multiaudio ]]; then
                        if [[ ! $dvdaudiolang ]] && grep -q 'ID_FILENAME=dvd://' "$output".log ; then
                            for i in $multiaudio ; do
                                dvdaudiolang=${dvdaudiolang:+$dvdaudiolang,}$(sed '/audio stream:/!d;/aid: '"$i"'/!d;s/.*language: //;s/ .*//' "$output".log)
                                [[ ${dvdaudiolang##*,} = unknown ]] && dvdaudiolang=${dvdaudiolang%unknown}nolang
                                [[ ! ${dvdaudiolang##*,} ]] && dvdaudiolang="${dvdaudiolang}nolang"
                            done
                        fi
                        Menu_MakeVtsAudio /dev/null
                    fi
                    ((${#addsub[*]}+${#txtsub[*]})) && Menu_MakeVtsSub /dev/null
                    Menu_MakeInfo
                    Menu_MakeVtsRoot
                fi

                vcdxopts=(-l "$output" --volume-count=${#MPGNAME[*]} --volume-number=$((n+1)))
                if [[ $cdi && $frameformat = VCD ]]; then
                    vcdxopts[${#vcdxopts[*]}]="--iso-application-id=CDI/CDI_VCD.APP;1"
                else
                    vcdxopts[${#vcdxopts[*]}]="--iso-application-id=$(echo $PROGNAME | tr '[:lower:]' '[:upper:]')-$VERSION"
                fi
                (( $(vcdxgen -V | sed 's/[^0-9]*//;s/[^0-9]*$//;s/\([0-9.]*\).*/\1/;s/\([^.]*\)\./(\1)*100+/;s/\([^.]*\)\./(\1)*100+/;q') >714 )) && \
                  VCDENC="--filename-encoding=$VCDENC" || VCDENC=
                if ! type vcdxbuild &>/dev/null || ! type -f vcdxgen &>/dev/null ; then
                    ((!iter)) && MPGITERSRC=( "${MPGSOURCE[n]}" )
                    ((DEBUG)) && debug_line $((LINENO+2)) vcdimager
                    filter_log2 vcdimager
                    vcdimager "${vcdxopts[@]}" $VCDENC $VCDIMAGEROPT -c "${MPGNAME[n]%mpg}cue" -b "${MPGNAME[n]%mpg}bin" "${MPGITERSRC[@]}" >"$output".fifo
                else
                    #### create xml for vcdxbuild
                    [[ $keep ]] || CLEAN[${#CLEAN[*]}]="${MPGNAME[n]%mpg}"cd.xml
                    ((!iter)) && MPGITERSRC=( "${MPGSOURCE[n]}" )
                    ((DEBUG)) && debug_line $((LINENO+1)) vcdxgen
                    vcdxgen "${MPGITERSRC[@]}" --nopbc "${vcdxopts[@]}" $VCDENC $VCDIMAGEROPT -o - | sed -n '1,/<\/pvd>/p' > "${MPGNAME[n]%mpg}"cd.xml
                    { if [[ $cdi && $frameformat = VCD ]]; then
                            echo '  <filesystem>'
                            echo '    <folder>'
                            echo '      <name>CDI</name>'
                            echo '      <file src="'"$(xmlchar "$cdi")"/CDI_IMAG.RTF'" format="mixed">'
                            echo '        <name>CDI_IMAG.RTF</name>'
                            echo '      </file>'
                            echo '      <file src="'"$(xmlchar "$cdi")"/CDI_TEXT.FNT'">'
                            echo '        <name>CDI_TEXT.FNT</name>'
                            echo '      </file>'
                            echo '      <file src="'"$(xmlchar "$cdi")"/CDI_VCD.APP'">'
                            echo '        <name>CDI_VCD.APP</name>'
                            echo '      </file>'
                            echo '    </folder>'
                            echo '    <file src="'"$(xmlchar "$output")".cdi'">'
                            echo '      <name>APPNAME.TXT</name>'
                            echo '    </file>'
                            echo '  </filesystem>'
                            echo "$PROGNAME-$VERSION" >"$output".cdi
                            CLEAN[${#CLEAN[*]}]="$output".cdi
                        fi
                        if [[ $menu ]]; then
                            echo '  <segment-items>'
                            [[ -f $output.segment.xml ]] && cat "$output".segment.xml
                            echo '  </segment-items>'
                        fi
                        echo '  <sequence-items>'
                        if [[ $addchapter || $iter -gt 0 || $menu ]]; then
                            #### add chapters information to the VCD/SVCD
                            m=1
                            if ((iter)); then
                                for a in "${MPGITERSRC[@]}" ; do
                                    echo '    <sequence-item src="'"$(xmlchar "$a")"'" id="entry-'$(printf "%02d" $m)'"/>'
                                    m=$((++m))
                                done
                            else
                                echo '    <sequence-item src="'"$(xmlchar "${MPGSOURCE[n]}")"'" id="sequence-01">'
                                #### I use now split_chapters(), therefore I can use the following code instead of the old one
                                CH=( ${DVDCHAPTERS[n]//,/ } )
                                awk -v c=${CH[0]:-1} 'BEGIN{if(c==0)exit 1}' && CH=( 0 "${CH[@]}" )
                                while ((m<=${#CH[*]})) ; do
                                    echo '      <entry id="entry-'$(printf "%02d" $m)'">'${CH[m-1]}'</entry>'
                                    m=$((++m))
                                done
                                echo '    </sequence-item>'
                            fi
                            echo '  </sequence-items>'
                            echo '  <pbc>'
                            if [[ $menu ]]; then
                                if ((DVDPLAY)); then
                                    echo '    <playlist id="play">'
                                    ((m>3)) && NEXT=selection-02 || NEXT=play-root
                                    echo '      <next ref="'"$NEXT"'"/>'
                                    echo '      <return ref="play-root"/>'
                                    ((iter)) && PLAY=entry || PLAY=sequence
                                    echo '      <play-item ref="'"$PLAY"'-01"/>'
                                    echo '    </playlist>'
                                fi
                                echo '    <playlist id="play-root">'
                                echo '      <prev ref="selection-01"/>'
                                echo -n '      '
                                if [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]]; then
                                      echo '<next ref="play-ptt-01"/>'
                                elif [[ $multiaudio ]]; then
                                      echo '<next ref="play-audio"/>'
                                elif ((${#addsub[*]}+${#txtsub[*]})); then
                                      echo '<next ref="play-subtitle"/>'
                                else
                                      echo '<next ref="play-info"/>'
                                fi
                                echo '      <return ref="end"/>'
                                echo '      <wait>-1</wait>'
                                echo '      <play-item ref="vtsroot"/>'
                                echo '    </playlist>'
                                [[ -f $output.selection.xml ]] && cat "$output".selection.xml
                            fi
                            if ((iter)); then
                                for ((i=1;i<m;i++)) ; do
                                    echo '    <playlist id="selection-'$(printf "%02d" $i)'">'
                                    echo '      <prev ref="selection-'$(printf "%02d" $((i<=1?i:i-1)))'"/>'
                                    [[ $menu ]] && NEXT=play-root || NEXT=end
                                    echo -n '      ' && \
                                       echo -n '<next ref="'
                                    ((i>=m-1)) && echo "$NEXT"'"/>' || echo "selection-$(printf "%02d" $((i+1)))\"/>"
                                    echo '      <return ref="'"$NEXT"'"/>'
                                    echo '      <wait>0</wait>'
                                    echo '      <play-item ref="entry-'$(printf "%02d" $i)'"/>'
                                    echo '    </playlist>'
                                done
                            else
                                for ((i=1;i<m;i++)) ; do
                                    echo '    <selection id="selection-'$(printf "%02d" $i)'">'
                                    echo '      <prev ref="selection-'$(printf "%02d" $((i<=1?i:i-1)))'"/>'
                                    echo -n '      ' && \
                                       echo -n '<next ref="'
                                    [[ $menu && $i -ge $((m-1)) ]] && echo 'play-root"/>' || echo 'selection-'$(printf "%02d" $((i>=m-1?i:i+1)))'"/>'
                                    [[ $menu ]] && echo '      <return ref="play-root"/>' || echo '      <return ref="end"/>'
                                    echo '      <timeout ref="end"/>'
                                    echo '      <wait>1</wait>'
                                    echo '      <loop jump-timing="immediate">1</loop>'
                                    echo '      <play-item ref="entry-'$(printf "%02d" $i)'"/>'
                                    echo '    </selection>'
                                done
                            fi
                            echo '    <endlist id="end" rejected="true"/>'
                            echo '  </pbc>'
                        else
                            #### no chapters
                            echo '    <sequence-item src="'"$(xmlchar "${MPGSOURCE[n]}")"'" id="sequence-01"/>'
                            echo '  </sequence-items>'
                        fi
                        echo '</videocd>'
                    } >>"${MPGNAME[n]%mpg}"cd.xml
                    ((DEBUG)) && debug_line $((LINENO+2)) vcdxbuild
                    filter_log2 vcdxbuild
                    vcdxbuild $VCDENC -c "${MPGNAME[n]%mpg}"cue -b "${MPGNAME[n]%mpg}"bin "${MPGNAME[n]%mpg}"cd.xml >"$output".fifo
                fi
                ret=$? ; (( ret )) && exit $ret
            done
            status_bit img set
            ;;
        DVD)
            #### g0: button of the root menu
            #### g1: root menu/chapter menu/resume
            #### g2: button of the chapter menu
            #### g3: titleset of the title menu
            #### g4: subtitle menu loop
            #### g5: play all titleset
            #### g6: extra menu button
            #### g7: reserved
            INITREG="audio=0; subtitle=0; g0=0; g1=0; g2=0; g3=1; g4=0; g5=0; g6=0; g7=0;"
            ((DVDPLAY)) && DVDPLAY="jump title 1; " || DVDPLAY="jump menu entry title;"
            #### put several titleset on one DVD
            if ((${#TITLESET[*]})); then
                if [[ $videonorm ]]; then
                    CLEAN[${#CLEAN[*]}]="$output".menu.mp2
                    Menu_MakeSilence "$output".menu.mp2
                    CLEAN[${#CLEAN[*]}]="$output".bg.png
                    Menu_MakeBg "$output".bg.png || Menu_Err Menu_MakeBg $LINENO
                    CLEAN[${#CLEAN[*]}]="$output".spu.xml
                    ((MASP)) && CLEAN[${#CLEAN[*]}]="$output".spu1.xml
                fi
                [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".dvd.xml
                { echo     '<?xml version="1.0" encoding="ISO-8859-1"?>'
                  echo     '<dvdauthor dest="'"$(xmlchar "$output")"'">'
                  echo     '  <vmgm>'
                  echo     '    <fpc>'
                  echo     '      { '"$INITREG $DVDPLAY"' }'
                  echo     '    </fpc>'
                  echo     '    <menus>'
                  if ((MASP)); then
                      ((MASP==1)) && s=noletterbox || s=nopanscan
                      echo '      <video widescreen="'$s'" />'
                  fi
                } >"$output".dvd.xml
                if [[ $videonorm ]]; then
                    Menu_MakeVmgm "$output".dvd.xml
                else
                    { echo '      <pgc entry="title" pause="0">'
                      echo '        <pre> {'
                      for ((i=1;i<=${#TITLESET[*]};i++)); do
                          echo -n '          ' && \
                                echo 'if (g3 eq '$i') jump title '$i';'
                      done
                      echo '        } </pre>'
                      echo '      </pgc>'
                    } >>"$output".dvd.xml
                fi
                { echo     '    </menus>'
                  echo     '  </vmgm>'
                  for ((i=0;i<${#TITLESET[*]};i++)); do
                      [[ ! $videonorm ]] && sed '/<titleset>/,/<\/titleset>/!d;/<menus>/,/<\/menus>/d' "${TITLESET[i]}".dvd.xml || \
                      sed '/<titleset>/,/<\/titleset>/!d;s/\(titleset \)[0-9]*\( menu entry\)/\1'$((i+1))'\2/' "${TITLESET[i]}".dvd.xml
                  done
                  echo     '</dvdauthor>'
                } >>"$output".dvd.xml
                dvddirdel -o "$output"
                ((DEBUG)) && debug_line $((LINENO+2)) dvdauthor
                filter_log2 dvdauthor
                dvdauthor -x "$output".dvd.xml 2>"$output".fifo
                ret=$? ; (( ret )) && exit $ret
                [[ $videonorm ]] || do_log "   INFO: [titleset] created a DVD filesystem without menu, add -n <norm> for menu"
                do_log "$(dvd_image_size $(mkisofs -dvd-video $slink -print-size "$output" 2>/dev/null) titleset "dvd image")"
            else
            #### single DVD title
                #### find ISO 639 audio langauges codes
                if [[ ! $dvdaudiolang ]]; then
                    if grep -q 'ID_FILENAME=dvd://' "$output".log ; then
                        if [[ $multiaudio ]]; then
                            for i in $multiaudio ; do
                                dvdaudiolang=${dvdaudiolang:+$dvdaudiolang,}$(sed '/audio stream:/!d;/aid: '"$i"'/!d;s/.*language: //;s/ .*//' "$output".log)
                                [[ ${dvdaudiolang##*,} = unknown ]] && dvdaudiolang=${dvdaudiolang%unknown}nolang
                                [[ ! ${dvdaudiolang##*,} ]] && dvdaudiolang="${dvdaudiolang}nolang"
                            done
                        else
                            #### pick the aid of the first audio stream found and hope it's the good one
                            [[ ! $audioid ]] && audioid=$(awk '/==> Found audio stream:/{print $NF;exit}' <"$output".log )
                            dvdaudiolang=$(sed '/audio stream:/!d;/aid: '"$audioid"'/!d;s/.*language: //;s/ .*//' "$output".log)
                            [[ $dvdaudiolang = unknown || ! $dvdaudiolang ]] && dvdaudiolang=nolang
                        fi
                    fi
                fi
                split_chapters "$addchapter" "${output}"?([0-9][0-9]).mpg
                [[ $nomamenu && $multiaudio ]] && ( set -- $multiaudio ; (($#==1)) ) && multiaudio=
                if [[ $menu ]]; then
                    CLEAN[${#CLEAN[*]}]="$output".menu.mp2
                    Menu_MakeSilence "$output".menu.mp2
                    CLEAN[${#CLEAN[*]}]="$output".bg.png
                    Menu_MakeBg "$output".bg.png || Menu_Err Menu_MakeBg $LINENO
                    CLEAN[${#CLEAN[*]}]="$output".spu.xml
                    ((MASP)) && CLEAN[${#CLEAN[*]}]="$output".spu1.xml
                    ((dvdtitle)) && keep=1
                    DVDPLAY="g0=$(((2+dvdtitle+(${#MEXTRATXT[*]}!=0))*1024)); $DVDPLAY"
                    [[ $keep ]] || CLEAN[${#CLEAN[*]}]="$output".dvd.xml
                    { echo             '<?xml version="1.0" encoding="ISO-8859-1"?>'
                      echo             '<dvdauthor dest="'"$(xmlchar "$output")"'">'
                      echo             '  <vmgm>'
                      echo             '    <fpc>'
                      echo             '      { '"$INITREG $DVDPLAY"' }'
                      echo             '    </fpc>'
                      echo             '    <menus>'
                      echo             '      <pgc entry="title" pause="0">'
                      echo             '        <pre> { jump titleset 1 menu; } </pre>'
                      echo             '      </pgc>'
                      echo             '    </menus>'
                      echo             '  </vmgm>'
 
                      echo             '  <titleset>'
                      echo             '    <menus>'
                      case $MASP in
                          1) echo      '      <video widescreen="noletterbox" />' ;;
                          2) echo      '      <video widescreen="nopanscan" />' ;;
                      esac
                      echo             '      <pgc entry="root" pause="0">'
                      if ((MASP)); then
                          echo         '        <subpicture>'
                          echo         '          <stream mode="widescreen" id="0"/>'
                          ((MASP==1)) && s=panscan || s=letterbox
                          echo         '          <stream mode="'$s'" id="1"/>'
                          echo         '        </subpicture>'
                      fi
                      echo             '        <pre> { if (g1 lt 9) g1=0; if (g0 lt 1024) button=1024; else button=g0; } </pre>'
                      echo             '        <vob file="'"$(xmlchar "$output.vtsroot.mpeg")"'" pause="inf"/>'
                      m=1
                      ((dvdtitle)) && \
                        echo           '        <button name="'$((m++))'"> { g5=0; jump vmgm menu entry title; } </button>'
                      ((${#MEXTRATXT[*]})) && \
                        echo           '        <button name="'$((m++))'"> { g6=3; jump menu 2; } </button>'
                      echo             '        <button name="'$((m++))'"> { g0=button; if (g1 eq 0) jump menu entry root; if (g1 eq 1) jump menu entry ptt; if (g1 eq 9) resume; } </button>'
                      echo             '        <button name="'$((m++))'"> { g0=button; jump title 1; } </button>'
                      [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && \
                        echo           '        <button name="'$((m++))'"> { g0=button; jump titleset 1 menu entry ptt; } </button>'
                      [[ $multiaudio ]] && \
                        echo           '        <button name="'$((m++))'"> { g0=button; jump titleset 1 menu entry audio; } </button>'
                      ((${#addsub[*]}+${#txtsub[*]})) && \
                        echo           '        <button name="'$((m++))'"> { g0=button; jump titleset 1 menu entry subtitle; } </button>'
                      echo             '      </pgc>'
                    } >"$output".dvd.xml
                    ((${#MEXTRATXT[*]})) && Menu_MakeVtsExtra "$output".dvd.xml
                    if [[ $addchapter || $multiaudio || ${#addsub[*]} -gt 0 || ${#txtsub[*]} -gt 0 || $iter -gt 0 ]]; then
                       ((menufix)) && CLEAN[${#CLEAN[*]}]="$output"_pic
                       [[ ( $addchapter || $iter -gt 0 ) && $TCPR -gt 0 ]] && Menu_MakeVtsChapter $TCPR "$output".dvd.xml
                       [[ $multiaudio ]] && Menu_MakeVtsAudio "$output".dvd.xml
                       ((${#addsub[*]}+${#txtsub[*]})) && Menu_MakeVtsSub "$output".dvd.xml
                    fi
                    Menu_MakeVtsRoot
                    { echo             '    </menus>'
                      echo             '    <titles>'
                      [[ $dvdaudiolang ]] && ( IFS=,
                        for a in $dvdaudiolang ; do
                            [[ $a = nolang ]] && a=
                            echo       '      <audio'"${a:+ lang=\"$a\"}"' />'
                        done )
                      if ((dvdsub)); then
                          for ((n=0;n<dvdsub;n++)); do
                              a=$(echo $SUBLANG | cut -f$((n+1)) -d,)
                              [[ $a = nolang ]] && a=
                              echo     '      <subpicture'"${a:+ lang=\"$a\"}"' />'
                          done
                      else
                          [[ $SUBLANG ]] && ( IFS=,
                            for a in $SUBLANG ; do
                                [[ $a = nolang ]] && a=
                                echo   '      <subpicture'"${a:+ lang=\"$a\"}"' />'
                            done )
                      fi
                      [[ $VIDEOATTR ]] && do_log "   INFO: [dvdimage] <video widescreen=\"$VIDEOATTR\" />" >/dev/null && \
                        echo           '      <video widescreen="'$VIDEOATTR'" />'
                      echo             '      <pgc pause="0">'
                      if ((dvdsub&&${#SUBSTREAMATTR[*]})); then
                          for ((n=0;n<dvdsub;n++)); do
                              echo     '        <subpicture>'
                              m=$(echo ${SUBSTREAMATTR[n]} | awk -F, '{print NF}')
                              for ((i=1;i<=m;i+=2)); do
                                  do_log "   INFO: [dvdimage] <substream ($n) mode=\"$(echo ${SUBSTREAMATTR[n]} | cut -f$i -d,)\" id=\"$(echo ${SUBSTREAMATTR[n]} | cut -f$((i+1)) -d,)\"/>" >/dev/null
                                  echo '          <stream mode="'$(echo ${SUBSTREAMATTR[n]} | cut -f$i -d,)'" id="'$(echo ${SUBSTREAMATTR[n]} | cut -f$((i+1)) -d,)'"/>'
                              done
                              echo     '        </subpicture>'
                          done
                      fi
                      echo             '        <pre> g1=9; </pre>'
                      for ((a=0;a<${#DVDMPEGS[*]};a++)); do
                          echo         '        <vob file="'"$(xmlchar "${DVDMPEGS[a]}")"'" '${DVDCHAPTERS[a]:+chapters=\"${DVDCHAPTERS[a]}\" }'/>'
                      done
                      #echo             '        <vob file="'"$(xmlchar "${DVDMPEGS[a]}")"'" '${DVDCHAPTERS[a]:+chapters=\"${DVDCHAPTERS[a]}\" }'pause="2" />'
                      echo             '        <post> g3=g3+1; g1=0; call vmgm menu entry title; </post>'
                      echo             '      </pgc>'
                      echo             '    </titles>'
                      echo             '  </titleset>'

                      echo             '</dvdauthor>'
                    } >>"$output".dvd.xml
                    Menu_ProcessTitle
                    dvddirdel -o "$output"
                    if [[ $dvdtitle -eq 0 || $DVDFS -gt 0 ]]; then
                        ((DEBUG)) && debug_line $((LINENO+2)) dvdauthor
                        filter_log2 dvdauthor
                        dvdauthor -x "$output".dvd.xml 2>"$output".fifo
                        ret=$? ; (( ret )) && exit $ret
                        ((dvdtitle)) || do_log "$(dvd_image_size $(mkisofs -dvd-video $slink -print-size "$output" 2>/dev/null) $PROGNAME "dvd image")"
                    fi
                else
                    dvddirdel -o "$output"
                    ((DEBUG)) && debug_line $((LINENO+2)) dvdauthor
                    filter_log2 dvdauthor
                    dvdauthor $DVDAUTHOROPT -o "$output" -t ${dvdaudiolang:+-a $dvdaudiolang} ${SUBLANG:+-s $SUBLANG} ${VIDEOATTR:+-v $VIDEOATTR} "${DVDAUTHORARG[@]}" 2>"$output".fifo
                    ret=$? ; (( ret )) && exit $ret
                    filter_log2 dvdauthor
                    dvdauthor -o "$output" -T 2>"$output".fifo
                    ret=$? ; (( ret )) && exit $ret
                    do_log "$(dvd_image_size $(mkisofs -dvd-video $slink -print-size "$output" 2>/dev/null) $PROGNAME "dvd image")"
                fi
            fi
            status_bit img set
            ;;
    esac
fi

###############################################################################
#### -imageonly? then exit
###############################################################################
if ((step <5)); then
    if [[ $burniso ]]; then
        burn_iso "$output"?([0-9][0-9]).mpg
        [[ $verify ]] && verify_burn "$output"?([0-9][0-9]).mpg || true
    fi
    exit
fi

###############################################################################
#### create the DVD iso image
###############################################################################
if ((step==5)); then
    if [[ $frameformat = DVD ]]; then
        ((DEBUG)) && debug_line $((LINENO+2)) mkisofs
        filter_log mkisofs '.*% done.*'
        mkisofs -dvd-video $slink -V "${output:0:32}" -A $PROGNAME-$VERSION -o "$output".iso "$output" 2>"$output".fifo >&2
        ret=$? ; (( ret )) && exit $ret
    else
        do_log "++ WARN: [$PROGNAME] cannot create an iso image for $frameformat; use -imageonly"
        step=4
    fi
fi

###############################################################################
#### -isoonly? then exit
###############################################################################
if ((step <6)); then
    if [[ $burniso ]]; then
        burn_iso "$output"?([0-9][0-9]).mpg
        [[ $verify ]] && verify_burn "$output"?([0-9][0-9]).mpg || true
    fi
    exit
fi

###############################################################################
#### burn
###############################################################################
sleep 1
case $frameformat in
    *VCD)
        for cue in "${output}"?([0-9][0-9]).cue; do
            [[ -f ${cue%cue}bin ]] || ! echo "**ERROR: $cue present but ${cue%cue}bin not present" || exit 1
            if [[ ! $nowait ]]; then
                echo "please insert a cd in your cdwriter, press any key to start burning:"
                read -n 1 i
            fi
            if [[ -n $blank ]]; then
                ((DEBUG)) && debug_line $((LINENO+1)) cdrdao/blank
                cdrdao blank $CDRDAOOPT --blank-mode minimal
            fi
            ((DEBUG)) && debug_line $((LINENO+2)) cdrdao
            filter_log cdrdao
            cdrdao write ${overburn:+--overburn} $CDRDAOOPT "$cue" 2>"$output".fifo
            nowait=
            if [[ $verify ]]; then
                while : ; do
                    do_log "   INFO: [verify] checking $frameformat image ${cue%cue}bin"
                    rm -rf "$output".dir
                    removedir=1
                    mkdir "$output".dir
                    pushd "$output".dir >/dev/null
                    vcdxrip -C $dvdburndevice
                    mkdir ISO
                    cd ISO
                    [[ ${cue:0:1} != / ]] && BIN="../../${cue%cue}bin" || BIN="${cue%cue}bin"
                    vcdxrip -b "$BIN"
                    ERR=
                    shopt -s nullglob
                    for a in * ; do
                        if [[ -f "../$a" ]]; then
                            cmp -s "../$a" "$a" || ! ERR=1 || ( pushd >/dev/null ; do_log "**ERROR: [verify] file $a is different" ; pushd >/dev/null )
                        else
                            ERR=1
                            ( pushd >/dev/null ; do_log "**ERROR: [verify] file $a is missing" ; pushd >/dev/null )
                        fi
                    done
                    shopt -u nullglob
                    popd >/dev/null
                    rm -rf "$output".dir
                    removedir=
                    if [[ $ERR ]]; then
                        do_log "++ WARN: [verify] $frameformat error(s) detected, but it may be a non permanent read error"
                        echo -n "do you want to retry [N/y]? "
                        read
                        [[ $REPLY != [yY]* ]] && break
                    else
                        do_log "   INFO: [verify] no errors found"
                        break
                    fi
                done
            fi
        done
        ;;
    DVD)
        if [[ ! $nowait ]]; then
            echo "please insert a dvd in your dvdwriter, press any key to start burning:"
            read -n 1 i
        fi
        ((DEBUG)) && debug_line $((LINENO+2)) growisofs
        filter_log growisofs '.*% done.*'
        growisofs ${overburn:+-overburn} $GROWISOFSOPT $slink -V "${output:0:32}" -A $PROGNAME-$VERSION "$output" 2>"$output".fifo >&2
        ret=$? ; (( ret )) && echo "**ERROR failure detected, exiting" && exit $ret
        [[ $verify ]] && verify_burn "$output" || true
        ;;
esac

################################################################################
#### done
################################################################################
exit
