#!/bin/bash

set -x
set -eu
set -o pipefail

size=""
file=""
tempfile="$(basename "$0").temp.flv"
keep_temp=False
do_postprocessing=True

function usage
{
    retval="$1"
    case "$retval" in
        0)
            ;;
        *)
            exec 1>&2
            ;;
    esac
    echo "Usage: --dimensions 1366x768 --output-file output.mp4 --keep-temporary --skip-postprocessing --help"
    echo
    echo "Capture a movie of the leftmost corner of your display(s), with sound, on X11 (and Wayland?)"
    echo
    echo "--dimensions specifies the dimensions of the region you want captured."
    echo
    echo "--output-file specifies the path to the file you wish to create.  Different formats can be output based on the"
    echo "file extension."
    echo
    echo "Hit 'q' when done recording."
    echo
    echo "Video will be written to disk as fast as possible, mostly uncompressed."
    echo "Then after you hit 'q', the video will be transcoded to something more practical for archival."

    exit "$retval"
}

while [ "$#" -ge 1 ]
do
    case "$1" in
        --dimensions)
            size="$2"
            shift
            ;;
        --output-file)
            file="$2"
            shift
            ;;
        --keep-temporary)
            keep_temp=True
            ;;
        --skip-postprocessing)
            do_postprocessing=False
            ;;
        --help|-h)
            usage 0
            ;;
        *)
            echo "$0: unrecognized option: $1" 1>&2
            usage 1
            ;;
    esac
    shift
done

all_good=True

case "$size" in
    "")
        echo "$0: --dimensions is a required option.  EG --dimensions 1366x768" 1>&2
        all_good=False
        ;;
esac

case "$file" in
    "")
        echo "$0: --output-file is a required option.  EG --output-file /tmp/output.mp4" 1>&2
        all_good=False
        ;;
esac

case "$all_good" in
    True)
        ;;
    False)
        echo "$0: one or more required options not specified" 1>&2
        usage 1
        ;;
    *)
        echo "$0: internal error: \$all_good is not True or False" 1>&2
        exit 1
        ;;
esac

# Based on https://www.bogotobogo.com/FFMpeg/ffmpeg_video_screencasting_screen_recording_capture.php

# Seems to work as long as you don't throw too many changes at it.

# I'm using this on a 5-year-old laptop:
# $ ./nbench 
# below cmd output started 2020 Fri Apr 03 11:53:52 AM PDT
# 
# BYTEmark* Native Mode Benchmark ver. 2 (10/95)
# Index-split by Andrew D. Balsa (11/97)
# Linux/Unix* port by Uwe F. Mayer (12/96,11/97)
# 
# TEST                : Iterations/sec.  : Old Index   : New Index
#                     :                  : Pentium 90* : AMD K6/233*
# --------------------:------------------:-------------:------------
# NUMERIC SORT        :          1009.5  :      25.89  :       8.50
# STRING SORT         :          850.75  :     380.14  :      58.84
# BITFIELD            :      3.9829e+08  :      68.32  :      14.27
# FP EMULATION        :          399.68  :     191.78  :      44.25
# FOURIER             :           37797  :      42.99  :      24.14
# ASSIGNMENT          :          40.518  :     154.18  :      39.99
# IDEA                :          8058.1  :     123.25  :      36.59
# HUFFMAN             :          3630.6  :     100.68  :      32.15
# NEURAL NET          :          66.155  :     106.27  :      44.70
# LU DECOMPOSITION    :          1966.3  :     101.86  :      73.56
# ==========================ORIGINAL BYTEMARK RESULTS==========================
# INTEGER INDEX       : 113.768
# FLOATING-POINT INDEX: 77.489
# Baseline (MSDOS*)   : Pentium* 90, 256 KB L2-cache, Watcom* compiler 10.0
# ==============================LINUX DATA BELOW===============================
# CPU                 : 4 CPU GenuineIntel Intel(R) Core(TM) i3-4000M CPU @ 2.40GHz 2395MHz
# L2 Cache            : 3072 KB
# OS                  : Linux 4.15.0-54-generic
# C compiler          : gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 
# libc                : libc-2.27.so
# MEMORY INDEX        : 32.261
# INTEGER INDEX       : 25.794
# FLOATING-POINT INDEX: 42.978
# Baseline (LINUX)    : AMD K6/233*, 512 KB L2-cache, gcc 2.7.2.3, libc-5.4.38
# * Trademarks are property of their respective holder.

# BTW, the above machine a bunch of dust clogging its CPU. After cleaning it, the system worked much better.
# As a result, I've changed the first ffmpeg below from 2Hz to 10Hz.

# shellcheck disable=SC2064
case "$keep_temp" in
    True)
        ;;
    False)
        trap "rm -f \"$tempfile\"" 0
        ;;
    *)
        echo "$0: Internal error: \$keep_temp has a strange value: $keep_temp" 1>&2
        exit 1
        ;;
esac

case "$do_postprocessing" in
    True)
        ;;
    False)
        case "$file" in
            *.flv)
                # Good, we've been asked to do .flv
                ;;
            *)
                echo "$0: Sorry, with --skip-postprocessing, you must specify an .flv --output-file" 1>&2
                exit 1
        esac
        ;;
    *)
        echo "$0: internal error: \$do_postprocessing has a strange value: $do_postprocessing" 1>&2
        exit 1
        ;;
esac
ffmpeg \
    -f pulse \
    -ac 2 \
    -i default \
    -f x11grab \
    -r 10 \
    -s "$size" \
    -i ':0.0' \
    -qmin 1 \
    -qmax 1 \
    -vcodec flv \
    -pix_fmt yuv420p \
    -preset ultrafast \
    -crf 0 \
    -threads 0 \
    -y \
    "$tempfile"

case "$do_postprocessing" in
    True)
        ffmpeg \
            -y \
            -r 30 \
            -i "$tempfile" \
            -ab 128k \
            -ac 2 \
            -vcodec libx264 \
            -preset slow \
            -crf 22 \
            -threads 0 \
           "$file"
        ;;
    False)
        # Move the tempfile to the output file, knowing already that we have a .flv requested for our output
        mv "$tempfile" "$file"
        ;;
    *)
        echo "$0: internal error: \$do_postprocessing has a strange value: $do_postprocessing" 1>&2
        exit 1
        ;;
esac