NvCodecTest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #include "pch.h"
  2. #include "Codec/NvCodec/NvCodec.h"
  3. #include "FrameGenerator.h"
  4. #include "GraphicsDevice/IGraphicsDevice.h"
  5. #include "GraphicsDeviceContainer.h"
  6. #include "NvCodecUtils.h"
  7. #include "VideoCodecTest.h"
  8. #include <common_video/h264/h264_bitstream_parser.h>
  9. #include <rtc_base/thread.h>
  10. namespace unity
  11. {
  12. namespace webrtc
  13. {
  14. using testing::Values;
  15. class NvCodecTest : public VideoCodecTest
  16. {
  17. public:
  18. NvCodecTest()
  19. : container_(CreateGraphicsDeviceContainer(GetParam()))
  20. , device_(container_->device())
  21. {
  22. }
  23. ~NvCodecTest() override
  24. {
  25. if (encoder_)
  26. encoder_ = nullptr;
  27. if (decoder_)
  28. decoder_ = nullptr;
  29. }
  30. void SetUp() override
  31. {
  32. if (!device_)
  33. GTEST_SKIP() << "The graphics driver is not installed on the device.";
  34. if (!device_->IsCudaSupport())
  35. GTEST_SKIP() << "CUDA is not supported on this device.";
  36. if (!NvEncoder::IsSupported())
  37. GTEST_SKIP() << "Current Driver Version does not support this NvEncodeAPI version.";
  38. context_ = device_->GetCUcontext();
  39. VideoCodecTest::SetUp();
  40. }
  41. protected:
  42. std::unique_ptr<VideoEncoder> CreateEncoder() override
  43. {
  44. cricket::VideoCodec codec = cricket::VideoCodec(cricket::kH264CodecName);
  45. codec.SetParam(cricket::kH264FmtpProfileLevelId, kProfileLevelIdString());
  46. return NvEncoder::Create(codec, context_, CU_MEMORYTYPE_ARRAY, NV_ENC_BUFFER_FORMAT_ARGB, nullptr);
  47. }
  48. std::unique_ptr<VideoDecoder> CreateDecoder() override
  49. {
  50. cricket::VideoCodec codec = cricket::VideoCodec(cricket::kH264CodecName);
  51. codec.SetParam(cricket::kH264FmtpProfileLevelId, kProfileLevelIdString());
  52. return NvDecoder::Create(codec, context_, nullptr);
  53. }
  54. std::unique_ptr<FrameGeneratorInterface> CreateFrameGenerator(
  55. int width,
  56. int height,
  57. absl::optional<FrameGeneratorInterface::OutputType> type,
  58. absl::optional<int> num_squares) override
  59. {
  60. return CreateVideoFrameGenerator(device_, width, height, type, num_squares);
  61. }
  62. void ModifyCodecSettings(VideoCodec* codec_settings) override { SetDefaultSettings(codec_settings); }
  63. void EncodeAndWaitForFrame(
  64. const VideoFrame& inputFrame,
  65. EncodedImage* encodedFrame,
  66. CodecSpecificInfo* codec_specific_info,
  67. bool keyframe = false)
  68. {
  69. std::vector<VideoFrameType> frame_types;
  70. if (keyframe)
  71. {
  72. frame_types.emplace_back(VideoFrameType::kVideoFrameKey);
  73. }
  74. else
  75. {
  76. frame_types.emplace_back(VideoFrameType::kVideoFrameDelta);
  77. }
  78. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Encode(inputFrame, &frame_types));
  79. ASSERT_TRUE(WaitForEncodedFrame(encodedFrame, codec_specific_info));
  80. VerifyQpParser(*encodedFrame);
  81. EXPECT_EQ(kVideoCodecH264, codec_specific_info->codecType);
  82. EXPECT_EQ(0, encodedFrame->SpatialIndex());
  83. }
  84. void VerifyQpParser(const EncodedImage& encoded_frame)
  85. {
  86. EXPECT_GT(encoded_frame.size(), 0u);
  87. bitstreamParser_.ParseBitstream(rtc::ArrayView<const uint8_t>(encoded_frame.data(), encoded_frame.size()));
  88. int qp = bitstreamParser_.GetLastSliceQp().value_or(-1);
  89. EXPECT_EQ(encoded_frame.qp_, qp) << "Encoder QP != parsed bitstream QP.";
  90. }
  91. CUdevice cudevice_;
  92. CUcontext context_;
  93. H264BitstreamParser bitstreamParser_;
  94. std::unique_ptr<GraphicsDeviceContainer> container_;
  95. IGraphicsDevice* device_;
  96. };
  97. TEST_P(NvCodecTest, SupportedNvEncoderCodecs)
  98. {
  99. std::vector<SdpVideoFormat> formats = SupportedNvEncoderCodecs(context_);
  100. EXPECT_GT(formats.size(), 0);
  101. }
  102. TEST_P(NvCodecTest, SupportedNvDecoderCodecs)
  103. {
  104. std::vector<SdpVideoFormat> formats = SupportedNvDecoderCodecs(context_);
  105. EXPECT_GT(formats.size(), 0);
  106. }
  107. TEST_P(NvCodecTest, SupportedEncoderCount) { EXPECT_GT(SupportedEncoderCount(context_), 0); }
  108. TEST_P(NvCodecTest, SetRates)
  109. {
  110. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  111. const uint32_t kBitrateBps = 300000;
  112. VideoBitrateAllocation bitrate_allocation;
  113. bitrate_allocation.SetBitrate(0, 0, kBitrateBps);
  114. // EXPECT_CALL(
  115. // *vpx,
  116. // codec_enc_config_set(
  117. // _,
  118. // AllOf(
  119. // Field(&vpx_codec_enc_cfg_t::rc_target_bitrate, kBitrateBps / 1000),
  120. // Field(&vpx_codec_enc_cfg_t::rc_undershoot_pct, 100u),
  121. // Field(&vpx_codec_enc_cfg_t::rc_overshoot_pct, 15u),
  122. // Field(&vpx_codec_enc_cfg_t::rc_buf_sz, 1000u),
  123. // Field(&vpx_codec_enc_cfg_t::rc_buf_optimal_sz, 600u),
  124. // Field(&vpx_codec_enc_cfg_t::rc_dropframe_thresh, 30u))))
  125. // .WillOnce(Return(VPX_CODEC_OK));
  126. encoder_->SetRates(
  127. VideoEncoder::RateControlParameters(bitrate_allocation, static_cast<double>(codecSettings_.maxFramerate)));
  128. }
  129. TEST_P(NvCodecTest, EncodeFrameAndRelease)
  130. {
  131. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  132. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  133. EncodedImage encoded_frame;
  134. CodecSpecificInfo codec_specific_info;
  135. EncodeAndWaitForFrame(NextInputFrame(), &encoded_frame, &codec_specific_info);
  136. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  137. EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, encoder_->Encode(NextInputFrame(), nullptr));
  138. }
  139. TEST_P(NvCodecTest, EncodeOnWorkerThread)
  140. {
  141. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  142. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  143. EncodedImage encoded_frame;
  144. CodecSpecificInfo codec_specific_info;
  145. std::unique_ptr<rtc::Thread> thread = rtc::Thread::CreateWithSocketServer();
  146. thread->Start();
  147. // Test for executing command on several thread asyncnously.
  148. int count = 100;
  149. std::queue<VideoFrame> frames;
  150. while (count)
  151. {
  152. frames.push(NextInputFrame());
  153. thread->PostTask(
  154. RTC_FROM_HERE,
  155. [&]()
  156. {
  157. VideoFrame frame = frames.front();
  158. EncodeAndWaitForFrame(frame, &encoded_frame, &codec_specific_info);
  159. frames.pop();
  160. });
  161. count--;
  162. }
  163. thread->Stop();
  164. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  165. }
  166. TEST_P(NvCodecTest, EncodeDecode)
  167. {
  168. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  169. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  170. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
  171. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codecSettings_, 1));
  172. EncodedImage encoded_frame;
  173. CodecSpecificInfo codec_specific_info;
  174. EncodeAndWaitForFrame(NextInputFrame(), &encoded_frame, &codec_specific_info);
  175. // First frame should be a key frame.
  176. encoded_frame._frameType = VideoFrameType::kVideoFrameKey;
  177. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encoded_frame, false, 0));
  178. std::unique_ptr<VideoFrame> decoded_frame;
  179. absl::optional<uint8_t> decoded_qp;
  180. ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
  181. ASSERT_TRUE(decoded_frame);
  182. // todo: set color space data on decode frame
  183. const ColorSpace color_space = *decoded_frame->color_space();
  184. EXPECT_EQ(ColorSpace::PrimaryID::kUnspecified, color_space.primaries());
  185. EXPECT_EQ(ColorSpace::TransferID::kUnspecified, color_space.transfer());
  186. EXPECT_EQ(ColorSpace::MatrixID::kUnspecified, color_space.matrix());
  187. EXPECT_EQ(ColorSpace::RangeID::kInvalid, color_space.range());
  188. EXPECT_EQ(ColorSpace::ChromaSiting::kUnspecified, color_space.chroma_siting_horizontal());
  189. EXPECT_EQ(ColorSpace::ChromaSiting::kUnspecified, color_space.chroma_siting_vertical());
  190. }
  191. TEST_P(NvCodecTest, ReconfigureDecoder)
  192. {
  193. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  194. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  195. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
  196. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codecSettings_, 1));
  197. EncodedImage encoded_frame;
  198. CodecSpecificInfo codec_specific_info;
  199. VideoFrame frame = NextInputFrame();
  200. EncodeAndWaitForFrame(frame, &encoded_frame, &codec_specific_info);
  201. encoded_frame._frameType = VideoFrameType::kVideoFrameKey;
  202. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encoded_frame, false, 0));
  203. std::unique_ptr<VideoFrame> decoded_frame;
  204. absl::optional<uint8_t> decoded_qp;
  205. ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
  206. ASSERT_TRUE(decoded_frame);
  207. EXPECT_EQ(decoded_frame->width(), frame.width());
  208. EXPECT_EQ(decoded_frame->height(), frame.height());
  209. // change resolution
  210. uint16_t width = codecSettings_.width / 2;
  211. uint16_t height = codecSettings_.height / 2;
  212. codecSettings_.width = width;
  213. codecSettings_.height = height;
  214. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  215. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  216. ChangeFrameResolution(static_cast<size_t>(width), static_cast<size_t>(height));
  217. VideoFrame frame2 = NextInputFrame();
  218. EncodeAndWaitForFrame(frame2, &encoded_frame, &codec_specific_info);
  219. encoded_frame._frameType = VideoFrameType::kVideoFrameKey;
  220. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encoded_frame, false, 33));
  221. ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
  222. ASSERT_TRUE(decoded_frame);
  223. // todo(kazuki): `pfnSequenceCallback` in NvEncoder.cpp is not called from NvDec when
  224. // the first frame after changing resolution, so the resolution of the first frame is old one.
  225. EXPECT_EQ(decoded_frame->width(), frame.width());
  226. EXPECT_EQ(decoded_frame->height(), frame.height());
  227. // The second frame after changing resolution is fine.
  228. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encoded_frame, false, 66));
  229. ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
  230. EXPECT_EQ(decoded_frame->width(), frame2.width());
  231. EXPECT_EQ(decoded_frame->height(), frame2.height());
  232. }
  233. TEST_P(NvCodecTest, DecodedQpEqualsEncodedQp)
  234. {
  235. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  236. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  237. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
  238. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codecSettings_, 1));
  239. EncodedImage encoded_frame;
  240. CodecSpecificInfo codec_specific_info;
  241. EncodeAndWaitForFrame(NextInputFrame(), &encoded_frame, &codec_specific_info);
  242. // First frame should be a key frame.
  243. encoded_frame._frameType = VideoFrameType::kVideoFrameKey;
  244. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encoded_frame, false, 0));
  245. std::unique_ptr<VideoFrame> decoded_frame;
  246. absl::optional<uint8_t> decoded_qp;
  247. ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
  248. ASSERT_TRUE(decoded_frame);
  249. ASSERT_TRUE(decoded_qp);
  250. EXPECT_EQ(encoded_frame.qp_, *decoded_qp);
  251. }
  252. TEST_P(NvCodecTest, DecodedTimeStampEqualsEncodedTimeStamp)
  253. {
  254. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
  255. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codecSettings_, kSettings()));
  256. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
  257. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codecSettings_, 1));
  258. EncodedImage encoded_frame;
  259. CodecSpecificInfo codec_specific_info;
  260. EncodeAndWaitForFrame(NextInputFrame(), &encoded_frame, &codec_specific_info);
  261. // First frame should be a key frame.
  262. encoded_frame._frameType = VideoFrameType::kVideoFrameKey;
  263. EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encoded_frame, false, 0));
  264. std::unique_ptr<VideoFrame> decoded_frame;
  265. absl::optional<uint8_t> decoded_qp;
  266. ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
  267. ASSERT_TRUE(decoded_frame);
  268. EXPECT_EQ(encoded_frame.Timestamp(), decoded_frame->timestamp());
  269. }
  270. INSTANTIATE_TEST_SUITE_P(GfxDevice, NvCodecTest, testing::ValuesIn(supportedGfxDevices));
  271. }
  272. }