#!/bin/bash

# Description: dvd_compliant.sh
#
# This script has been written so that vdr users are able to convert their
# recordings into a dvd compliant format by using either the replex method
# or by re-encoding using mplayer, ffmpeg, mpeg2enc, and mplex.
# This script has also been improved to give the vdr user the ability to
# re-encode avi files into mpg format. This is usefull for those who use
# the nexus video out and would like a smoother, crisper output of their
# externally obtained (downloaded, etc.) shows.
#
#	This script is part of the vdr-roaster plugin
#
#		    TESTED WITH VDR-1.4.4
#
#
# command-line usage:   sh dvd_compliant.sh /full/path/to/video_file
#
#
#					11/14/2006 John Germs

# Variables
MPG_FOLDER="/video/mpgs"
AVI_FOLDER="/video/avis"
THE_RECORDING="$1"
TMP_FOLDER="/tmp"
TEMP_FILE_INFO="$TMP_FOLDER/_VDR_recording_info.txt"
TEMPORARY_VID_FILE="$MPG_FOLDER/rawtempfile"
USE_REPLEX="yes"
AVI_METHOD="0" # default - dont use avi method unless an avi is detected 
###  Encoding method settings
#USE_REPLEX="no"
AUDIO_BITRATE="224"
ACCEPTABLE_DVD_WIDTH="704"
ASPECT_RATIO="2"  # default    1 = 1:1, 2 = 4:3, 3 = 16:9, 4 = 2.21:1
# We hard coded our vdr build to 30 fps, if yours is still 25 then use 24000/1001
# This variable is used on the vdr recordings to keep the audio and video in sync
FIXED_FPS="-fps 30000/1001"
# Confirm file size is larger than previous step
#    wanted a way to confirm it completed each step before it went to next step
#    but it looks like it only works right half the time - anyone have ideas?
#CONFIRM="yes"
CONFIRM="no"  


# step 1
# check if its a vdr file
case "$THE_RECORDING" in
*.vdr)
  echo "Vdr recording detected"
  ;;
*.avi)
  echo "Avi file detected"
  AVI_METHOD="1"
  USE_REPLEX="no"
  ;;
*.mpg)
  echo "This file is already an mpg"
  exit
  ;;
*.iso)
  echo "This file is ready to roast"
  exit
  ;;
*)
  echo "Unknown file format"
  exit
  ;;
esac

# create working directories
for X in "$MPG_FOLDER" "$AVI_FOLDER"
do
if [ ! -d "$X" ]; then
  echo $X" not found??!! .. Creating directory!"
  mkdir $X
  if [ ! -d "$X" ]; then
  echo
  echo "Unable to create "$X
  echo "Check the main folder permissions."
  echo "Maybe the folder variables in dvd_compliant.sh"
  echo "need to be altered?"
  exit
  fi
fi
done

if [ "$USE_REPLEX" = "yes" ]; then
  COMMAND_LIST=(awk cat df du echo grep nice replex rm sed sleep tr which)
  RATIO_OF_SPACE_NEEDED=$(echo "scale=1; (15/10)" | bc)
  echo
  echo "We need about 1.5 times the size of your recording"
  echo "as free space for working room... Let's check it out"
else
  COMMAND_LIST=(awk bc cat df du echo ffmpeg grep mencoder mkfifo mpeg2enc mplayer mplex nice rm sed sleep tr which)
  RATIO_OF_SPACE_NEEDED=$(echo "scale=1; (33/10)" | bc)
  echo
  echo "We need just over 3 times the size of your recording"
  echo "as free space for working room... Let's check it out"
fi

sleep 2

