OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include "base/macros.h" | 7 #include "base/macros.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "content/child/child_process.h" | 10 #include "content/child/child_process.h" |
11 #include "content/renderer/media/media_recorder_handler.h" | 11 #include "content/renderer/media/media_recorder_handler.h" |
12 #include "content/renderer/media/mock_media_stream_registry.h" | 12 #include "content/renderer/media/mock_media_stream_registry.h" |
13 #include "media/audio/simple_sources.h" | 13 #include "media/audio/simple_sources.h" |
14 #include "media/base/audio_bus.h" | 14 #include "media/base/audio_bus.h" |
15 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
16 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
18 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" | 18 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" |
19 #include "third_party/WebKit/public/platform/WebString.h" | 19 #include "third_party/WebKit/public/platform/WebString.h" |
20 #include "third_party/WebKit/public/web/WebHeap.h" | 20 #include "third_party/WebKit/public/web/WebHeap.h" |
21 | 21 |
22 using ::testing::_; | 22 using ::testing::_; |
23 using ::testing::AtLeast; | 23 using ::testing::AtLeast; |
24 using ::testing::InSequence; | 24 using ::testing::InSequence; |
| 25 using ::testing::Gt; |
25 using ::testing::Lt; | 26 using ::testing::Lt; |
26 using ::testing::Mock; | 27 using ::testing::Mock; |
27 using ::testing::TestWithParam; | 28 using ::testing::TestWithParam; |
28 using ::testing::ValuesIn; | 29 using ::testing::ValuesIn; |
29 | 30 |
30 using blink::WebString; | 31 using blink::WebString; |
31 | 32 |
32 namespace content { | 33 namespace content { |
33 | 34 |
34 ACTION_P(RunClosure, closure) { | 35 ACTION_P(RunClosure, closure) { |
35 closure.Run(); | 36 closure.Run(); |
36 } | 37 } |
37 | 38 |
38 static const std::string kTestStreamUrl = "stream_url"; | 39 static const std::string kTestStreamUrl = "stream_url"; |
39 static const std::string kTestVideoTrackId = "video_track_id"; | 40 static const std::string kTestVideoTrackId = "video_track_id"; |
40 static const std::string kTestAudioTrackId = "audio_track_id"; | 41 static const std::string kTestAudioTrackId = "audio_track_id"; |
41 static const int kTestAudioChannels = 2; | 42 static const int kTestAudioChannels = 2; |
42 static const int kTestAudioBitsPerSample = 16; | 43 static const int kTestAudioBitsPerSample = 16; |
43 static const int kTestAudioSampleRate = 48000; | 44 static const int kTestAudioSampleRate = 48000; |
44 static const int kTestAudioBufferDurationMS = 60; | 45 static const int kTestAudioBufferDurationMs = 10; |
| 46 // Opus works with 60ms buffers, so 6 MediaStreamAudioTrack Buffers are needed |
| 47 // to encode one output buffer. |
| 48 static const int kRatioOpusToTestAudioBuffers = 6; |
45 | 49 |
46 struct MediaRecorderTestParams { | 50 struct MediaRecorderTestParams { |
47 const bool has_video; | 51 const bool has_video; |
48 const bool has_audio; | 52 const bool has_audio; |
49 const char* const mime_type; | 53 const char* const mime_type; |
50 const char* const codecs; | 54 const char* const codecs; |
51 const size_t first_encoded_video_frame_size; | |
52 const size_t second_encoded_video_frame_size; | |
53 const size_t first_encoded_audio_frame_size; | |
54 const size_t second_encoded_audio_frame_size; | |
55 }; | 55 }; |
56 | 56 |
57 // Array of valid combinations of video/audio/codecs and expected collected | 57 // Array of valid combinations of video/audio/codecs and expected collected |
58 // encoded sizes to use for parameterizing MediaRecorderHandlerTest. | 58 // encoded sizes to use for parameterizing MediaRecorderHandlerTest. |
59 static const MediaRecorderTestParams kMediaRecorderTestParams[] = { | 59 static const MediaRecorderTestParams kMediaRecorderTestParams[] = { |
60 {true, false, "video/webm", "vp8", 52, 32, 0, 0}, | 60 {true, false, "video/webm", "vp8"}, |
61 {true, false, "video/webm", "vp9", 33, 18, 0, 0}, | 61 {true, false, "video/webm", "vp9"}, |
62 {false, true, "video/webm", "vp8", 0, 0, 990, 706}}; | 62 {false, true, "video/webm", "vp8"}}; |
63 | 63 |
64 class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>, | 64 class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>, |
65 public blink::WebMediaRecorderHandlerClient { | 65 public blink::WebMediaRecorderHandlerClient { |
66 public: | 66 public: |
67 MediaRecorderHandlerTest() | 67 MediaRecorderHandlerTest() |
68 : media_recorder_handler_(new MediaRecorderHandler()), | 68 : media_recorder_handler_(new MediaRecorderHandler()), |
69 audio_source_(kTestAudioChannels, | 69 audio_source_(kTestAudioChannels, |
70 440 /* freq */, | 70 440 /* freq */, |
71 kTestAudioSampleRate) { | 71 kTestAudioSampleRate) { |
72 EXPECT_FALSE(media_recorder_handler_->recording_); | 72 EXPECT_FALSE(media_recorder_handler_->recording_); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 // Avoid issues with non-parameterized tests by calling this outside of ctr. | 106 // Avoid issues with non-parameterized tests by calling this outside of ctr. |
107 if (GetParam().has_video) | 107 if (GetParam().has_video) |
108 registry_.AddVideoTrack(kTestVideoTrackId); | 108 registry_.AddVideoTrack(kTestVideoTrackId); |
109 if (GetParam().has_audio) | 109 if (GetParam().has_audio) |
110 registry_.AddAudioTrack(kTestAudioTrackId); | 110 registry_.AddAudioTrack(kTestAudioTrackId); |
111 } | 111 } |
112 | 112 |
113 scoped_ptr<media::AudioBus> NextAudioBus() { | 113 scoped_ptr<media::AudioBus> NextAudioBus() { |
114 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create( | 114 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create( |
115 kTestAudioChannels, | 115 kTestAudioChannels, |
116 kTestAudioSampleRate * kTestAudioBufferDurationMS / 1000)); | 116 kTestAudioSampleRate * kTestAudioBufferDurationMs / 1000)); |
117 audio_source_.OnMoreData(bus.get(), 0, 0); | 117 audio_source_.OnMoreData(bus.get(), 0, 0); |
118 return bus; | 118 return bus; |
119 } | 119 } |
120 | 120 |
121 // A ChildProcess and a MessageLoopForUI are both needed to fool the Tracks | 121 // A ChildProcess and a MessageLoopForUI are both needed to fool the Tracks |
122 // and Sources in |registry_| into believing they are on the right threads. | 122 // and Sources in |registry_| into believing they are on the right threads. |
123 const base::MessageLoopForUI message_loop_; | 123 const base::MessageLoopForUI message_loop_; |
124 const ChildProcess child_process_; | 124 const ChildProcess child_process_; |
125 MockMediaStreamRegistry registry_; | 125 MockMediaStreamRegistry registry_; |
126 | 126 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type)); | 214 const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type)); |
215 const WebString codecs(base::UTF8ToUTF16(GetParam().codecs)); | 215 const WebString codecs(base::UTF8ToUTF16(GetParam().codecs)); |
216 EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(), | 216 EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(), |
217 mime_type, codecs, 0, 0)); | 217 mime_type, codecs, 0, 0)); |
218 EXPECT_TRUE(media_recorder_handler_->start()); | 218 EXPECT_TRUE(media_recorder_handler_->start()); |
219 | 219 |
220 InSequence s; | 220 InSequence s; |
221 const scoped_refptr<media::VideoFrame> video_frame = | 221 const scoped_refptr<media::VideoFrame> video_frame = |
222 media::VideoFrame::CreateBlackFrame(gfx::Size(160, 80)); | 222 media::VideoFrame::CreateBlackFrame(gfx::Size(160, 80)); |
223 | 223 |
| 224 const size_t kEncodedSizeThreshold = 16; |
224 { | 225 { |
225 base::RunLoop run_loop; | 226 base::RunLoop run_loop; |
226 base::Closure quit_closure = run_loop.QuitClosure(); | 227 base::Closure quit_closure = run_loop.QuitClosure(); |
227 // writeData() is pinged a number of times as the WebM header is written; | 228 // writeData() is pinged a number of times as the WebM header is written; |
228 // the last time it is called it has the encoded data. | 229 // the last time it is called it has the encoded data. |
229 const size_t encoded_data_size = GetParam().first_encoded_video_frame_size; | 230 EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _)) |
230 EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _)) | |
231 .Times(AtLeast(1)); | 231 .Times(AtLeast(1)); |
232 EXPECT_CALL(*this, writeData(_, encoded_data_size, _)) | 232 EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _)) |
233 .Times(1) | 233 .Times(1) |
234 .WillOnce(RunClosure(quit_closure)); | 234 .WillOnce(RunClosure(quit_closure)); |
235 | 235 |
236 OnVideoFrameForTesting(video_frame); | 236 OnVideoFrameForTesting(video_frame); |
237 run_loop.Run(); | 237 run_loop.Run(); |
238 } | 238 } |
| 239 Mock::VerifyAndClearExpectations(this); |
239 | 240 |
240 { | 241 { |
241 base::RunLoop run_loop; | 242 base::RunLoop run_loop; |
242 base::Closure quit_closure = run_loop.QuitClosure(); | 243 base::Closure quit_closure = run_loop.QuitClosure(); |
243 // The second time around writeData() is called a number of times to write | 244 // The second time around writeData() is called a number of times to write |
244 // the WebM frame header, and then is pinged with the encoded data. | 245 // the WebM frame header, and then is pinged with the encoded data. |
245 const size_t encoded_data_size = GetParam().second_encoded_video_frame_size; | 246 EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _)) |
246 EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _)) | |
247 .Times(AtLeast(1)); | 247 .Times(AtLeast(1)); |
248 EXPECT_CALL(*this, writeData(_, encoded_data_size, _)) | 248 EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _)) |
249 .Times(1) | 249 .Times(1) |
250 .WillOnce(RunClosure(quit_closure)); | 250 .WillOnce(RunClosure(quit_closure)); |
251 | 251 |
252 OnVideoFrameForTesting(video_frame); | 252 OnVideoFrameForTesting(video_frame); |
253 run_loop.Run(); | 253 run_loop.Run(); |
254 } | 254 } |
255 | 255 |
256 media_recorder_handler_->stop(); | 256 media_recorder_handler_->stop(); |
257 | 257 |
258 // Expect a last call on destruction, with size 0 and |lastInSlice| true. | 258 // Expect a last call on destruction, with size 0 and |lastInSlice| true. |
(...skipping 18 matching lines...) Expand all Loading... |
277 this, registry_.test_stream(), mime_type, WebString(), 0, 0)); | 277 this, registry_.test_stream(), mime_type, WebString(), 0, 0)); |
278 EXPECT_TRUE(media_recorder_handler_->start()); | 278 EXPECT_TRUE(media_recorder_handler_->start()); |
279 | 279 |
280 InSequence s; | 280 InSequence s; |
281 const scoped_ptr<media::AudioBus> audio_bus1 = NextAudioBus(); | 281 const scoped_ptr<media::AudioBus> audio_bus1 = NextAudioBus(); |
282 const scoped_ptr<media::AudioBus> audio_bus2 = NextAudioBus(); | 282 const scoped_ptr<media::AudioBus> audio_bus2 = NextAudioBus(); |
283 | 283 |
284 media::AudioParameters params( | 284 media::AudioParameters params( |
285 media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO, | 285 media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO, |
286 kTestAudioSampleRate, kTestAudioBitsPerSample, | 286 kTestAudioSampleRate, kTestAudioBitsPerSample, |
287 kTestAudioSampleRate * kTestAudioBufferDurationMS / 1000); | 287 kTestAudioSampleRate * kTestAudioBufferDurationMs / 1000); |
288 SetAudioFormatForTesting(params); | 288 SetAudioFormatForTesting(params); |
289 | 289 |
| 290 const size_t kEncodedSizeThreshold = 24; |
290 { | 291 { |
291 base::RunLoop run_loop; | 292 base::RunLoop run_loop; |
292 base::Closure quit_closure = run_loop.QuitClosure(); | 293 base::Closure quit_closure = run_loop.QuitClosure(); |
293 // writeData() is pinged a number of times as the WebM header is written; | 294 // writeData() is pinged a number of times as the WebM header is written; |
294 // the last time it is called it has the encoded data. | 295 // the last time it is called it has the encoded data. |
295 const size_t kEncodedDataSize = GetParam().first_encoded_audio_frame_size; | 296 EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _)) |
296 EXPECT_CALL(*this, writeData(_, Lt(kEncodedDataSize), _)).Times(AtLeast(1)); | 297 .Times(AtLeast(1)); |
297 EXPECT_CALL(*this, writeData(_, kEncodedDataSize, _)) | 298 EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _)) |
298 .Times(1) | 299 .Times(1) |
299 .WillOnce(RunClosure(quit_closure)); | 300 .WillOnce(RunClosure(quit_closure)); |
300 | 301 |
301 OnAudioBusForTesting(*audio_bus1); | 302 for (int i = 0; i < kRatioOpusToTestAudioBuffers; ++i) |
| 303 OnAudioBusForTesting(*audio_bus1); |
302 run_loop.Run(); | 304 run_loop.Run(); |
303 } | 305 } |
| 306 Mock::VerifyAndClearExpectations(this); |
304 | 307 |
305 { | 308 { |
306 base::RunLoop run_loop; | 309 base::RunLoop run_loop; |
307 base::Closure quit_closure = run_loop.QuitClosure(); | 310 base::Closure quit_closure = run_loop.QuitClosure(); |
308 // The second time around writeData() is called a number of times to write | 311 // The second time around writeData() is called a number of times to write |
309 // the WebM frame header, and then is pinged with the encoded data. | 312 // the WebM frame header, and then is pinged with the encoded data. |
310 const size_t kSecondEncodedDataSize = | 313 EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _)) |
311 GetParam().second_encoded_audio_frame_size; | |
312 EXPECT_CALL(*this, writeData(_, Lt(kSecondEncodedDataSize), _)) | |
313 .Times(AtLeast(1)); | 314 .Times(AtLeast(1)); |
314 EXPECT_CALL(*this, writeData(_, kSecondEncodedDataSize, _)) | 315 EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _)) |
315 .Times(1) | 316 .Times(1) |
316 .WillOnce(RunClosure(quit_closure)); | 317 .WillOnce(RunClosure(quit_closure)); |
317 | 318 |
318 OnAudioBusForTesting(*audio_bus2); | 319 for (int i = 0; i < kRatioOpusToTestAudioBuffers; ++i) |
| 320 OnAudioBusForTesting(*audio_bus2); |
319 run_loop.Run(); | 321 run_loop.Run(); |
320 } | 322 } |
321 | 323 |
322 media_recorder_handler_->stop(); | 324 media_recorder_handler_->stop(); |
323 | 325 |
324 // Expect a last call on destruction, with size 0 and |lastInSlice| true. | 326 // Expect a last call on destruction, with size 0 and |lastInSlice| true. |
325 EXPECT_CALL(*this, writeData(nullptr, 0, true)).Times(1); | 327 EXPECT_CALL(*this, writeData(nullptr, 0, true)).Times(1); |
326 media_recorder_handler_.reset(); | 328 media_recorder_handler_.reset(); |
327 } | 329 } |
328 | 330 |
329 } // namespace content | 331 } // namespace content |
OLD | NEW |