#!/usr/bin/env bash
#
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"



function main {
    local cmd
    cmd=$1
    shift
    if [ "$cmd" = "copy" ]; then
        copy "${@}"
    elif [ "$cmd" = "av1" ]; then
        av1 "${@}"
    elif [ "$cmd" = "stream_software_h264" ]; then
        stream_software_h264 "${@}"
    elif [ "$cmd" = "stream_hardware_h264" ]; then
        stream_hardware_h264 "${@}"
    elif [ "$cmd" = "preprocess_software_h264" ]; then
        preprocess_software_h264 "${@}"
    elif [ "$cmd" = "preprocess_hardware_h264" ]; then
        preprocess_hardware_h264 "${@}"
    elif [ "$cmd" = "vp9" ]; then
        vp9 "${@}"
    elif [ "$cmd" = "preprocess_hardware_vp9" ]; then
        preprocess_hardware_vp9 "${@}"
    elif [ "$cmd" = "vp8" ]; then
        vp8 "${@}"
    elif [ "$cmd" = "software_vp8" ]; then
        software_vp8 "${@}"
    elif [ "$cmd" = "preprocess_h264" ]; then
        preprocess_h264 "${@}"
    elif [ "$cmd" = "preprocess_vp8" ]; then
        preprocess_vp8 "${@}"
    elif [ "$cmd" = "webcam" ]; then
        webcam "${@}"
    elif [ "$cmd" = "encode_webcam" ]; then
        encode_webcam "${@}"
    else
        (>&2 echo "Unknown command: $cmd")
        exit 1
    fi
}

function copy {
    local file_to_cast
    file_to_cast="$3"

    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    set -x
    </dev/null exec ffmpeg \
        -re \
        -stream_loop -1 \
        -i "$file_to_cast" \
        -c copy \
        -strict experimental \
        -f rtsp \
        -rtsp_transport tcp \
        "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}



function av1 {
    # local additional_flags=()
    # additional_flags+=(--profile "$PROFILE")
    # (cd "$DIR/../" && cargo build --no-default-features "${additional_flags[@]}")

    local destination_type="$1" # "stream" or "preprocess"
    local acceleration_type="$2" # "software" or "hardware"
    # shift 2

    local args=()

    if [ "$destination_type" == "stream" ]; then
        args+=(-re -stream_loop -1)
    elif [ "$destination_type" == "preproces" ]; then
        true
    else
        (>&2 echo "Unknown destination type: $destination_type")
        exit 1
    fi

    if [ "$acceleration_type" == "software" ]; then
        true
    elif [ "$acceleration_type" == "hardware" ]; then
        args+=(-vaapi_device /dev/dri/renderD128)
    else
        (>&2 echo "Unknown acceleration type: $acceleration_type")
        exit 1
    fi

    args+=(-i "$file_to_cast")

    if [ "$acceleration_type" == "software" ]; then
        args+=(-c:v h264)
    elif [ "$acceleration_type" == "hardware" ]; then
        args+=(-vf 'format=nv12|vaapi,hwupload')
        args+=(-c:v h264_vaapi)
    else
        (>&2 echo "Unknown acceleration type: $acceleration_type")
        exit 1
    fi

    args+=(-b:v 2M)
    args+=(-profile:v high)
    args+=(-bf 0)
    args+=(-strict -2)
    args+=(-c:a opus)
    args+=(-ac 2)
    args+=(-b:a 320k)
    args+=(-ar 48000)

    if [ "$destination_type" == "stream" ]; then
        args+=(-f rtsp)
        args+=(-rtsp_transport tcp)
        args+=("rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch")
    elif [ "$destination_type" == "preproces" ]; then
        args+=("$file_to_save")
    else
        (>&2 echo "Unknown destination type: $destination_type")
        exit 1
    fi
}

function stream_software_h264 {
    local file_to_cast
    file_to_cast="$3"

    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    </dev/null exec ffmpeg \
               -re \
               -stream_loop -1 \
               -i "$file_to_cast" \
               -c:v h264 \
               -b:v 2M \
               -profile:v high \
               -bf 0 \
               -strict -2 \
               -c:a opus \
               -ac 2 \
               -b:a 320k \
               -ar 48000 \
               -f rtsp \
               -rtsp_transport tcp \
               "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}

function stream_hardware_h264 {
    local file_to_cast
    file_to_cast="$3"

    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    </dev/null exec ffmpeg \
               -re \
               -stream_loop -1 \
               -vaapi_device /dev/dri/renderD128 \
               -i "$file_to_cast" \
               -vf 'format=nv12|vaapi,hwupload' \
               -c:v h264_vaapi \
               -b:v 2M \
               -profile:v high \
               -bf 0 \
               -strict -2 \
               -c:a opus \
               -ac 2 \
               -b:a 320k \
               -ar 48000 \
               -f rtsp \
               -rtsp_transport tcp \
               "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}

function preprocess_software_h264 {
    local file_to_cast file_to_save
    file_to_cast="$1"
    file_to_save="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    </dev/null exec ffmpeg \
               -i "$file_to_cast" \
               -c:v h264 \
               -b:v 2M \
               -profile:v high \
               -bf 0 \
               -strict -2 \
               -c:a opus \
               -ac 2 \
               -b:a 320k \
               -ar 48000 \
               "$file_to_save"
}

function preprocess_hardware_h264 {
    local file_to_cast file_to_save
    file_to_cast="$1"
    file_to_save="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    </dev/null exec ffmpeg \
               -vaapi_device /dev/dri/renderD128 \
               -i "$file_to_cast" \
               -vf 'format=nv12,hwupload' \
               -c:v h264_vaapi \
               -b:v 2M \
               -profile:v high \
               -bf 0 \
               -strict -2 \
               -c:a opus \
               -ac 2 \
               -b:a 320k \
               -ar 48000 \
               "$file_to_save"
}

function vp9 {
    local file_to_cast
    file_to_cast="$3"

    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    </dev/null exec ffmpeg \
        -re \
        -stream_loop -1 \
        -init_hw_device vaapi=foo:/dev/dri/renderD128 \
        -hwaccel vaapi \
        -hwaccel_output_format vaapi \
        -hwaccel_device foo \
        -i "$file_to_cast" \
        -filter_hw_device foo \
        -vf 'format=nv12|vaapi,hwupload' \
        -c:v vp9_vaapi \
        -bf 0 \
        -strict -2 \
        -c:a opus \
        -b:a 320k \
        -ar 48000 \
        -f rtsp \
        -rtsp_transport tcp \
        "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}

function preprocess_hardware_vp9 {
    local file_to_cast file_to_save
    file_to_cast="$1"
    file_to_save="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    </dev/null exec ffmpeg \
        -init_hw_device vaapi=foo:/dev/dri/renderD128 \
        -hwaccel vaapi \
        -hwaccel_output_format vaapi \
        -hwaccel_device foo \
        -i "$file_to_cast" \
        -filter_hw_device foo \
        -vf 'format=nv12|vaapi,hwupload' \
        -c:v vp9_vaapi \
        -bf 0 \
        -strict -2 \
        -c:a opus \
        -b:a 320k \
        -ar 48000 \
        "$file_to_save"
}

function software_vp8 {
    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    local file_to_cast
    file_to_cast="$3"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    # -strict -2 :: Enable support for experimental codecs like opus.
    # -b:v 2M :: Target 2 megabit/s
    # -crf 10 :: Target a quality level and adjust bitrate accordingly. This should be preferred, but ideally both should be used.
    </dev/null exec ffmpeg \
        -re \
        -stream_loop -1 \
        -i "$file_to_cast" \
        -c:v vp8 \
        -b:v 2M \
        -crf 10 \
        -bf 0 \
        -c:a opus \
        -b:a 320k \
        -ar 48000 \
        -strict -2 \
        -f rtsp \
        -rtsp_transport tcp \
        "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}

function preprocess_vp8 {
    local file_to_cast file_to_save
    file_to_cast="$1"
    file_to_save="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    # -strict -2 :: Enable support for experimental codecs like opus.
    # -b:v 2M :: Target 2 megabit/s
    # -crf 10 :: Target a quality level and adjust bitrate accordingly. This should be preferred, but ideally both should be used.
    </dev/null exec ffmpeg \
        -i "$file_to_cast" \
        -c:v vp8 \
        -b:v 2M \
        -crf 10 \
        -bf 0 \
        -c:a opus \
        -b:a 320k \
        -ar 48000 \
        -strict -2 \
        "$file_to_save"
}

function webcam {
    # Uses on-webcam h264 encoding.

    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    set -x

    </dev/null exec ffmpeg \
        -re \
        -input_format h264 \
        -video_size 1920x1080 \
        -i /dev/video0 \
        -c:v copy \
        -an \
        -f rtsp \
        -rtsp_transport tcp \
        "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}

function encode_webcam {
    # Uses hardware accelerated gpu-based encoding.

    local USERNAME PASSWORD
    USERNAME="$1"
    PASSWORD="$2"

    set -x

    </dev/null exec ffmpeg \
        -re \
        -vaapi_device /dev/dri/renderD128 \
        -i /dev/video0 \
        -vf 'format=nv12,hwupload' \
        -c:v h264_vaapi \
        -an \
        -f rtsp \
        -rtsp_transport tcp \
        "rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}

function speed_up_preprocess_vp8 {
    local file_to_cast file_to_save
    file_to_cast="$1"
    file_to_save="$2"

    set -x

    # -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
    # -strict -2 :: Enable support for experimental codecs like opus.
    # -b:v 2M :: Target 2 megabit/s
    # -crf 10 :: Target a quality level and adjust bitrate accordingly. This should be preferred, but ideally both should be used.
    # Could also use -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]"
    </dev/null exec ffmpeg \
               -i "$file_to_cast" \
               -filter:v "setpts=0.66666666*PTS" \
               -filter:a "atempo=1.5" \
               -c:v vp8 \
               -b:v 2M \
               -crf 10 \
               -bf 0 \
               -c:a opus \
               -b:a 320k \
               -ar 48000 \
               -strict -2 \
               "$file_to_save"
}


main "${@}"