diff options
-rwxr-xr-x | localvideowebencode | 74 |
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" |