# FIRST LETS CHECK IF USER HAS THE PROPER DEPENDENCIES TO RUN THIS SCRIPT ------------
for command in ${COMMAND_LIST[@]}; do
        if [ ! -x "`which $command 2>&1`" ]; then
                echo -e "\nERROR: $command not found! "
                base=`basename $command`
                if [ "`which $base 2>&1 | grep "no \`basename $command\` in"`" != "" ]; then
                        echo -e "ERROR: $base was not found anywhere in your \$PATH."
                fi
                exit
        fi
done
# ------------------------------------------------------------------------------------

# Check the size of the recording
THE_RECORDING_SIZE=$(du -k $THE_RECORDING | awk '{print $1}')
echo
echo -e "Your VDR Recording\t"$(($THE_RECORDING_SIZE / 1024))" megs"

# how much room do we need for encoding
SPACE_NEEDED=$(echo "scale=0; ($THE_RECORDING_SIZE * $RATIO_OF_SPACE_NEEDED)/ 1024" | bc)
echo -e "Free Space Needed\t"$SPACE_NEEDED" megs"
echo
# how much room do we have
HD_SPACE=$(/bin/df $MPG_FOLDER | /bin/awk '/^\/dev\// {print $4}')
# now convert the format to megs
FREE_SPACE=$(echo "scale=0; ($HD_SPACE / 1024)" | bc)
# do we have enough room
if [ "$SPACE_NEEDED" -gt "$FREE_SPACE" ]; then
    echo "You only have "$FREE_SPACE" megs of free space"
    echo
    echo "It looks like you dont have enough room"
    echo "to make this mpg"
    exit
fi
echo -e "Your total Free Space\t"$FREE_SPACE" megs"
echo
echo "You are good to go !"
echo
sleep 4

# Naming Convention 
#           - theres probably a thousand better ways to do this, but

# append the recording number (ie. 001.vdr) to title to create mpg name (ie. Biography_001.mpg)
#    dump variable to file
echo $THE_RECORDING > $TMP_FOLDER/_VDR_current_file.txt
# remove the linux carriage return
tr -d '\012' < $TMP_FOLDER/_VDR_current_file.txt > $TMP_FOLDER/_VDR__current_file.txt

if [ "$AVI_METHOD" = "1" ]; then
  # remove path to avi file so that we can create a variable of just the name
  # sed trick: if you are trying to replace / sed will use whatever character follows it as a seperator
  # our avi folder variable contains /
  sed -i 's#'$AVI_FOLDER/'##g' $TMP_FOLDER/_VDR__current_file.txt
  # alter the .avi file extension to .mpg for mpg name
  sed -i 's/avi/mpg/g' $TMP_FOLDER/_VDR__current_file.txt
  # replace spaces with underscores
  sed -i 's/ /_/g' $TMP_FOLDER/_VDR__current_file.txt
  # load the finished title name as a variable (ie. Star Trek.avi now equals Star_Trek.mpg)
  MPG_NAME=$(tail $TMP_FOLDER/_VDR__current_file.txt)
else
# load current file name as a variable
CURRENT_FILE=$(tail -c 7 $TMP_FOLDER/_VDR__current_file.txt)
# establish path for info.vdr file
sed -i '/0/s/'$CURRENT_FILE'/info.vdr/g' $TMP_FOLDER/_VDR__current_file.txt
# load info.vdr path as a variable
RECORDING_INFO=$(tail $TMP_FOLDER/_VDR__current_file.txt)
# find the recording title
grep 'T ' $RECORDING_INFO > $TMP_FOLDER/_VDR_title.txt
# copy title name to temp file
sed 's/T //' $TMP_FOLDER/_VDR_title.txt > $TMP_FOLDER/_VDR_name.txt
# remove the linux carriage return
tr -d '\012' < $TMP_FOLDER/_VDR_name.txt > $TMP_FOLDER/_VDR__name.txt
# append the recording name (ie. 001.vdr)
echo ' '$CURRENT_FILE >> $TMP_FOLDER/_VDR__name.txt
# replace .vdr with .mpg
sed -i '/0/s/.vdr/.mpg/g' $TMP_FOLDER/_VDR__name.txt
# replace spaces with underscores
sed -i '/mpg/s/ /_/g' $TMP_FOLDER/_VDR__name.txt
# load the finished title name as a variable (ie. Star_Trek_001.mpg)
MPG_NAME=$(tail $TMP_FOLDER/_VDR__name.txt)
fi

# clean up temp files
rm -r -f $TMP_FOLDER/_VDR_*.txt 

echo "We will use the name "$MPG_NAME
sleep 2

if [ "$USE_REPLEX" = "yes" ]; then
  echo
  echo "Using the Replex method"
  echo
  sleep 1
  # commands for using replex -- windryer
  # normal
  nice -n 0 cat $THE_RECORDING | replex -t DVD -k -o $MPG_FOLDER/$MPG_NAME
  # for ac3
  # nice -n 0 cat $THE_RECORDING | replex -t DVD -k -o $MPG_FOLDER/$MPG_NAME -c 128
else
  echo
  echo "Using the Re-encoding method"
  echo
  sleep 1

if [ "$AVI_METHOD" = "1" ]; then
 TEMPORARY_VID_FILE="$THE_RECORDING" # we will rip directly from the avi instead of using rawtempfile
 FIXED_FPS=""	# No entry = auto
# ASPECT_RATIO="$AVI_ASPECT" # lets rem this out and try the aspect code on/around line 311
 # skip the initial copy copy/creation of rawtempfile 
else
# step 1 - get rid of the damn fps flip flop from the vdr recording
#		(this creates a raw temporary telecined file)
#
# use old 'tried and true' method (supposedly obsolete)
#nice -n 0 mencoder $THE_RECORDING -oac copy -quiet -vf softpulldown,ivtc=1 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=7840 -ofps 30000/1001 -o $TEMPORARY_VID_FILE & wait
#
# use latest method (supposed to be better - you'll have to decide)
#nice -n 0 mencoder $THE_RECORDING -oac copy -vf pullup,softskip -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=7840 -ofps 30000/1001 -quiet -o $TEMPORARY_VID_FILE & wait
#
# use simple approach (do a quick copy of both audio and video) - quickest method -- PenGun
#	the next steps will repair the rest of the problems anyway 
nice -n 0 mencoder $THE_RECORDING -oac copy -ovc copy -quiet -o $TEMPORARY_VID_FILE & wait
 
# Check sizes before deleting
RAW_TEMP_FILE_SIZE=$(du -k $TEMPORARY_VID_FILE | awk '{print $1}')

# errrrrr there is the odd time this raw temp file will be smaller.. this won't work!
#if [ "$THE_RECORDING_SIZE" -gt "$RAW_TEMP_FILE_SIZE" ]; then
#    echo "Something has gone wrong. The temp mpg is smaller than the recording."
#    echo "Scroll up to see if there were any errors"
#    exit
#fi
fi

# change to the mpg folder
cd $MPG_FOLDER

echo
echo
echo
# step 2 - make audio track dvd compliant
#	a) rip to wav file
echo "Ripping audio"
echo
sleep 1
nice -n 0 mplayer -quiet -vc null -vo null -ao pcm:waveheader:file=audiodump.wav $TEMPORARY_VID_FILE & wait
#	b) convert to ac3
nice -n 0 ffmpeg -i audiodump.wav -ab $AUDIO_BITRATE -ar 48000 -ac 2 -acodec ac3 -y "dvd_compliant.ac3" & wait

# remove the wav file
rm -f audiodump.wav
echo
echo
echo
# step 3 - make video track dvd compliant
echo "Examining video"
echo
sleep 1

# get info and load into variables 
mplayer -vo null -ao null -frames 1 -channels 6 -identify $THE_RECORDING > "$TEMP_FILE_INFO" 2>&1
eval `cat "$TEMP_FILE_INFO" | grep "^ID_[VAL]" | grep -v "[()\[]"`

# for some reason the eval statement doesn't handle decimal places so we'll load it with sed
cat $TEMP_FILE_INFO | grep ID_VIDEO_FPS > $TMP_FOLDER/_VDR_fps_of_recording.txt
sed -i 's/ID_VIDEO_FPS=//g' $TMP_FOLDER/_VDR_fps_of_recording.txt
VIDEO_FPS=$(tail $TMP_FOLDER/_VDR_fps_of_recording.txt)

echo "Video file was encoded with "$VIDEO_FPS" fps"

# Find frame rate
# 1=24000/1001, 2=24, 3=25, 4=30000/1001, 5=30, 6=50, 7=60000/1001, 8=60
if [ "$VIDEO_FPS" = "23.976" ]; then
  FRAME_RATE="1"
  else if [ "$VIDEO_FPS" = "24" ]; then
  FRAME_RATE="2"
  else if [ "$VIDEO_FPS" = "25" ]; then
  FRAME_RATE="3"
  else if [ "$VIDEO_FPS" = "29.970" ]; then
  FRAME_RATE="4"
  else
  FRAME_RATE="5"
  fi
  fi
  fi
fi

echo
echo "Using an frame rate setting of "$FRAME_RATE
sleep 1
# determine proper aspect ratio  (what a hassle .. hehe)
# bash cant do floating point calculations so we use bc then times by 10 to get a good integer
ASPECT_CALCULATION=$(echo "scale=1; ($ID_VIDEO_WIDTH/$ID_VIDEO_HEIGHT)*10" | bc)
# remove the decimal place (didn't know how else to do it)
echo $ASPECT_CALCULATION > $TMP_FOLDER/_VDR_aspect_caculation.txt
sed -i 's/.0//g' $TMP_FOLDER/_VDR_aspect_caculation.txt
# load the integer as a variable
CORRECT_ASPECT=$(tail $TMP_FOLDER/_VDR_aspect_caculation.txt)
if [ "$CORRECT_ASPECT" -ge "17" ]; then
  ASPECT_RATIO="3"  # change to 16:9      1 = 1:1, 2 = 4:3, 3 = 16:9, 4 = 2.21:1
fi
echo "Using an aspect setting of "$ASPECT_RATIO
sleep 2

echo
echo "Ripping video"
#	a) create a 'first in first out' buffer
mkfifo -m 660 stream.yuv

if [ "$ID_VIDEO_WIDTH" = "$ACCEPTABLE_DVD_WIDTH" ]||[ "$AVI_METHOD" = "1" ]; then
    echo "The resolution of this video is "$ID_VIDEO_WIDTH"x"$ID_VIDEO_HEIGHT" pixels"
    echo
    echo "No scaling will be performed"
    echo
#	b) export video track at a fixed rate of 29.97002997... fps to fifo buffer
#	   no scaling
   sleep 2
	nice -n 0 mplayer -quiet -benchmark -nosound -noframedrop $FIXED_FPS -noautosub -vo yuv4mpeg $TEMPORARY_VID_FILE &
   else
#	b) export video track at a fixed rate of 29.97002997... fps to fifo buffer
#	   scaled to 704x480
	echo "The resolution of your recording is only "$ID_VIDEO_WIDTH"x"$ID_VIDEO_HEIGHT" pixels"
	echo
	echo "Scaling to 704x480 to make it dvd compliant"
	echo
        sleep 2
	nice -n 0 mplayer -quiet -benchmark -nosound -noframedrop $FIXED_FPS -noautosub -vo yuv4mpeg -vf-add scale=704:480 $TEMPORARY_VID_FILE &
fi

#	c) import video track and encode at a controlled rate
cat stream.yuv | nice -n 0 mpeg2enc --sequence-length 4300 --sequence-header-every-gop --nonvideo-bitrate 304 --aspect $ASPECT_RATIO -f 8 -b 7840 -g 4 -G 11 -D 10 -K hi-res --frame-rate $FRAME_RATE -v 0 --video-norm n --reduction-4x4 2 --reduction-2x2 1 -q 5 -o "dvd_compliant.m2v" & wait

if [ "$AVI_METHOD" = "1" ]; then
    # don't delete the users avi file or there might be hell to pay ... hehe.
    # change the tempfile variable back to rawtempfile (could probably just nullify it, but)
    TEMPORARY_VID_FILE="$MPG_FOLDER/rawtempfile"
fi

# Check size of dvd_compliant.m2v before deleting rawtempfile
M2V_FILE_SIZE=$(du -k dvd_compliant.m2v | awk '{print $1}')

if [ "$CONFIRM" = "yes" ]; then
# did the complete file get done
if [ "$RAW_TEMP_FILE_SIZE" -gt "$M2V_FILE_SIZE" ]; then
  echo "Something may have gone wrong. The video stream file is smaller than the raw temp file."
  echo "Leaving the raw temp file..."
  rm -f stream.yuv
  # do we have enough room to continue while keeping the rawtempfile
  ROOM_NEEDED=$(($SPACE_NEEDED * 1024 + $RAW_TEMP_FILE_SIZE))
   if [ "$ROOM_NEEDED" -gt "$HD_SPACE" ]; then
     echo "ABORTING ..."
     echo "You won't have enough space to continue even if the file is valid"
     echo
     echo "IF YOU WANT TO TRY CONTINUING MANUALLY, OPEN THIS SCRIPT WITH"
     echo "AN EDITOR AND USE COMMANDS STEP3a AND ON FROM THIS SCRIPT"
     echo "IT MAY SAVE YOU TIME ..."
     exit
   fi
 else
   # remove the fifo and the raw temporary file
   echo
   echo " Removing the raw temp file now that the audio and video stream files have been created"
   echo
   rm -f stream.yuv
   rm -f $TEMPORARY_VID_FILE
fi
else
   # remove the fifo and the raw temporary file - I know .. double code .. doing it in a hurry
   echo
   echo " Removing the raw temp file now that the audio and video stream files have been created"
   echo
   rm -f stream.yuv
   rm -f $TEMPORARY_VID_FILE
fi

# step 4 - join the video and audio tracks again 
nice -n 0 mplex -f 8 -o $MPG_NAME "dvd_compliant.m2v" "dvd_compliant.ac3" & wait

# Check sizes before deleting
FINAL_MPG_FILE_SIZE=$(du -k $MPG_NAME | awk '{print $1}')
if [ "$CONFIRM" = "yes" ]; then
if [ "$M2V_FILE_SIZE" -gt "$FINAL_MPG_FILE_SIZE" ]; then
    echo "Something may have gone wrong. The final mpg is smaller than the video stream."
    echo "Leaving the streams for you to mplex manually... exiting..."
    rm -f $TEMP_FILE_INFO
    exit
fi
fi

# remove the video and audio track files
echo
echo "Removing the stream files now that the final mpg has been created"
rm -f dvd_compliant.m2v
rm -f dvd_compliant.ac3
rm -f $TEMP_FILE_INFO

fi
echo
echo "Done"
exit
