summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xlocalvideowebencode74
1 files changed, 64 insertions, 10 deletions
diff --git a/localvideowebencode b/localvideowebencode
index bb1ce63..4476047 100755
--- a/localvideowebencode
+++ b/localvideowebencode
@@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Depends: ffmpeg melt mediainfo
-# Recommends: moreutils vpx-tools vorbis-tools opus-tools
+# Recommends: moreutils vainfo vpx-tools vorbis-tools opus-tools
#
# TODO:
# * Offer to skip rendering again if an output file exist already.
@@ -124,6 +124,10 @@ html favoring open formats with optional non-JavaScript Flash fallback.
(default: normal)
--quality Quality rate factor: auto [integer] none
(default: auto)
+ --gpu Use hardware acceleration: none auto vaapi qsv
+ (default: auto when compression=dirty, else none)
+ --gpudevice Device used for hardware acceleration
+ (default: /dev/dri/renderD128)
-h, --help This help text
Examples:
@@ -196,7 +200,7 @@ factor_vp9=70/100
lufs=-18
# parse cmdline options
-TEMP="`getopt -s sh -o hp:s:a:r:b:t: -l help,profile:,size:,aspect:,rate:,video:,refbpp:,formats:,audio:,audioprefilter:,loudness,loudness-data:,filter:,stem:,title:,still-frame:,sample,sample-start:,sample-length:,compression:,quality: -n "$PRG" -- "$@"`" || exit1 "Internal getopt error."
+TEMP="`getopt -s sh -o hp:s:a:r:b:t: -l help,profile:,size:,aspect:,rate:,video:,refbpp:,formats:,audio:,audioprefilter:,loudness,loudness-data:,filter:,stem:,title:,still-frame:,sample,sample-start:,sample-length:,compression:,quality:,gpu:,gpudevice: -n "$PRG" -- "$@"`" || exit1 "Internal getopt error."
eval set -- "$TEMP"
while true ; do
case "$1" in
@@ -221,6 +225,8 @@ while true ; do
--sample-length) sample=yes; samplelength="$2"; shift 2;;
--compression) compression="$2"; shift 2;;
--quality) quality="$2"; shift 2;;
+ --gpu) gpu="$2"; shift 2;;
+ --gpudevice) gpudevice="$2"; shift 2;;
--) shift; break;;
*) exit1 "Internal error resolving options.";;
esac
@@ -274,6 +280,7 @@ profile_h264=baseline
case "$compression" in
normal) :;;
dirty)
+ gpu=${gpu:-auto}
q_theora=1
cpu_vp8=4
cpu_vp9=4
@@ -299,7 +306,42 @@ case "$quality" in
none) no_q=yes;;
*) q=$quality;;
esac
+gpudevice=${gpudevice:-/dev/dri/renderD128}
+if [ auto = "$gpu" ]; then
+ vainfo=$(vainfo --display drm --device "$gpudevice" 2>/dev/null | perl -nE '/Driver version:\s*\K.*/ and say $&; /VAProfile\S+\s*:\s*VAEntrypointEncSliceLP/ and say $&')
+ case "$vainfo" in
+ '') gpu=;;
+# TODO *"Intel iHD driver"*) gpu=qsv;;
+ *) gpu=vaapi;;
+ esac
+fi
+case "$gpu" in
+ none|'') gpu=;;
+ qsv)
+ multipass=
+ preset_vp8=medium
+ preset_vp9=medium
+ preset_h264=
+ profile_h264=578
+ use_ffmpeg_h264=yes
+ qkey_h264=qp
+ ;;
+ vaapi)
+ multipass=
+ preset_h264=
+ profile_h264=578
+ use_ffmpeg_h264=yes
+ qkey_h264=qp
+ case "$compression" in
+ dirty)
+ preset_h264=
+ ;;
+ esac
+ ;;
+ *) exit1 "Unknown GPU type \"$gpu\".";;
+esac
[ -n "$multipass" ] || singlepass=yes
+[ -z "$gpu" ] && no_gpu=yes || eval "gpu_$gpu=yes"
# parse/resolve size and framerate
case "$profile" in
@@ -506,6 +548,7 @@ for vformat in vp8 vp9 h264; do
eval "[ -z \"$no_q\$no_q_$vformat\" ] || q_$vformat="
[ -z "$q" ] || eval "q_$vformat=$q"
eval "[ -n \"\$q_$vformat\" ] || no_q_$vformat=yes"
+ [ -z "$gpu" ] || eval "encoder_$vformat=${vformat}_$gpu"
# melt supports dual-pass only for h.264
[ h264 = "$vformat" ] || [ -n "$vpxenc" ] || eval "[ -z \"$multipass\" ] || use_ffmpeg_$vformat=yes"
@@ -518,19 +561,30 @@ if [ -n "$use_ffmpeg_vp8$use_ffmpeg_vp9$use_vpxenc" ]; then
[ -z "$use_ffmpeg_ogg$use_ffmpeg_opus" ] || use_matroska=yes
fi
+[ -z "$gpu" ] || echo >&2 "GPU platform enabled: $gpu"
+
+# gpu options
+_melt_gpu_init=${gpu:+ ${gpu}_device=$gpudevice}
+_ffmpeg_gpu_vaapi_init="-${gpu}_device $gpudevice"
+_ffmpeg_gpu_qsv_init="-init_hw_device qsv=hw:$gpudevice -filter_hw_device hw"
+_ffmpeg_gpu_init="${gpu_vaapi:+ ${_ffmpeg_gpu_vaapi_init}}${gpu_qsv:+ ${_ffmpeg_gpu_qsv_init}}"
+_ffmpeg_gpu_vaapi_filter="-vf 'format=nv12|$gpu,hwupload'"
+_ffmpeg_gpu_qsv_filter="-vf 'hwupload=extra_hw_frames=64,format=qsv'"
+_ffmpeg_gpu_filter="${gpu_vaapi:+ ${_ffmpeg_gpu_vaapi_filter}}${gpu_qsv:+ ${_ffmpeg_gpu_qsv_filter}}"
+
# generic options
-melt="melt -progress"
+melt="melt -progress$_melt_gpu_init"
which ffmpeg > /dev/null && ffmpeg=ffmpeg || ffmpeg=avconv
-ffmpeg_alone="$ffmpeg -threads auto -y -v info -stats"
-ffmpeg_chained="$ffmpeg -threads auto -y -v warning"
+ffmpeg_alone="$ffmpeg -threads auto -y -v info -stats$_ffmpeg_gpu_init"
+ffmpeg_chained="$ffmpeg -threads auto -y -v warning$_ffmpeg_gpu_init"
vpxenc_chained="vpxenc --quiet ${processors:+-t $((processors-1))}"
oggenc="oggenc"
opusenc="opusenc"
_melt_infiles="${notsample:+$infiles}${sample:+$infile_first in=$((samplestart)) out=$((samplestart + samplelength))}"
# filter options
-_melt_video="progressive=1${framerate:+ frame_rate_num="$framerate_num" frame_rate_den="$framerate_den"}${size:+ s=${width:+$width}x${height:+$height}}${aspect:+ aspect=$aspect}"
-_ffmpeg_video="${do_deinterlace:+-filter:v yadif}${framerate:+ -r $framerate_num/$framerate_den}${size:+ -s ${width:+$width}x${height:+$height}}${aspect:+ -aspect $aspect}"
+_melt_video="${no_gpu:+progressive=1${framerate:+ frame_rate_num="$framerate_num" frame_rate_den="$framerate_den"}${size:+ s=${width:+$width}x${height:+$height}}${aspect:+ aspect=$aspect}}"
+_ffmpeg_video="${no_gpu:+${do_deinterlace:+-filter:v yadif}${framerate:+ -r $framerate_num/$framerate_den}${size:+ -s ${width:+$width}x${height:+$height}}${aspect:+ -aspect $aspect}}"
_melt_downmix="${downmix_melt:+ac=$channels}"
_ffmpeg_downmix="${downmix_ffmpeg:+-ac $channels}"
# FIXME: how to downmix to stereo?
@@ -564,8 +618,8 @@ _vpxenc_vp8="--codec=vp8${do_bitrate_vp8:+ $_vpxenc_bitrate_vp8} --end-usage=${n
_melt_vp9="vcodec=$encoder_vp9${pre_vp9:+ vpreset=$pre_vp9}${preset_vp9:+ preset=$preset_vp9}${do_bitrate_vp9:+ $_melt_bitrate_vp9}${q_vp9:+ ${no_bitrate_vp9:+vb=0 }$qkey_vp9=$q_vp9} $_melt_misc_vp9"
_ffmpeg_vp9="-c:v $encoder_vp9${pre_vp9:+ -vpre $pre_vp9}${preset_vp9:+ -preset $preset_vp9}${do_bitrate_vp9:+ $_ffmpeg_bitrate_vp9}${q_vp9:+ ${no_bitrate_vp9:+-b:v 0 }-$qkey_vp9 $q_vp9} $_ffmpeg_misc_vp9"
_vpxenc_vp9="--codec=vp9${do_bitrate_vp9:+ $_vpxenc_bitrate_vp9} --end-usage=${no_q_vp9:+vbr}${q_vp9:+cq --cq-level=$q_vp9} $_vpxenc_misc_vp8"
-_melt_h264="vcodec=$encoder_h264${preset_h264:+ vpreset=$preset_h264}${profile_h264:+ vprofile=$profile_h264}${x264tune:+ tune=$x264tune}${do_bitrate_h264:+ maxrate=$bitrate_h264 bufsize=$((bitrate_h264*2))}${q_h264:+ $qkey_h264=$q_h264} threads=0 movflags=+faststart"
-_ffmpeg_h264="-c:v $encoder_h264${preset_h264:+ -preset $preset_h264}${profile_h264:+ -profile:v $profile_h264}${x264tune:+ -tune $x264tune}${do_bitrate_h264:+ -maxrate $bitrate_h264 -bufsize $((bitrate_h264*2))}${q_h264:+ -$qkey_h264 $q_h264} -movflags +faststart"
+_melt_h264="vcodec=$encoder_h264${preset_h264:+ vpreset=$preset_h264}${profile_h264:+ vprofile=$profile_h264}${x264tune:+ tune=$x264tune}${do_bitrate_h264:+ maxrate=$bitrate_h264${no_gpu:+ bufsize=$((bitrate_h264*2))}}${q_h264:+ $qkey_h264=$q_h264} threads=0${no_gpu:+ movflags=+faststart}"
+_ffmpeg_h264="-c:v $encoder_h264${preset_h264:+ -preset $preset_h264}${profile_h264:+ -profile:v $profile_h264}${x264tune:+ -tune $x264tune}${do_bitrate_h264:+ -maxrate $bitrate_h264${no_gpu:+ -bufsize $((bitrate_h264*2))}}${q_h264:+ -$qkey_h264 $q_h264}${no_gpu:+ -movflags +faststart}"
_melt_pcm="$_melt_downmix acodec=pcm_s16le"
_melt_vorbis="$_melt_downmix acodec=libvorbis aq=$quality_vorbis"
_ffmpeg_vorbis="$_ffmpeg_downmix -c:a libvorbis -aq $quality_vorbis"
@@ -580,7 +634,7 @@ _ffmpeg_aac="$_ffmpeg_downmix -c:a aac -b:a $((channels*bitrate_aac))k"
# container options
_melt_stdout="-consumer avformat:pipe:1 f=yuv4mpegpipe $_melt_video pix_fmt=yuv420p an=1 audio_off=1"
-_ffmpeg_stdin="-f yuv4mpegpipe -i pipe:0"
+_ffmpeg_stdin="-f yuv4mpegpipe -i pipe:0$_ffmpeg_gpu_filter"
_ffmpeg_rawvideo="-f rawvideo"
_melt_wav="f=wav $_melt_pcm vn=1 video_off=1"
_ffmpeg_wav_in="-f wav"