Created
October 6, 2020 03:04
-
-
Save YukinoAi/3002c3b5697e9b1b3781ae52c9e0c40f to your computer and use it in GitHub Desktop.
Wrapper script for ld-decode toolset.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/bin/bash | |
#exit script if an error occurs | |
set -e | |
if [ -z "$1" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ] ; then \ | |
echo Syntax: $0 inputFile.ldf cavOrClv ntscOrPal combFilter digitalOrAnalogAudio length startAt white ntscj | |
echo Examples: | |
echo $0 /home/user/Downloads/myFile.lds clv ntsc | |
echo $0 myFile.lds cav ntsc ntsc3d digital 1000 500 true true | |
echo $0 myFile.ldf clv pal pal2d none 0 500 | |
echo There must not be any spaces in "myFile.ldf". | |
exit 0 | |
fi | |
#default settings | |
cavOrClv="cav" | |
#cav,clv | |
ntscOrPal="ntsc" | |
#ntsc, pal | |
defaultNtscCombFilter="ntsc2d" | |
defaultPalCombFilter="pal2d" | |
#ntsc1d, ntsc2d, ntsc3d, pal2d, transform2d, transform3d | |
lumaNoiseReduction="0.0" | |
#0.0,0.5,(1.0),1.5,2.0... | |
chromaNoiseReduction="0.0" | |
#(0.0),0.5,1.0,1.5,2.0... | |
videoCodec="ffv1" | |
#ffv1, ffvhuff, huffyuv, libx264, libx264rgb, libx265, libvpx-vp9, vp9_vaapi, h264_nvenc, hevc_nvenc, utvideo | |
outputColorspace="444" | |
#444, 422, 420; used in yuv420p, yuv422p, yuv444p | |
defaultDigitalOrAnalogAudioMode="digital" | |
#digital,analog, none | |
audioCodec="flac" | |
#flac,aac, libopus, ac3 | |
defaultLength=0 | |
#0,200,500,1000,any non-negative integer; "0" means no length limit=process entire disc, Also valid: full, all, entire, fullLength | |
defaultStartAt=500 | |
#0,200,500,1000,any non-negative integer; "0" means 0, This is the amount of frames to skip. This might need to be a float instead of integer. | |
defaultSeekFrame=0 | |
#0, 1; Use 0 for CLV, Use 1 for CAV. Instead of using seek and to start at the first frame, sometimes --start may need to be adjusted manually instead. | |
#This might be better off as true/false is there are no exceptions. | |
defaultWhite=true | |
#true,false | |
defaultNtscjSetting=false | |
#true,false | |
defaultWibbleSetting=false | |
#true,false | |
cpuThreads="16" | |
#suggested:4,8 | |
cleanupFilesAfterMkv=false | |
#true,false | |
miscLdDecodeSettings=" --start 500" | |
#--NTSCJ, for CLV use seek=0 for , or for CAV use --seek 1 | |
miscLdChromaDecodeSettings="" | |
#--white | |
#static variables, #this is for NTSC, what are the formats for PAL? | |
rawVideoFormatNtsc="rawvideo -pix_fmt gray16le -s 910x263 -r 60000/1001" | |
rawVideoFormatPal="rawvideo -pix_fmt gray16le -s 1135x313 -r 50000/1000" | |
#should resolution not instead be "910x525"? "[ld-decode outputs] 910x525 16-bit values [for NTSC]" | |
#https://github.com/happycube/ld-decode/wiki/File-formats | |
#263*2=500+13+13=526 | |
rawVideoFormatAfterChromaNtsc="rawvideo -pix_fmt rgb48 -s 760x488 -r 30000/1001" | |
rawVideoFormatAfterChromaPal="rawvideo -pix_fmt rgb48 -s ------- -r 25000/1000" | |
#signed pcm 16-bit stereo little endian "s16le" @ 44.1 kHz, is PAL digital or PAL/NTSC analog audio different? | |
rawAudioFormat="s16le -ac 2 -r 44.1k" | |
#function definitions, these have to be defined prior to being invoked :-( | |
#usage: myVar=$(makeLowercaseFunct $myVar) | |
function makeLowercaseFunct() { echo $1 | tr '[:upper:]' '[:lower:]' | |
} | |
#ldprocess.sh inputFile.ldf cavOrClv ntscOrPal combFilter digitalOrAnalogAudio length startAt seekFrame white #choose to include seek frame or not | |
#ldprocess.sh inputFile.ldf cavOrClv ntscOrPal combFilter digitalOrAnalogAudio length startAt white ntscj #always include seek frame | |
#ldprocess.sh 1)inputFile.ldf 2)cavOrClv 3)ntscOrPal 4)combFilter 5)digitalOrAnalogAudio 6)length 7)startAt 8)white 9)ntscj | |
#not included: wibble, 8)seekFrame | |
#ldprocess.sh cav ntsc ntsc3d | |
#read input and assign variables | |
#debug code | |
echo User first entered:\"$1\" | |
echo second variable \"$2\" | |
echo third variable \"$3\" | |
echo fourth variable \"$4\" | |
echo fifth variable \"$5\" | |
echo sixth variable \"$6\" | |
echo seventh variable \"$7\" | |
echo eighth variable \"$8\" | |
echo ninth variable \"$9\" | |
#read input | |
#"-z" means "if the variable is empty", might want to make this output clearer to the user at some point | |
if [ ! -z "$1" ] ; then rawFileName=$1 ; echo Using file: \"$1\" ; else echo Error. Please specify a file. ; exit ; fi | |
if [ ! -z "$2" ] ; then cavOrClv=$2 ; echo Decoding as RF capture of \"$2\" disc. ; else echo Error. Please specify an LD format, cav or clv. ; exit ; fi | |
if [ ! -z "$3" ] ; then ntscOrPal=$3 ; echo Decoding disc as \"$3\". ; else echo Error. Please specify television standard, ntsc or pal. ; exit ; fi | |
if [ ! -z "$4" ] ; then combFilter=$4 ; echo Using CombFilter \"$4\" ; combFilterSpecified=true ; else echo No comb filter specified. ; combFilterSpecified=false ; fi | |
if [ ! -z "$5" ] ; then digitalOrAnalogAudio=$5 ; echo Audio mode:\"$5\". ; \ | |
else echo Audio mode not specified. Defaulting to \"$defaultDigitalOrAnalogAudioMode\". ; digitalOrAnalogAudio=$defaultDigitalOrAnalogAudioMode ; fi | |
if [ ! -z "$6" ] ; then length=$6 ; echo Length=\"$6\". ; else echo Length not specified. Using length=\"$defaultLength\". ; length=$defaultLength ; fi | |
if [ ! -z "$7" ] ; then startAt=$7 ; echo Starting at frame=\"$7\". ; startAtSpecified=true ; \ | |
else echo Seek amount not specified. ; startAt=$defaultStartAt ; startAtSpecified=false ; fi | |
#Using default of \"$defaultStartAt\". If a startAt was not specified, should there be a default startAt regardless? | |
#if [ ! -z "$8" ] ; then seekFrame=$8 ; echo Seeking to frame=\"$8\". ; seekFrameSpecified=true; else echo Seek frame not specified. Using default for CAV/CLV. ; seekFrameSpecified=false; fi | |
#same as above. If not specified, should this be included?, currently *always* being included as derivative value of $2 cavOrClv. | |
if [ ! -z "$8" ] ; then white=$8 ; echo "Use White point at 75%? "\"$8\". ; else echo 75% white point not specified. Defaulting to \"$defaultWhite\". ; white=$defaultWhite ; fi | |
if [ ! -z "$9" ] ; then ntscj=$9 ; echo "NTSCJ disc? "\"$9\". ; else echo NTSCJ not specified. Defaulting to \"$defaultNtscjSetting\". ; ntscj=$defaultNtscjSetting ; fi | |
#Validate input | |
#ldprocess.sh 1)inputFile.ldf 2)cavOrClv 3)ntscOrPal 4)combFilter 5)digitalOrAnalogAudio 6)length 7)startAt 8)white 9)ntscj | |
#-e means "if exists" | |
if [ ! -e "$rawFileName" ] ; then echo "Error: \"$rawFileName\" does not exist." ; exit 1 ; fi | |
#cavOrClv#cav,clv | |
#need to figure out how to pipe this properly at some point | |
#echo $cavOrClv | tr '[:upper:]' '[:lower:]' > temp.txt | |
#myvar2=$(cat temp.txt) | |
#rm temp.txt | |
#edit, moved to function, output gets assigned to variable via command substitution | |
cavOrClv=$(makeLowercaseFunct $cavOrClv) | |
if [ ! "$cavOrClv" = "cav" ] ; then \ | |
if [ ! "$cavOrClv" = "clv" ] ; then \ | |
echo Error: "cavOrClv" value is not "cav" or "clv" | |
echo Value:\"$cavOrClv\" | |
exit 1 | |
fi fi | |
#ntscOrPal#ntsc, pal | |
ntscOrPal=$(makeLowercaseFunct $ntscOrPal) | |
if [ ! "$ntscOrPal" = "ntsc" ] && [ ! "ntscOrPal" = "pal" ] ; then \ | |
echo Error: "ntscOrPal" value is not "ntsc" or "pal" | |
echo Value:\"$ntscOrPal\". | |
exit 1 | |
fi | |
#combFilter#ntsc1d, ntsc2d, ntsc3d, pal2d, transform2d, transform3d | |
combFilter=$(makeLowercaseFunct $combFilter) | |
if [ "$combFilterSpecified" = "false" ] ; then \ | |
if [ ! "$ntscOrPal" = "ntsc" ] ; then \ | |
combFilter=$defaultNtscCombFilter ; else \ | |
combFilter=$defaultPalCombFilter | |
fi fi | |
if [ ! "$combFilter" = "ntsc1d" ] && [ ! "$combFilter" = "ntsc2d" ] && [ ! "$combFilter" = "ntsc3d" ] && \ | |
[ ! "$combFilter" = "pal2d" ] && [ ! "$combFilter" = "transform2d" ] && [ ! "$combFilter" = "transform3d" ] ; then \ | |
echo Error: Selected "combFilter" is not valid. | |
echo Valid values: ntsc1d, ntsc2d, ntsc3d, pal2d, transform2d, transform3d | |
echo Actual Value:\"$ntscOrPal\" | |
exit 1 | |
fi | |
#digitalOrAnalogAudio#digital,analog, none | |
digitalOrAnalogAudio=$(makeLowercaseFunct $digitalOrAnalogAudio) | |
if [ ! "$digitalOrAnalogAudio" = "digital" ] && [ ! "$digitalOrAnalogAudio" = "analog" ] && [ ! "$digitalOrAnalogAudio" = "none" ] && [ ! "$digitalOrAnalogAudio" = "no" ] ; then \ | |
echo Error: "digitalOrAnalogAudio" value is not "digital" or "analog" or "none" | |
echo Value:\"$digitalOrAnalogAudio\" | |
exit 1 | |
fi | |
if [ "$digitalOrAnalogAudio" = "no" ] ; then digitalOrAnalogAudio=none ; fi | |
#length#0, 1-1000+, full, all; maybe check if zero or an integer? | |
length=$(makeLowercaseFunct $length) | |
#check if integer, if an integer, assume it is valid, if not an integer, check for valid values, if integer, check if 0 and set to all | |
case $length in | |
''|*[!0-9]*) lengthIsInteger=false ;; | |
*) lengthIsInteger=true ;; | |
esac | |
if [ ! "$lengthIsInteger" = "true" ] ; then \ | |
if [ ! "$length" = "full" ] && [ ! "$length" = "all" ] && [ ! "$length" = "entire" ] && [ ! "$length" = "fullLength" ] ; then \ | |
echo Error: Selected length is not valid. | |
echo Valid values: Any non-negative integer 0, 200, 500, 100 and "full", "all", "entire", "fullLength". | |
echo Selected length:\"$length\". | |
exit 1 | |
fi fi | |
#check if integer, if an integer, assume it is valid, if not an integer, check for valid values, if integer, check if 0 and set to all | |
#Technically float values are valid so may not be able to check if a valid value was entered at all. 2.3=string in bash | |
startAt=$(makeLowercaseFunct $startAt) | |
case $startAt in | |
''|*[!0-9]*) startAtIsInteger=false ;; | |
*) startAtIsInteger=true ;; | |
esac | |
if [ "$startAtIsInteger" = "false" ] ; then \ | |
echo Error: Selected start/skip amount is not valid. | |
echo Entered skip amount \"$startAt\". | |
exit 1 | |
fi | |
##seekFrame, 0 or 1; 0 for CLV, 1 for CAV, must be an integer | |
#if [ "$seekFrameSpecified"="false" ] | |
#then , currently using $2 cavOrClv to determine this instead as mandatory always included option, code below is for optionally including it if specified (as hardcoded values) | |
#if [ "$seekFrameSpecified" = "true" ] ; then \ | |
#if [ "$cavOrClv" = "clv" ] ; then miscLdDecodeSettings="$miscLdDecodeSettings ""--seek 0" ; else \ | |
#miscLdDecodeSettings="$miscLdDecodeSettings ""--seek 1" ; fi fi | |
#white, boolean | |
white=$(makeLowercaseFunct $white) | |
if [ ! "$white" = "true" ] ; then \ | |
if [ ! "$white" = "false" ] ; then \ | |
echo Error: "white" value is not true or false. | |
echo Value:\"$white\" | |
exit 1 | |
fi fi | |
#ntscj, boolean | |
if [ -z $ntscj ] ; then ntscj=$defaultNtscjSetting ; fi | |
ntscj=$(makeLowercaseFunct $ntscj) | |
if [ ! "$ntscj" = "true" ] ; then \ | |
if [ ! "$ntscj" = "false" ] ; then \ | |
echo Error: "ntscj" value is not true or false. | |
echo Value:\"$ntscj\" | |
exit 1 | |
fi fi | |
#wibble, boolean | |
if [ -z $wibble ] ; then wibble=$defaultWibbleSetting ; fi | |
wibble=$(makeLowercaseFunct $wibble) | |
if [ ! "$wibble" = "true" ] ; then \ | |
if [ ! "$wibble" = "false" ] ; then \ | |
echo Error: "wibble" value is not true or false. | |
echo Value:\"$wibble\". | |
exit 1 | |
fi fi | |
#calculate variable names | |
#might want to remove the .tbc extension from the rawFileName | |
fileNameNoExt=$(basename -s .lds $rawFileName) #myfile.ldf->myfile.ldf; myfile.lds->myfile | |
fileNameNoExt=$(basename -s .ldf $fileNameNoExt) #myfile.ldf->myfile; myfile->myfile | |
tbcOutputFileName="$fileNameNoExt".raw | |
#.tbc gets appended to tbcOutputFileName and it becomes tbcFileName | |
tbcFileName="$fileNameNoExt".raw.tbc | |
audioTrackName="$fileNameNoExt".raw.pcm | |
efmFileName="$fileNameNoExt".raw.efm | |
ldsJson="$fileNameNoExt".raw.tbc.json | |
#VDIjson="$LDSjson".vdi.json #wrong name | |
#if --output-json is not specified when using "ld-process-vbi", then a "...tbc.json.bup" file is created as a backup and the original json is overwritten | |
ldsJsonBackup="$ldsJson".bup | |
chaptersFile="$fileNameNoExt".txt | |
#chapters file is also known as "ffmetadata" | |
outputFileName="$fileNameNoExt".mkv | |
#determine additional variables | |
#use seek=0 for CLV, or --seek 1 for CAV, append to miscLdDecodeSettings | |
#miscLdDecodeSettings="$miscLdDecodeSettings "--seek | |
if [ "$cavOrClv" = "clv" ] ; then miscLdDecodeSettings="$miscLdDecodeSettings ""--seek 0" | |
else miscLdDecodeSettings="$miscLdDecodeSettings ""--seek 1" ; fi | |
if [ "$ntscOrPal" = "ntsc" ] ; then \ | |
rawVideoFormat=$rawVideoFormatNtsc | |
rawVideoFormatAfterChroma=$rawVideoFormatAfterChromaNtsc | |
else \ | |
rawVideoFormat=$rawVideoFormatPal | |
rawVideoFormatAfterChroma=$rawVideoFormatAfterChromaPal | |
fi | |
#append length to ld-decode settings if it was specified | |
#if [ "$length" eq "0" ] ; then miscLdDecodeSettings=$miscLdDecodeSettings" --length $length" ; fi | |
if [ "$lengthIsInteger" = "true" ] ; then \ | |
if [ "$length" = "0" ] ; then \ | |
length=fullLength #pointless | |
#else if an non-zero integer, append --length $length to ld-decode | |
else miscLdDecodeSettings="$miscLdDecodeSettings ""--length $length" | |
fi fi | |
if [ ! "$startAtIsInteger" = "false" ] ; then \ | |
if [ "$startAtSpecified" = "true" ] ; then \ | |
miscLdDecodeSettings="$miscLdDecodeSettings ""--start $startAt" | |
fi fi | |
#miscLdChromaDecodeSettings --white, #white, boolean | |
if [ "$white" = "true" ] ; then miscLdChromaDecodeSettings="$miscLdChromaDecodeSettings ""--white" ; fi | |
#miscLdDecodeSettings --NTSCJ, #ntscj, boolean | |
if [ "$ntscj" = "true" ] ; then miscLdDecodeSettings="$miscLdDecodeSettings ""--NTSCJ" ; fi | |
#debug code, print out all variables | |
#debug code, exit early | |
#exit 0 | |
#might want to also check if ld-decode is invokable first | |
#also, might want to skip running ld-decode, ld-process-vbi and ls-export-metadata if $tbcFileName already exists | |
#extract out 1) .tbc raw video, 2) .wav audio, 3) .efm data and 4) .json metadata | |
if [ -e "$tbcFileName" ] ; then \ | |
echo \"$tbcFileName\" already exists. Will reuse existing .tbc file. | |
echo Delete/move/rename .tbc file if reuse is not desired. | |
else \ | |
echo Starting LD-Decode.... | |
echo ld-decode "$miscLdDecodeSettings" -t $cpuThreads --$ntscOrPal "$rawFileName" "$tbcOutputFileName" | |
ld-decode $miscLdDecodeSettings -t $cpuThreads --$ntscOrPal "$rawFileName" "$tbcOutputFileName" | |
#update vbi data | |
echo Updating VBI metadata... | |
echo ld-process-vbi --threads $cpuThreads --input-json "$ldsJson" "$tbcFileName" | |
ld-process-vbi --threads $cpuThreads --input-json "$ldsJson" "$tbcFileName" | |
echo Extracting ffmetadata chapters... | |
#extract out LD chapters (if present), how to check if present? how to exclude from next command if not present? | |
ld-export-metadata "$ldsJson" --ffmetadata "$chaptersFile" | |
#merge pieces and encode a/v losslessly | |
#ffmpeg -f $rawVideoFormat - | \ #this is used...when? | |
#\ | |
fi | |
echo ld-dropout-correct --intra --overcorrect --input-json "$ldsJson" --output-json /dev/null --quiet "$tbcFileName" - \| \\ | |
echo ld-chroma-decoder -t $cpuThreads --decoder $combFilter --luma-nr $lumaNoiseReduction --chroma-nr $chromaNoiseReduction --input-json "$ldsJson" -q $miscLdChromaDecodeSettings - - \| \\ | |
echo ffmpeg -f $rawVideoFormatAfterChroma -i - -f $rawAudioFormat -i "$audioTrackName" -i "$chaptersFile" -c:v $videoCodec -pix_fmt yuv"$outputColorspace"p -y -c:a $audioCodec "$outputFileName" | |
#debug code | |
#echo end | |
#exit 0 | |
echo Performing magic on black and white signal... | |
ld-dropout-correct --intra --overcorrect --input-json "$ldsJson" --output-json /dev/null --quiet "$tbcFileName" - | \ | |
\ | |
ld-chroma-decoder -t $cpuThreads --decoder $combFilter --luma-nr $lumaNoiseReduction --chroma-nr $chromaNoiseReduction --input-json "$ldsJson" -q $miscLdChromaDecodeSettings - - | \ | |
\ | |
ffmpeg -f $rawVideoFormatAfterChroma -i - -f $rawAudioFormat -i "$audioTrackName" -i "$chaptersFile" -c:v $videoCodec -pix_fmt yuv"$outputColorspace"p -y -c:a $audioCodec "$outputFileName" | |
#-aspect 4:3 | |
#for flac use "-compression_level 5", higher is more compression, max is 12, default is 5, consider using 11 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment