#!/bin/sh

error() {
	echo "$@" >&2
	exit 1
}

set_video() {
	local hw

	preset='-preset slow'
	case "$1" in
	copy)
		codec=copy
		hw=0
		;;
	h264_sw)
		codec=libx264
		hw=0
		;;
	h264_hw)
		codec=h264_qsv
		hw=1
		;;
	h265_sw)
		codec=libx265
		tag='-tag:v hvc1' # this is needed by broken devices like Apple ones
		hw=0
		;;
	h265_hw)
		codec=hevc_qsv
		tag='-tag:v hvc1'
		hw=1
		;;
	av1_sw)
		codec=libsvtav1
		preset='-preset 6'
		hw=0
		;;
	av1_hw)
		codec=av1_qsv
		hw=1
		;;
	*)
		error "Invalid video codec '$1'"
		;;
	esac

	if [ $hw -eq 1 ]; then
		hwaccel='-hwaccel qsv -hwaccel_output_format qsv'
		# see https://github.com/intel/media-delivery/blob/master/doc/quality.rst
		quality="
			-global_quality $q
			-g 256
			-bf 7
			-extbrc 1
			-look_ahead_depth 40
			-b_strategy 1
			-refs 5
			-adaptive_i 1
			-adaptive_b 1
			-strict -1
		"
	else
		quality="-crf $q"
	fi
}

codec=av1_hw
q=25
getopts=':v:q:h'

usage() {
	cat <<- EOF
		Usage: ${0##*/} [-v codec] [-q quality] <input.avi> <output.mp4>
		    video codecs: copy, h264_sw, h264_hw, h265_sw, h265_hw, av1_sw, av1_hw. Default av1_hw
		    quality: 1-51 (lower is better). Default 25
	EOF
	exit $1
}

while getopts $getopts arg; do
	case "$arg" in
	v)
		codec=$OPTARG
		;;
	h)
		usage 0
		;;
	q)
		q=$OPTARG
		case "$q" in *[!0-9]*) usage 1 ;; esac
		{ [ "$q" -lt 1 ] || [ "$q" -gt 51 ] ; } && usage 1
		;;
	*)
		usage 1
		;;
	esac

done

shift $((OPTIND - 1))

in=$1
out=$2

[ $# -ne 2 ] && usage 1

[ -f "$in" ] || error "file '$in' not found"

set_video "$codec"

exec ffmpeg -y -loglevel quiet -stats $hwaccel -i "$in" -c:v $codec $preset $quality $tag -c:a copy "$out"
