source_buffer_state_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // Copyright 2016 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/filters/source_buffer_state.h"
  5. #include <vector>
  6. #include "base/bind.h"
  7. #include "base/memory/ptr_util.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/strings/string_number_conversions.h"
  10. #include "base/test/gmock_callback_support.h"
  11. #include "base/time/time.h"
  12. #include "media/base/media_util.h"
  13. #include "media/base/mock_filters.h"
  14. #include "media/base/mock_media_log.h"
  15. #include "media/base/test_helpers.h"
  16. #include "media/filters/chunk_demuxer.h"
  17. #include "media/filters/frame_processor.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. namespace media {
  20. using base::test::RunClosure;
  21. using testing::_;
  22. using testing::InvokeWithoutArgs;
  23. using testing::SaveArg;
  24. namespace {
  25. AudioDecoderConfig CreateAudioConfig(AudioCodec codec) {
  26. return AudioDecoderConfig(codec, kSampleFormatPlanarF32,
  27. CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(),
  28. EncryptionScheme::kUnencrypted);
  29. }
  30. VideoDecoderConfig CreateVideoConfig(VideoCodec codec, int w, int h) {
  31. gfx::Size size(w, h);
  32. gfx::Rect visible_rect(size);
  33. return VideoDecoderConfig(codec, VIDEO_CODEC_PROFILE_UNKNOWN,
  34. VideoDecoderConfig::AlphaMode::kIsOpaque,
  35. VideoColorSpace::REC709(), kNoTransformation, size,
  36. visible_rect, size, EmptyExtraData(),
  37. EncryptionScheme::kUnencrypted);
  38. }
  39. void AddAudioTrack(std::unique_ptr<MediaTracks>& t, AudioCodec codec, int id) {
  40. t->AddAudioTrack(CreateAudioConfig(codec), id, MediaTrack::Kind(),
  41. MediaTrack::Label(), MediaTrack::Language());
  42. }
  43. void AddVideoTrack(std::unique_ptr<MediaTracks>& t, VideoCodec codec, int id) {
  44. t->AddVideoTrack(CreateVideoConfig(codec, 16, 16), id, MediaTrack::Kind(),
  45. MediaTrack::Label(), MediaTrack::Language());
  46. }
  47. } // namespace
  48. class SourceBufferStateTest : public ::testing::Test {
  49. public:
  50. SourceBufferStateTest() : mock_stream_parser_(nullptr) {}
  51. std::unique_ptr<SourceBufferState> CreateSourceBufferState() {
  52. std::unique_ptr<FrameProcessor> frame_processor =
  53. std::make_unique<FrameProcessor>(
  54. base::BindRepeating(&SourceBufferStateTest::OnUpdateDuration,
  55. base::Unretained(this)),
  56. &media_log_);
  57. mock_stream_parser_ = new testing::StrictMock<MockStreamParser>();
  58. return base::WrapUnique(new SourceBufferState(
  59. base::WrapUnique(mock_stream_parser_.get()), std::move(frame_processor),
  60. base::BindRepeating(&SourceBufferStateTest::CreateDemuxerStream,
  61. base::Unretained(this)),
  62. &media_log_));
  63. }
  64. std::unique_ptr<SourceBufferState> CreateAndInitSourceBufferState(
  65. const std::string& expected_codecs) {
  66. std::unique_ptr<SourceBufferState> sbs = CreateSourceBufferState();
  67. // Instead of using SaveArg<> to update |new_config_cb_| when mocked Init is
  68. // called, we use a lambda because SaveArg<> doesn't work if any of the
  69. // mocked method's arguments are move-only type.
  70. EXPECT_CALL(*mock_stream_parser_, Init(_, _, _, _, _, _, _, _))
  71. .WillOnce([&](auto init_cb, auto config_cb, auto new_buffers_cb,
  72. auto ignore_text_track, auto encrypted_media_init_data_cb,
  73. auto new_segment_cb, auto end_of_segment_cb,
  74. auto media_log) { new_config_cb_ = config_cb; });
  75. sbs->Init(
  76. base::BindOnce(&SourceBufferStateTest::SourceInitDone,
  77. base::Unretained(this)),
  78. expected_codecs,
  79. base::BindRepeating(
  80. &SourceBufferStateTest::StreamParserEncryptedInitData,
  81. base::Unretained(this)),
  82. base::BindRepeating(&SourceBufferStateTest::StreamParserNewTextTrack,
  83. base::Unretained(this)));
  84. sbs->SetTracksWatcher(base::BindRepeating(
  85. &SourceBufferStateTest::OnMediaTracksUpdated, base::Unretained(this)));
  86. // These tests are not expected to issue any parse warnings.
  87. EXPECT_CALL(*this, OnParseWarningMock(_)).Times(0);
  88. sbs->SetParseWarningCallback(base::BindRepeating(
  89. &SourceBufferStateTest::OnParseWarningMock, base::Unretained(this)));
  90. return sbs;
  91. }
  92. // Emulates appending some data to the SourceBufferState, since OnNewConfigs
  93. // can only be invoked when append is in progress.
  94. bool AppendDataAndReportTracks(const std::unique_ptr<SourceBufferState>& sbs,
  95. std::unique_ptr<MediaTracks> tracks) {
  96. const uint8_t stream_data[] = "stream_data";
  97. const int data_size = sizeof(stream_data);
  98. base::TimeDelta t;
  99. StreamParser::TextTrackConfigMap text_track_config_map;
  100. bool new_configs_result = false;
  101. EXPECT_CALL(*mock_stream_parser_, Parse(stream_data, data_size))
  102. .WillOnce(InvokeWithoutArgs([&] {
  103. new_configs_result =
  104. new_config_cb_.Run(std::move(tracks), text_track_config_map);
  105. return true;
  106. }));
  107. sbs->Append(stream_data, data_size, t, t, &t);
  108. return new_configs_result;
  109. }
  110. MOCK_METHOD1(OnParseWarningMock, void(const SourceBufferParseWarning));
  111. MOCK_METHOD1(OnUpdateDuration, void(base::TimeDelta));
  112. MOCK_METHOD1(SourceInitDone, void(const StreamParser::InitParameters&));
  113. MOCK_METHOD2(StreamParserEncryptedInitData,
  114. void(EmeInitDataType, const std::vector<uint8_t>&));
  115. MOCK_METHOD2(StreamParserNewTextTrack,
  116. void(ChunkDemuxerStream*, const TextTrackConfig&));
  117. MOCK_METHOD1(MediaTracksUpdatedMock, void(std::unique_ptr<MediaTracks>&));
  118. void OnMediaTracksUpdated(std::unique_ptr<MediaTracks> tracks) {
  119. MediaTracksUpdatedMock(tracks);
  120. }
  121. ChunkDemuxerStream* CreateDemuxerStream(DemuxerStream::Type type) {
  122. static unsigned track_id = 0;
  123. demuxer_streams_.push_back(base::WrapUnique(new ChunkDemuxerStream(
  124. type, MediaTrack::Id(base::NumberToString(++track_id)))));
  125. return demuxer_streams_.back().get();
  126. }
  127. testing::StrictMock<MockMediaLog> media_log_;
  128. std::vector<std::unique_ptr<ChunkDemuxerStream>> demuxer_streams_;
  129. raw_ptr<MockStreamParser> mock_stream_parser_;
  130. StreamParser::NewConfigCB new_config_cb_;
  131. };
  132. TEST_F(SourceBufferStateTest, InitSingleAudioTrack) {
  133. std::unique_ptr<SourceBufferState> sbs =
  134. CreateAndInitSourceBufferState("vorbis");
  135. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  136. AddAudioTrack(tracks, AudioCodec::kVorbis, 1);
  137. EXPECT_FOUND_CODEC_NAME(Audio, "vorbis");
  138. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  139. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  140. }
  141. TEST_F(SourceBufferStateTest, InitSingleVideoTrack) {
  142. std::unique_ptr<SourceBufferState> sbs =
  143. CreateAndInitSourceBufferState("vp8");
  144. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  145. AddVideoTrack(tracks, VideoCodec::kVP8, 1);
  146. EXPECT_FOUND_CODEC_NAME(Video, "vp8");
  147. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  148. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  149. }
  150. TEST_F(SourceBufferStateTest, InitMultipleTracks) {
  151. std::unique_ptr<SourceBufferState> sbs =
  152. CreateAndInitSourceBufferState("vorbis,vp8,opus,vp9");
  153. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  154. AddAudioTrack(tracks, AudioCodec::kVorbis, 1);
  155. AddAudioTrack(tracks, AudioCodec::kOpus, 2);
  156. AddVideoTrack(tracks, VideoCodec::kVP8, 3);
  157. AddVideoTrack(tracks, VideoCodec::kVP9, 4);
  158. EXPECT_FOUND_CODEC_NAME(Audio, "vorbis");
  159. EXPECT_FOUND_CODEC_NAME(Audio, "opus");
  160. EXPECT_FOUND_CODEC_NAME(Video, "vp9");
  161. EXPECT_FOUND_CODEC_NAME(Video, "vp8");
  162. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  163. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  164. }
  165. TEST_F(SourceBufferStateTest, AudioStreamMismatchesExpectedCodecs) {
  166. std::unique_ptr<SourceBufferState> sbs =
  167. CreateAndInitSourceBufferState("opus");
  168. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  169. AddAudioTrack(tracks, AudioCodec::kVorbis, 1);
  170. EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("Audio", "vorbis"));
  171. EXPECT_FALSE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  172. }
  173. TEST_F(SourceBufferStateTest, VideoStreamMismatchesExpectedCodecs) {
  174. std::unique_ptr<SourceBufferState> sbs =
  175. CreateAndInitSourceBufferState("vp9");
  176. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  177. AddVideoTrack(tracks, VideoCodec::kVP8, 1);
  178. EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("Video", "vp8"));
  179. EXPECT_FALSE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  180. }
  181. TEST_F(SourceBufferStateTest, MissingExpectedAudioStream) {
  182. std::unique_ptr<SourceBufferState> sbs =
  183. CreateAndInitSourceBufferState("opus,vp9");
  184. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  185. AddVideoTrack(tracks, VideoCodec::kVP9, 1);
  186. EXPECT_FOUND_CODEC_NAME(Video, "vp9");
  187. EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("opus"));
  188. EXPECT_FALSE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  189. }
  190. TEST_F(SourceBufferStateTest, MissingExpectedVideoStream) {
  191. std::unique_ptr<SourceBufferState> sbs =
  192. CreateAndInitSourceBufferState("opus,vp9");
  193. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  194. tracks->AddAudioTrack(CreateAudioConfig(AudioCodec::kOpus), 1,
  195. MediaTrack::Kind(), MediaTrack::Label(),
  196. MediaTrack::Language());
  197. EXPECT_FOUND_CODEC_NAME(Audio, "opus");
  198. EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vp9"));
  199. EXPECT_FALSE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  200. }
  201. TEST_F(SourceBufferStateTest, TrackIdsChangeInSecondInitSegment) {
  202. std::unique_ptr<SourceBufferState> sbs =
  203. CreateAndInitSourceBufferState("opus,vp9");
  204. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  205. AddAudioTrack(tracks, AudioCodec::kOpus, 1);
  206. AddVideoTrack(tracks, VideoCodec::kVP9, 2);
  207. EXPECT_FOUND_CODEC_NAME(Audio, "opus");
  208. EXPECT_FOUND_CODEC_NAME(Video, "vp9");
  209. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  210. AppendDataAndReportTracks(sbs, std::move(tracks));
  211. // This second set of tracks have bytestream track ids that differ from the
  212. // first init segment above (audio track id 1 -> 3, video track id 2 -> 4).
  213. // Bytestream track ids are allowed to change when there is only a single
  214. // track of each type.
  215. std::unique_ptr<MediaTracks> tracks2(new MediaTracks());
  216. AddAudioTrack(tracks2, AudioCodec::kOpus, 3);
  217. AddVideoTrack(tracks2, VideoCodec::kVP9, 4);
  218. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  219. AppendDataAndReportTracks(sbs, std::move(tracks2));
  220. }
  221. TEST_F(SourceBufferStateTest, TrackIdChangeWithTwoAudioTracks) {
  222. std::unique_ptr<SourceBufferState> sbs =
  223. CreateAndInitSourceBufferState("vorbis,opus");
  224. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  225. AddAudioTrack(tracks, AudioCodec::kVorbis, 1);
  226. AddAudioTrack(tracks, AudioCodec::kOpus, 2);
  227. EXPECT_FOUND_CODEC_NAME(Audio, "vorbis");
  228. EXPECT_FOUND_CODEC_NAME(Audio, "opus");
  229. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  230. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  231. // Since we have two audio tracks, bytestream track ids must match the first
  232. // init segment.
  233. std::unique_ptr<MediaTracks> tracks2(new MediaTracks());
  234. AddAudioTrack(tracks2, AudioCodec::kVorbis, 1);
  235. AddAudioTrack(tracks2, AudioCodec::kOpus, 2);
  236. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  237. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks2)));
  238. // Emulate the situation where bytestream track ids have changed in the third
  239. // init segment. This must cause failure in the OnNewConfigs.
  240. std::unique_ptr<MediaTracks> tracks3(new MediaTracks());
  241. AddAudioTrack(tracks3, AudioCodec::kVorbis, 1);
  242. AddAudioTrack(tracks3, AudioCodec::kOpus, 3);
  243. EXPECT_MEDIA_LOG(UnexpectedTrack("audio", "3"));
  244. EXPECT_FALSE(AppendDataAndReportTracks(sbs, std::move(tracks3)));
  245. }
  246. TEST_F(SourceBufferStateTest, TrackIdChangeWithTwoVideoTracks) {
  247. std::unique_ptr<SourceBufferState> sbs =
  248. CreateAndInitSourceBufferState("vp8,vp9");
  249. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  250. AddVideoTrack(tracks, VideoCodec::kVP8, 1);
  251. AddVideoTrack(tracks, VideoCodec::kVP9, 2);
  252. EXPECT_FOUND_CODEC_NAME(Video, "vp8");
  253. EXPECT_FOUND_CODEC_NAME(Video, "vp9");
  254. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  255. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks)));
  256. // Since we have two video tracks, bytestream track ids must match the first
  257. // init segment.
  258. std::unique_ptr<MediaTracks> tracks2(new MediaTracks());
  259. AddVideoTrack(tracks2, VideoCodec::kVP8, 1);
  260. AddVideoTrack(tracks2, VideoCodec::kVP9, 2);
  261. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  262. EXPECT_TRUE(AppendDataAndReportTracks(sbs, std::move(tracks2)));
  263. // Emulate the situation where bytestream track ids have changed in the third
  264. // init segment. This must cause failure in the OnNewConfigs.
  265. std::unique_ptr<MediaTracks> tracks3(new MediaTracks());
  266. AddVideoTrack(tracks3, VideoCodec::kVP8, 1);
  267. AddVideoTrack(tracks3, VideoCodec::kVP9, 3);
  268. EXPECT_MEDIA_LOG(UnexpectedTrack("video", "3"));
  269. EXPECT_FALSE(AppendDataAndReportTracks(sbs, std::move(tracks3)));
  270. }
  271. TEST_F(SourceBufferStateTest, TrackIdsSwappedInSecondInitSegment) {
  272. std::unique_ptr<SourceBufferState> sbs =
  273. CreateAndInitSourceBufferState("opus,vp9");
  274. std::unique_ptr<MediaTracks> tracks(new MediaTracks());
  275. AddAudioTrack(tracks, AudioCodec::kOpus, 1);
  276. AddVideoTrack(tracks, VideoCodec::kVP9, 2);
  277. EXPECT_FOUND_CODEC_NAME(Audio, "opus");
  278. EXPECT_FOUND_CODEC_NAME(Video, "vp9");
  279. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  280. AppendDataAndReportTracks(sbs, std::move(tracks));
  281. // Track ids are swapped in the second init segment.
  282. std::unique_ptr<MediaTracks> tracks2(new MediaTracks());
  283. AddAudioTrack(tracks2, AudioCodec::kOpus, 2);
  284. AddVideoTrack(tracks2, VideoCodec::kVP9, 1);
  285. EXPECT_CALL(*this, MediaTracksUpdatedMock(_));
  286. AppendDataAndReportTracks(sbs, std::move(tracks2));
  287. }
  288. } // namespace media