From 9174c56b820e9e9fbd6a39e11add39e3d0e0a200 Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Wed, 17 Mar 2021 18:10:39 -0700 Subject: [PATCH] Increase video-rotation test tolerance, add vp9 version. (#3262) Speed focused software yuv conversion libraries may be off by more than 5 points in a channel for values near the channel maximum. There's also no reason we can't have a vp9 version of this test, so add encodes for clients who want to test w/o proprietary codecs. Run both h264 and vp9 tests if supported. --- .../textures/misc/video-rotation.html | 56 ++++++++++++------ sdk/tests/resources/video-rotation-0.vp9.mp4 | Bin 0 -> 2917 bytes .../resources/video-rotation-180.vp9.mp4 | Bin 0 -> 2926 bytes .../resources/video-rotation-270.vp9.mp4 | Bin 0 -> 2939 bytes sdk/tests/resources/video-rotation-90.vp9.mp4 | Bin 0 -> 2950 bytes 5 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 sdk/tests/resources/video-rotation-0.vp9.mp4 create mode 100644 sdk/tests/resources/video-rotation-180.vp9.mp4 create mode 100644 sdk/tests/resources/video-rotation-270.vp9.mp4 create mode 100644 sdk/tests/resources/video-rotation-90.vp9.mp4 diff --git a/sdk/tests/conformance/textures/misc/video-rotation.html b/sdk/tests/conformance/textures/misc/video-rotation.html index 322c278f48..1ebf5b56c0 100644 --- a/sdk/tests/conformance/textures/misc/video-rotation.html +++ b/sdk/tests/conformance/textures/misc/video-rotation.html @@ -29,7 +29,7 @@ let gl = wtu.create3DContext(canvas); let program = tiu.setupTexturedQuad(gl, gl.RGBA); const resourcePath = "../../../resources/"; - const tolerance = 5; + const tolerance = 6; const expectedColors = { top: { location: [0.5, 0.25], color: [255, 0, 0] }, @@ -89,11 +89,12 @@ return; } - const type = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; - if (!video.canPlayType(type).replace(/no/, '')) { - debug(type + " unsupported"); + let supports_h264 = !!video.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/no/, ''); + let supports_vp9 = !!video.canPlayType('video/mp4; codecs="vp09.00.10.08"').replace(/no/, ''); + if (!supports_h264 && !supports_vp9) { + testFailed("No supported video types."); return; - }; + } let tex = gl.createTexture(); // Bind the texture to the default texture unit 0 @@ -107,27 +108,44 @@ // These files were created by converting exif-orientation-test-1-normal.jpg to mp4 // files, rotating them using the transpose filter, and adding rotate metadata, all // using the ffmpeg command-line tool. + // + // From sdk/tests/resources/ directory: + // // 0: - // ffmpeg -noautorotate -i sdk/tests/resources/exif-orientation-test-1-normal.jpg -pix_fmt yuv420p temp.mp4 && - // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 sdk/tests/resources/video-rotation-0.mp + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -pix_fmt yuv420p -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 video-rotation-0.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 video-rotation-0.vp9.mp4 // 90: - // ffmpeg -noautorotate -i sdk/tests/resources/exif-orientation-test-1-normal.jpg -vf "transpose=2" -pix_fmt yuv420p temp.mp4 && - // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 sdk/tests/resources/video-rotation-90.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -vf "transpose=2" -pix_fmt yuv420p -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 video-rotation-90.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -vf "transpose=2" -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 video-rotation-90.vp9.mp4 // 180: - // ffmpeg -noautorotate -i sdk/tests/resources/exif-orientation-test-1-normal.jpg -vf "transpose=2,transpose=2" -pix_fmt yuv420p temp.mp4 && - // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 sdk/tests/resources/video-rotation-180.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -vf "transpose=2,transpose=2" -pix_fmt yuv420p -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 video-rotation-180.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -vf "transpose=2,transpose=2" -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 video-rotation-180.vp9.mp4 // 270: - // ffmpeg -noautorotate -i sdk/tests/resources/exif-orientation-test-1-normal.jpg -vf "transpose=1" -pix_fmt yuv420p temp.mp4 && - // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 sdk/tests/resources/video-rotation-270.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -vf "transpose=1" -pix_fmt yuv420p -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 video-rotation-270.mp4 + // ffmpeg -noautorotate -i exif-orientation-test-1-normal.jpg -vf "transpose=1" -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4 && + // ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 video-rotation-270.vp9.mp4 const filenames = [ - "video-rotation-0.mp4", - "video-rotation-90.mp4", - "video-rotation-180.mp4", - "video-rotation-270.mp4", + "video-rotation-0", + "video-rotation-90", + "video-rotation-180", + "video-rotation-270", ]; - for (let fn of filenames) { - await testVideoElement(fn); + if (supports_h264) { + for (let fn of filenames) + await testVideoElement(fn + ".mp4"); + } + + if (supports_vp9) { + for (let fn of filenames) + await testVideoElement(fn + ".vp9.mp4"); } finishTest(); diff --git a/sdk/tests/resources/video-rotation-0.vp9.mp4 b/sdk/tests/resources/video-rotation-0.vp9.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ec4990e59d2f751d4ea2b7cd7bfebfd7406882b5 GIT binary patch literal 2917 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 N2AcZ1n%Y`g{{gjNin0Iz literal 0 HcmV?d00001 diff --git a/sdk/tests/resources/video-rotation-180.vp9.mp4 b/sdk/tests/resources/video-rotation-180.vp9.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..9ee8608b36cb447af3caf47a075b4f1bb17fbd8d GIT binary patch literal 2926 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 literal 0 HcmV?d00001 diff --git a/sdk/tests/resources/video-rotation-90.vp9.mp4 b/sdk/tests/resources/video-rotation-90.vp9.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..3a66083ec4dd0c22700d7713d723e5424c00ce43 GIT binary patch literal 2950 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 pF#7Y4DByM{e58o%%_t}ay`dRJ7>59s2tTZ