1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------ 2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests 3e5c31af7Sopenharmony_ci * ------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2023 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci */ 20e5c31af7Sopenharmony_ci/*! 21e5c31af7Sopenharmony_ci * \file 22e5c31af7Sopenharmony_ci * \brief Video decoding tests 23e5c31af7Sopenharmony_ci */ 24e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*/ 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "vktVideoDecodeTests.hpp" 27e5c31af7Sopenharmony_ci#include "vktVideoTestUtils.hpp" 28e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp" 29e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp" 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_ci#include "tcuFunctionLibrary.hpp" 32e5c31af7Sopenharmony_ci#include "tcuPlatform.hpp" 33e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp" 36e5c31af7Sopenharmony_ci#include "vkDefs.hpp" 37e5c31af7Sopenharmony_ci#include "vkImageWithMemory.hpp" 38e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp" 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_ci#include "vktVideoClipInfo.hpp" 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_ci#include <deDefs.h> 43e5c31af7Sopenharmony_ci 44e5c31af7Sopenharmony_ci#ifdef DE_BUILD_VIDEO 45e5c31af7Sopenharmony_ci#include "extESExtractor.hpp" 46e5c31af7Sopenharmony_ci#include "vktVideoBaseDecodeUtils.hpp" 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_ci#include "extNvidiaVideoParserIf.hpp" 49e5c31af7Sopenharmony_ci// FIXME: The samples repo is missing this internal include from their H265 decoder 50e5c31af7Sopenharmony_ci#include "nvVulkanh265ScalingList.h" 51e5c31af7Sopenharmony_ci#include <VulkanH264Decoder.h> 52e5c31af7Sopenharmony_ci#include <VulkanH265Decoder.h> 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_ci#include <utility> 55e5c31af7Sopenharmony_ci#endif 56e5c31af7Sopenharmony_ci 57e5c31af7Sopenharmony_cinamespace vkt 58e5c31af7Sopenharmony_ci{ 59e5c31af7Sopenharmony_cinamespace video 60e5c31af7Sopenharmony_ci{ 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_ci// Set this to 1 to have the decoded YCbCr frames written to the 63e5c31af7Sopenharmony_ci// filesystem in the YV12 format. 64e5c31af7Sopenharmony_ci// Check the relevant sections to change the file name and so on... 65e5c31af7Sopenharmony_ci#define FRAME_DUMP_DEBUG 0 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_cinamespace 68e5c31af7Sopenharmony_ci{ 69e5c31af7Sopenharmony_ciusing namespace vk; 70e5c31af7Sopenharmony_ciusing namespace std; 71e5c31af7Sopenharmony_ci 72e5c31af7Sopenharmony_ciusing de::MovePtr; 73e5c31af7Sopenharmony_ci 74e5c31af7Sopenharmony_cienum TestType 75e5c31af7Sopenharmony_ci{ 76e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_I, // Case 6 77e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_I_P, // Case 7 78e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_CLIP_A, 79e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_I_P_B_13, // Case 7a 80e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_I_P_NOT_MATCHING_ORDER, // Case 8 81e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_I_P_B_13_NOT_MATCHING_ORDER, // Case 8a 82e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_QUERY_RESULT_WITH_STATUS, // Case 9 83e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE, // Case 17 84e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE_DPB, // Case 18 85e5c31af7Sopenharmony_ci TEST_TYPE_H264_DECODE_INTERLEAVED, // Case 21 86e5c31af7Sopenharmony_ci TEST_TYPE_H264_BOTH_DECODE_ENCODE_INTERLEAVED, // Case 23 TODO 87e5c31af7Sopenharmony_ci TEST_TYPE_H264_H265_DECODE_INTERLEAVED, // Case 24 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_ci TEST_TYPE_H265_DECODE_I, // Case 15 90e5c31af7Sopenharmony_ci TEST_TYPE_H265_DECODE_I_P, // Case 16 91e5c31af7Sopenharmony_ci TEST_TYPE_H265_DECODE_CLIP_D, 92e5c31af7Sopenharmony_ci TEST_TYPE_H265_DECODE_I_P_NOT_MATCHING_ORDER, // Case 16-2 93e5c31af7Sopenharmony_ci TEST_TYPE_H265_DECODE_I_P_B_13, // Case 16-3 94e5c31af7Sopenharmony_ci TEST_TYPE_H265_DECODE_I_P_B_13_NOT_MATCHING_ORDER, // Case 16-4 95e5c31af7Sopenharmony_ci 96e5c31af7Sopenharmony_ci TEST_TYPE_LAST 97e5c31af7Sopenharmony_ci}; 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_ciconst char* getTestName(TestType type) 100e5c31af7Sopenharmony_ci{ 101e5c31af7Sopenharmony_ci const char* testName; 102e5c31af7Sopenharmony_ci switch (type) 103e5c31af7Sopenharmony_ci { 104e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I: 105e5c31af7Sopenharmony_ci testName = "h264_i"; 106e5c31af7Sopenharmony_ci break; 107e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P: 108e5c31af7Sopenharmony_ci testName = "h264_i_p"; 109e5c31af7Sopenharmony_ci break; 110e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_CLIP_A: 111e5c31af7Sopenharmony_ci testName = "h264_420_8bit_high_176x144_30frames"; 112e5c31af7Sopenharmony_ci break; 113e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P_NOT_MATCHING_ORDER: 114e5c31af7Sopenharmony_ci testName = "h264_i_p_not_matching_order"; 115e5c31af7Sopenharmony_ci break; 116e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P_B_13: 117e5c31af7Sopenharmony_ci testName = "h264_i_p_b_13"; 118e5c31af7Sopenharmony_ci break; 119e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P_B_13_NOT_MATCHING_ORDER: 120e5c31af7Sopenharmony_ci testName = "h264_i_p_b_13_not_matching_order"; 121e5c31af7Sopenharmony_ci break; 122e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_QUERY_RESULT_WITH_STATUS: 123e5c31af7Sopenharmony_ci testName = "h264_query_with_status"; 124e5c31af7Sopenharmony_ci break; 125e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE: 126e5c31af7Sopenharmony_ci testName = "h264_resolution_change"; 127e5c31af7Sopenharmony_ci break; 128e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE_DPB: 129e5c31af7Sopenharmony_ci testName = "h264_resolution_change_dpb"; 130e5c31af7Sopenharmony_ci break; 131e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_INTERLEAVED: 132e5c31af7Sopenharmony_ci testName = "h264_interleaved"; 133e5c31af7Sopenharmony_ci break; 134e5c31af7Sopenharmony_ci case TEST_TYPE_H264_H265_DECODE_INTERLEAVED: 135e5c31af7Sopenharmony_ci testName = "h264_h265_interleaved"; 136e5c31af7Sopenharmony_ci break; 137e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I: 138e5c31af7Sopenharmony_ci testName = "h265_i"; 139e5c31af7Sopenharmony_ci break; 140e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P: 141e5c31af7Sopenharmony_ci testName = "h265_i_p"; 142e5c31af7Sopenharmony_ci break; 143e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_CLIP_D: 144e5c31af7Sopenharmony_ci testName = "h265_420_8bit_main_176x144_30frames"; 145e5c31af7Sopenharmony_ci break; 146e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P_NOT_MATCHING_ORDER: 147e5c31af7Sopenharmony_ci testName = "h265_i_p_not_matching_order"; 148e5c31af7Sopenharmony_ci break; 149e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P_B_13: 150e5c31af7Sopenharmony_ci testName = "h265_i_p_b_13"; 151e5c31af7Sopenharmony_ci break; 152e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P_B_13_NOT_MATCHING_ORDER: 153e5c31af7Sopenharmony_ci testName = "h265_i_p_b_13_not_matching_order"; 154e5c31af7Sopenharmony_ci break; 155e5c31af7Sopenharmony_ci default: 156e5c31af7Sopenharmony_ci TCU_THROW(InternalError, "Unknown TestType"); 157e5c31af7Sopenharmony_ci } 158e5c31af7Sopenharmony_ci return testName; 159e5c31af7Sopenharmony_ci} 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_cienum DecoderOption : deUint32 163e5c31af7Sopenharmony_ci{ 164e5c31af7Sopenharmony_ci // The default is to do nothing additional to ordinary playback. 165e5c31af7Sopenharmony_ci Default = 0, 166e5c31af7Sopenharmony_ci // All decode operations will have their status checked for success (Q2 2023: not all vendors support these) 167e5c31af7Sopenharmony_ci UseStatusQueries = 1 << 0, 168e5c31af7Sopenharmony_ci // Do not playback the clip in the "normal fashion", instead cached decode parameters for later process 169e5c31af7Sopenharmony_ci // this is primarily used to support out-of-order submission test cases, and per-GOP handling. 170e5c31af7Sopenharmony_ci CachedDecoding = 1 << 1, 171e5c31af7Sopenharmony_ci // When a parameter object changes the resolution of the test content, and the new video session would otherwise 172e5c31af7Sopenharmony_ci // still be compatible with the last session (for example, larger decode surfaces preceeding smaller decode surfaces, 173e5c31af7Sopenharmony_ci // a frame downsize), force the session to be recreated anyway. 174e5c31af7Sopenharmony_ci RecreateDPBImages = 1 << 2, 175e5c31af7Sopenharmony_ci}; 176e5c31af7Sopenharmony_cistatic const int ALL_FRAMES = 0; 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_cistruct BaseDecodeParam 179e5c31af7Sopenharmony_ci{ 180e5c31af7Sopenharmony_ci ClipName clip; 181e5c31af7Sopenharmony_ci int framesToCheck; 182e5c31af7Sopenharmony_ci DecoderOption decoderOptions; 183e5c31af7Sopenharmony_ci}; 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_cistruct DecodeTestParam 186e5c31af7Sopenharmony_ci{ 187e5c31af7Sopenharmony_ci TestType type; 188e5c31af7Sopenharmony_ci BaseDecodeParam stream; 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_ci} g_DecodeTests[] = { 191e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_I, {CLIP_A, 1, DecoderOption::Default}}, 192e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_I_P, {CLIP_A, 2, DecoderOption::Default}}, 193e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_I_P_NOT_MATCHING_ORDER, {CLIP_A, 2, DecoderOption::CachedDecoding}}, 194e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_CLIP_A, {CLIP_A, ALL_FRAMES, DecoderOption::Default}}, 195e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_I_P_B_13, {CLIP_H264_4K_26_IBP_MAIN, ALL_FRAMES, DecoderOption::Default}}, 196e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_I_P_B_13_NOT_MATCHING_ORDER, {CLIP_H264_4K_26_IBP_MAIN, ALL_FRAMES, DecoderOption::CachedDecoding}}, 197e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_QUERY_RESULT_WITH_STATUS, {CLIP_A, ALL_FRAMES, DecoderOption::UseStatusQueries}}, 198e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE, {CLIP_C, ALL_FRAMES, DecoderOption::Default}}, 199e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE_DPB, {CLIP_C, ALL_FRAMES, DecoderOption::RecreateDPBImages}}, 200e5c31af7Sopenharmony_ci 201e5c31af7Sopenharmony_ci {TEST_TYPE_H265_DECODE_I, {CLIP_D, 1, DecoderOption::Default}}, 202e5c31af7Sopenharmony_ci {TEST_TYPE_H265_DECODE_I_P, {CLIP_D, 2, DecoderOption::Default}}, 203e5c31af7Sopenharmony_ci {TEST_TYPE_H265_DECODE_I_P_NOT_MATCHING_ORDER, {CLIP_D, 2, DecoderOption::CachedDecoding}}, 204e5c31af7Sopenharmony_ci {TEST_TYPE_H265_DECODE_I_P_B_13, {CLIP_JELLY_HEVC, ALL_FRAMES, DecoderOption::Default}}, 205e5c31af7Sopenharmony_ci {TEST_TYPE_H265_DECODE_I_P_B_13_NOT_MATCHING_ORDER, {CLIP_JELLY_HEVC, ALL_FRAMES, DecoderOption::CachedDecoding}}, 206e5c31af7Sopenharmony_ci {TEST_TYPE_H265_DECODE_CLIP_D, {CLIP_D, ALL_FRAMES, DecoderOption::Default}}, 207e5c31af7Sopenharmony_ci}; 208e5c31af7Sopenharmony_ci 209e5c31af7Sopenharmony_cistruct InterleavingDecodeTestParams 210e5c31af7Sopenharmony_ci{ 211e5c31af7Sopenharmony_ci TestType type; 212e5c31af7Sopenharmony_ci BaseDecodeParam streamA; 213e5c31af7Sopenharmony_ci BaseDecodeParam streamB; 214e5c31af7Sopenharmony_ci} g_InterleavingTests[] = { 215e5c31af7Sopenharmony_ci {TEST_TYPE_H264_DECODE_INTERLEAVED, {CLIP_A, ALL_FRAMES, DecoderOption::CachedDecoding}, {CLIP_A, ALL_FRAMES, DecoderOption::CachedDecoding}}, 216e5c31af7Sopenharmony_ci {TEST_TYPE_H264_H265_DECODE_INTERLEAVED, {CLIP_A, ALL_FRAMES, DecoderOption::CachedDecoding}, {CLIP_D, ALL_FRAMES, DecoderOption::CachedDecoding}}, 217e5c31af7Sopenharmony_ci}; 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ciclass TestDefinition 220e5c31af7Sopenharmony_ci{ 221e5c31af7Sopenharmony_cipublic: 222e5c31af7Sopenharmony_ci static MovePtr<TestDefinition> create(DecodeTestParam params, deUint32 baseSeed) 223e5c31af7Sopenharmony_ci { 224e5c31af7Sopenharmony_ci return MovePtr<TestDefinition>(new TestDefinition(params, baseSeed)); 225e5c31af7Sopenharmony_ci } 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci TestDefinition(DecodeTestParam params, deUint32 baseSeed) 228e5c31af7Sopenharmony_ci : m_params(params) 229e5c31af7Sopenharmony_ci , m_info(clipInfo(params.stream.clip)) 230e5c31af7Sopenharmony_ci , m_hash(baseSeed) 231e5c31af7Sopenharmony_ci { 232e5c31af7Sopenharmony_ci m_profile = VkVideoCoreProfile(m_info->profile.codecOperation, m_info->profile.subsamplingFlags, m_info->profile.lumaBitDepth, m_info->profile.chromaBitDepth, m_info->profile.profileIDC); 233e5c31af7Sopenharmony_ci if (m_params.stream.framesToCheck == ALL_FRAMES) 234e5c31af7Sopenharmony_ci { 235e5c31af7Sopenharmony_ci m_params.stream.framesToCheck = m_info->totalFrames; 236e5c31af7Sopenharmony_ci } 237e5c31af7Sopenharmony_ci if (params.type == TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE_DPB) 238e5c31af7Sopenharmony_ci { 239e5c31af7Sopenharmony_ci m_pictureParameterUpdateTriggerHack = 3; 240e5c31af7Sopenharmony_ci } 241e5c31af7Sopenharmony_ci } 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci TestType getTestType() const 244e5c31af7Sopenharmony_ci { 245e5c31af7Sopenharmony_ci return m_params.type; 246e5c31af7Sopenharmony_ci } 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci const char* getClipFilename() const 249e5c31af7Sopenharmony_ci { 250e5c31af7Sopenharmony_ci return m_info->filename; 251e5c31af7Sopenharmony_ci } 252e5c31af7Sopenharmony_ci 253e5c31af7Sopenharmony_ci const ClipInfo* getClipInfo() const 254e5c31af7Sopenharmony_ci { 255e5c31af7Sopenharmony_ci return m_info; 256e5c31af7Sopenharmony_ci }; 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci VkVideoCodecOperationFlagBitsKHR getCodecOperation() const 259e5c31af7Sopenharmony_ci { 260e5c31af7Sopenharmony_ci return m_profile.GetCodecType(); 261e5c31af7Sopenharmony_ci } 262e5c31af7Sopenharmony_ci const VkVideoCoreProfile* getProfile() const 263e5c31af7Sopenharmony_ci { 264e5c31af7Sopenharmony_ci return &m_profile; 265e5c31af7Sopenharmony_ci } 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_ci int framesToCheck() const 268e5c31af7Sopenharmony_ci { 269e5c31af7Sopenharmony_ci return m_params.stream.framesToCheck; 270e5c31af7Sopenharmony_ci } 271e5c31af7Sopenharmony_ci 272e5c31af7Sopenharmony_ci bool hasOption(DecoderOption o) const 273e5c31af7Sopenharmony_ci { 274e5c31af7Sopenharmony_ci return (m_params.stream.decoderOptions & o) != 0; 275e5c31af7Sopenharmony_ci } 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_ci int getParamaterUpdateHackRequirement() const 278e5c31af7Sopenharmony_ci { 279e5c31af7Sopenharmony_ci return m_pictureParameterUpdateTriggerHack; 280e5c31af7Sopenharmony_ci } 281e5c31af7Sopenharmony_ci 282e5c31af7Sopenharmony_ci VideoDevice::VideoDeviceFlags requiredDeviceFlags() const 283e5c31af7Sopenharmony_ci { 284e5c31af7Sopenharmony_ci return VideoDevice::VIDEO_DEVICE_FLAG_REQUIRE_SYNC2_OR_NOT_SUPPORTED | 285e5c31af7Sopenharmony_ci (hasOption(DecoderOption::UseStatusQueries) ? VideoDevice::VIDEO_DEVICE_FLAG_QUERY_WITH_STATUS_FOR_DECODE_SUPPORT : VideoDevice::VIDEO_DEVICE_FLAG_NONE); 286e5c31af7Sopenharmony_ci } 287e5c31af7Sopenharmony_ci 288e5c31af7Sopenharmony_ci const VkExtensionProperties* extensionProperties() const 289e5c31af7Sopenharmony_ci { 290e5c31af7Sopenharmony_ci static const VkExtensionProperties h264StdExtensionVersion = { 291e5c31af7Sopenharmony_ci VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION}; 292e5c31af7Sopenharmony_ci static const VkExtensionProperties h265StdExtensionVersion = { 293e5c31af7Sopenharmony_ci VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION}; 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci switch (m_profile.GetCodecType()) 296e5c31af7Sopenharmony_ci { 297e5c31af7Sopenharmony_ci case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: 298e5c31af7Sopenharmony_ci return &h264StdExtensionVersion; 299e5c31af7Sopenharmony_ci case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: 300e5c31af7Sopenharmony_ci return &h265StdExtensionVersion; 301e5c31af7Sopenharmony_ci default: 302e5c31af7Sopenharmony_ci tcu::die("Unsupported video codec %s\n", util::codecToName(m_profile.GetCodecType())); 303e5c31af7Sopenharmony_ci break; 304e5c31af7Sopenharmony_ci } 305e5c31af7Sopenharmony_ci 306e5c31af7Sopenharmony_ci TCU_THROW(InternalError, "Unsupported codec"); 307e5c31af7Sopenharmony_ci }; 308e5c31af7Sopenharmony_ci 309e5c31af7Sopenharmony_ci void updateHash(deUint32 baseHash) 310e5c31af7Sopenharmony_ci { 311e5c31af7Sopenharmony_ci m_hash = deUint32Hash(baseHash); 312e5c31af7Sopenharmony_ci } 313e5c31af7Sopenharmony_ci 314e5c31af7Sopenharmony_ciprivate: 315e5c31af7Sopenharmony_ci DecodeTestParam m_params; 316e5c31af7Sopenharmony_ci const ClipInfo* m_info{}; 317e5c31af7Sopenharmony_ci deUint32 m_hash{}; 318e5c31af7Sopenharmony_ci VkVideoCoreProfile m_profile; 319e5c31af7Sopenharmony_ci // The 1-based count of parameter set updates after which to force a parameter object release. 320e5c31af7Sopenharmony_ci // This is required due to the design of the NVIDIA decode-client API. It sends parameter updates and expects constructed parameter 321e5c31af7Sopenharmony_ci // objects back synchronously, before the next video session is created in a following BeginSequence call. 322e5c31af7Sopenharmony_ci int m_pictureParameterUpdateTriggerHack{0}; // Zero is "off" 323e5c31af7Sopenharmony_ci}; 324e5c31af7Sopenharmony_ci 325e5c31af7Sopenharmony_ci 326e5c31af7Sopenharmony_ci// Vulkan video is not supported on android platform 327e5c31af7Sopenharmony_ci// all external libraries, helper functions and test instances has been excluded 328e5c31af7Sopenharmony_ci#ifdef DE_BUILD_VIDEO 329e5c31af7Sopenharmony_ciusing VkVideoParser = VkSharedBaseObj<VulkanVideoDecodeParser>; 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_civoid createParser(const TestDefinition* params, VideoBaseDecoder* decoder, VkSharedBaseObj<VulkanVideoDecodeParser>& parser) 332e5c31af7Sopenharmony_ci{ 333e5c31af7Sopenharmony_ci VkVideoCapabilitiesKHR videoCaps{}; 334e5c31af7Sopenharmony_ci VkVideoDecodeCapabilitiesKHR videoDecodeCaps{}; 335e5c31af7Sopenharmony_ci util::getVideoDecodeCapabilities(*decoder->m_deviceContext, decoder->m_profile, videoCaps, videoDecodeCaps); 336e5c31af7Sopenharmony_ci 337e5c31af7Sopenharmony_ci const VkParserInitDecodeParameters pdParams = { 338e5c31af7Sopenharmony_ci NV_VULKAN_VIDEO_PARSER_API_VERSION, 339e5c31af7Sopenharmony_ci dynamic_cast<VkParserVideoDecodeClient*>(decoder), 340e5c31af7Sopenharmony_ci static_cast<deUint32>(2 * 1024 * 1024), // 2MiB is the default bitstream buffer size 341e5c31af7Sopenharmony_ci static_cast<deUint32>(videoCaps.minBitstreamBufferOffsetAlignment), 342e5c31af7Sopenharmony_ci static_cast<deUint32>(videoCaps.minBitstreamBufferSizeAlignment), 343e5c31af7Sopenharmony_ci 0, 344e5c31af7Sopenharmony_ci 0, 345e5c31af7Sopenharmony_ci nullptr, 346e5c31af7Sopenharmony_ci true, 347e5c31af7Sopenharmony_ci }; 348e5c31af7Sopenharmony_ci 349e5c31af7Sopenharmony_ci if (videoLoggingEnabled()) 350e5c31af7Sopenharmony_ci { 351e5c31af7Sopenharmony_ci tcu::print("Creating a parser with offset alignment=%d and size alignment=%d\n", 352e5c31af7Sopenharmony_ci static_cast<deUint32>(videoCaps.minBitstreamBufferOffsetAlignment), 353e5c31af7Sopenharmony_ci static_cast<deUint32>(videoCaps.minBitstreamBufferSizeAlignment)); 354e5c31af7Sopenharmony_ci } 355e5c31af7Sopenharmony_ci 356e5c31af7Sopenharmony_ci const VkExtensionProperties* pStdExtensionVersion = params->extensionProperties(); 357e5c31af7Sopenharmony_ci DE_ASSERT(pStdExtensionVersion); 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci switch (params->getCodecOperation()) 360e5c31af7Sopenharmony_ci { 361e5c31af7Sopenharmony_ci case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: 362e5c31af7Sopenharmony_ci { 363e5c31af7Sopenharmony_ci if (strcmp(pStdExtensionVersion->extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME) || pStdExtensionVersion->specVersion != VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION) 364e5c31af7Sopenharmony_ci { 365e5c31af7Sopenharmony_ci tcu::die("The requested decoder h.264 Codec STD version is NOT supported. The supported decoder h.264 Codec STD version is version %d of %s\n", 366e5c31af7Sopenharmony_ci VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION, 367e5c31af7Sopenharmony_ci VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME); 368e5c31af7Sopenharmony_ci } 369e5c31af7Sopenharmony_ci VkSharedBaseObj<VulkanH264Decoder> nvVideoH264DecodeParser(new VulkanH264Decoder(params->getCodecOperation())); 370e5c31af7Sopenharmony_ci parser = nvVideoH264DecodeParser; 371e5c31af7Sopenharmony_ci break; 372e5c31af7Sopenharmony_ci } 373e5c31af7Sopenharmony_ci case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: 374e5c31af7Sopenharmony_ci { 375e5c31af7Sopenharmony_ci if (strcmp(pStdExtensionVersion->extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME) || pStdExtensionVersion->specVersion != VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION) 376e5c31af7Sopenharmony_ci { 377e5c31af7Sopenharmony_ci tcu::die("The requested decoder h.265 Codec STD version is NOT supported. The supported decoder h.265 Codec STD version is version %d of %s\n", 378e5c31af7Sopenharmony_ci VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION, 379e5c31af7Sopenharmony_ci VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME); 380e5c31af7Sopenharmony_ci } 381e5c31af7Sopenharmony_ci VkSharedBaseObj<VulkanH265Decoder> nvVideoH265DecodeParser(new VulkanH265Decoder(params->getCodecOperation())); 382e5c31af7Sopenharmony_ci parser = nvVideoH265DecodeParser; 383e5c31af7Sopenharmony_ci break; 384e5c31af7Sopenharmony_ci } 385e5c31af7Sopenharmony_ci default: 386e5c31af7Sopenharmony_ci TCU_FAIL("Unsupported codec type!"); 387e5c31af7Sopenharmony_ci } 388e5c31af7Sopenharmony_ci 389e5c31af7Sopenharmony_ci VK_CHECK(parser->Initialize(&pdParams)); 390e5c31af7Sopenharmony_ci} 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_cistatic MovePtr<VideoBaseDecoder> decoderFromTestDefinition(DeviceContext* devctx, const TestDefinition& test) 393e5c31af7Sopenharmony_ci{ 394e5c31af7Sopenharmony_ci VkSharedBaseObj<VulkanVideoFrameBuffer> vkVideoFrameBuffer; 395e5c31af7Sopenharmony_ci VK_CHECK(VulkanVideoFrameBuffer::Create(devctx, 396e5c31af7Sopenharmony_ci test.hasOption(DecoderOption::UseStatusQueries), 397e5c31af7Sopenharmony_ci vkVideoFrameBuffer)); 398e5c31af7Sopenharmony_ci 399e5c31af7Sopenharmony_ci VideoBaseDecoder::Parameters params; 400e5c31af7Sopenharmony_ci params.profile = test.getProfile(); 401e5c31af7Sopenharmony_ci params.context = devctx; 402e5c31af7Sopenharmony_ci params.framebuffer = vkVideoFrameBuffer; 403e5c31af7Sopenharmony_ci params.framesToCheck = test.framesToCheck(); 404e5c31af7Sopenharmony_ci params.queryDecodeStatus = test.hasOption(DecoderOption::UseStatusQueries); 405e5c31af7Sopenharmony_ci params.outOfOrderDecoding = test.hasOption(DecoderOption::CachedDecoding); 406e5c31af7Sopenharmony_ci params.alwaysRecreateDPB = test.hasOption(DecoderOption::RecreateDPBImages); 407e5c31af7Sopenharmony_ci params.pictureParameterUpdateTriggerHack = test.getParamaterUpdateHackRequirement(); 408e5c31af7Sopenharmony_ci 409e5c31af7Sopenharmony_ci return MovePtr<VideoBaseDecoder>(new VideoBaseDecoder(std::move(params))); 410e5c31af7Sopenharmony_ci} 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ciclass FrameProcessor 413e5c31af7Sopenharmony_ci{ 414e5c31af7Sopenharmony_cipublic: 415e5c31af7Sopenharmony_ci static const int DECODER_QUEUE_SIZE = 6; 416e5c31af7Sopenharmony_ci 417e5c31af7Sopenharmony_ci FrameProcessor(DeviceContext* devctx, const TestDefinition* params, VideoBaseDecoder* decoder, tcu::TestLog& log) 418e5c31af7Sopenharmony_ci : m_devctx(devctx) 419e5c31af7Sopenharmony_ci , m_demuxer(params->getClipFilename(), log) 420e5c31af7Sopenharmony_ci , m_decoder(decoder) 421e5c31af7Sopenharmony_ci , m_frameData(DECODER_QUEUE_SIZE) 422e5c31af7Sopenharmony_ci , m_frameDataIdx(0) 423e5c31af7Sopenharmony_ci { 424e5c31af7Sopenharmony_ci createParser(params, m_decoder, m_parser); 425e5c31af7Sopenharmony_ci for (auto& frame : m_frameData) 426e5c31af7Sopenharmony_ci frame.Reset(); 427e5c31af7Sopenharmony_ci } 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci void parseNextChunk() 430e5c31af7Sopenharmony_ci { 431e5c31af7Sopenharmony_ci deUint8* pData = 0; 432e5c31af7Sopenharmony_ci deInt64 size = 0; 433e5c31af7Sopenharmony_ci bool demuxerSuccess = m_demuxer.Demux(&pData, &size); 434e5c31af7Sopenharmony_ci 435e5c31af7Sopenharmony_ci VkParserBitstreamPacket pkt; 436e5c31af7Sopenharmony_ci pkt.pByteStream = pData; // Ptr to byte stream data decode/display event 437e5c31af7Sopenharmony_ci pkt.nDataLength = size; // Data length for this packet 438e5c31af7Sopenharmony_ci pkt.llPTS = 0; // Presentation Time Stamp for this packet (clock rate specified at initialization) 439e5c31af7Sopenharmony_ci pkt.bEOS = !demuxerSuccess; // true if this is an End-Of-Stream packet (flush everything) 440e5c31af7Sopenharmony_ci pkt.bPTSValid = false; // true if llPTS is valid (also used to detect frame boundaries for VC1 SP/MP) 441e5c31af7Sopenharmony_ci pkt.bDiscontinuity = false; // true if DecMFT is signalling a discontinuity 442e5c31af7Sopenharmony_ci pkt.bPartialParsing = 0; // 0: parse entire packet, 1: parse until next 443e5c31af7Sopenharmony_ci pkt.bEOP = false; // true if the packet in pByteStream is exactly one frame 444e5c31af7Sopenharmony_ci pkt.pbSideData = nullptr; // Auxiliary encryption information 445e5c31af7Sopenharmony_ci pkt.nSideDataLength = 0; // Auxiliary encrypton information length 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_ci size_t parsedBytes = 0; 448e5c31af7Sopenharmony_ci const bool parserSuccess = m_parser->ParseByteStream(&pkt, &parsedBytes); 449e5c31af7Sopenharmony_ci if (videoLoggingEnabled()) 450e5c31af7Sopenharmony_ci std::cout << "Parsed " << parsedBytes << " bytes from bitstream" << std::endl; 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci m_videoStreamHasEnded = !(demuxerSuccess && parserSuccess); 453e5c31af7Sopenharmony_ci } 454e5c31af7Sopenharmony_ci 455e5c31af7Sopenharmony_ci int getNextFrame(DecodedFrame* pFrame) 456e5c31af7Sopenharmony_ci { 457e5c31af7Sopenharmony_ci // The below call to DequeueDecodedPicture allows returning the next frame without parsing of the stream. 458e5c31af7Sopenharmony_ci // Parsing is only done when there are no more frames in the queue. 459e5c31af7Sopenharmony_ci int32_t framesInQueue = m_decoder->GetVideoFrameBuffer()->DequeueDecodedPicture(pFrame); 460e5c31af7Sopenharmony_ci 461e5c31af7Sopenharmony_ci // Loop until a frame (or more) is parsed and added to the queue. 462e5c31af7Sopenharmony_ci while ((framesInQueue == 0) && !m_videoStreamHasEnded) 463e5c31af7Sopenharmony_ci { 464e5c31af7Sopenharmony_ci parseNextChunk(); 465e5c31af7Sopenharmony_ci framesInQueue = m_decoder->GetVideoFrameBuffer()->DequeueDecodedPicture(pFrame); 466e5c31af7Sopenharmony_ci } 467e5c31af7Sopenharmony_ci 468e5c31af7Sopenharmony_ci if ((framesInQueue == 0) && m_videoStreamHasEnded) 469e5c31af7Sopenharmony_ci { 470e5c31af7Sopenharmony_ci return -1; 471e5c31af7Sopenharmony_ci } 472e5c31af7Sopenharmony_ci 473e5c31af7Sopenharmony_ci return framesInQueue; 474e5c31af7Sopenharmony_ci } 475e5c31af7Sopenharmony_ci 476e5c31af7Sopenharmony_ci const DecodedFrame* decodeFrame() 477e5c31af7Sopenharmony_ci { 478e5c31af7Sopenharmony_ci auto& vk = m_devctx->getDeviceDriver(); 479e5c31af7Sopenharmony_ci auto device = m_devctx->device; 480e5c31af7Sopenharmony_ci DecodedFrame* pLastDecodedFrame = &m_frameData[m_frameDataIdx]; 481e5c31af7Sopenharmony_ci 482e5c31af7Sopenharmony_ci // Make sure the frame complete fence signaled (video frame is processed) before returning the frame. 483e5c31af7Sopenharmony_ci if (pLastDecodedFrame->frameCompleteFence != VK_NULL_HANDLE) 484e5c31af7Sopenharmony_ci { 485e5c31af7Sopenharmony_ci VK_CHECK(vk.waitForFences(device, 1, &pLastDecodedFrame->frameCompleteFence, true, TIMEOUT_100ms)); 486e5c31af7Sopenharmony_ci VK_CHECK(vk.getFenceStatus(device, pLastDecodedFrame->frameCompleteFence)); 487e5c31af7Sopenharmony_ci } 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci m_decoder->ReleaseDisplayedFrame(pLastDecodedFrame); 490e5c31af7Sopenharmony_ci pLastDecodedFrame->Reset(); 491e5c31af7Sopenharmony_ci 492e5c31af7Sopenharmony_ci TCU_CHECK_MSG(getNextFrame(pLastDecodedFrame) > 0, "Unexpected decode result"); 493e5c31af7Sopenharmony_ci TCU_CHECK_MSG(pLastDecodedFrame, "Unexpected decode result"); 494e5c31af7Sopenharmony_ci 495e5c31af7Sopenharmony_ci if (videoLoggingEnabled()) 496e5c31af7Sopenharmony_ci std::cout << "<= Wait on picIdx: " << pLastDecodedFrame->pictureIndex 497e5c31af7Sopenharmony_ci << "\t\tdisplayWidth: " << pLastDecodedFrame->displayWidth 498e5c31af7Sopenharmony_ci << "\t\tdisplayHeight: " << pLastDecodedFrame->displayHeight 499e5c31af7Sopenharmony_ci << "\t\tdisplayOrder: " << pLastDecodedFrame->displayOrder 500e5c31af7Sopenharmony_ci << "\tdecodeOrder: " << pLastDecodedFrame->decodeOrder 501e5c31af7Sopenharmony_ci << "\ttimestamp " << pLastDecodedFrame->timestamp 502e5c31af7Sopenharmony_ci << "\tdstImageView " << (pLastDecodedFrame->outputImageView ? pLastDecodedFrame->outputImageView->GetImageResource()->GetImage() : VK_NULL_HANDLE) 503e5c31af7Sopenharmony_ci << std::endl; 504e5c31af7Sopenharmony_ci 505e5c31af7Sopenharmony_ci m_frameDataIdx = (m_frameDataIdx + 1) % m_frameData.size(); 506e5c31af7Sopenharmony_ci return pLastDecodedFrame; 507e5c31af7Sopenharmony_ci } 508e5c31af7Sopenharmony_ci 509e5c31af7Sopenharmony_ci void bufferFrames(int framesToDecode) 510e5c31af7Sopenharmony_ci { 511e5c31af7Sopenharmony_ci // This loop is for the out-of-order submissions cases. First all the frame information is gathered from the parser<->decoder loop 512e5c31af7Sopenharmony_ci // then the command buffers are recorded in a random order, as well as the queue submissions, depending on the configuration of 513e5c31af7Sopenharmony_ci // the test. 514e5c31af7Sopenharmony_ci // NOTE: For this sequence to work, the frame buffer must have enough decode surfaces for the GOP intended for decode, otherwise 515e5c31af7Sopenharmony_ci // picture allocation will fail pretty quickly! See m_numDecodeSurfaces, m_maxDecodeFramesCount 516e5c31af7Sopenharmony_ci // The previous CTS cases were not actually randomizing the queue submission order (despite claiming too!) 517e5c31af7Sopenharmony_ci DE_ASSERT(m_decoder->m_outOfOrderDecoding); 518e5c31af7Sopenharmony_ci do 519e5c31af7Sopenharmony_ci { 520e5c31af7Sopenharmony_ci parseNextChunk(); 521e5c31af7Sopenharmony_ci size_t decodedFrames = m_decoder->GetVideoFrameBuffer()->GetDisplayedFrameCount(); 522e5c31af7Sopenharmony_ci if (decodedFrames == framesToDecode) 523e5c31af7Sopenharmony_ci break; 524e5c31af7Sopenharmony_ci } 525e5c31af7Sopenharmony_ci while (!m_videoStreamHasEnded); 526e5c31af7Sopenharmony_ci DE_ASSERT(m_decoder->m_cachedDecodeParams.size() == framesToDecode); 527e5c31af7Sopenharmony_ci } 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci int getBufferedDisplayCount() const { return m_decoder->GetVideoFrameBuffer()->GetDisplayedFrameCount(); } 530e5c31af7Sopenharmony_ciprivate: 531e5c31af7Sopenharmony_ci DeviceContext* m_devctx; 532e5c31af7Sopenharmony_ci ESEDemuxer m_demuxer; 533e5c31af7Sopenharmony_ci VkVideoParser m_parser; 534e5c31af7Sopenharmony_ci VideoBaseDecoder* m_decoder; 535e5c31af7Sopenharmony_ci 536e5c31af7Sopenharmony_ci std::vector<DecodedFrame> m_frameData; 537e5c31af7Sopenharmony_ci size_t m_frameDataIdx{}; 538e5c31af7Sopenharmony_ci 539e5c31af7Sopenharmony_ci bool m_videoStreamHasEnded{false}; 540e5c31af7Sopenharmony_ci}; 541e5c31af7Sopenharmony_ci 542e5c31af7Sopenharmony_cide::MovePtr<vkt::ycbcr::MultiPlaneImageData> getDecodedImage(DeviceContext& devctx, 543e5c31af7Sopenharmony_ci VkImageLayout layout, 544e5c31af7Sopenharmony_ci const DecodedFrame* frame) 545e5c31af7Sopenharmony_ci{ 546e5c31af7Sopenharmony_ci auto& vkd = devctx.getDeviceDriver(); 547e5c31af7Sopenharmony_ci auto device = devctx.device; 548e5c31af7Sopenharmony_ci auto queueFamilyIndexDecode = devctx.decodeQueueFamilyIdx(); 549e5c31af7Sopenharmony_ci auto queueFamilyIndexTransfer = devctx.transferQueueFamilyIdx(); 550e5c31af7Sopenharmony_ci const VkExtent2D imageExtent{(deUint32)frame->displayWidth, (deUint32)frame->displayHeight}; 551e5c31af7Sopenharmony_ci const VkImage image = frame->outputImageView->GetImageResource()->GetImage(); 552e5c31af7Sopenharmony_ci const VkFormat format = frame->outputImageView->GetImageResource()->GetImageCreateInfo().format; 553e5c31af7Sopenharmony_ci const uint32_t videoImageLayerIndex = frame->imageLayerIndex; 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci MovePtr<vkt::ycbcr::MultiPlaneImageData> multiPlaneImageData(new vkt::ycbcr::MultiPlaneImageData(format, tcu::UVec2(imageExtent.width, imageExtent.height))); 556e5c31af7Sopenharmony_ci const VkQueue queueDecode = getDeviceQueue(vkd, device, queueFamilyIndexDecode, 0u); 557e5c31af7Sopenharmony_ci const VkQueue queueTransfer = getDeviceQueue(vkd, device, queueFamilyIndexTransfer, 0u); 558e5c31af7Sopenharmony_ci const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, videoImageLayerIndex, 1); 559e5c31af7Sopenharmony_ci const VkImageMemoryBarrier2KHR imageBarrierDecode = makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR, 560e5c31af7Sopenharmony_ci VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR, 561e5c31af7Sopenharmony_ci VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR, 562e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 563e5c31af7Sopenharmony_ci layout, 564e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 565e5c31af7Sopenharmony_ci image, 566e5c31af7Sopenharmony_ci imageSubresourceRange); 567e5c31af7Sopenharmony_ci const VkImageMemoryBarrier2KHR imageBarrierOwnershipDecode = makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR, 568e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 569e5c31af7Sopenharmony_ci VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 570e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 571e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 572e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 573e5c31af7Sopenharmony_ci image, 574e5c31af7Sopenharmony_ci imageSubresourceRange, 575e5c31af7Sopenharmony_ci queueFamilyIndexDecode, 576e5c31af7Sopenharmony_ci queueFamilyIndexTransfer); 577e5c31af7Sopenharmony_ci const VkImageMemoryBarrier2KHR imageBarrierOwnershipTransfer = makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 578e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 579e5c31af7Sopenharmony_ci VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, 580e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 581e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 582e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 583e5c31af7Sopenharmony_ci image, 584e5c31af7Sopenharmony_ci imageSubresourceRange, 585e5c31af7Sopenharmony_ci queueFamilyIndexDecode, 586e5c31af7Sopenharmony_ci queueFamilyIndexTransfer); 587e5c31af7Sopenharmony_ci const VkImageMemoryBarrier2KHR imageBarrierTransfer = makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, 588e5c31af7Sopenharmony_ci VK_ACCESS_2_TRANSFER_READ_BIT_KHR, 589e5c31af7Sopenharmony_ci VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR, 590e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 591e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_GENERAL, 592e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 593e5c31af7Sopenharmony_ci image, 594e5c31af7Sopenharmony_ci imageSubresourceRange); 595e5c31af7Sopenharmony_ci const Move<VkCommandPool> cmdDecodePool(makeCommandPool(vkd, device, queueFamilyIndexDecode)); 596e5c31af7Sopenharmony_ci const Move<VkCommandBuffer> cmdDecodeBuffer(allocateCommandBuffer(vkd, device, *cmdDecodePool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 597e5c31af7Sopenharmony_ci const Move<VkCommandPool> cmdTransferPool(makeCommandPool(vkd, device, queueFamilyIndexTransfer)); 598e5c31af7Sopenharmony_ci const Move<VkCommandBuffer> cmdTransferBuffer(allocateCommandBuffer(vkd, device, *cmdTransferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 599e5c31af7Sopenharmony_ci Move<VkSemaphore> semaphore = createSemaphore(vkd, device); 600e5c31af7Sopenharmony_ci Move<VkFence> decodeFence = createFence(vkd, device); 601e5c31af7Sopenharmony_ci Move<VkFence> transferFence = createFence(vkd, device); 602e5c31af7Sopenharmony_ci VkFence fences[] = {*decodeFence, *transferFence}; 603e5c31af7Sopenharmony_ci const VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 604e5c31af7Sopenharmony_ci VkSubmitInfo decodeSubmitInfo{ 605e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 606e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 607e5c31af7Sopenharmony_ci 0u, // deUint32 waitSemaphoreCount; 608e5c31af7Sopenharmony_ci DE_NULL, // const VkSemaphore* pWaitSemaphores; 609e5c31af7Sopenharmony_ci DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; 610e5c31af7Sopenharmony_ci 1u, // deUint32 commandBufferCount; 611e5c31af7Sopenharmony_ci &*cmdDecodeBuffer, // const VkCommandBuffer* pCommandBuffers; 612e5c31af7Sopenharmony_ci 1u, // deUint32 signalSemaphoreCount; 613e5c31af7Sopenharmony_ci &*semaphore, // const VkSemaphore* pSignalSemaphores; 614e5c31af7Sopenharmony_ci }; 615e5c31af7Sopenharmony_ci if (frame->frameCompleteSemaphore != VK_NULL_HANDLE) 616e5c31af7Sopenharmony_ci { 617e5c31af7Sopenharmony_ci decodeSubmitInfo.waitSemaphoreCount = 1; 618e5c31af7Sopenharmony_ci decodeSubmitInfo.pWaitSemaphores = &frame->frameCompleteSemaphore; 619e5c31af7Sopenharmony_ci decodeSubmitInfo.pWaitDstStageMask = &waitDstStageMask; 620e5c31af7Sopenharmony_ci } 621e5c31af7Sopenharmony_ci const VkSubmitInfo transferSubmitInfo{ 622e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 623e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 624e5c31af7Sopenharmony_ci 1u, // deUint32 waitSemaphoreCount; 625e5c31af7Sopenharmony_ci &*semaphore, // const VkSemaphore* pWaitSemaphores; 626e5c31af7Sopenharmony_ci &waitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask; 627e5c31af7Sopenharmony_ci 1u, // deUint32 commandBufferCount; 628e5c31af7Sopenharmony_ci &*cmdTransferBuffer, // const VkCommandBuffer* pCommandBuffers; 629e5c31af7Sopenharmony_ci 0u, // deUint32 signalSemaphoreCount; 630e5c31af7Sopenharmony_ci DE_NULL, // const VkSemaphore* pSignalSemaphores; 631e5c31af7Sopenharmony_ci }; 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci DEBUGLOG(std::cout << "getDecodedImage: " << image << " " << layout << std::endl); 634e5c31af7Sopenharmony_ci 635e5c31af7Sopenharmony_ci beginCommandBuffer(vkd, *cmdDecodeBuffer, 0u); 636e5c31af7Sopenharmony_ci cmdPipelineImageMemoryBarrier2(vkd, *cmdDecodeBuffer, &imageBarrierDecode); 637e5c31af7Sopenharmony_ci cmdPipelineImageMemoryBarrier2(vkd, *cmdDecodeBuffer, &imageBarrierOwnershipDecode); 638e5c31af7Sopenharmony_ci endCommandBuffer(vkd, *cmdDecodeBuffer); 639e5c31af7Sopenharmony_ci 640e5c31af7Sopenharmony_ci beginCommandBuffer(vkd, *cmdTransferBuffer, 0u); 641e5c31af7Sopenharmony_ci cmdPipelineImageMemoryBarrier2(vkd, *cmdTransferBuffer, &imageBarrierOwnershipTransfer); 642e5c31af7Sopenharmony_ci cmdPipelineImageMemoryBarrier2(vkd, *cmdTransferBuffer, &imageBarrierTransfer); 643e5c31af7Sopenharmony_ci endCommandBuffer(vkd, *cmdTransferBuffer); 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci VK_CHECK(vkd.queueSubmit(queueDecode, 1u, &decodeSubmitInfo, *decodeFence)); 646e5c31af7Sopenharmony_ci VK_CHECK(vkd.queueSubmit(queueTransfer, 1u, &transferSubmitInfo, *transferFence)); 647e5c31af7Sopenharmony_ci 648e5c31af7Sopenharmony_ci VK_CHECK(vkd.waitForFences(device, DE_LENGTH_OF_ARRAY(fences), fences, DE_TRUE, ~0ull)); 649e5c31af7Sopenharmony_ci 650e5c31af7Sopenharmony_ci vkt::ycbcr::downloadImage(vkd, device, queueFamilyIndexTransfer, devctx.allocator(), image, 651e5c31af7Sopenharmony_ci multiPlaneImageData.get(), 0, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 652e5c31af7Sopenharmony_ci videoImageLayerIndex); 653e5c31af7Sopenharmony_ci 654e5c31af7Sopenharmony_ci const VkImageMemoryBarrier2KHR imageBarrierTransfer2 = makeImageMemoryBarrier2(VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, 655e5c31af7Sopenharmony_ci VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR, 656e5c31af7Sopenharmony_ci VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR, 657e5c31af7Sopenharmony_ci VK_ACCESS_NONE_KHR, 658e5c31af7Sopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 659e5c31af7Sopenharmony_ci layout, 660e5c31af7Sopenharmony_ci image, 661e5c31af7Sopenharmony_ci imageSubresourceRange); 662e5c31af7Sopenharmony_ci 663e5c31af7Sopenharmony_ci vkd.resetCommandBuffer(*cmdTransferBuffer, 0u); 664e5c31af7Sopenharmony_ci vkd.resetFences(device, 1, &*transferFence); 665e5c31af7Sopenharmony_ci beginCommandBuffer(vkd, *cmdTransferBuffer, 0u); 666e5c31af7Sopenharmony_ci cmdPipelineImageMemoryBarrier2(vkd, *cmdTransferBuffer, &imageBarrierTransfer2); 667e5c31af7Sopenharmony_ci endCommandBuffer(vkd, *cmdTransferBuffer); 668e5c31af7Sopenharmony_ci 669e5c31af7Sopenharmony_ci const VkSubmitInfo transferSubmitInfo2{ 670e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 671e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 672e5c31af7Sopenharmony_ci 0u, // deUint32 waitSemaphoreCount; 673e5c31af7Sopenharmony_ci DE_NULL, // const VkSemaphore* pWaitSemaphores; 674e5c31af7Sopenharmony_ci DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; 675e5c31af7Sopenharmony_ci 1u, // deUint32 commandBufferCount; 676e5c31af7Sopenharmony_ci &*cmdTransferBuffer, // const VkCommandBuffer* pCommandBuffers; 677e5c31af7Sopenharmony_ci 0u, // deUint32 signalSemaphoreCount; 678e5c31af7Sopenharmony_ci DE_NULL, // const VkSemaphore* pSignalSemaphores; 679e5c31af7Sopenharmony_ci }; 680e5c31af7Sopenharmony_ci 681e5c31af7Sopenharmony_ci VK_CHECK(vkd.queueSubmit(queueTransfer, 1u, &transferSubmitInfo2, *transferFence)); 682e5c31af7Sopenharmony_ci VK_CHECK(vkd.waitForFences(device, 1, &*transferFence, DE_TRUE, ~0ull)); 683e5c31af7Sopenharmony_ci 684e5c31af7Sopenharmony_ci return multiPlaneImageData; 685e5c31af7Sopenharmony_ci} 686e5c31af7Sopenharmony_ci 687e5c31af7Sopenharmony_ci 688e5c31af7Sopenharmony_ciclass VideoDecodeTestInstance : public VideoBaseTestInstance 689e5c31af7Sopenharmony_ci{ 690e5c31af7Sopenharmony_cipublic: 691e5c31af7Sopenharmony_ci VideoDecodeTestInstance(Context& context, const TestDefinition* testDefinition); 692e5c31af7Sopenharmony_ci tcu::TestStatus iterate(void); 693e5c31af7Sopenharmony_ci 694e5c31af7Sopenharmony_ciprotected: 695e5c31af7Sopenharmony_ci const TestDefinition* m_testDefinition; 696e5c31af7Sopenharmony_ci MovePtr<VideoBaseDecoder> m_decoder{}; 697e5c31af7Sopenharmony_ci static_assert(sizeof(DeviceContext) < 128, "DeviceContext has grown bigger than expected!"); 698e5c31af7Sopenharmony_ci DeviceContext m_deviceContext; 699e5c31af7Sopenharmony_ci}; 700e5c31af7Sopenharmony_ci 701e5c31af7Sopenharmony_ciclass InterleavingDecodeTestInstance : public VideoBaseTestInstance 702e5c31af7Sopenharmony_ci{ 703e5c31af7Sopenharmony_cipublic: 704e5c31af7Sopenharmony_ci InterleavingDecodeTestInstance(Context& context, const std::vector<MovePtr<TestDefinition>>& testDefinitions); 705e5c31af7Sopenharmony_ci tcu::TestStatus iterate(void); 706e5c31af7Sopenharmony_ci 707e5c31af7Sopenharmony_ciprotected: 708e5c31af7Sopenharmony_ci const std::vector<MovePtr<TestDefinition>>& m_testDefinitions; 709e5c31af7Sopenharmony_ci std::vector<MovePtr<VideoBaseDecoder>> m_decoders{}; 710e5c31af7Sopenharmony_ci static_assert(sizeof(DeviceContext) < 128, "DeviceContext has grown bigger than expected!"); 711e5c31af7Sopenharmony_ci DeviceContext m_deviceContext; 712e5c31af7Sopenharmony_ci}; 713e5c31af7Sopenharmony_ci 714e5c31af7Sopenharmony_ciInterleavingDecodeTestInstance::InterleavingDecodeTestInstance(Context& context, const std::vector<MovePtr<TestDefinition>>& testDefinitions) 715e5c31af7Sopenharmony_ci : VideoBaseTestInstance(context), m_testDefinitions(std::move(testDefinitions)) 716e5c31af7Sopenharmony_ci{ 717e5c31af7Sopenharmony_ci int requiredCodecs = VK_VIDEO_CODEC_OPERATION_NONE_KHR; 718e5c31af7Sopenharmony_ci VideoDevice::VideoDeviceFlags requiredDeviceFlags = VideoDevice::VideoDeviceFlagBits::VIDEO_DEVICE_FLAG_NONE; 719e5c31af7Sopenharmony_ci for (const auto& test : m_testDefinitions) 720e5c31af7Sopenharmony_ci { 721e5c31af7Sopenharmony_ci VkVideoCodecOperationFlagBitsKHR testBits = test->getCodecOperation(); 722e5c31af7Sopenharmony_ci requiredCodecs |= testBits; 723e5c31af7Sopenharmony_ci requiredDeviceFlags |= test->requiredDeviceFlags(); 724e5c31af7Sopenharmony_ci } 725e5c31af7Sopenharmony_ci VkDevice device = getDeviceSupportingQueue(VK_QUEUE_VIDEO_DECODE_BIT_KHR | VK_QUEUE_TRANSFER_BIT, requiredCodecs, requiredDeviceFlags); 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci m_deviceContext.context = &m_context; 728e5c31af7Sopenharmony_ci m_deviceContext.device = device; 729e5c31af7Sopenharmony_ci m_deviceContext.phys = m_context.getPhysicalDevice(); 730e5c31af7Sopenharmony_ci m_deviceContext.vd = &m_videoDevice; 731e5c31af7Sopenharmony_ci // TODO: Support for multiple queues / multithreading 732e5c31af7Sopenharmony_ci m_deviceContext.transferQueue = 733e5c31af7Sopenharmony_ci getDeviceQueue(m_context.getDeviceInterface(), device, m_videoDevice.getQueueFamilyIndexTransfer(), 0); 734e5c31af7Sopenharmony_ci m_deviceContext.decodeQueue = 735e5c31af7Sopenharmony_ci getDeviceQueue(m_context.getDeviceInterface(), device, m_videoDevice.getQueueFamilyIndexDecode(), 0); 736e5c31af7Sopenharmony_ci 737e5c31af7Sopenharmony_ci for (const auto& test : m_testDefinitions) 738e5c31af7Sopenharmony_ci m_decoders.push_back(decoderFromTestDefinition(&m_deviceContext, *test)); 739e5c31af7Sopenharmony_ci} 740e5c31af7Sopenharmony_ci 741e5c31af7Sopenharmony_ciVideoDecodeTestInstance::VideoDecodeTestInstance(Context& context, const TestDefinition* testDefinition) 742e5c31af7Sopenharmony_ci : VideoBaseTestInstance(context), m_testDefinition(testDefinition) 743e5c31af7Sopenharmony_ci{ 744e5c31af7Sopenharmony_ci VkDevice device = getDeviceSupportingQueue(VK_QUEUE_VIDEO_DECODE_BIT_KHR | VK_QUEUE_TRANSFER_BIT, 745e5c31af7Sopenharmony_ci m_testDefinition->getCodecOperation(), 746e5c31af7Sopenharmony_ci m_testDefinition->requiredDeviceFlags()); 747e5c31af7Sopenharmony_ci 748e5c31af7Sopenharmony_ci m_deviceContext.context = &m_context; 749e5c31af7Sopenharmony_ci m_deviceContext.device = device; 750e5c31af7Sopenharmony_ci m_deviceContext.phys = m_context.getPhysicalDevice(); 751e5c31af7Sopenharmony_ci m_deviceContext.vd = &m_videoDevice; 752e5c31af7Sopenharmony_ci // TODO: Support for multiple queues / multithreading 753e5c31af7Sopenharmony_ci m_deviceContext.transferQueue = 754e5c31af7Sopenharmony_ci getDeviceQueue(m_context.getDeviceInterface(), device, m_videoDevice.getQueueFamilyIndexTransfer(), 0); 755e5c31af7Sopenharmony_ci m_deviceContext.decodeQueue = 756e5c31af7Sopenharmony_ci getDeviceQueue(m_context.getDeviceInterface(), device, m_videoDevice.getQueueFamilyIndexDecode(), 0); 757e5c31af7Sopenharmony_ci 758e5c31af7Sopenharmony_ci m_decoder = decoderFromTestDefinition(&m_deviceContext, *m_testDefinition); 759e5c31af7Sopenharmony_ci} 760e5c31af7Sopenharmony_ci 761e5c31af7Sopenharmony_citcu::TestStatus VideoDecodeTestInstance::iterate() 762e5c31af7Sopenharmony_ci{ 763e5c31af7Sopenharmony_ci#if FRAME_DUMP_DEBUG 764e5c31af7Sopenharmony_ci#ifdef _WIN32 765e5c31af7Sopenharmony_ci FILE* output = fopen("C:\\output.yuv", "wb"); 766e5c31af7Sopenharmony_ci#else 767e5c31af7Sopenharmony_ci FILE* output = fopen("/tmp/output.yuv", "wb"); 768e5c31af7Sopenharmony_ci#endif 769e5c31af7Sopenharmony_ci#endif 770e5c31af7Sopenharmony_ci 771e5c31af7Sopenharmony_ci FrameProcessor processor(&m_deviceContext, m_testDefinition, m_decoder.get(), m_context.getTestContext().getLog()); 772e5c31af7Sopenharmony_ci std::vector<int> incorrectFrames; 773e5c31af7Sopenharmony_ci std::vector<int> correctFrames; 774e5c31af7Sopenharmony_ci 775e5c31af7Sopenharmony_ci if (m_testDefinition->hasOption(DecoderOption::CachedDecoding)) 776e5c31af7Sopenharmony_ci { 777e5c31af7Sopenharmony_ci processor.bufferFrames(m_testDefinition->framesToCheck()); 778e5c31af7Sopenharmony_ci m_decoder->decodeFramesOutOfOrder(); 779e5c31af7Sopenharmony_ci } 780e5c31af7Sopenharmony_ci 781e5c31af7Sopenharmony_ci for (int frameNumber = 0; frameNumber < m_testDefinition->framesToCheck(); frameNumber++) 782e5c31af7Sopenharmony_ci { 783e5c31af7Sopenharmony_ci const DecodedFrame* decodedFrame = processor.decodeFrame(); 784e5c31af7Sopenharmony_ci TCU_CHECK_MSG(decodedFrame, "Decoder did not produce the expected amount of frames"); 785e5c31af7Sopenharmony_ci auto resultImage = getDecodedImage(m_deviceContext, m_decoder->dpbAndOutputCoincide() ? VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR : VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, decodedFrame); 786e5c31af7Sopenharmony_ci 787e5c31af7Sopenharmony_ci#if FRAME_DUMP_DEBUG 788e5c31af7Sopenharmony_ci auto bytes = semiplanarToYV12(*resultImage); 789e5c31af7Sopenharmony_ci fwrite(bytes.data(), 1, bytes.size(), output); 790e5c31af7Sopenharmony_ci#endif 791e5c31af7Sopenharmony_ci std::string checksum = checksumForClipFrame(m_testDefinition->getClipInfo(), frameNumber); 792e5c31af7Sopenharmony_ci if (imageMatchesReferenceChecksum(*resultImage, checksum)) 793e5c31af7Sopenharmony_ci { 794e5c31af7Sopenharmony_ci correctFrames.push_back(frameNumber); 795e5c31af7Sopenharmony_ci } 796e5c31af7Sopenharmony_ci else 797e5c31af7Sopenharmony_ci { 798e5c31af7Sopenharmony_ci incorrectFrames.push_back(frameNumber); 799e5c31af7Sopenharmony_ci } 800e5c31af7Sopenharmony_ci } 801e5c31af7Sopenharmony_ci 802e5c31af7Sopenharmony_ci#if FRAME_DUMP_DEBUG 803e5c31af7Sopenharmony_ci fclose(output); 804e5c31af7Sopenharmony_ci#endif 805e5c31af7Sopenharmony_ci if (!correctFrames.empty() && correctFrames.size() == m_testDefinition->framesToCheck()) 806e5c31af7Sopenharmony_ci return tcu::TestStatus::pass(de::toString(m_testDefinition->framesToCheck()) + " correctly decoded frames"); 807e5c31af7Sopenharmony_ci else 808e5c31af7Sopenharmony_ci { 809e5c31af7Sopenharmony_ci stringstream ss; 810e5c31af7Sopenharmony_ci ss << correctFrames.size() << " out of " << m_testDefinition->framesToCheck() << " frames rendered correctly ("; 811e5c31af7Sopenharmony_ci if (correctFrames.size() < incorrectFrames.size()) 812e5c31af7Sopenharmony_ci { 813e5c31af7Sopenharmony_ci ss << "correct frames: "; 814e5c31af7Sopenharmony_ci for (int i : correctFrames) 815e5c31af7Sopenharmony_ci ss << i << " "; 816e5c31af7Sopenharmony_ci } 817e5c31af7Sopenharmony_ci else 818e5c31af7Sopenharmony_ci { 819e5c31af7Sopenharmony_ci ss << "incorrect frames: "; 820e5c31af7Sopenharmony_ci for (int i : incorrectFrames) 821e5c31af7Sopenharmony_ci ss << i << " "; 822e5c31af7Sopenharmony_ci } 823e5c31af7Sopenharmony_ci ss << "\b)"; 824e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(ss.str()); 825e5c31af7Sopenharmony_ci } 826e5c31af7Sopenharmony_ci} 827e5c31af7Sopenharmony_ci 828e5c31af7Sopenharmony_citcu::TestStatus InterleavingDecodeTestInstance::iterate(void) 829e5c31af7Sopenharmony_ci{ 830e5c31af7Sopenharmony_ci DE_ASSERT(m_testDefinitions.size() == m_decoders.size()); 831e5c31af7Sopenharmony_ci DE_ASSERT(m_decoders.size() > 1); 832e5c31af7Sopenharmony_ci 833e5c31af7Sopenharmony_ci std::vector<MovePtr<FrameProcessor>> processors; 834e5c31af7Sopenharmony_ci for (int i = 0; i < m_testDefinitions.size(); i++) 835e5c31af7Sopenharmony_ci { 836e5c31af7Sopenharmony_ci processors.push_back(MovePtr<FrameProcessor>(new FrameProcessor(&m_deviceContext, m_testDefinitions[i].get(), m_decoders[i].get(), m_context.getTestContext().getLog()))); 837e5c31af7Sopenharmony_ci } 838e5c31af7Sopenharmony_ci 839e5c31af7Sopenharmony_ci#if FRAME_DUMP_DEBUG 840e5c31af7Sopenharmony_ci#ifdef _WIN32 841e5c31af7Sopenharmony_ci FILE* output = fopen("C:\\output.yuv", "wb"); 842e5c31af7Sopenharmony_ci#else 843e5c31af7Sopenharmony_ci FILE* output = fopen("/tmp/output.yuv", "wb"); 844e5c31af7Sopenharmony_ci#endif 845e5c31af7Sopenharmony_ci#endif 846e5c31af7Sopenharmony_ci 847e5c31af7Sopenharmony_ci // First cache up all the decoded frames from the various decode sessions 848e5c31af7Sopenharmony_ci for (int i = 0; i < m_testDefinitions.size(); i++) 849e5c31af7Sopenharmony_ci { 850e5c31af7Sopenharmony_ci const auto& test = m_testDefinitions[i]; 851e5c31af7Sopenharmony_ci auto& processor = processors[i]; 852e5c31af7Sopenharmony_ci processor->bufferFrames(test->framesToCheck()); 853e5c31af7Sopenharmony_ci DE_ASSERT(processor->getBufferedDisplayCount() == test->framesToCheck()); 854e5c31af7Sopenharmony_ci } 855e5c31af7Sopenharmony_ci 856e5c31af7Sopenharmony_ci auto interleaveCacheSize = m_decoders[0]->m_cachedDecodeParams.size(); 857e5c31af7Sopenharmony_ci auto firstStreamDecodeQueue = m_decoders[0]->m_deviceContext->decodeQueue; 858e5c31af7Sopenharmony_ci 859e5c31af7Sopenharmony_ci size_t totalFrames = 0; 860e5c31af7Sopenharmony_ci for (auto& decoder : m_decoders) 861e5c31af7Sopenharmony_ci { 862e5c31af7Sopenharmony_ci DE_ASSERT(decoder->m_cachedDecodeParams.size() == interleaveCacheSize); 863e5c31af7Sopenharmony_ci DE_ASSERT(decoder->m_deviceContext->decodeQueue == firstStreamDecodeQueue); 864e5c31af7Sopenharmony_ci totalFrames += decoder->m_cachedDecodeParams.size(); 865e5c31af7Sopenharmony_ci } 866e5c31af7Sopenharmony_ci 867e5c31af7Sopenharmony_ci DE_UNREF(firstStreamDecodeQueue); 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_ci // Interleave command buffer recording 870e5c31af7Sopenharmony_ci for (int i = 0; i < interleaveCacheSize; i++) 871e5c31af7Sopenharmony_ci { 872e5c31af7Sopenharmony_ci for (auto& decoder : m_decoders) 873e5c31af7Sopenharmony_ci { 874e5c31af7Sopenharmony_ci decoder->WaitForFrameFences(decoder->m_cachedDecodeParams[i]); 875e5c31af7Sopenharmony_ci decoder->ApplyPictureParameters(decoder->m_cachedDecodeParams[i]); 876e5c31af7Sopenharmony_ci decoder->RecordCommandBuffer(decoder->m_cachedDecodeParams[i]); 877e5c31af7Sopenharmony_ci } 878e5c31af7Sopenharmony_ci } 879e5c31af7Sopenharmony_ci 880e5c31af7Sopenharmony_ci // Interleave submissions 881e5c31af7Sopenharmony_ci for (int i = 0; i < interleaveCacheSize; i++) 882e5c31af7Sopenharmony_ci { 883e5c31af7Sopenharmony_ci for (int decoderIdx = 0; decoderIdx < m_decoders.size(); decoderIdx++) 884e5c31af7Sopenharmony_ci { 885e5c31af7Sopenharmony_ci auto& decoder = m_decoders[decoderIdx]; 886e5c31af7Sopenharmony_ci auto& test = m_testDefinitions[decoderIdx]; 887e5c31af7Sopenharmony_ci decoder->SubmitQueue(decoder->m_cachedDecodeParams[i]); 888e5c31af7Sopenharmony_ci if (test->hasOption(DecoderOption::UseStatusQueries)) 889e5c31af7Sopenharmony_ci { 890e5c31af7Sopenharmony_ci decoder->QueryDecodeResults(decoder->m_cachedDecodeParams[i]); 891e5c31af7Sopenharmony_ci } 892e5c31af7Sopenharmony_ci } 893e5c31af7Sopenharmony_ci } 894e5c31af7Sopenharmony_ci 895e5c31af7Sopenharmony_ci struct InterleavedDecodeResults 896e5c31af7Sopenharmony_ci { 897e5c31af7Sopenharmony_ci std::vector<int> correctFrames; 898e5c31af7Sopenharmony_ci std::vector<int> incorrectFrames; 899e5c31af7Sopenharmony_ci }; 900e5c31af7Sopenharmony_ci std::vector<InterleavedDecodeResults> results(m_testDefinitions.size()); 901e5c31af7Sopenharmony_ci 902e5c31af7Sopenharmony_ci for (int i = 0; i < m_testDefinitions.size(); i++) 903e5c31af7Sopenharmony_ci { 904e5c31af7Sopenharmony_ci auto& test = m_testDefinitions[i]; 905e5c31af7Sopenharmony_ci auto& decoder = m_decoders[i]; 906e5c31af7Sopenharmony_ci auto& processor = processors[i]; 907e5c31af7Sopenharmony_ci for (int frameNumber = 0; frameNumber < m_testDefinitions[i]->framesToCheck(); frameNumber++) 908e5c31af7Sopenharmony_ci { 909e5c31af7Sopenharmony_ci const DecodedFrame* frame = processor->decodeFrame(); 910e5c31af7Sopenharmony_ci auto resultImage = getDecodedImage(m_deviceContext, decoder->dpbAndOutputCoincide() ? VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR : VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, frame); 911e5c31af7Sopenharmony_ci#if FRAME_DUMP_DEBUG 912e5c31af7Sopenharmony_ci auto bytes = semiplanarToYV12(*resultImage); 913e5c31af7Sopenharmony_ci fwrite(bytes.data(), 1, bytes.size(), output); 914e5c31af7Sopenharmony_ci#endif 915e5c31af7Sopenharmony_ci auto checksum = checksumForClipFrame(test->getClipInfo(), frameNumber); 916e5c31af7Sopenharmony_ci if (imageMatchesReferenceChecksum(*resultImage, checksum)) 917e5c31af7Sopenharmony_ci { 918e5c31af7Sopenharmony_ci results[i].correctFrames.push_back(frameNumber); 919e5c31af7Sopenharmony_ci } 920e5c31af7Sopenharmony_ci else 921e5c31af7Sopenharmony_ci { 922e5c31af7Sopenharmony_ci results[i].incorrectFrames.push_back(frameNumber); 923e5c31af7Sopenharmony_ci } 924e5c31af7Sopenharmony_ci } 925e5c31af7Sopenharmony_ci } 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ci#if FRAME_DUMP_DEBUG 928e5c31af7Sopenharmony_ci fclose(output); 929e5c31af7Sopenharmony_ci#endif 930e5c31af7Sopenharmony_ci 931e5c31af7Sopenharmony_ci bool allTestsPassed = true; 932e5c31af7Sopenharmony_ci int totalFramesCheck = 0; 933e5c31af7Sopenharmony_ci for (const auto& res : results) 934e5c31af7Sopenharmony_ci { 935e5c31af7Sopenharmony_ci if (!res.incorrectFrames.empty()) 936e5c31af7Sopenharmony_ci allTestsPassed = false; 937e5c31af7Sopenharmony_ci totalFramesCheck += (res.correctFrames.size() + res.incorrectFrames.size()); 938e5c31af7Sopenharmony_ci } 939e5c31af7Sopenharmony_ci DE_ASSERT(totalFramesCheck == totalFrames); 940e5c31af7Sopenharmony_ci 941e5c31af7Sopenharmony_ci if (allTestsPassed) 942e5c31af7Sopenharmony_ci return tcu::TestStatus::pass(de::toString(totalFrames) + " correctly decoded frames"); 943e5c31af7Sopenharmony_ci else 944e5c31af7Sopenharmony_ci { 945e5c31af7Sopenharmony_ci stringstream ss; 946e5c31af7Sopenharmony_ci ss << "Interleaving failure: "; 947e5c31af7Sopenharmony_ci for (int i = 0; i < results.size(); i++) 948e5c31af7Sopenharmony_ci { 949e5c31af7Sopenharmony_ci const auto& result = results[i]; 950e5c31af7Sopenharmony_ci if (!result.incorrectFrames.empty()) 951e5c31af7Sopenharmony_ci { 952e5c31af7Sopenharmony_ci ss << " (stream #" << i << " incorrect frames: "; 953e5c31af7Sopenharmony_ci for (int frame : result.incorrectFrames) 954e5c31af7Sopenharmony_ci ss << frame << " "; 955e5c31af7Sopenharmony_ci ss << "\b)"; 956e5c31af7Sopenharmony_ci } 957e5c31af7Sopenharmony_ci } 958e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(ss.str()); 959e5c31af7Sopenharmony_ci } 960e5c31af7Sopenharmony_ci} 961e5c31af7Sopenharmony_ci 962e5c31af7Sopenharmony_ci#endif // #ifdef DE_BUILD_VIDEO 963e5c31af7Sopenharmony_ci 964e5c31af7Sopenharmony_ciclass VideoDecodeTestCase : public vkt::TestCase 965e5c31af7Sopenharmony_ci{ 966e5c31af7Sopenharmony_cipublic: 967e5c31af7Sopenharmony_ci VideoDecodeTestCase(tcu::TestContext& context, const char* name, MovePtr<TestDefinition> testDefinition) 968e5c31af7Sopenharmony_ci : vkt::TestCase(context, name), m_testDefinition(testDefinition) 969e5c31af7Sopenharmony_ci { 970e5c31af7Sopenharmony_ci } 971e5c31af7Sopenharmony_ci 972e5c31af7Sopenharmony_ci TestInstance* createInstance(Context& context) const override; 973e5c31af7Sopenharmony_ci void checkSupport(Context& context) const override; 974e5c31af7Sopenharmony_ci 975e5c31af7Sopenharmony_ciprivate: 976e5c31af7Sopenharmony_ci MovePtr<TestDefinition> m_testDefinition; 977e5c31af7Sopenharmony_ci}; 978e5c31af7Sopenharmony_ci 979e5c31af7Sopenharmony_ciclass InterleavingDecodeTestCase : public vkt::TestCase 980e5c31af7Sopenharmony_ci{ 981e5c31af7Sopenharmony_cipublic: 982e5c31af7Sopenharmony_ci InterleavingDecodeTestCase(tcu::TestContext& context, const char* name, std::vector<MovePtr<TestDefinition>>&& testDefinitions) 983e5c31af7Sopenharmony_ci : vkt::TestCase(context, name), m_testDefinitions(std::move(testDefinitions)) 984e5c31af7Sopenharmony_ci { 985e5c31af7Sopenharmony_ci } 986e5c31af7Sopenharmony_ci 987e5c31af7Sopenharmony_ci TestInstance* createInstance(Context& context) const override 988e5c31af7Sopenharmony_ci { 989e5c31af7Sopenharmony_ci#ifdef DE_BUILD_VIDEO 990e5c31af7Sopenharmony_ci return new InterleavingDecodeTestInstance(context, m_testDefinitions); 991e5c31af7Sopenharmony_ci#endif 992e5c31af7Sopenharmony_ci DE_UNREF(context); 993e5c31af7Sopenharmony_ci return nullptr; 994e5c31af7Sopenharmony_ci } 995e5c31af7Sopenharmony_ci void checkSupport(Context& context) const override; 996e5c31af7Sopenharmony_ci 997e5c31af7Sopenharmony_ciprivate: 998e5c31af7Sopenharmony_ci std::vector<MovePtr<TestDefinition>> m_testDefinitions; 999e5c31af7Sopenharmony_ci}; 1000e5c31af7Sopenharmony_ci 1001e5c31af7Sopenharmony_ciTestInstance* VideoDecodeTestCase::createInstance(Context& context) const 1002e5c31af7Sopenharmony_ci{ 1003e5c31af7Sopenharmony_ci#ifdef DE_BUILD_VIDEO 1004e5c31af7Sopenharmony_ci return new VideoDecodeTestInstance(context, m_testDefinition.get()); 1005e5c31af7Sopenharmony_ci#endif 1006e5c31af7Sopenharmony_ci 1007e5c31af7Sopenharmony_ci#ifndef DE_BUILD_VIDEO 1008e5c31af7Sopenharmony_ci DE_UNREF(context); 1009e5c31af7Sopenharmony_ci return nullptr; 1010e5c31af7Sopenharmony_ci#endif 1011e5c31af7Sopenharmony_ci} 1012e5c31af7Sopenharmony_ci 1013e5c31af7Sopenharmony_civoid VideoDecodeTestCase::checkSupport(Context& context) const 1014e5c31af7Sopenharmony_ci{ 1015e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_queue"); 1016e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_synchronization2"); 1017e5c31af7Sopenharmony_ci 1018e5c31af7Sopenharmony_ci switch (m_testDefinition->getTestType()) 1019e5c31af7Sopenharmony_ci { 1020e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I: 1021e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P: 1022e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_CLIP_A: 1023e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P_NOT_MATCHING_ORDER: 1024e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P_B_13: 1025e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_I_P_B_13_NOT_MATCHING_ORDER: 1026e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_QUERY_RESULT_WITH_STATUS: 1027e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE: 1028e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_RESOLUTION_CHANGE_DPB: 1029e5c31af7Sopenharmony_ci { 1030e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_decode_h264"); 1031e5c31af7Sopenharmony_ci break; 1032e5c31af7Sopenharmony_ci } 1033e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I: 1034e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P: 1035e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_CLIP_D: 1036e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P_NOT_MATCHING_ORDER: 1037e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P_B_13: 1038e5c31af7Sopenharmony_ci case TEST_TYPE_H265_DECODE_I_P_B_13_NOT_MATCHING_ORDER: 1039e5c31af7Sopenharmony_ci { 1040e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_decode_h265"); 1041e5c31af7Sopenharmony_ci break; 1042e5c31af7Sopenharmony_ci } 1043e5c31af7Sopenharmony_ci default: 1044e5c31af7Sopenharmony_ci TCU_THROW(InternalError, "Unknown TestType"); 1045e5c31af7Sopenharmony_ci } 1046e5c31af7Sopenharmony_ci} 1047e5c31af7Sopenharmony_ci 1048e5c31af7Sopenharmony_civoid InterleavingDecodeTestCase::checkSupport(Context& context) const 1049e5c31af7Sopenharmony_ci{ 1050e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_queue"); 1051e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_synchronization2"); 1052e5c31af7Sopenharmony_ci 1053e5c31af7Sopenharmony_ci#ifdef DE_DEBUG 1054e5c31af7Sopenharmony_ci DE_ASSERT(!m_testDefinitions.empty()); 1055e5c31af7Sopenharmony_ci TestType firstType = m_testDefinitions[0]->getTestType(); 1056e5c31af7Sopenharmony_ci for (const auto& test : m_testDefinitions) 1057e5c31af7Sopenharmony_ci DE_ASSERT(test->getTestType() == firstType); 1058e5c31af7Sopenharmony_ci#endif 1059e5c31af7Sopenharmony_ci switch (m_testDefinitions[0]->getTestType()) 1060e5c31af7Sopenharmony_ci { 1061e5c31af7Sopenharmony_ci case TEST_TYPE_H264_DECODE_INTERLEAVED: 1062e5c31af7Sopenharmony_ci { 1063e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_decode_h264"); 1064e5c31af7Sopenharmony_ci break; 1065e5c31af7Sopenharmony_ci } 1066e5c31af7Sopenharmony_ci case TEST_TYPE_H264_H265_DECODE_INTERLEAVED: 1067e5c31af7Sopenharmony_ci { 1068e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_decode_h264"); 1069e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_video_decode_h265"); 1070e5c31af7Sopenharmony_ci break; 1071e5c31af7Sopenharmony_ci } 1072e5c31af7Sopenharmony_ci default: 1073e5c31af7Sopenharmony_ci TCU_THROW(InternalError, "Unknown interleaving test type"); 1074e5c31af7Sopenharmony_ci } 1075e5c31af7Sopenharmony_ci} 1076e5c31af7Sopenharmony_ci 1077e5c31af7Sopenharmony_ci} // namespace 1078e5c31af7Sopenharmony_ci 1079e5c31af7Sopenharmony_citcu::TestCaseGroup* createVideoDecodeTests(tcu::TestContext& testCtx) 1080e5c31af7Sopenharmony_ci{ 1081e5c31af7Sopenharmony_ci const deUint32 baseSeed = static_cast<deUint32>(testCtx.getCommandLine().getBaseSeed()); 1082e5c31af7Sopenharmony_ci MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "decode")); 1083e5c31af7Sopenharmony_ci 1084e5c31af7Sopenharmony_ci for (const auto& decodeTest : g_DecodeTests) 1085e5c31af7Sopenharmony_ci { 1086e5c31af7Sopenharmony_ci auto defn = TestDefinition::create(decodeTest, baseSeed); 1087e5c31af7Sopenharmony_ci 1088e5c31af7Sopenharmony_ci const char* testName = getTestName(defn->getTestType()); 1089e5c31af7Sopenharmony_ci deUint32 rngSeed = baseSeed ^ deStringHash(testName); 1090e5c31af7Sopenharmony_ci defn->updateHash(rngSeed); 1091e5c31af7Sopenharmony_ci group->addChild(new VideoDecodeTestCase(testCtx, testName, defn)); 1092e5c31af7Sopenharmony_ci } 1093e5c31af7Sopenharmony_ci 1094e5c31af7Sopenharmony_ci for (const auto& interleavingTest : g_InterleavingTests) 1095e5c31af7Sopenharmony_ci { 1096e5c31af7Sopenharmony_ci const char* testName = getTestName(interleavingTest.type); 1097e5c31af7Sopenharmony_ci std::vector<MovePtr<TestDefinition>> defns; 1098e5c31af7Sopenharmony_ci DecodeTestParam streamA{interleavingTest.type, interleavingTest.streamA}; 1099e5c31af7Sopenharmony_ci defns.push_back(TestDefinition::create(streamA, baseSeed)); 1100e5c31af7Sopenharmony_ci DecodeTestParam streamB{interleavingTest.type, interleavingTest.streamB}; 1101e5c31af7Sopenharmony_ci defns.push_back(TestDefinition::create(streamB, baseSeed)); 1102e5c31af7Sopenharmony_ci group->addChild(new InterleavingDecodeTestCase(testCtx, testName, std::move(defns))); 1103e5c31af7Sopenharmony_ci } 1104e5c31af7Sopenharmony_ci 1105e5c31af7Sopenharmony_ci return group.release(); 1106e5c31af7Sopenharmony_ci} 1107e5c31af7Sopenharmony_ci 1108e5c31af7Sopenharmony_ci} // namespace video 1109e5c31af7Sopenharmony_ci} // namespace vkt 1110