Skip to content

Commit

Permalink
quality: add HEVC 4:2:2 8b and 10b support
Browse files Browse the repository at this point in the history
Issue: VSMGWL-66311

Signed-off-by: Daniel Socek <[email protected]>
  • Loading branch information
dsocek authored and dvrogozh committed Aug 16, 2023
1 parent 38ac18f commit 7f65350
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 18 deletions.
16 changes: 10 additions & 6 deletions doc/man/measure-quality.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ Search is done in the root `<folder>` and all subfolders.
+
In this case the quality measure is run only for the specified stream. If the stream is in YUV format,
then its characteristics must be specified via command line optins (`-w`, `-h`, `-f`,
etc.). The script accepts 8-bit I420 YUV input streams and 10-bit P010LE YUV input streams. If the
input stream is uncompressed YUV or elementary compressed bitstream (e.g. standard compliant h264),
quality will be measured using both ffmpeg-qsv and Media SDK Sample Multi-Transcode. On the other
hand, a stream encapsulated in a container (e.g. MP4, TS, etc.) will be measured only using
ffmpeg-qsv (since Sample Multi-Transcode does not support containers).
etc.). The script accepts 8-bit YUV4:2:0 (yuv420p) input for AVC, HEVC and AV1. For HEVC, the script also
accepts 10-bit YUV4:2:0 (p010le), 8-bit YUV4:2:2 (yuv422p), and 10-bit YUV4:2:2 (yuv422p10le) input, provided that
EncTools is enabled for 4:2:2 inputs. If the input stream is uncompressed YUV or elementary compressed bitstream
(e.g. standard compliant h264), quality will be measured using both ffmpeg-qsv and Media SDK Sample Multi-Transcode
(with the exception of HEVC 4:2:2 raw YUV inputs which are currently only supported through ffmpeg-qsv). On the other
hand, a stream encapsulated in a container (e.g. MP4, TS, etc.) will be measured only using ffmpeg-qsv
(since Sample Multi-Transcode does not support containers).
3. Run quality measure for the pre-defined sequence
+
Expand Down Expand Up @@ -98,6 +100,8 @@ HEVC also supports an additional set of predefined 10-bit sequences when using -
| Starting_1920x1080p_50_10b_pq_709_ct2020_p010le.yuv | 1920x1080 | 50 | 500 | 7d04491468b82db2ccbb7a4f822a0ef7 | JVET Test Suite
|===

HEVC 4:2:2 formats currently do not feature predefined sequences in this suite.

Script checks whether the input stream is YUV by the following file
extensions: '.yuv', '.YUV'. Any other file is considered to be an encoded
bitstream (either raw or in a container).
Expand Down Expand Up @@ -446,7 +450,7 @@ Only valid for YUV input stream.
--framerate|-f <uint>::
Input framerate

--pix-fmt yuv420p|p010le::
--pix-fmt yuv420p|p010le|yuv422p|yuv422p10le::
Input pixel format (default: `yuv420p`)

PREREQUISITES
Expand Down
2 changes: 2 additions & 0 deletions measure/quality/HEVC/run_cbr_ffmpeg-qsv-ld.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ vframes="-frames:v $nframes"

profile="main"
[[ "$format" = "p010le" ]] && profile="main10"
[[ "$format" = "yuv422p" ]] && profile="rext"
[[ "$format" = "yuv422p10le" ]] && profile="rext"

DEVICE=${DEVICE:-/dev/dri/renderD128}
if [ -z "$rawvideo" ] && [ "$std" != "UNSUPPORTED" ]; then
Expand Down
2 changes: 2 additions & 0 deletions measure/quality/HEVC/run_cbr_ffmpeg-qsv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ vframes="-frames:v $nframes"

profile="main"
[[ "$format" = "p010le" ]] && profile="main10"
[[ "$format" = "yuv422p" ]] && profile="rext"
[[ "$format" = "yuv422p10le" ]] && profile="rext"

DEVICE=${DEVICE:-/dev/dri/renderD128}
if [ -z "$rawvideo" ] && [ "$std" != "UNSUPPORTED" ]; then
Expand Down
2 changes: 2 additions & 0 deletions measure/quality/HEVC/run_vbr_ffmpeg-qsv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ vframes="-frames:v $nframes"

