[MPlayer-users] Re: problem encoding a compliant DVD from an XviD source movie

Tobias Diedrich ranma at tdiedrich.de
Sun Apr 15 10:13:35 CEST 2007


Joey Parrish wrote:
> On 4/14/07, Prabu(A.G.Oliveira) <mahaprabr at yahoo.com.br> wrote:
> >Hi friends from Mplayer&Mencoder list!!!
> >
> >I'm a beginner and I've been trying hard (without sucess) to encode some
> >movies to see on TV.
> >
> >for example, one of my source movie is:
> >
> >Lost_S03_E01.avi - VIDEO:  [XVID]  608x336  24bpp  23.976 fps  1019.6
> >kbps (124.5 kbyte/s
> >
> >And I would like to put it on a dvd (with subtitles) to watch on tv.
> 
> I tried to author compliant DVDs with MEncoder a couple years ago and
> had no success.  But I would find it great to be able to do so.  I'll
> try again over the next couple days, beginning with your options and
> report back what, if anything, works for me.  I'll also compare
> results to TMPG, which isn't free but always works.

FWIW, I've used the following script with acceptable results in the
past (Well, mainly for encoding anime episodes with a Pioneer DV 535
as the target hardware player).
Uses Debian dotlockfile unless you modify the script.

#!/bin/bash

PATH="$PATH:/usr/local/bin:/bin:/usr/bin"

# $Id: transcode_to_mpeg2,v 1.22 2006-04-26 19:30:05 ranma Exp $
#
# needed software:
#
# midentify (mplayer/CONTRIB), mencoder [, mplayer]
# dotlockfile
# mplex (mjpegtools)
#

# 'constants' :)

# quantisation matrices from TMPGEnc
tmpgenc_intra_matrix="\
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,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"
tmpgenc_inter_matrix="\
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,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"

# default quantisation matrix from libavcodec for reference
default_intra_matrix="\
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,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_matrix="\
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,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 mpeg4 quantisation matrix from libavcodec
mpeg4_intra_matrix="\
8,17,18,19,21,23,25,27,\
17,18,19,21,23,25,27,28,\
20,21,22,23,24,26,28,30,\
21,22,23,24,26,28,30,32,\
22,23,24,26,28,30,32,35,\
23,24,26,28,30,32,35,38,\
25,26,28,30,32,35,38,41,\
27,28,30,32,35,38,41,45"
mpeg4_inter_matrix="\
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,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"

# CG quantization matrices from TMPGEnc
cg_intra_matrix="\
8,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32,\
32,32,32,32,32,32,32,32"
cg_inter_matrix="\
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,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"

# (still hardcoded) defaults

intra_matrix="$mpeg4_intra_matrix" # quantisation matrix for I-Frames
inter_matrix="$mpeg4_inter_matrix" # quantisation matrix for P- and B-Frames
npass=3          # 3-pass encoding (should give less vbv buffer underruns than 2-pass)
dstrate="48000"  # 48kHz sampling rate
bitrate="2000"   # 4MBit bitrate
dstw=720         # 720 pixel destination width
border=16        # Width of black border
# cmp is used for macroblock decision
# dia is used for motion estimation
##cmp=10         # NSSE (noise preserving sum of squared differences)
##dia=3          # normal size 3 diamond
#cmp=2           # SATD (sum of absolute Hadamard transformed differences)
#dia=-2          # shape adaptive (fast) diamond with size 2
cmp=2            # SATD (sum of absolute Hadamard transformed differences)
dia=-4           # shape adaptive (fast) diamond with size 4
mplex=1          # Use mplex for muxing instead of MEncoder built-in muxer

aopts="acodec=mp2:abitrate=224"
cmpopts="ildctcmp=$cmp:precmp=$cmp:cmp=$cmp:subcmp=$cmp:mbcmp=$cmp:nssew=100"
diaopts="predia=$dia:dia=$dia"


# supported environment variables
#
# FORCEFPS: override fps value reported by midentify, might be broken
# MENCODEROPTS: additional options to pass on to mencoder
#               e.g. '-endpos 60' for testing

# support functions

# cleanup was once called multiple times and thus made a function

cleanup() {
	trap '' ERR
	echo "Done encoding `date`" >> "$logfile"
	rm -f "$tmpwav" "$tmpm2v" "$tmpmp2"
	rm -rf "$workdir"
	dotlockfile -u "$lockfile"
#	kill -SIGTERM $tailpid
	exit 0
}

# signal handlers

error() {
	echo "Terminating due to error condition $1 `date`" >> "$logfile"
	echo "Terminating due to error condition $1"
	rm -rf "$workdir"
	rm -f "$tmpwav"
	dotlockfile -u "$lockfile"
#	kill -SIGTERM $tailpid
	exit 1
}

# did we get a source file name?

if [ ! -r "$1" ]; then
	echo "Usage: $0 <sourcefile> [<destinationfile>]"
	exit 0
fi

# be nice

renice 5 $$

# work out temporary filenames, lots of no longer used stuff here...

tmpdir="${TMPDIR-/tmp}" # where the files go
workdir="$tmpdir/`basename "$0"`-`basename "$1"`-$$" # for stream.yuv
wd=`pwd`
if [ "`dirname "$1" | awk '{ print substr($0, 1, 1) }'`" != "/" ]; then
	source="$wd/$1"
else
	source="$1"
fi
base="${source%avi}"
lockfile="${base}lock"
tmpbase="$tmpdir/`basename "${source%avi}"`"
logfile="${tmpbase}logfile"
tmpmpg="${tmpbase}tmp"
tmpmp2="${tmpbase}mp2"
tmpac3="${tmpbase}ac3"
tmpm2v="${tmpbase}m2v"
tmpraw="${tmpbase}raw"
tmpwav="${tmpbase}wav"
tmplog="${tmpbase}log"
tmpyuv="${tmpbase}yuv"
result="${base}mpg"

# did we get a destination file name?

if [ "$2" != "" ]; then
	if [ "`dirname "$2" | awk '{ print substr($0, 1, 1) }'`" != "/" ]; then
		result="$wd/$2"
	else
		result="$2"
	fi
fi

# we don't want to overwrite by accident

if [ -f "$result" ]; then
	echo "Destination $result already exists, giving up"
	exit 1
fi

# try locking locking the source file

if ! dotlockfile -l -r 0 "$lockfile"; then
	echo "Could not lock $source, giving up"
	exit 1
fi

# setup signal handlers

trap 'error "Exit status != 0"' ERR
trap 'error "SIGTERM received"' SIGTERM
trap 'error "SIGINT received"' SIGINT

# create logfile

touch "$logfile"
#tail -f "$logfile" &
#tailpid=$!

# all systems go

echo "Starting encode on `hostname` pid $$ `date`" > "$logfile"

# create temporary and working directory

test -d "$tmpdir" || mkdir "$tmpdir"
test -d "$workdir" || mkdir "$workdir"
pushd "$workdir"

# check out source file properties

eval `midentify "$source"`

if [ "$FORCEFPS" != "" ]; then
	ID_VIDEO_FPS="$FORCEFPS"
fi

# is the aspect ratio stored in the source file?
# calculate aspect as width/height if not (assume square pixels, normal for avi)

if [ "$ID_VIDEO_ASPECT" = "0.0000" ]; then
aspect=`bc <<EOF
scale=0
100*${ID_VIDEO_WIDTH}/${ID_VIDEO_HEIGHT}/1
EOF`
else
aspect=`bc <<EOF
scale=0
100*$ID_VIDEO_ASPECT/1
EOF`
fi

# get scaled video fps

rate=`bc <<EOF
scale=0
1000*$ID_VIDEO_FPS/1
EOF`

echo "Rate: $rate"

# handle 120fps files

decimate=$((($rate+12000) / 24000))
decimated=$(($rate / $decimate))
if [ $decimate -gt 1 -a \
     $decimated -gt 23000 -a \
     $decimated -lt 25000 ]; then
	echo "Decimated: $decimated (factor $decimate)"
	rate=$decimated
else
	decimate=1
fi

# determine desired output norm based on fps

if [ $rate -gt 27000 ]; then
	norm=ntsc
	dsth=480
	fps="30000/1001"  # ntsc
	telecine=""
elif [ $rate -lt 24100 -a \
       "$mplex" != "1" ]; then
	norm=ntsc
	dsth=480
	fps="24000/1001"  # telecined progressive
	telecine=":telecine"
else
	norm=pal
	dsth=576
	fps="25"          # pal
	telecine=""
fi

# determine needed speedup value to get from source fps to destination fps

speed=`bc <<EOF
scale=10
1000*$fps/$rate
EOF`

# get output mpeg aspect ratio

if [ $aspect -gt 155 ]; then
	dvdaspect="16/9"
else
	dvdaspect="4/3"
fi

echo "Working directory: $workdir"
echo "Source:"
echo "  ${ID_VIDEO_WIDTH}x${ID_VIDEO_HEIGHT}@${ID_VIDEO_FPS}fps, aspect ${aspect}/100, ${ID_AUDIO_RATE}Hz."

# determine the scaling width/height

scalew=`expr $dstw - $border \* 2`
scaleh=`expr $dsth - $border \* 2`

echo "Speedup: $speed"
echo "Destination:"
echo "  $norm ${dstw}x${dsth} ${dvdaspect} border=${border}."

#forcesrate=`bc <<EOF
#(100*${ID_AUDIO_RATE}*${fps}/${ID_VIDEO_FPS}+50)/100
#EOF`

echo "Scaling to ${scalew}x${scaleh}"
#echo "Resampling from ${forcesrate}Hz to ${dstrate}Hz."
echo "Using ${npass}pass-encoding"
echo

# we are ready to go

sleep 2

# refer to mencoder manpage for most options ^^;
#
# vqmin: minimum quantiser (should be 1)
# lmin: should be equal to or less than vqmin ('Minimum Lagrange multiplier for ratecontrol')
# vrc_maxrate: maximum allowed bitrate (7500kbit should be safe)
# vrc_buf_size: vbv buffer (1835 => 229KB, dvd standard (stupid option is in kbit))
# keyint: keyframe every 15 frames (dvd standard)
# vmax_b_frames: 0 => no b frames, 1 could be safe but might throw off ratecontrol
# mbd: 2 => high quality (macro block decision mode)
# trell: 'trellis searched quantization' => high quality
# vpsize: 2000 seems to improve hardware player compatibility ('video packet size')
# sc_threshold: scene change threshold
# cgop: closed gop

# filters:
# pp=ac => deblock+dering
# softskip: allows filters  which  need to  see  all frames (inverse telecine, temporal denoising, etc.)
#           to function properly
# harddup:  necessary for mpeg-encoding, always last in chain

vopts="vcodec=mpeg2video:aspect=${dvdaspect}:vbitrate=${bitrate}:lmin=0.9:vqmin=1:vrc_maxrate=7500:vrc_buf_size=1835:keyint=15:vmax_b_frames=0:vpsize=2000:mbd=2:$cmpopts:$diaopts:trell" #trell:cbp:mv0
vopts="${vopts}:sc_threshold=-1500" # 23:45 <@nicodvb> poirierg: using sc_threshold=-1500 improved a lot the quality for my encodings
#vopts="${vopts}:cgop"
vopts="${vopts}:inter_matrix=${inter_matrix}:intra_matrix=${intra_matrix}"
mpegopts="format=dvd:vaspect=${dvdaspect}${telecine}"
prefilters="pp=ac"
postfilters="scale=${scalew}:${scaleh},expand=${dstw}:${dsth}"
filters="$prefilters,softskip,$postfilters,harddup"
mencoderopts="$MENCODEROPTS -slang en -alang ja -subfont-text-scale 3 -subpos 95 -subalign 2 -speed $speed -ofps $fps -oac lavc -sws 2 -ssf ls=0.9:cs=0.9 -vf ${filters} -af lavcresample=$dstrate"

echo Audio Command line: mencoder -cache 1024 \
         -o "$tmpmp2" \
         -lavcopts $aopts \
         -ovc copy \
         -of rawaudio \
         $mencoderopts \
         "$source"

if [ "$mplex" = "1" ]; then
	echo "Audio encoding..."
	mencoder -cache 1024 \
	         -o "$tmpmp2" \
	         -lavcopts $aopts \
	         -ovc copy \
	         -of rawaudio \
	         $mencoderopts \
	         "$source"
	mencoderopts="$mencoderopts -ovc lavc -of rawvideo"
else
	mencoderopts="$mencoderopts -ovc lavc -of mpeg"
fi

echo Video Command line: mencoder -cache 1024 \
         -o "$result" \
         -lavcopts $aopts:$vopts:psnr:vpass=1 \
         -mpegopts $mpegopts \
         -passlogfile "$tmplog" \
         $mencoderopts \
         "$source"

pass=1
passopt=1
while [ $pass -le $npass ]; do
	echo "Video encoding pass $pass..."
	echo "Video encoding pass $pass... `date`" >> "$logfile"
	outfile="$result"
	if [ "$mplex" = "1" ]; then
		outfile="$tmpm2v"
		rm -f "$tmpm2v"
		mkfifo "$tmpm2v"
		mplex --verbose 0 -f8 -V -o "$result" "$tmpm2v" "$tmpmp2" &
	fi
	mencoder -cache 1024 \
	         -o "$outfile" \
	         -lavcopts $aopts:$vopts:psnr:vpass=$passopt \
	         -mpegopts $mpegopts \
	         -passlogfile "$tmplog" \
	         $mencoderopts \
	         "$source"
	cp "$tmplog" "${tmplog}.$pass"
	passopt=3
	pass=$(($pass + 1))
done

popd

cleanup

-- 
Tobias						PGP: http://9ac7e0bc.uguu.de
このメールは十割再利用されたビットで作られています。



More information about the MPlayer-users mailing list