gav1_video_decoder_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <memory>
  5. #include <string>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/hash/md5.h"
  11. #include "base/run_loop.h"
  12. #include "base/strings/string_piece.h"
  13. #include "base/test/task_environment.h"
  14. #include "build/build_config.h"
  15. #include "media/base/decoder_buffer.h"
  16. #include "media/base/limits.h"
  17. #include "media/base/mock_media_log.h"
  18. #include "media/base/test_data_util.h"
  19. #include "media/base/test_helpers.h"
  20. #include "media/base/video_frame.h"
  21. #include "media/ffmpeg/ffmpeg_common.h"
  22. #include "media/filters/gav1_video_decoder.h"
  23. #include "media/filters/in_memory_url_protocol.h"
  24. #include "testing/gmock/include/gmock/gmock.h"
  25. using ::testing::_;
  26. namespace media {
  27. namespace {
  28. MATCHER(ContainsDecoderErrorLog, "") {
  29. return CONTAINS_STRING(arg, "libgav1::Decoder::DequeueFrame failed");
  30. }
  31. // Similar to VideoFrame::HashFrameForTesting(), but uses visible_data() and
  32. // visible_rect() instead of data() and coded_size() to determine the region to
  33. // hash.
  34. //
  35. // The VideoFrame objects created by Gav1VideoDecoder have extended pixels
  36. // outside the visible_rect(). Those extended pixels are for libgav1 internal
  37. // use and are not part of the actual video frames. Unlike
  38. // VideoFrame::HashFrameForTesting(), this function excludes the extended pixels
  39. // and hashes only the actual video frames.
  40. void HashFrameVisibleRectForTesting(base::MD5Context* context,
  41. const VideoFrame& frame) {
  42. DCHECK(context);
  43. for (size_t plane = 0; plane < VideoFrame::NumPlanes(frame.format());
  44. ++plane) {
  45. int rows = frame.Rows(plane, frame.format(), frame.visible_rect().height());
  46. for (int row = 0; row < rows; ++row) {
  47. int row_bytes =
  48. frame.RowBytes(plane, frame.format(), frame.visible_rect().width());
  49. base::MD5Update(context, base::StringPiece(reinterpret_cast<const char*>(
  50. frame.visible_data(plane) +
  51. frame.stride(plane) * row),
  52. row_bytes));
  53. }
  54. }
  55. }
  56. } // namespace
  57. class Gav1VideoDecoderTest : public testing::Test {
  58. public:
  59. Gav1VideoDecoderTest()
  60. : decoder_(new Gav1VideoDecoder(&media_log_)),
  61. i_frame_buffer_(ReadTestDataFile("av1-I-frame-320x240")) {}
  62. Gav1VideoDecoderTest(const Gav1VideoDecoderTest&) = delete;
  63. Gav1VideoDecoderTest& operator=(const Gav1VideoDecoderTest&) = delete;
  64. ~Gav1VideoDecoderTest() override { Destroy(); }
  65. void Initialize() {
  66. InitializeWithConfig(TestVideoConfig::Normal(VideoCodec::kAV1));
  67. }
  68. void InitializeWithConfigWithResult(const VideoDecoderConfig& config,
  69. bool success) {
  70. decoder_->Initialize(config, false, nullptr,
  71. base::BindOnce(
  72. [](bool success, DecoderStatus status) {
  73. EXPECT_EQ(status.is_ok(), success);
  74. },
  75. success),
  76. base::BindRepeating(&Gav1VideoDecoderTest::FrameReady,
  77. base::Unretained(this)),
  78. base::NullCallback());
  79. base::RunLoop().RunUntilIdle();
  80. }
  81. void InitializeWithConfig(const VideoDecoderConfig& config) {
  82. InitializeWithConfigWithResult(config, true);
  83. }
  84. void Reinitialize() {
  85. InitializeWithConfig(TestVideoConfig::Large(VideoCodec::kAV1));
  86. }
  87. void Reset() {
  88. decoder_->Reset(NewExpectedClosure());
  89. base::RunLoop().RunUntilIdle();
  90. }
  91. void Destroy() {
  92. decoder_.reset();
  93. base::RunLoop().RunUntilIdle();
  94. }
  95. // Sets up expectations and actions to put Gav1VideoDecoder in an active
  96. // decoding state.
  97. void ExpectDecodingState() {
  98. EXPECT_TRUE(DecodeSingleFrame(i_frame_buffer_).is_ok());
  99. ASSERT_EQ(1U, output_frames_.size());
  100. }
  101. // Sets up expectations and actions to put Gav1VideoDecoder in an end
  102. // of stream state.
  103. void ExpectEndOfStreamState() {
  104. EXPECT_TRUE(DecodeSingleFrame(DecoderBuffer::CreateEOSBuffer()).is_ok());
  105. ASSERT_FALSE(output_frames_.empty());
  106. }
  107. using InputBuffers = std::vector<scoped_refptr<DecoderBuffer>>;
  108. using OutputFrames = std::vector<scoped_refptr<VideoFrame>>;
  109. // Decodes all buffers in |input_buffers| and push all successfully decoded
  110. // output frames into |output_frames|. Returns the last decode status returned
  111. // by the decoder.
  112. DecoderStatus DecodeMultipleFrames(const InputBuffers& input_buffers) {
  113. for (auto iter = input_buffers.begin(); iter != input_buffers.end();
  114. ++iter) {
  115. DecoderStatus status = Decode(*iter);
  116. switch (status.code()) {
  117. case DecoderStatus::Codes::kOk:
  118. break;
  119. case DecoderStatus::Codes::kAborted:
  120. NOTREACHED();
  121. [[fallthrough]];
  122. default:
  123. DCHECK(output_frames_.empty());
  124. return status;
  125. }
  126. }
  127. return DecoderStatus::Codes::kOk;
  128. }
  129. // Decodes the single compressed frame in |buffer|.
  130. DecoderStatus DecodeSingleFrame(scoped_refptr<DecoderBuffer> buffer) {
  131. InputBuffers input_buffers;
  132. input_buffers.push_back(std::move(buffer));
  133. return DecodeMultipleFrames(input_buffers);
  134. }
  135. // Decodes |i_frame_buffer_| and then decodes the data contained in the file
  136. // named |test_file_name|. This function expects both buffers to decode to
  137. // frames that are the same size.
  138. void DecodeIFrameThenTestFile(const std::string& test_file_name,
  139. const gfx::Size& expected_size) {
  140. Initialize();
  141. scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name);
  142. InputBuffers input_buffers;
  143. input_buffers.push_back(i_frame_buffer_);
  144. input_buffers.push_back(buffer);
  145. input_buffers.push_back(DecoderBuffer::CreateEOSBuffer());
  146. EXPECT_TRUE(DecodeMultipleFrames(input_buffers).is_ok());
  147. ASSERT_EQ(2U, output_frames_.size());
  148. gfx::Size original_size = TestVideoConfig::NormalCodedSize();
  149. EXPECT_EQ(original_size.width(),
  150. output_frames_[0]->visible_rect().size().width());
  151. EXPECT_EQ(original_size.height(),
  152. output_frames_[0]->visible_rect().size().height());
  153. EXPECT_EQ(expected_size.width(),
  154. output_frames_[1]->visible_rect().size().width());
  155. EXPECT_EQ(expected_size.height(),
  156. output_frames_[1]->visible_rect().size().height());
  157. }
  158. DecoderStatus Decode(scoped_refptr<DecoderBuffer> buffer) {
  159. DecoderStatus status;
  160. EXPECT_CALL(*this, DecodeDone(_)).WillOnce(testing::SaveArg<0>(&status));
  161. decoder_->Decode(std::move(buffer),
  162. base::BindOnce(&Gav1VideoDecoderTest::DecodeDone,
  163. base::Unretained(this)));
  164. base::RunLoop().RunUntilIdle();
  165. return status;
  166. }
  167. void FrameReady(scoped_refptr<VideoFrame> frame) {
  168. DCHECK(!frame->metadata().end_of_stream);
  169. output_frames_.push_back(std::move(frame));
  170. }
  171. std::string GetVideoFrameHash(const VideoFrame& frame) {
  172. base::MD5Context md5_context;
  173. base::MD5Init(&md5_context);
  174. HashFrameVisibleRectForTesting(&md5_context, frame);
  175. base::MD5Digest digest;
  176. base::MD5Final(&digest, &md5_context);
  177. return base::MD5DigestToBase16(digest);
  178. }
  179. MOCK_METHOD1(DecodeDone, void(DecoderStatus));
  180. testing::StrictMock<MockMediaLog> media_log_;
  181. base::test::SingleThreadTaskEnvironment task_environment_;
  182. std::unique_ptr<Gav1VideoDecoder> decoder_;
  183. scoped_refptr<DecoderBuffer> i_frame_buffer_;
  184. OutputFrames output_frames_;
  185. };
  186. TEST_F(Gav1VideoDecoderTest, Initialize_Normal) {
  187. Initialize();
  188. }
  189. TEST_F(Gav1VideoDecoderTest, Reinitialize_Normal) {
  190. Initialize();
  191. Reinitialize();
  192. }
  193. TEST_F(Gav1VideoDecoderTest, Reinitialize_AfterDecodeFrame) {
  194. Initialize();
  195. ExpectDecodingState();
  196. Reinitialize();
  197. }
  198. TEST_F(Gav1VideoDecoderTest, Reinitialize_AfterReset) {
  199. Initialize();
  200. ExpectDecodingState();
  201. Reset();
  202. Reinitialize();
  203. }
  204. TEST_F(Gav1VideoDecoderTest, DecodeFrame_Normal) {
  205. Initialize();
  206. // Simulate decoding a single frame.
  207. EXPECT_TRUE(DecodeSingleFrame(i_frame_buffer_).is_ok());
  208. ASSERT_EQ(1U, output_frames_.size());
  209. const auto& frame = output_frames_.front();
  210. EXPECT_EQ(PIXEL_FORMAT_I420, frame->format());
  211. EXPECT_EQ("589dc641b7742ffe7a2b0d4c16aa3e86", GetVideoFrameHash(*frame));
  212. }
  213. TEST_F(Gav1VideoDecoderTest, DecodeFrame_8bitMono) {
  214. Initialize();
  215. EXPECT_TRUE(
  216. DecodeSingleFrame(ReadTestDataFile("av1-monochrome-I-frame-320x240-8bpp"))
  217. .is_ok());
  218. ASSERT_EQ(1U, output_frames_.size());
  219. const auto& frame = output_frames_.front();
  220. EXPECT_EQ(PIXEL_FORMAT_I420, frame->format());
  221. EXPECT_EQ("eeba03dcc9c22c4632bf74b481db36b2", GetVideoFrameHash(*frame));
  222. }
  223. TEST_F(Gav1VideoDecoderTest, DecodeFrame_10bitMono) {
  224. Initialize();
  225. EXPECT_TRUE(DecodeSingleFrame(
  226. ReadTestDataFile("av1-monochrome-I-frame-320x240-10bpp"))
  227. .is_ok());
  228. ASSERT_EQ(1U, output_frames_.size());
  229. const auto& frame = output_frames_.front();
  230. EXPECT_EQ(PIXEL_FORMAT_YUV420P10, frame->format());
  231. EXPECT_EQ("026c1fed9e161f09d816ac7278458a80", GetVideoFrameHash(*frame));
  232. }
  233. // libgav1 does not support bit depth 12.
  234. TEST_F(Gav1VideoDecoderTest, DISABLED_DecodeFrame_12bitMono) {
  235. Initialize();
  236. EXPECT_TRUE(DecodeSingleFrame(
  237. ReadTestDataFile("av1-monochrome-I-frame-320x240-12bpp"))
  238. .is_ok());
  239. ASSERT_EQ(1U, output_frames_.size());
  240. const auto& frame = output_frames_.front();
  241. EXPECT_EQ(PIXEL_FORMAT_YUV420P12, frame->format());
  242. EXPECT_EQ("32115092dc00fbe86823b0b714a0f63e", GetVideoFrameHash(*frame));
  243. }
  244. // Decode |i_frame_buffer_| and then a frame with a larger width and verify
  245. // the output size was adjusted.
  246. TEST_F(Gav1VideoDecoderTest, DecodeFrame_LargerWidth) {
  247. DecodeIFrameThenTestFile("av1-I-frame-1280x720", gfx::Size(1280, 720));
  248. }
  249. // Decode a VP9 frame which should trigger a decoder error.
  250. TEST_F(Gav1VideoDecoderTest, DecodeFrame_Error) {
  251. Initialize();
  252. EXPECT_MEDIA_LOG(ContainsDecoderErrorLog());
  253. DecodeSingleFrame(ReadTestDataFile("vp9-I-frame-320x240"));
  254. }
  255. // Test resetting when decoder has initialized but not decoded.
  256. TEST_F(Gav1VideoDecoderTest, Reset_Initialized) {
  257. Initialize();
  258. Reset();
  259. }
  260. // Test resetting when decoder has decoded single frame.
  261. TEST_F(Gav1VideoDecoderTest, Reset_Decoding) {
  262. Initialize();
  263. ExpectDecodingState();
  264. Reset();
  265. }
  266. // Test resetting when decoder has hit end of stream.
  267. TEST_F(Gav1VideoDecoderTest, Reset_EndOfStream) {
  268. Initialize();
  269. ExpectDecodingState();
  270. ExpectEndOfStreamState();
  271. Reset();
  272. }
  273. // Test destruction when decoder has initialized but not decoded.
  274. TEST_F(Gav1VideoDecoderTest, Destroy_Initialized) {
  275. Initialize();
  276. Destroy();
  277. }
  278. // Test destruction when decoder has decoded single frame.
  279. TEST_F(Gav1VideoDecoderTest, Destroy_Decoding) {
  280. Initialize();
  281. ExpectDecodingState();
  282. Destroy();
  283. }
  284. // Test destruction when decoder has hit end of stream.
  285. TEST_F(Gav1VideoDecoderTest, Destroy_EndOfStream) {
  286. Initialize();
  287. ExpectDecodingState();
  288. ExpectEndOfStreamState();
  289. Destroy();
  290. }
  291. TEST_F(Gav1VideoDecoderTest, FrameValidAfterPoolDestruction) {
  292. Initialize();
  293. Decode(i_frame_buffer_);
  294. Destroy();
  295. ASSERT_FALSE(output_frames_.empty());
  296. // Write to the Y plane. The memory tools should detect a
  297. // use-after-free if the storage was actually removed by pool destruction.
  298. memset(output_frames_.front()->data(VideoFrame::kYPlane), 0xff,
  299. output_frames_.front()->rows(VideoFrame::kYPlane) *
  300. output_frames_.front()->stride(VideoFrame::kYPlane));
  301. }
  302. } // namespace media