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