Mercurial > mplayer.hg
diff TOOLS/encode2mpeglight @ 17507:c658a7107209
new tool to encode to mpeg using only mencoder; patch by Giacomo Comes <comes ad naic punctum edu>
author | nicodvb |
---|---|
date | Sun, 29 Jan 2006 20:42:34 +0000 |
parents | |
children | 36589811e5d0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TOOLS/encode2mpeglight Sun Jan 29 20:42:34 2006 +0000 @@ -0,0 +1,1852 @@ +#!/bin/bash +# +# Version: 0.5.5 +# +# Licence: GPL +# +# 2004-05-22 Giacomo Comes <encode2mpeg at users.sourceforge.net> +# 2006-01-14 <encode2mpeg at katamail.com> +# +# Pourpose: Convert anything MPlayer can play to AVI/VCD/SVCD/DVD mpeg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License. + +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +############################################################################### +# encode2mpeglight is a program that can create VCD/SVCD/DVD mpegs +# and eventually extract VobSub subtitles from a DVD using only +# MEncoder/MPlayer. +# +# encode2mpeglight is a stripped release of encode2mpeg and therefore the +# code is redundant in several places, with many variables defined and +# used for no apparent reason. This cannot be avoided easily. +# A command line like: +# encode2mpeglight <encode2mpeglight options> +# will produce almost the same results as: +# encode2mpeg -mpeg -mpegonly <encode2mpeglight options> +# +# If you need more features like: +# - two or more audio streams, chapters, subtitles, menu +# - creation, burn and verification of the disk image +# - creation of MPEG-4 avi and subtitles for a hardware player +# and more, consider to use the full release (http://encode2mpeg.sf.net) +# +# encode2mpeglight is mainly tested with the stable release of MPlayer, +# I try to make it work with CVS too, but due to the "instable" nature of +# CVS, bugs may suddenly appear. If you find any, please report it to me. +############################################################################### + +############################################################################### +#### start +############################################################################### +export LC_ALL=POSIX +set -B +f +shopt -u xpg_echo nullglob +PROGNAME=${0##*/} +PROGFILE=$(type -p "$0") +VERSION=$(awk '$2=="Version:"{print $3;exit}' <"$PROGFILE") +BROWSER= + +############################################################################### +#### some functions +############################################################################### +OptionsText () { + echo + echo "Arguments enclosed in [ ] are optional" +} +############################################################################### +ModeText () { + echo + echo -e "$PROGNAME defaults to encode2mpeg's Mpeg Mode, the others mode are not" + echo -e "available" +} +############################################################################### +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-2006 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 -identify -vo null -ao null -nocache "$@" -frames 0 2>/dev/null +} +############################################################################### +get_aspect () { + mplayer -vo null -ao null -nocache -frames 4 "$@" 2>/dev/null | sed '/^Movie-Aspect is/!d;s/.*Movie-Aspect is //;s/:.*//' +} +############################################################################### +mlistopt () { + mplayer -list-options 2>&1 | awk '$1=="Name"{m=1}{if(m&&$1!="Name"&&$1!=""&&$1!="Total:")print "\""$1"\""}' +} +############################################################################### +pre_log () { + echo "$1" + 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 | sed '/^ '$1'$/,/^ -/!d' | sed '$d' + "$PROGFILE" -norc -l | sed '/^ '$1'[ |]/,/^ -/!d' | sed '$d' + exit 1 + fi + if [[ $2 = doc ]]; then + show_html ${3:+$3.html} + exit + fi +} +############################################################################### +pr_date () { + echo "[$(date '+%Y-%m-%d %H:%M:%S')]" +} +############################################################################### +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' | cut -f2 -d=) + case $(echo "$INFO" | grep '^ID_AUDIO_CODEC' | cut -f2 -d=) in + dvdpcm) abr=$((abr+ABR/1024)) ;; + *) abr=$((abr+ABR/1000)) ;; + esac +} +############################################################################### +get_pwd () { + pushd &>/dev/null "$1" + echo "$PWD/$2" + popd &>/dev/null +} +############################################################################### +show_html () { + local i LIST HTML PREFIX OPTION INSTDOCDIR SRCDOCDIR + INSTDOCDIR=${PROGFILE%/bin/$PROGNAME}/share/doc/encode2mpeg + 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=(mozilla firefox) + [[ ${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=(mozilla firefox 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 +} + +############################################################################### +#### variables initialization +############################################################################### +abr=;asr=;vbr=;vfr=;videonorm=;frameformat=;output=;audioformat=;mp1=;mp2=;mp3=;ac3=;dts=;lpcm=;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=;ac=;afm=;cache=;removecache=;turbo=;dvddev=;srate=;endpos=;fourcc=;menu=;menubg=;dvdtitle=;rotate=;menuvtsbg=;autosync=;telecine=;AFMT=;telesrc=;vcodec=;vrfyumnt=;burniso=;verify=;fixasync=;removedir=;MPGRES=;GOP=;TXTSUBOPT=;usespeed=;testmca=;chconf=;noodml=;pictsrc=;slideaudio=;audioonly=;norc= +unset encsid encsdx encsla addsub addsdx addsla savecache txtsub txtsubopts +zoom=0 +scale=1 +fast=1 +MAXSTEP=6 # burn is the default +step=$MAXSTEP +split=0 +vbitrate=16000 +mpegmbr=0 +overscan=0 +iter=0 +bakiter=0 +hispeed=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 +menufix=0 +cdburndevice=0,0,0 +dvdburndevice=/dev/cdrecorder +fsize=;fint=;ffrac=;fpre=;audiosize=0 +ASPECT=(1 1 4/3 16/9 2.21) +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 +unset CLEAN +DEBUG=0 +LAVC= +WARN= +LOG= +MAXFIX=20 +timelen=0 +ocrsub=0 +slidefps=1 +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 ) + +#### encode2mpeglight defauls +mpeg=1 +encode=7:2:2 + +(($#)) || ! 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 -vophelp 2>&1 | awk '/vop-/{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 + WARN="$WARN${WARN:+\n}++ WARN: [$PROGNAME] ~/.encode2mpegrc appears to contain comments, ignoring it" + 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> + # 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] + # 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> + # 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 + echo "$2" | grep -q '^[0-3]$' && rotate=$2 + isarg $1 "$2" aspect + 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 + echo "$2" | grep -qE '^-?[0-9]?[0-9]$' && overscan=$2 + [[ ${2:0:1} = - ]] && mpegfixaspect=1 || mpegfixaspect=0 + isarg $1 "${2#-}" $( ((step==1)) && echo Avi || echo aspect) + 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 + isarg $1 "$2" direct + shift + ;; + -asr) #<n> + #-audio sample rate of the VCD/SVCD/DVD [MP2/MP3:44100,AC3:48000] + asr=$2 + isarg $1 "$2" direct + shift + ;; + -vbr) #<n> + #-video bit rate of the VCD/SVCD/DVD [VCD:1152,SVCD:2500,DVD:7500] + vbr=$2 + isarg $1 "$2" 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> + #-set the video norm of the VCD/SVCD/DVD + 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) # + # 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> + # 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 + 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> + # 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 + shift 2 + set -- " " -qmatrix kvcd -res $((3+(a+1)/2)) $([[ $a == [13] ]] && echo "-gop 24") "$@" + ;; + -vcd) # + #-generate VCD compliant frames on output (default) + [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct + frameformat=VCD + ;; + -svcd) #[1-2] + # 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) # + # 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] + # 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 + ;; + -vcodec) #<mpeg1|mpeg2|mpeg4> + #-force the selected video codec [VCD:mpeg1,SVCD-DVD:mpeg2,AVI:mpeg4] + isarg $1 "$2" Avi + [[ $2 == mpeg[124] ]] && 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) # + # 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" + ;; + -mpegmbr) #<n> + # 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 + ;; + -mpegchannels) #<1-6> + # 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 + isarg $1 "$2" direct + echo "$2" | grep -q '^[1-6]$' && mpegchannels=$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 + ;; + -noscale) # + # encode2mpeg automatically scales the video according to the mpeg + # profile chosen, this option disable this feature; used mainly + #-for debug purpose + [[ $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" + ;; + -split) #<n> + #-split the resulting mpeg stream in <n> MB chunks. + split=$2 + isarg $1 "$2" direct + shift + ;; + -encode) #<n:m:i[,b]> + # 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/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 + #- with n=[3-7] b specify the audio bit rate + encode=5:3:2 + echo "$2" | grep -qE '^[0-7]:[0-4]:[1-9](,[0-9]+)?$' && encode=$2 + isarg $1 "$2" $([[ $mpeg ]] && echo mpeg || echo Avi) + shift + ;; + -telecinesrc) # + # 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> + # disable (0) or force (1) turbo mode for the first pass of N pass + #-encoding (N>1) + echo "$2" | grep -q '^[0-1]$' && turbo=$2 + isarg $1 "$2" Avi + shift + ;; + -hispeed) # + # 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 mpeg4/avi or a DVD + [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi + hispeed=1 + ;; + -bframes) #<0-4> + # 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 + echo "$2" | grep -q '^[0-4]$' && bframes=$2 + isarg $1 "$2" Avi + shift + ;; + -vcustom) #<libavcodec options> + # specify a custom set of video options for libavcodec, use with + #--encode n:1:i + vcustom=$2 + isarg $1 "$2" Avi + shift + ;; + -acustom) #<mp3lame options> + #-specify a custom set of lame options, use with -encode 2: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) # + # 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] + # 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 + ;; + -cpu) #<n> + #-number of cpu to use, default all the cpu present in the system + cpu=1 + echo "$2" | grep -q '^[1-8]$' && cpu=$2 + isarg $1 "$2" Avi + shift + ;; + -interlaced) + #-turn on optimization for interlaced source video. + [[ $2 = doc || $2 = help ]] && isarg $1 $2 $([[ $mpeg ]] && echo mpeg || echo Avi) + interlaced=1 + ;; + -slidefps) #<n> + # fps to use when creating video from pictures, default is 1; if + # there is a audio file associated with a picture, the duration of + #-the audio file is used + slidefps=$(awk -v a=$2 'BEGIN{printf("%.3f",1/a)}') + isarg $1 "$2" images + 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 + [[ $2 = doc || $2 = help ]] && isarg $1 $2 + ((DEBUG)) && DEBUG=2 || DEBUG=1 + ;; + (-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 + ;; + (-endpos) + endpos=$2 + isarg $1 $2 + shift + ;; + (-hr-edl-seek) + MENCODEROPT=( "${MENCODEROPT[@]}" $1 ) + ;; + (-vf) + vf="-vf $2" + MPLAYEROPT=( "${MPLAYEROPT[@]}" $vf ) + 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 + ;; + (-mpeg|-mpegonly|-nosplit) ;; + *) + 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 + *) + MPLAYEROPT[${#MPLAYEROPT[*]}]=$1 + ;; + esac + fi + ;; + esac + shift +done + +[[ -s ~/.encode2mpegrc && ! $norc ]] && pre_log " INFO: [$PROGNAME] using .encode2mpegrc settings: '$(<~/.encode2mpegrc)'" + +############################################################################### +#### redirect stdout and stderr to the debug file +############################################################################### +if ((DEBUG)); then + exec 3>&1 + rm -f "$output".debug.fifo + mkfifo "$output".debug.fifo + tee "$output".debug <"$output".debug.fifo >&3 & + PROCTEE=$! + exec &>"$output".debug.fifo + ((DEBUG==2)) && set -x +fi + +############################################################################### +#### ERROR if some options conflict is detected part 1/2 +############################################################################### +#### mplayer/mencoder +for a in mplayer mencoder ; do + type $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 ]] && echo "**ERROR: [$PROGNAME] name of the output stream missing (-o name)" && exit 1 +#### unspecified video norm +[[ ! $videonorm && step -gt 1 && ! ( $mpeg && ${encode%,*} == ?:0:? && ! $menu ) ]] && \ + echo "**ERROR: [$PROGNAME] you must specify a video norm (-n n|p|s)" && exit 1 +#### pictsrc +if [[ $pictsrc ]]; then + [[ $slideaudio != /dev/null && ${encode%,*} == 0:?:? && $mpeg ]] && \ + echo "**ERROR: [$PROGNAME] -encode 0:m:i is not compatible with mf:// in Mpeg Mode" && exit 1 + [[ $audioonly ]] && echo "**ERROR: [$PROGNAME] -audioonly does not work with mf://" && exit 1 +fi +#### -encode 1:m:i is not allowed +[[ ${encode%,*} == 1:?:? ]] && echo "**ERROR: [$PROGNAME] do not use -encode 1:m:i" && exit 1 + +############################################################################### +#### WARN if some options conflict is detected +############################################################################### +#### missing toolame support +if [[ ${encode%,*} == 7:?:? ]]; then + if ! mencoder -oac help 2>/dev/null | grep -q toolame ; then + encode=4:${encode#?:} + pre_log "++ WARN: [$PROGNAME] missing toolame support in mencoder, setting -encode $encode" + fi +fi + +############################################################################### +#### set default values for unspecified parameters +############################################################################### +if [[ ! $multiaudio ]]; then + audiostream=1 +fi +############################################################################### +if [[ $encode ]]; then + case ${encode%%:*} in + 0) [[ ! $pictsrc ]] && + AFMT=acopy ;; + 2|3|5) AFMT=mp3 ;; + 4|7) AFMT=mp2 ;; + 6) AFMT=ac3 ;; + esac + [[ $AFMT ]] && eval : ${audioformat:-\${$AFMT:=copy}} +fi +: ${frameformat:=VCD} +: ${audioformat:=${AFMT:-mp2}} +: ${mp1:=mp2enc} +((${mpegchannels:-2}>2)) && : ${mp2:=musicin} || : ${mp2:=mp2enc} +: ${mp3:=lame} +: ${ac3:=mencoder} +: ${dts:=copy} +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 + ;; + #### 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 + fi +fi +[[ $mpeg && ${encode%,*} == ?:0:? ]] && \ + vbr=$(($(mp_identify "${MPLAYEROPT[@]}" ${dvddev:+-dvd-device "$dvddev"} "$@" | grep '^ID_VIDEO_BITRATE' | cut -f2 -d=)/1000)) +case $frameformat in + DVD) : ${asr:=48000} ;; + *) : ${asr:=44100} ;; +esac +case $videonorm in + p|s) + : ${vfr:=3} + ;; + n) + #FIXME remove the encode 3 check once the mpeg muxer is fixed + [[ $frameformat != VCD && ! $vfr && $hispeed -eq 0 && ! $testmca && ${encode%,*} != ?:3:? ]] && vfr=1 && telecine=1 + : ${vfr:=4} + ;; +esac +[[ $encode ]] && : ${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 +############################################################################### +PCM=(pcm:waveheader:file="$output".wav) +PCMTMP=(pcm:waveheader:file="$output".tmp) +PCMNOWYUV=(pcm:nowaveheader:file=/dev/fd/4) + +[[ $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[@]}" ) + +#### mf:// case +if [[ $pictsrc ]]; then + if [[ $slideaudio && $slideaudio != /dev/null ]]; then + [[ $(mp_identify "$slideaudio" | grep ID_AUDIO_RATE | cut -f2 -d=) != $asr ]] && SRATE="-srate $asr -af-adv force=1" || SRATE= + CLEAN[${#CLEAN[*]}]="$output".wav + mplayer "$slideaudio" $SRATE -vo null -vc dummy -ao "${PCM[@]}" $VOL $ac $afm ${mpegchannels:+-channels $mpegchannels -af channels=$mpegchannels} + MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps 1/$(mp_identify "$output".wav | sed -n '/^ID_LENGTH=/s/.*=//p') -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} ) + +MENCODERARG=( "${MENCODERARG[@]}" "${MENCODEROPT[@]}" ${endpos:+-endpos $endpos} ) +if [[ $mpeg && $mpegchannels ]]; then + MENCODERARG=( "${MENCODERARG[@]}" -channels $mpegchannels ) +else + MENCODERARG=( "${MENCODERARG[@]}" ${channels:+-channels $channels} ) +fi +#### if video copy then no ofps +[[ ${encode%,*} != ?:0:? ]] && MENCODERARG=( "${MENCODERARG[@]}" ${ofps:+-ofps $ofps} ) + +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" + +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 +case $frameformat in + 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" + 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 + +############################################################################### +#### mencoder audio/video/pass options +############################################################################### +if [[ $encode ]]; then + OPTIONS="-noskiplimit -sws $((hispeed?1:7))" + 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 ${mpegaspect:+vaspect=${ASPECT[mpegaspect]}:}" + MUX2="${telecine:+:telecine}" + case $frameformat in + 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 really means aspect undefined (do not scale), not aspect 1:1 + [[ $vcodec != mpeg4 || $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}}" + OF="-of mpeg" + NOSKIP=-noskip + vbitrate=$vbr + 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 + fi + + BASIC="$LAVC:vbitrate=${vbitrate}${cpu:+:threads=$cpu}${bframes:+:vmax_b_frames=$bframes}" + ((hispeed)) && BASIC="$BASIC:vme=0" || BASIC="$BASIC:psnr" + [[ $mpeg && $frameformat = VCD ]] || 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:vlelim=-4:vcelim=7:trell: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:precmp=6:cmp=6:subcmp=6" + [[ $vbitrate -ge 3500 && $frameformat != VCD && $vcodec != mpeg1video ]] && BESTQUALITY="$BESTQUALITY:dc=9" + fi + + case $encode in + 0:?:?|0:?:?,*) AUDIOPASS="-oac copy" ;; + 1:?:?|1:?:?,*) AUDIOPASS="-oac pcm" ;; + 2:?:?|2:?:?,*) AUDIOPASS="-oac mp3lame -lameopts ${acustom:-fast}" ;; + 3:?:?) AUDIOPASS="-oac mp3lame -lameopts preset=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 -toolameopts br=$abr" ;; + 3:?:?,*) AUDIOPASS="-oac mp3lame -lameopts preset=${encode#*,}" ;; + 4:?:?,*) AUDIOPASS="-oac lavc -lavcopts acodec=mp2:abitrate=${encode#*,}" ;; + 5:?:?,*) AUDIOPASS="-oac lavc -lavcopts acodec=mp3:abitrate=${encode#*,}" ;; + 6:?:?,*) AUDIOPASS="-oac lavc -lavcopts acodec=ac3:abitrate=${encode#*,}" ;; + 7:?:?,*) AUDIOPASS="-oac toolame -toolameopts br=${encode#*,}" ;; + esac + encode=${encode%,*} + 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 lavc -lavcopts ${BASIC}${vcustom:+:$vcustom}" ; : ${turbo:=0} ;; + ?:2:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${HQ}" ; : ${turbo:=1} ;; + ?:3:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${BESTSIZE}" ; : ${turbo:=1} ;; + ?:4:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${BESTQUALITY}" ; : ${turbo:=1} ;; + esac + ((turbo)) && turbo=:turbo || turbo= + PASS=${encode##*:} + [[ $normalize && $encode != 0:?:? ]] && AUDIOPASS="-af volnorm $AUDIOPASS" +fi + + +############################################################################### +#### more functions +############################################################################### +status_bit () { + local a + 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 ;; + esac + if [[ $2 = set ]]; then + skip=$((skip|1<<bit)) + 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=$(ls -l "$1" | awk '{print $5}') + fint=$fsize + ffrac=0 + while ((fint>=1024)) ; do + ((fint/1024 < 1024)) && fint=$((fint+51)) + i=$((++i)) + ffrac=$((fint%1024)) + 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 + VIDEO="$(mplayer -nocache -frames 0 -vo null -nosound "$2" 2>/dev/null | grep "^VIDEO:")" + if [[ ! $VIDEO ]]; then + # mpegs with mpeg4 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: MPEG4 $(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 + echo " $1: $VIDEO" >>"$output".log + #### 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/.* //') + 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"'/;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}' +} +############################################################################### +job_exit () { + EXIT=$? + status_bit mpg || [[ ! -f ${output}.mpg && ! -f ${output}01.mpg ]] || show_finalvideo_info "MPEG" "${output}"*.mpg + sec=$(($(pr_time)-STARTTIME)) + echo " JOBEND: $output $(pr_date) ($((sec/3600))h$((sec/60%60))m$((sec%60))s)" >>"$output".log + rm -f "${CLEAN[@]}" psnr_??????.log + ((DEBUG)) && exec >&1- >&2- && exec >&3 + if [[ -f $output.yuvscaler.log || -f $output.mpeg2enc.log ]]; then + echo + else + ((!EXIT)) && [[ ! $quiet ]] && cat "$output".log + fi + ((DEBUG)) && rm -f "$output".debug.fifo && kill $PROCTEE +} +############################################################################### +mplayer_log () { + tee -a /dev/stderr | sed 's/.*\r//' | \ + awk '/^PSNR:|^M[EP][ln]|^There are |^\[open]|^==> |^Recommended video bitrate/{sub(/^/," INFO: ['"$1"'] ");print}' >>"$output".log +} +############################################################################### +mp_single_log () { + tee -a /dev/stderr | sed 's/.*\r//;/'"$2"'/!d;s/^/ INFO: ['$1'] /' >>"$output".log +} +############################################################################### +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 +} +############################################################################### +debug_line () { + echo "--DEBUG: [$PROGNAME] $2($1) $(eval echo $(sed -n $1p "$PROGFILE" | sed 's/ |.*//;s/.>.*//;s/</\\\</'))" >>"$output".log +} +############################################################################### +check_mencoder_abr () { + local codec lib ASR + codec=([4]=mp2 mp3 ac3 mp2) + lib=([4]=libavcodec libavcodec libavcodec libtoolame) + 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 +} + +############################################################################### +#### ERROR if some options conflict is detected part 2/2 +############################################################################### +#### libavcodec codec/asr/abr +#### libtoolame asr/abr +#### libmp3lame asr +#### no check is done on the other channel in case of multiaudio +if [[ $encode == [2-7]:?:? ]]; then + if [[ $srate ]]; then + r=$srate + else + r=$(mp_identify "${MPLAYERINFO[@]}" | sed -n '/^ID_AUDIO_RATE=/s/.*=//p') + if [[ $mpeg && ! $usespeed ]]; then + case $frameformat in + *VCD) ((r != 44100)) && pre_log "++ WARN: [$PROGNAME] $frameformat standard requires 44100kHz audio, add -srate 44100" ;; + DVD) ((r != 48000)) && pre_log "++ WARN: [$PROGNAME] $frameformat standard requires 48000kHz audio, add -srate 48000" ;; + esac + fi + fi + if [[ $encode == [4-7]:?:? ]]; then + check_mencoder_abr $r ${AUDIOPASS##*=} + 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 +#### copy of non mpeg audio in a VCD +if [[ $step -gt 1 && $frameformat = VCD && $encode == 0:?:? && ( $mpeg || ${!audioformat} = copy ) && ! $testmca && ! $pictsrc ]]; then + a=$(mp_identify "${MPLAYERINFO[@]}" | sed -n '/^ID_AUDIO_CODEC=/s/.*=//p') + [[ $a != mp3 ]] && echo "**ERROR: [$PROGNAME] you cannot copy $a audio in a $frameformat" && exit 1 +fi +#### mpegchannels > 2 only with ac3 +[[ $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 +############################################################################### +#### set cleanup +############################################################################### +trap 'job_exit' 0 +CLEAN[${#CLEAN[*]}]="$output".fifo + +skip=0 + +############################################################################### +#### start the log file +############################################################################### +if [[ ! $resume ]] ; then + { 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" + else + if [[ $mpeg ]]; then + [[ $testmca ]] && echo -n "Testmca Mode" || echo -n "Mpeg Mode" + fi + fi + echo "${cpu:+ (cpu=$cpu)}" + echo " INFO: [$PROGNAME] command line: '${CMD[@]}'" + } >"$output".log +fi + +############################################################################### +#### WARNING if some requested tools are missing and can be replaced +############################################################################### +#### WARN +if [[ $WARN ]]; then + echo -e "$WARN" >>"$output".log +fi +#### volume and audio copy +if [[ $volume ]]; then + [[ $encode == 0:?:? && ( ${!audioformat} = copy || $step -eq 1 || $mpeg ) || ${!audioformat} = copy && ! $encode ]] && \ + echo "++ WARN: [$PROGNAME] you cannot modify the volume of the output audio stream if you are making a copy the input audio stream" | \ + tee -a "$output".log +fi +#### cpu and bframes +if [[ $cpu && $bframes ]]; then + ((bframes)) && echo "++ WARN: [$PROGNAME] with bframes>0 the encoding will be faster with cpu=1" | tee -a "$output".log +fi +#### -usespeed +if [[ $usespeed && ( $encode == 0:?:? || $encode == ?:0:? ) ]]; then + echo -en "++ WARN: [$PROGNAME] -usespeed may not work if you do not encode both audio and video.\nPress return to proceed" | tee -a "$output".log && read +fi +#### total br +[[ $encode != ?:0:? ]] && ((step>1&&abr*audiostream*1024/1000+vbr>MAXBR)) && \ + echo "++ WARN: [$PROGNAME] total video+audio bitrate ($vbr+$((abr*audiostream*1024/1000))kbps) exceed $frameformat specifications (${MAXBR}kbps)" | \ + tee -a "$output".log +#### -slideaudio/single picture +if [[ $slideaudio && $slideaudio != /dev/null && $pictsrc ]]; then + ((${#PICTSRC[*]}!=1||$(ls ${PICTSRC[0]} | wc -l)!=1)) && \ + echo "++ WARN: [$PROGNAME] you should use only one source image if you use the option -slideaudio" | tee -a "$output".log +fi +#FIXME remove once the mpeg muxer is fixed +#### NTSC telecined with B-frames +if [[ $mpeg && $telecine && $videonorm = n && ( $frameformat = DVD || $frameformat = SVCD ) && ( $bframes -gt 0 || ! $bframes && $encode == ?:3:? ) ]]; then + echo "++ WARN: [$PROGNAME] mpeg telecined and with B-frames are not created correctly by mencoder, do not use telecine or do not use B-frames" | \ + tee -a "$output".log + echo -n "Press return to proceed" && read +fi + +############################################################################### +#### dump some info in the log file +############################################################################### +{ 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 + echo -n " MPEG: " + for ((i=0;i<${#VARS[*]};i++)) ; do + echo -n "${VARS[i]}:${!VARS[i]} " + done + 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 + VARS=(encode ${vcodec:+vcodec} ${volume:+volume} ${usesbr:+usesbr} ${avisplit:+avisplit} ${channels:+channels} AUDIOPASS VIDEOPASS PASS) + if [[ $encode ]]; then + echo -n " $([ $mpeg ] && echo MPEG || echo \ AVI): " + for ((i=0;i<${#VARS[*]};i++)) ; do + echo -n "${VARS[i]}:${!VARS[i]} " + done + if ((PASS>1)); then + [[ $turbo ]] && echo -n "TURBO:on " || echo -n "TURBO:off " + fi + txt= + [[ $(echo $encode | cut -f 2 -d:) = 1 && $vcustom ]] && txt="libavcodec" + [[ ${encode%%:*} = 2 && $acustom ]] && txt=${txt:+${txt} and} && txt="$txt lame" + txt=${txt:+(custom ${txt} options)} + echo $txt + fi + [[ ! $resume ]] && { [[ $audioonly ]] && mp_identify "$audioonly" || mp_identify "${MPLAYERINFO[@]}" ; } | sed -n '/^ID_/s/^/ INFO: [identify] /p' | uniq + VARS=(${encode:+MENCODERARG} MPLAYERYUVOPT) + VARS=(${encode:+MENCODERARG}) + for ((i=0;i<${#VARS[*]};i++)) ; do + s="INFO: [${VARS[i]}] \${${VARS[i]}[*]}" + eval echo "\ \ \ $s" + done +} >>"$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 + v_res=$(mplayer -vo null "${MPLAYERINFO[@]}" -frames 1 2>/dev/null | awk '/^VO:/{print $3}' | head -n 1) + h_res=${v_res%x*} + v_res=${v_res#*x} +fi +[[ $mpeg && ${encode%,*} == ?:0:? ]] && H_RES=$h_res && V_RES=$v_res + +############################################################################### +#### put the volume in DB +############################################################################### +[[ $volume ]] && volume="-af volume=$(awk -v a=$volume 'BEGIN{if(a>0) print 20*log(a)/log(10) ; else print 0}')" + +############################################################################### +#### NTSC telecined 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 + echo "++ WARN: [$PROGNAME] input video frame rate is not exactly ${FPS[i]}fps" | tee -a "$output".log + FPS[0]=${FPS[i]} + fi + FPS[10]=$i + break + fi + done + [[ $usespeed && $i -eq 9 ]] && \ + echo "++ WARN: [$PROGNAME] input video frame rate is not a valid NTSC/PAL value; disabling -usespeed" | tee -a "$output".log && 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)) + 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 ) + echo " INFO: [usespeed] using speed factor $a" | tee -a "$output".log + fi + elif [[ ${FPS[0]} = ${FPS[4]} || ${FPS[0]} = ${FPS[5]} ]]; 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" + echo " telecined source" + } | tee -a "$output".log + MENCODERARG=( "${MENCODERARG[@]}" -ofps 24000/1001 -mc 0 ) + fi + fi +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 crop=$mpegfixaspect -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=16/9 + if(a==1.33)a=4/3 + if(A=="4/3")A=4/3 + if(A=="16/9")A=16/9 + if(r!=""){ + A=1/A + tmp=W + W=H + H=tmp + } + if(a>A&&crop==0||a<A&&crop==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("-vf scale=%d:%d",Ew,Eh) + printf(" INFO: [mpegfixaspect] -vf scale=%d:%d",Ew,Eh) >>logfile + if(i==1)printf(":1") + if(i==1)printf(":1") >>logfile + if(crop==0){ + printf(",expand=%d:%d",W,H) + printf(",expand=%d:%d",W,H) >>logfile + }else{ + printf(",crop=%d:%d",W,H) + printf(",crop=%d:%d",W,H) >>logfile + } + if(r!=""){ + printf(",rotate=%d",r) + printf(",rotate=%d",r) >>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 + fi +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") + echo " INFO: [$PROGNAME] dumping subtitle ${encsid[idx]} to vobsub ${encsdx[idx]}${encsla:+ (${encsla[idx]})}" | tee -a "$output".log + 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=) +[[ $mpeg && ! $pictsrc && ( $encode == 1:?:? || $multiaudio || $encode == 0:?:? && $IDACOD != mp3 && $IDACOD != a52 ) ]] && extra=1 || extra= +[[ $extra ]] && echo "**ERROR: [$PROGNAME] output stream: unsupported audio codec $IDACOD" | tee -a "$output".log && exit 1 + +CLEAN[${#CLEAN[*]}]="$output".tmp + +############################################################################### +#### avi/mpeg section +############################################################################### +if [[ $encode ]]; then + if status_bit avi ; then + find_sbr () { + local kv k ka + if [[ $mpeg ]]; then + kv=9888 ; k=33 ; ka=996 + fi + if ((usesbr<=6)); then + sbr=$(awk '/for '"${SBR[usesbr-1]}"'MB CD/{print $NF}' <"$output".log) + [[ $sbr ]] && ((sbr<vbitrate)) && VIDEOPASS=${VIDEOPASS/vbitrate=$vbitrate:/vbitrate=$sbr:} && \ + echo " INFO: [mencoder] using vbitrate=$sbr" | tee -a "$output".log + 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]<vbitrate && sbr[4]>0)) && VIDEOPASS=${VIDEOPASS/vbitrate=$vbitrate:/vbitrate=${sbr[4]}:} && \ + echo " INFO: [mencoder] using vbitrate=${sbr[4]}" | tee -a "$output".log + fi + } + AID= + #### start mencoder + PLOG=( -passlogfile "$output".avi2pass.log ) + rm -f frameno.avi + if ((PASS==1)); then + if [[ $usesbr && ! $extra ]]; then + mencoder $OPTIONS -ovc frameno -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS 2>&1 | \ + mp_single_log mencoder '^Recommended video bitrate' + find_sbr + next_vobsub_idx + fi + ((DEBUG)) && debug_line $((LINENO+1)) "PASS 1/$PASS" + mencoder $OPTIONS $VIDEOPASS -o "$output".$SUF "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume -v | mplayer_log mencoder + next_vobsub_idx + else + #### N pass + if [[ $usesbr && ! $extra ]]; then + mencoder $OPTIONS -ovc frameno -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS 2>&1 | \ + mp_single_log mencoder '^Recommended video bitrate' + find_sbr + next_vobsub_idx + fi + CLEAN[${#CLEAN[*]}]="$output".avi2pass.log + ((DEBUG)) && debug_line $((LINENO+1)) "PASS 1/$PASS" + mencoder $OPTIONS ${VIDEOPASS}:vpass=1$turbo -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" + next_vobsub_idx + if ((PASS==2)); then + ((DEBUG)) && debug_line $((LINENO+1)) "PASS 2/$PASS" + mencoder $OPTIONS ${VIDEOPASS}:vpass=2 -o "$output".$SUF "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" -v | \ + mplayer_log mencoder + next_vobsub_idx + else + for ((a=2;a<PASS;a++)); do + ((DEBUG)) && debug_line $((LINENO+1)) "PASS $a/$PASS" + mencoder $OPTIONS ${VIDEOPASS}:vpass=3 -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" + next_vobsub_idx + done + ((DEBUG)) && debug_line $((LINENO+1)) "PASS $PASS/$PASS" + mencoder $OPTIONS ${VIDEOPASS}:vpass=3 -o "$output".$SUF "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" -v | \ + mplayer_log mencoder + next_vobsub_idx + 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 + status_bit sub set + fi +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 + fi + fi + #FIXME remove once the mpeg muxer is fixed + #### NTSC dvd warn + [[ $videonorm = n && $frameformat = DVD ]] && \ + echo "++ WARN: [$PROGNAME] mencoder does not multiplex correctly NTSC mpeg, you may want to use encode2mpeg instead" | tee -a "$output".log +fi + +############################################################################### +#### split the mpeg stream (for Mpeg Mode) +############################################################################### +if status_bit spl ; then + #### split for Mpeg Mode (mpeg4 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 ]]; then + [[ ! $fast ]] && mv "$output"01.mpg "$output".mpg + file_size "$output".mpg + if ((split*1024*1024<fsize)); then + chunks=$((fsize/(split*1024*1024)+1)) + 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,1,index(f,"/")-1);t=$2;f=$3}' >"$output".framelist + m=0 + #### removed -vc dummy + [[ $multiaudio ]] && 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/') + 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 30 | \ + 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 + +################################################################################ +#### done +################################################################################ +exit +