test_helpers.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. // Copyright (c) 2012 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 "media/base/test_helpers.h"
  5. #include <stdint.h>
  6. #include <memory>
  7. #include "base/bind.h"
  8. #include "base/check_op.h"
  9. #include "base/notreached.h"
  10. #include "base/pickle.h"
  11. #include "base/run_loop.h"
  12. #include "base/test/test_timeouts.h"
  13. #include "base/time/time.h"
  14. #include "base/timer/timer.h"
  15. #include "media/base/audio_buffer.h"
  16. #include "media/base/bind_to_current_loop.h"
  17. #include "media/base/decoder_buffer.h"
  18. #include "media/base/media_util.h"
  19. #include "media/base/mock_filters.h"
  20. #include "ui/gfx/geometry/rect.h"
  21. using ::testing::_;
  22. using ::testing::StrictMock;
  23. namespace media {
  24. // Utility mock for testing methods expecting Closures and PipelineStatusCBs.
  25. class MockCallback : public base::RefCountedThreadSafe<MockCallback> {
  26. public:
  27. MockCallback();
  28. MockCallback(const MockCallback&) = delete;
  29. MockCallback& operator=(const MockCallback&) = delete;
  30. MOCK_METHOD0(Run, void());
  31. MOCK_METHOD1(RunWithBool, void(bool));
  32. MOCK_METHOD1(RunWithStatus, void(PipelineStatus));
  33. protected:
  34. friend class base::RefCountedThreadSafe<MockCallback>;
  35. virtual ~MockCallback();
  36. };
  37. MockCallback::MockCallback() = default;
  38. MockCallback::~MockCallback() = default;
  39. base::OnceClosure NewExpectedClosure() {
  40. StrictMock<MockCallback>* callback = new StrictMock<MockCallback>();
  41. EXPECT_CALL(*callback, Run());
  42. return base::BindOnce(&MockCallback::Run, WrapRefCounted(callback));
  43. }
  44. base::OnceCallback<void(bool)> NewExpectedBoolCB(bool success) {
  45. StrictMock<MockCallback>* callback = new StrictMock<MockCallback>();
  46. EXPECT_CALL(*callback, RunWithBool(success));
  47. return base::BindOnce(&MockCallback::RunWithBool, WrapRefCounted(callback));
  48. }
  49. PipelineStatusCallback NewExpectedStatusCB(PipelineStatus status) {
  50. StrictMock<MockCallback>* callback = new StrictMock<MockCallback>();
  51. EXPECT_CALL(*callback, RunWithStatus(status));
  52. return base::BindOnce(&MockCallback::RunWithStatus, WrapRefCounted(callback));
  53. }
  54. WaitableMessageLoopEvent::WaitableMessageLoopEvent()
  55. : WaitableMessageLoopEvent(TestTimeouts::action_timeout()) {}
  56. WaitableMessageLoopEvent::WaitableMessageLoopEvent(base::TimeDelta timeout)
  57. : signaled_(false), status_(PIPELINE_OK), timeout_(timeout) {}
  58. WaitableMessageLoopEvent::~WaitableMessageLoopEvent() {
  59. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  60. }
  61. base::OnceClosure WaitableMessageLoopEvent::GetClosure() {
  62. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  63. return BindToCurrentLoop(base::BindOnce(&WaitableMessageLoopEvent::OnCallback,
  64. base::Unretained(this), PIPELINE_OK));
  65. }
  66. PipelineStatusCallback WaitableMessageLoopEvent::GetPipelineStatusCB() {
  67. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  68. return BindToCurrentLoop(base::BindOnce(&WaitableMessageLoopEvent::OnCallback,
  69. base::Unretained(this)));
  70. }
  71. void WaitableMessageLoopEvent::RunAndWait() {
  72. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  73. RunAndWaitForStatus(PIPELINE_OK);
  74. }
  75. void WaitableMessageLoopEvent::RunAndWaitForStatus(PipelineStatus expected) {
  76. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  77. if (signaled_) {
  78. EXPECT_EQ(expected, status_);
  79. return;
  80. }
  81. run_loop_ = std::make_unique<base::RunLoop>();
  82. base::OneShotTimer timer;
  83. timer.Start(FROM_HERE, timeout_,
  84. base::BindOnce(&WaitableMessageLoopEvent::OnTimeout,
  85. base::Unretained(this)));
  86. run_loop_->Run();
  87. EXPECT_TRUE(signaled_);
  88. EXPECT_EQ(expected, status_);
  89. run_loop_.reset();
  90. }
  91. void WaitableMessageLoopEvent::OnCallback(PipelineStatus status) {
  92. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  93. signaled_ = true;
  94. status_ = status;
  95. // |run_loop_| may be null if the callback fires before RunAndWaitForStatus().
  96. if (run_loop_)
  97. run_loop_->Quit();
  98. }
  99. void WaitableMessageLoopEvent::OnTimeout() {
  100. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  101. ADD_FAILURE() << "Timed out waiting for message loop to quit";
  102. run_loop_->Quit();
  103. }
  104. static VideoDecoderConfig GetTestConfig(VideoCodec codec,
  105. VideoCodecProfile profile,
  106. const VideoColorSpace& color_space,
  107. VideoRotation rotation,
  108. gfx::Size coded_size,
  109. bool is_encrypted) {
  110. gfx::Rect visible_rect(coded_size.width(), coded_size.height());
  111. gfx::Size natural_size = coded_size;
  112. return VideoDecoderConfig(
  113. codec, profile, VideoDecoderConfig::AlphaMode::kIsOpaque, color_space,
  114. VideoTransformation(rotation), coded_size, visible_rect, natural_size,
  115. EmptyExtraData(),
  116. is_encrypted ? EncryptionScheme::kCenc : EncryptionScheme::kUnencrypted);
  117. }
  118. static VideoCodecProfile MinProfile(VideoCodec codec) {
  119. switch (codec) {
  120. case VideoCodec::kUnknown:
  121. case VideoCodec::kVC1:
  122. case VideoCodec::kMPEG2:
  123. case VideoCodec::kMPEG4:
  124. return VIDEO_CODEC_PROFILE_UNKNOWN;
  125. case VideoCodec::kH264:
  126. return H264PROFILE_MIN;
  127. case VideoCodec::kTheora:
  128. return THEORAPROFILE_MIN;
  129. case VideoCodec::kVP8:
  130. return VP8PROFILE_MIN;
  131. case VideoCodec::kVP9:
  132. return VP9PROFILE_MIN;
  133. case VideoCodec::kHEVC:
  134. return HEVCPROFILE_MIN;
  135. case VideoCodec::kDolbyVision:
  136. return DOLBYVISION_PROFILE0;
  137. case VideoCodec::kAV1:
  138. return AV1PROFILE_MIN;
  139. }
  140. }
  141. static const gfx::Size kNormalSize(320, 240);
  142. static const gfx::Size kLargeSize(640, 480);
  143. static const gfx::Size kExtraLargeSize(15360, 8640);
  144. // static
  145. VideoDecoderConfig TestVideoConfig::Invalid() {
  146. return GetTestConfig(VideoCodec::kUnknown, VIDEO_CODEC_PROFILE_UNKNOWN,
  147. VideoColorSpace::JPEG(), VIDEO_ROTATION_0, kNormalSize,
  148. false);
  149. }
  150. // static
  151. VideoDecoderConfig TestVideoConfig::Normal(VideoCodec codec) {
  152. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  153. VIDEO_ROTATION_0, kNormalSize, false);
  154. }
  155. // static
  156. VideoDecoderConfig TestVideoConfig::NormalWithColorSpace(
  157. VideoCodec codec,
  158. const VideoColorSpace& color_space) {
  159. return GetTestConfig(codec, MinProfile(codec), color_space, VIDEO_ROTATION_0,
  160. kNormalSize, false);
  161. }
  162. // static
  163. VideoDecoderConfig TestVideoConfig::NormalH264(VideoCodecProfile config) {
  164. return GetTestConfig(VideoCodec::kH264, MinProfile(VideoCodec::kH264),
  165. VideoColorSpace::JPEG(), VIDEO_ROTATION_0, kNormalSize,
  166. false);
  167. }
  168. // static
  169. VideoDecoderConfig TestVideoConfig::NormalCodecProfile(
  170. VideoCodec codec,
  171. VideoCodecProfile profile) {
  172. return GetTestConfig(codec, profile, VideoColorSpace::JPEG(),
  173. VIDEO_ROTATION_0, kNormalSize, false);
  174. }
  175. // static
  176. VideoDecoderConfig TestVideoConfig::NormalEncrypted(VideoCodec codec,
  177. VideoCodecProfile profile) {
  178. return GetTestConfig(codec, profile, VideoColorSpace::JPEG(),
  179. VIDEO_ROTATION_0, kNormalSize, true);
  180. }
  181. // static
  182. VideoDecoderConfig TestVideoConfig::NormalRotated(VideoRotation rotation) {
  183. return GetTestConfig(VideoCodec::kVP8, MinProfile(VideoCodec::kVP8),
  184. VideoColorSpace::JPEG(), rotation, kNormalSize, false);
  185. }
  186. // static
  187. VideoDecoderConfig TestVideoConfig::Large(VideoCodec codec) {
  188. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  189. VIDEO_ROTATION_0, kLargeSize, false);
  190. }
  191. // static
  192. VideoDecoderConfig TestVideoConfig::LargeEncrypted(VideoCodec codec) {
  193. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  194. VIDEO_ROTATION_0, kLargeSize, true);
  195. }
  196. // static
  197. VideoDecoderConfig TestVideoConfig::ExtraLarge(VideoCodec codec) {
  198. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  199. VIDEO_ROTATION_0, kExtraLargeSize, false);
  200. }
  201. // static
  202. VideoDecoderConfig TestVideoConfig::ExtraLargeEncrypted(VideoCodec codec) {
  203. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  204. VIDEO_ROTATION_0, kExtraLargeSize, true);
  205. }
  206. // static
  207. VideoDecoderConfig TestVideoConfig::Custom(gfx::Size size, VideoCodec codec) {
  208. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  209. VIDEO_ROTATION_0, size, false);
  210. }
  211. // static
  212. VideoDecoderConfig TestVideoConfig::CustomEncrypted(gfx::Size size,
  213. VideoCodec codec) {
  214. return GetTestConfig(codec, MinProfile(codec), VideoColorSpace::JPEG(),
  215. VIDEO_ROTATION_0, size, true);
  216. }
  217. // static
  218. gfx::Size TestVideoConfig::NormalCodedSize() {
  219. return kNormalSize;
  220. }
  221. // static
  222. gfx::Size TestVideoConfig::LargeCodedSize() {
  223. return kLargeSize;
  224. }
  225. // static
  226. gfx::Size TestVideoConfig::ExtraLargeCodedSize() {
  227. return kExtraLargeSize;
  228. }
  229. AudioDecoderConfig TestAudioConfig::Normal() {
  230. return AudioDecoderConfig(AudioCodec::kVorbis, kSampleFormatPlanarF32,
  231. CHANNEL_LAYOUT_STEREO, NormalSampleRateValue(),
  232. EmptyExtraData(), EncryptionScheme::kUnencrypted);
  233. }
  234. AudioDecoderConfig TestAudioConfig::NormalEncrypted() {
  235. return AudioDecoderConfig(AudioCodec::kVorbis, kSampleFormatPlanarF32,
  236. CHANNEL_LAYOUT_STEREO, NormalSampleRateValue(),
  237. EmptyExtraData(), EncryptionScheme::kCenc);
  238. }
  239. AudioDecoderConfig TestAudioConfig::HighSampleRate() {
  240. return AudioDecoderConfig(AudioCodec::kVorbis, kSampleFormatPlanarF32,
  241. CHANNEL_LAYOUT_STEREO, HighSampleRateValue(),
  242. EmptyExtraData(), EncryptionScheme::kUnencrypted);
  243. }
  244. AudioDecoderConfig TestAudioConfig::HighSampleRateEncrypted() {
  245. return AudioDecoderConfig(AudioCodec::kVorbis, kSampleFormatPlanarF32,
  246. CHANNEL_LAYOUT_STEREO, HighSampleRateValue(),
  247. EmptyExtraData(), EncryptionScheme::kCenc);
  248. }
  249. int TestAudioConfig::NormalSampleRateValue() {
  250. return 44100;
  251. }
  252. int TestAudioConfig::HighSampleRateValue() {
  253. return 192000;
  254. }
  255. // static
  256. AudioParameters TestAudioParameters::Normal() {
  257. return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
  258. CHANNEL_LAYOUT_STEREO, 48000, 2048);
  259. }
  260. template <class T>
  261. scoped_refptr<AudioBuffer> MakeAudioBuffer(SampleFormat format,
  262. ChannelLayout channel_layout,
  263. size_t channel_count,
  264. int sample_rate,
  265. T start,
  266. T increment,
  267. size_t frames,
  268. base::TimeDelta timestamp) {
  269. const size_t channels = ChannelLayoutToChannelCount(channel_layout);
  270. scoped_refptr<AudioBuffer> output =
  271. AudioBuffer::CreateBuffer(format,
  272. channel_layout,
  273. static_cast<int>(channel_count),
  274. sample_rate,
  275. static_cast<int>(frames));
  276. output->set_timestamp(timestamp);
  277. const bool is_planar = IsPlanar(format);
  278. // Values in channel 0 will be:
  279. // start
  280. // start + increment
  281. // start + 2 * increment, ...
  282. // While, values in channel 1 will be:
  283. // start + frames * increment
  284. // start + (frames + 1) * increment
  285. // start + (frames + 2) * increment, ...
  286. for (size_t ch = 0; ch < channels; ++ch) {
  287. T* buffer =
  288. reinterpret_cast<T*>(output->channel_data()[is_planar ? ch : 0]);
  289. const T v = static_cast<T>(start + ch * frames * increment);
  290. for (size_t i = 0; i < frames; ++i) {
  291. buffer[is_planar ? i : ch + i * channels] =
  292. static_cast<T>(v + i * increment);
  293. }
  294. }
  295. return output;
  296. }
  297. template <>
  298. scoped_refptr<AudioBuffer> MakeAudioBuffer<float>(SampleFormat format,
  299. ChannelLayout channel_layout,
  300. size_t channel_count,
  301. int sample_rate,
  302. float start,
  303. float increment,
  304. size_t frames,
  305. base::TimeDelta timestamp) {
  306. const size_t channels = ChannelLayoutToChannelCount(channel_layout);
  307. scoped_refptr<AudioBuffer> output = AudioBuffer::CreateBuffer(
  308. format, channel_layout, static_cast<int>(channel_count), sample_rate,
  309. static_cast<int>(frames));
  310. output->set_timestamp(timestamp);
  311. const bool is_planar =
  312. format == kSampleFormatPlanarS16 || format == kSampleFormatPlanarF32;
  313. // Values in channel 0 will be:
  314. // (start) / max_value
  315. // (start + increment) / max_value
  316. // (start + 2 * increment) / max_value, ...
  317. // While, values in channel 1 will be:
  318. // (start + frames * increment) / max_value
  319. // (start + (frames + 1) * increment) / max_value
  320. // (start + (frames + 2) * increment) / max_value, ...
  321. for (size_t ch = 0; ch < channels; ++ch) {
  322. float* buffer =
  323. reinterpret_cast<float*>(output->channel_data()[is_planar ? ch : 0]);
  324. const float v = static_cast<float>(start + ch * frames * increment);
  325. for (size_t i = 0; i < frames; ++i) {
  326. buffer[is_planar ? i : ch + i * channels] =
  327. static_cast<float>(v + i * increment) /
  328. std::numeric_limits<uint16_t>::max();
  329. }
  330. }
  331. return output;
  332. }
  333. scoped_refptr<AudioBuffer> MakeBitstreamAudioBuffer(
  334. SampleFormat format,
  335. ChannelLayout channel_layout,
  336. size_t channel_count,
  337. int sample_rate,
  338. uint8_t start,
  339. uint8_t increment,
  340. size_t frames,
  341. size_t data_size,
  342. base::TimeDelta timestamp) {
  343. scoped_refptr<AudioBuffer> output = AudioBuffer::CreateBitstreamBuffer(
  344. format, channel_layout, static_cast<int>(channel_count), sample_rate,
  345. static_cast<int>(frames), data_size);
  346. output->set_timestamp(timestamp);
  347. // Values in channel 0 will be:
  348. // start
  349. // start + increment
  350. // start + 2 * increment, ...
  351. uint8_t* buffer = reinterpret_cast<uint8_t*>(output->channel_data()[0]);
  352. for (size_t i = 0; i < data_size; ++i) {
  353. buffer[i] = static_cast<uint8_t>(start + i * increment);
  354. }
  355. return output;
  356. }
  357. void VerifyBitstreamAudioBus(AudioBus* bus,
  358. size_t data_size,
  359. uint8_t start,
  360. uint8_t increment) {
  361. ASSERT_TRUE(bus->is_bitstream_format());
  362. // Values in channel 0 will be:
  363. // start
  364. // start + increment
  365. // start + 2 * increment, ...
  366. uint8_t* buffer = reinterpret_cast<uint8_t*>(bus->channel(0));
  367. for (size_t i = 0; i < data_size; ++i) {
  368. ASSERT_EQ(buffer[i], static_cast<uint8_t>(start + i * increment));
  369. }
  370. }
  371. // Instantiate all the types of MakeAudioBuffer() and
  372. // MakeAudioBuffer() needed.
  373. #define DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(type) \
  374. template scoped_refptr<AudioBuffer> MakeAudioBuffer<type>( \
  375. SampleFormat format, \
  376. ChannelLayout channel_layout, \
  377. size_t channel_count, \
  378. int sample_rate, \
  379. type start, \
  380. type increment, \
  381. size_t frames, \
  382. base::TimeDelta start_time)
  383. DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(uint8_t);
  384. DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int16_t);
  385. DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int32_t);
  386. static const char kFakeVideoBufferHeader[] = "FakeVideoBufferForTest";
  387. scoped_refptr<DecoderBuffer> CreateFakeVideoBufferForTest(
  388. const VideoDecoderConfig& config,
  389. base::TimeDelta timestamp, base::TimeDelta duration) {
  390. base::Pickle pickle;
  391. pickle.WriteString(kFakeVideoBufferHeader);
  392. pickle.WriteInt(config.coded_size().width());
  393. pickle.WriteInt(config.coded_size().height());
  394. pickle.WriteInt64(timestamp.InMilliseconds());
  395. scoped_refptr<DecoderBuffer> buffer =
  396. DecoderBuffer::CopyFrom(static_cast<const uint8_t*>(pickle.data()),
  397. static_cast<int>(pickle.size()));
  398. buffer->set_timestamp(timestamp);
  399. buffer->set_duration(duration);
  400. buffer->set_is_key_frame(true);
  401. return buffer;
  402. }
  403. bool VerifyFakeVideoBufferForTest(const DecoderBuffer& buffer,
  404. const VideoDecoderConfig& config) {
  405. // Check if the input |buffer| matches the |config|.
  406. base::PickleIterator pickle(
  407. base::Pickle(reinterpret_cast<const char*>(buffer.data()),
  408. static_cast<int>(buffer.data_size())));
  409. std::string header;
  410. int width = 0;
  411. int height = 0;
  412. bool success = pickle.ReadString(&header) && pickle.ReadInt(&width) &&
  413. pickle.ReadInt(&height);
  414. return (success && header == kFakeVideoBufferHeader &&
  415. width == config.coded_size().width() &&
  416. height == config.coded_size().height());
  417. }
  418. std::unique_ptr<StrictMock<MockDemuxerStream>> CreateMockDemuxerStream(
  419. DemuxerStream::Type type,
  420. bool encrypted) {
  421. auto stream = std::make_unique<StrictMock<MockDemuxerStream>>(type);
  422. switch (type) {
  423. case DemuxerStream::AUDIO:
  424. stream->set_audio_decoder_config(encrypted
  425. ? TestAudioConfig::NormalEncrypted()
  426. : TestAudioConfig::Normal());
  427. break;
  428. case DemuxerStream::VIDEO:
  429. stream->set_video_decoder_config(encrypted
  430. ? TestVideoConfig::NormalEncrypted()
  431. : TestVideoConfig::Normal());
  432. break;
  433. default:
  434. NOTREACHED();
  435. break;
  436. }
  437. return stream;
  438. }
  439. } // namespace media