profile="main"
[[ "$format" = "p010le" ]] && profile="main10"
[[ "$format" = "yuv422p" ]] && profile="rext"
[[ "$format" = "yuv422p10le" ]] && profile="rext"

DEVICE=${DEVICE:-/dev/dri/renderD128}
if [ -z "$rawvideo" ] && [ "$std" != "UNSUPPORTED" ]; then
Expand Down
38 changes: 30 additions & 8 deletions measure/quality/measure-quality
Original file line number Diff line number Diff line change
Expand Up @@ -265,18 +265,26 @@ fi

# make sure pixel format is supported
case ${pix_fmt} in
yuv420p|p010le) ;;
yuv420p|p010le|yuv422p|yuv422p10le) ;;
*)
echo "error: unsupported pixel format ${pix_fmt}" >&2
exit -1
;;
esac
if [ "$pix_fmt" = "p010le" ] && [ "$codec" = "AVC" ]; then
echo "error: AVC does not currently support pixel format ${pix_fmt}" >&2
if [ "$pix_fmt" = "p010le" ] && ([ "$codec" = "AVC" ] || [ "$codec" = "AV1" ]); then
echo "error: the scripts currently do not support pixel format ${pix_fmt} for ${codec}" >&2
exit -1
fi
if [ "$pix_fmt" = "p010le" ] && [ "$codec" = "AV1" ]; then
echo "error: AV1 does not currently support pixel format ${pix_fmt}" >&2
if [ "$pix_fmt" = "yuv422p" ] && ([ "$codec" = "AVC" ] || [ "$codec" = "AV1" ]); then
echo "error: the scripts currently do not support pixel format ${pix_fmt} for ${codec}" >&2
exit -1
fi
if [ "$pix_fmt" = "yuv422p10le" ] && ([ "$codec" = "AVC" ] || [ "$codec" = "AV1" ]); then
echo "error: the scripts currently do not support pixel format ${pix_fmt} for ${codec}" >&2
exit -1
fi
if ([ "$pix_fmt" = "yuv422p" ] || [ "$pix_fmt" = "yuv422p10le" ]) && [ "$codec" = "HEVC" ] && [ "$use_enctools" = "no" ]; then
echo "error: the scripts currently only support pixel format ${pix_fmt} via ${codec} EncTools" >&2
exit -1
fi

Expand All @@ -299,13 +307,17 @@ else
fi

if [ "$pix_fmt" = "p010le" ]; then
ref_bit="-10bit"
ref_fmt="-10bit"
elif [ "$pix_fmt" = "yuv422p" ]; then
ref_fmt="-422"
elif [ "$pix_fmt" = "yuv422p10le" ]; then
ref_fmt="-10bit422"
fi

# make sure gold references are available for user selected reference codec/preset
if [ "$use_gold_ref" = "yes" ]; then
path=$(dirname $(readlink -f $0))
ref_path="$path/REF/${use_case}/${codec}/${ref_codec}-${ref_preset}${ref_ext}${ref_bit}"
ref_path="$path/REF/${use_case}/${codec}/${ref_codec}-${ref_preset}${ref_ext}${ref_fmt}"
if ! [ -e "$ref_path" ]; then
echo "warning: golden references not available for the selected preset" >&2
use_gold_ref=no
Expand Down Expand Up @@ -634,7 +646,7 @@ function get_coding_commandline_options() {
options_smt+="-dist 1 -num_ref 4 -gop_size 9999 -NalHrdConformance:on -VuiNalHrdParameters:on"
else
if [ "$use_enctools" = "yes" ]; then
if [ "$pix_fmt" = "p010le" ]; then
if [ "$pix_fmt" = "p010le" ] || [ "$pix_fmt" = "yuv422p" ] || [ "$pix_fmt" = "yuv422p10le" ]; then
options_qsv+="-look_ahead_depth ${enctools_lad} -extbrc 1 -adaptive_i 1 -adaptive_b 0 -b_strategy 1 -bf 7 -refs 4 -g 256 -idr_interval begin_only -strict -1"
options_smt+="-lad ${enctools_lad} -extbrc::implicit -AdaptiveI:on -AdaptiveB:off -dist 8 -num_ref 4 -gop_size 256 -NalHrdConformance:off -VuiNalHrdParameters:off"
else
Expand Down Expand Up @@ -1062,7 +1074,17 @@ if [[ ! -d "$file" ]]; then
fi
fi

# skip presets and SMT encoding for 422 case
skip_presets="no"
if [ "$is_yuv" = "yes" ]; then
if [ "$pix_fmt" = "yuv422p" ] || [ "$pix_fmt" = "yuv422p10le" ]; then
skip_presets="yes"
skip_msdk="yes"
fi
fi

if [[ -d "$file" ||
"$skip_presets" = "no" &&
"$is_yuv" = "yes" &&
"$(can_process_yuv $width $height $framerate)" = "no" &&
"$(is_preset_stream ${file##*/})" = "yes" ]]; then
Expand Down
132 changes: 128 additions & 4 deletions tests/measure-quality.bats
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,46 @@ getmp4hevc10b="ffmpeg -i WAR.mp4 \
[ $status -eq 0 ]
}

