#!/bin/bash

# MythTV ffmpeg transcode to H.264, remove commercials, delete original recording, and
# make database entry point to transcoded file
#
# Modified by Lucas Christian to add progress output, subtitles, etc.
# Original script written by Defcronyke Webmaster, copyright 2012.
# Version 0.2

# Arguments
# $1 must be the directory/file to be transcoded.
# $2 must be chanid
# $3 must be starttime
# $4 is optional scheduled job id for progress feedback
# the full userjob command in mythtv-setup should look like this: /path/to/this-script/mythtranscode-h264.sh "%DIR%/%FILE%" "%DIR%/%TITLE% - %PROGSTART%.mkv" "%CHANID%" "%STARTTIME%"

# MySQL database login information (for mythconverg database)
DATABASEUSER="mythtv"
DATABASEPASSWORD="mythtv"

# MythTV Install Prefix (make sure this matches with the directory where MythTV is installed)
INSTALLPREFIX="/usr/bin"

# Number of threads to use (default uses all threads)
NUMTHREADS="0"

# Language of primary Closed Captioning feed
CC_LANGUAGE="eng"
AUDIO_LANGUAGE="eng"

# Declare Variables
MYPID=$$
ORIG_DIR=`dirname "$1"`
ORIG_BASE=`basename "$1"`
DEST_BASE="${ORIG_BASE%.*}.mp4"
JOB_ID=$4

# Helper Functions
function report_progress {
    echo "$1"

    # Report progress on Job Queue
    if [[ ! -z "$JOB_ID" ]]; then
        echo "UPDATE jobqueue SET comment='$1' WHERE id='$JOB_ID';" > $TMP/update-database_$MYPID.sql
        mysql --user=$DATABASEUSER --password=$DATABASEPASSWORD mythconverg < $TMP/update-database_$MYPID.sql
    fi
}

function fail_with_error {
    report_progress $1

    # Generate log
    cat $TMP/mythtranscode.log $TMP/ccextractor.log $TMP/ffmpeg.log > $ORIG_DIR/${ORIG_BASE%.*}.transcode_failure.log

    rm -r "$TMP"
    rm "$ORIG_DIR/$DEST_BASE"
    exit 1
}

# Don't monopolize the CPU
renice 19 $MYPID > /dev/null
ionice -c 3 -p $MYPID > /dev/null

# Create temporary directory
TMP=/tmp/mythtmp-$MYPID
mkdir $TMP

# Generate cutlist from flagged commercials
# $INSTALLPREFIX/mythcommflag -c "$3" -s "$4" --gencutlist

# Lossless transcode to strip cutlist
report_progress "Progress: Removing cutlist"
$INSTALLPREFIX/mythtranscode --chanid "$2" --starttime "$3" --mpeg2 --honorcutlist -o "$TMP/$ORIG_BASE.tmp" 1> $TMP/mythtranscode.log 2>&1
if [ "$?" -ne 0 ]; then
    fail_with_error "Mythtranscode failed. Exiting."
fi

# Extract subtitles from ATSC stream
report_progress "Progress: Extracting closed captions"
ccextractor "$TMP/$ORIG_BASE.tmp" -o "$TMP/$ORIG_BASE.srt" 1> "$TMP/ccextractor.log" 2>&1

# Transcode to mp4 (include captions if found)
actualsize=$(wc -c "$TMP/$ORIG_BASE.srt" | cut -f 1 -d ' ')
if [ $actualsize -ge 100 ]; then
    report_progress "Starting transcode to MP4 with captions"
    ffmpeg -i "$TMP/$ORIG_BASE.tmp" -i "$TMP/$ORIG_BASE.srt" -vcodec libx264 -preset medium -crf 20 -threads $NUMTHREADS -acodec libfdk_aac -vbr 5 -scodec mov_text -metadata:s:s:0 language="$CC_LANGUAGE" -metadata:s:a:0 language="$AUDIO_LANGUAGE" "$ORIG_DIR/$DEST_BASE" 1> $TMP/ffmpeg.log 2>&1 &
    FFMPEG_PID=$!
else
    report_progress "Starting transcode to MP4 (no captions found)"
    ffmpeg -i "$TMP/$ORIG_BASE.tmp" -vcodec libx264 -preset medium -crf 20 -threads $NUMTHREADS -acodec libfdk_aac -vbr 5 -metadata:s:a:0 language="$AUDIO_LANGUAGE" "$ORIG_DIR/$DEST_BASE" 1> $TMP/ffmpeg.log 2>&1 &
    FFMPEG_PID=$!
fi

echo "PID= $FFMPEG_PID"
function abort {
    kill $FFMPEG_PID 2> /dev/null
    fail_with_error "ERROR: Transcode aborted by user."
}

trap abort EXIT

while kill -0 $FFMPEG_PID 2> /dev/null; do
    # Determine total duration
    if [[ -z "$CLIP_DURATION" ]]; then
        # Determine total duration
        CLIP_DURATION=`cat $TMP/ffmpeg.log | sed -n 's/Duration: \(.*\), start.*/\1/gp'`
        if [[ ! -z "$CLIP_DURATION" ]]; then
            report_progress "Duration to transcode: $CLIP_DURATION"
        fi
    else
        # Grab current time from progress output
        CUR_TIME=`tail -n 1 $TMP/ffmpeg.log | sed -n 's/.*time=\(.*\) bitrate.*/\1/gp'`
        if [[ ! -z "$CUR_TIME" ]]; then
            report_progress "Progress: $CUR_TIME / $CLIP_DURATION"
        fi
    fi

    sleep 3
done

trap - EXIT

wait $FFMPEG_PID
if [ "$?" -ne 0 ]; then
    fail_with_error "ERROR: FFmpeg Transcode failed. Exiting."
fi

report_progress "Updating database"

# Update DB to point to transcoded file
echo "UPDATE recorded SET basename='$DEST_BASE',transcoded='1',bookmark='0',editing='0',cutlist='0',commflagged='0' WHERE chanid='$2' AND starttime='$3';" > $TMP/update-database_$MYPID.sql
mysql --user=$DATABASEUSER --password=$DATABASEPASSWORD mythconverg < $TMP/update-database_$MYPID.sql

# Make backup of old file
mv $1 "$1.old"

# Remove stale bookmark data
echo "DELETE FROM recordedmarkup WHERE chanid='$2' AND starttime='$3';" > $TMP/update-database_$MYPID.sql
mysql --user=$DATABASEUSER --password=$DATABASEPASSWORD mythconverg < $TMP/update-database_$MYPID.sql

# Remove of outdated thumbnails
rm $ORIG_DIR/$ORIG_BASE.*.png
rm $ORIG_DIR/$ORIG_BASE.png

# Rebuild seektable & update filesize
report_progress "Rebuilding seektable"
$INSTALLPREFIX/mythcommflag --chanid "$2" --starttime "$3" --rebuild

# Calculate space savings
OLD_SIZE=`du -h "$1" | cut -f1`
NEW_SIZE=`du -h "$ORIG_DIR/$DEST_BASE" | cut -f1`
report_progress "MP4: $OLD_SIZE -> $NEW_SIZE"

# Dispose of temporary directory
rm -r $TMP