# convert to HEVC 4:2:2 mp4
getmp4hevc422="ffmpeg -i WAR.mp4 \
-pix_fmt yuv422p -c:v libx265 -preset medium -b:v 15M -fps_mode passthrough WAR_422.mp4"

@test "measure quality: transcode 100 frames of 4:2:2 mp4 video via HEVC EncTools, calculate metrics, measure bdrate and check measuring artifacts" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain422_10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $getmp4hevc422; \
measure quality --pix-fmt yuv422p --codec HEVC --nframes 100 --use-enctools --enctools-lad 8 --bitrates 0.5:1:1.5:2:3 WAR_422.mp4; \
result=\$(cat ${ARTIFACTS}/measure/quality/*{.metrics,bdrate} | grep -v :: | wc -l); \
[[ \$result = 24 ]]"
print_output
[ $status -eq 0 ]
}

# convert to HEVC 10bit 4:2:2 mp4
getmp4hevc10b422="ffmpeg -i WAR.mp4 \
-pix_fmt yuv422p10le -c:v libx265 -preset medium -b:v 15M -fps_mode passthrough WAR_10bit422.mp4"

@test "measure quality: transcode 100 frames of 10bit 4:2:2 mp4 video via HEVC EncTools, calculate metrics, measure bdrate and check measuring artifacts" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain422_10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $getmp4hevc10b422; \
measure quality --pix-fmt yuv422p10le --codec HEVC --nframes 100 --use-enctools --enctools-lad 8 --bitrates 0.5:1:1.5:2:3 WAR_10bit422.mp4; \
result=\$(cat ${ARTIFACTS}/measure/quality/*{.metrics,bdrate} | grep -v :: | wc -l); \
[[ \$result = 24 ]]"
print_output
[ $status -eq 0 ]
}

# convert to yuv420
cyuv="ffmpeg -i WAR.mp4 \
-c:v rawvideo -pix_fmt yuv420p -fps_mode passthrough WAR.yuv"
Expand Down Expand Up @@ -244,6 +284,46 @@ get26510b="ffmpeg -i WAR_10bit.mp4 -y -vframes 5 -c:v libx265 -preset medium -b:
[ $status -eq 0 ]
}

# get raw HEVC 4:2:2 stream from an mp4 container
get265422="ffmpeg -i WAR_422.mp4 -y -vframes 5 -c:v libx265 -preset medium -b:v 15M -fps_mode passthrough WAR_422.h265"

@test "measure quality: transcode 5 frames of a user-defined raw HEVC 4:2:2 video stream via HEVC EncTools into HEVC 4:2:2 stream" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain422_10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $getmp4hevc422; $get265422; \
measure quality --codec HEVC --nframes 5 --pix-fmt yuv422p --skip-metrics --skip-bdrate --use-enctools --enctools-lad 8 \
WAR_422.h265; \
result=\$(find ${ARTIFACTS}/measure/quality/ -not -empty -type f -ls | wc -l); \
[[ \$result = 30 ]]"
print_output
[ $status -eq 0 ]
}

# get raw HEVC 10bit 4:2:2 stream from an mp4 container
get26510b422="ffmpeg -i WAR_10bit422.mp4 -y -vframes 5 -c:v libx265 -preset medium -b:v 15M -fps_mode passthrough WAR_10bit422.h265"

@test "measure quality: transcode 5 frames of a user-defined raw HEVC 10bit 4:2:2 video stream via EncTools into HEVC 10bit 4:2:2 stream" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain422_10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $getmp4hevc10b422; $get26510b422; \
measure quality --codec HEVC --nframes 5 --pix-fmt yuv422p10le --skip-metrics --skip-bdrate --use-enctools --enctools-lad 8 \
WAR_10bit422.h265; \
result=\$(find ${ARTIFACTS}/measure/quality/ -not -empty -type f -ls | wc -l); \
[[ \$result = 30 ]]"
print_output
[ $status -eq 0 ]
}

@test "measure quality: transcode 5 frames of a user-defined raw HEVC video stream into AV1 stream" {
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
Expand Down Expand Up @@ -342,13 +422,13 @@ cyuv10b="ffmpeg -i WAR.mp4 \
-c:v rawvideo -pix_fmt p010le -fps_mode passthrough WAR_10bit.yuv"

@test "measure quality: encode 5 frames of a YUV 10bit video with HEVC encTools" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $cyuv10b; \
measure quality -w 480 -h 270 --pix-fmt p010le -f 24 \
--codec HEVC --nframes 5 --skip-metrics --skip-bdrate --use-enctools \
Expand All @@ -359,14 +439,58 @@ cyuv10b="ffmpeg -i WAR.mp4 \
[ $status -eq 0 ]
}

# get yuv422 from mp4
cyuv422="ffmpeg -i WAR.mp4 \
-c:v rawvideo -pix_fmt yuv422p -fps_mode passthrough WAR_422.yuv"

@test "measure quality: encode 5 frames of a YUV 4:2:2 video with HEVC encTools" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain422_10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $cyuv422; \
measure quality -w 480 -h 270 --pix-fmt yuv422p -f 24 \
--codec HEVC --nframes 5 --skip-metrics --skip-bdrate --use-enctools --enctools-lad 8 \
WAR_422.yuv; \
result=\$(find ${ARTIFACTS}/measure/quality/ -not -empty -type f -ls | wc -l); \
[[ \$result = 20 ]]"
print_output
[ $status -eq 0 ]
}

# get 10bit yuv422 from mp4
cyuv10b422="ffmpeg -i WAR.mp4 \
-c:v rawvideo -pix_fmt yuv422p10le -fps_mode passthrough WAR_10bit422.yuv"

@test "measure quality: encode 5 frames of a YUV 4:2:2 10bit video with HEVC encTools" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh HEVCMain422_10);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $cyuv10b422; \
measure quality -w 480 -h 270 --pix-fmt yuv422p10le -f 24 \
--codec HEVC --nframes 5 --skip-metrics --skip-bdrate --use-enctools --enctools-lad 8 \
WAR_10bit422.yuv; \
result=\$(find ${ARTIFACTS}/measure/quality/ -not -empty -type f -ls | wc -l); \
[[ \$result = 20 ]]"
print_output
[ $status -eq 0 ]
}

@test "measure quality: encode 5 frames of a YUV video with AV1 encTools" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh AV1Profile0);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $cyuv; \
measure quality -w 480 -h 270 -f 24 \
--codec AV1 --nframes 5 --skip-metrics --skip-bdrate --use-enctools \
Expand Down Expand Up @@ -400,13 +524,13 @@ cyuv10b="ffmpeg -i WAR.mp4 \
}

@test "measure quality: transcode 5 frames of a user-defined raw H.264 video stream into AV1 stream using encTools" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh AV1Profile0);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $get264; \
measure quality --codec AV1 --nframes 5 --skip-metrics --skip-bdrate --use-enctools \
WAR.h264; \
Expand Down Expand Up @@ -439,13 +563,13 @@ cyuv10b="ffmpeg -i WAR.mp4 \
}

@test "measure quality: transcode 5 frames of a user-defined raw HEVC video stream into AV1 stream using encTools" {
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run_opts "--security-opt=no-new-privileges:true -v $(pwd)/tests:/opt/tests" \
/bin/bash -c "set -ex; \
supported=\$(/opt/tests/profile-supported.sh AV1Profile0);
[[ "\$supported" = "yes" ]]"
print_output
if [ $status -eq 1 ]; then skip; fi
if ! [[ "$TEST_ENCTOOLS" =~ ^(on|ON) ]]; then skip; fi
run docker_run /bin/bash -c "set -ex; $subs; $get265; \
measure quality --codec AV1 --nframes 5 --skip-metrics --skip-bdrate --use-enctools \
WAR.h265; \
Expand Down

0 comments on commit 7f65350

Please sign in to comment.