Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: content/renderer/media/media_recorder_handler_unittest.cc

Issue 1407083006: Update MediaRecorderHandler to use AudioTrackRecorder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: trybots Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/run_loop.h" 5 #include "base/run_loop.h"
6 #include "base/strings/utf_string_conversions.h" 6 #include "base/strings/utf_string_conversions.h"
7 #include "content/child/child_process.h" 7 #include "content/child/child_process.h"
8 #include "content/renderer/media/media_recorder_handler.h" 8 #include "content/renderer/media/media_recorder_handler.h"
9 #include "content/renderer/media/mock_media_stream_registry.h" 9 #include "content/renderer/media/mock_media_stream_registry.h"
10 #include "media/audio/simple_sources.h"
11 #include "media/base/audio_bus.h"
10 #include "media/base/video_frame.h" 12 #include "media/base/video_frame.h"
11 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h" 15 #include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h"
14 #include "third_party/WebKit/public/platform/WebString.h" 16 #include "third_party/WebKit/public/platform/WebString.h"
15 #include "third_party/WebKit/public/web/WebHeap.h" 17 #include "third_party/WebKit/public/web/WebHeap.h"
16 18
17 using ::testing::_; 19 using ::testing::_;
18 using ::testing::AtLeast; 20 using ::testing::AtLeast;
19 using ::testing::InSequence; 21 using ::testing::InSequence;
20 using ::testing::Lt; 22 using ::testing::Lt;
21 using ::testing::Mock; 23 using ::testing::Mock;
22 using ::testing::TestWithParam; 24 using ::testing::TestWithParam;
23 using ::testing::ValuesIn; 25 using ::testing::ValuesIn;
24 26
25 using blink::WebString; 27 using blink::WebString;
26 28
27 namespace content { 29 namespace content {
28 30
29 ACTION_P(RunClosure, closure) { 31 ACTION_P(RunClosure, closure) {
30 closure.Run(); 32 closure.Run();
31 } 33 }
32 34
33 static const std::string kTestStreamUrl = "stream_url"; 35 static const std::string kTestStreamUrl = "stream_url";
34 static const std::string kTestVideoTrackId = "video_track_id"; 36 static const std::string kTestVideoTrackId = "video_track_id";
37 static const std::string kTestAudioTrackId = "audio_track_id";
38 static const int kTestAudioChannels = 2;
39 static const int kTestAudioBitsPerSample = 16;
40 static const int kTestAudioSampleRate = 48000;
41 static const int kTestAudioBufferDurationMS = 60;
35 42
36 struct MediaRecorderTestParams { 43 struct MediaRecorderTestParams {
44 const bool has_video;
45 const bool has_audio;
37 const char* const mime_type; 46 const char* const mime_type;
38 const size_t first_encoded_frame_size; 47 const size_t first_encoded_video_frame_size;
39 const size_t second_encoded_frame_size; 48 const size_t second_encoded_video_frame_size;
49 const size_t first_encoded_audio_frame_size;
50 const size_t second_encoded_audio_frame_size;
40 }; 51 };
41 52
42 static const MediaRecorderTestParams kMediaRecorderTestParams[] = { 53 static const MediaRecorderTestParams kMediaRecorderTestParams[] = {
43 {"video/vp8", 52, 32}, 54 {true, false, "video/vp8", 52, 32, 0, 0},
44 {"video/vp9", 33, 18}}; 55 {true, false, "video/vp9", 33, 18, 0, 0},
56 {false, true, "video/vp8", 0, 0, 990, 706}};
45 57
46 class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>, 58 class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>,
47 public blink::WebMediaRecorderHandlerClient { 59 public blink::WebMediaRecorderHandlerClient {
48 public: 60 public:
49 MediaRecorderHandlerTest() 61 MediaRecorderHandlerTest()
50 : media_recorder_handler_(new MediaRecorderHandler()) { 62 : media_recorder_handler_(new MediaRecorderHandler()),
63 audio_source_(kTestAudioChannels,
64 440 /* freq */,
65 kTestAudioSampleRate) {
51 EXPECT_FALSE(media_recorder_handler_->recording_); 66 EXPECT_FALSE(media_recorder_handler_->recording_);
52 67
53 registry_.Init(kTestStreamUrl); 68 registry_.Init(kTestStreamUrl);
54 registry_.AddVideoTrack(kTestVideoTrackId); 69 if (GetParam().has_video)
70 registry_.AddVideoTrack(kTestVideoTrackId);
71 if (GetParam().has_audio)
72 registry_.AddAudioTrack(kTestAudioTrackId);
55 } 73 }
56 74
57 ~MediaRecorderHandlerTest() { 75 ~MediaRecorderHandlerTest() {
58 registry_.reset(); 76 registry_.reset();
59 blink::WebHeap::collectAllGarbageForTesting(); 77 blink::WebHeap::collectAllGarbageForTesting();
60 } 78 }
61 79
62 MOCK_METHOD3(writeData, void(const char*, size_t, bool)); 80 MOCK_METHOD3(writeData, void(const char*, size_t, bool));
63 MOCK_METHOD1(failOutOfMemory, void(const WebString& message)); 81 MOCK_METHOD1(failOutOfMemory, void(const WebString& message));
64 MOCK_METHOD1(failIllegalStreamModification, void(const WebString& message)); 82 MOCK_METHOD1(failIllegalStreamModification, void(const WebString& message));
65 MOCK_METHOD1(failOtherRecordingError, void(const WebString& message)); 83 MOCK_METHOD1(failOtherRecordingError, void(const WebString& message));
66 84
67 bool recording() const { return media_recorder_handler_->recording_; } 85 bool recording() const { return media_recorder_handler_->recording_; }
68 bool hasVideoRecorders() const { 86 bool hasVideoRecorders() const {
69 return !media_recorder_handler_->video_recorders_.empty(); 87 return !media_recorder_handler_->video_recorders_.empty();
70 } 88 }
89 bool hasAudioRecorders() const {
90 return !media_recorder_handler_->audio_recorders_.empty();
91 }
71 92
72 void OnVideoFrameForTesting(const scoped_refptr<media::VideoFrame>& frame) { 93 void OnVideoFrameForTesting(const scoped_refptr<media::VideoFrame>& frame) {
73 media_recorder_handler_->OnVideoFrameForTesting(frame, 94 media_recorder_handler_->OnVideoFrameForTesting(frame,
74 base::TimeTicks::Now()); 95 base::TimeTicks::Now());
75 } 96 }
97 void OnAudioBusForTesting(const media::AudioBus& audio_bus) {
98 media_recorder_handler_->OnAudioBusForTesting(audio_bus,
99 base::TimeTicks::Now());
100 }
101 void SetAudioFormatForTesting(const media::AudioParameters& params) {
102 media_recorder_handler_->SetAudioFormatForTesting(params);
103 }
104
105 scoped_ptr<media::AudioBus> NextAudioBus() {
106 scoped_ptr<media::AudioBus> bus(media::AudioBus::Create(
107 kTestAudioChannels,
108 kTestAudioSampleRate * kTestAudioBufferDurationMS / 1000));
109 audio_source_.OnMoreData(bus.get(), 0);
110 return bus.Pass();
111 }
76 112
77 // A ChildProcess and a MessageLoopForUI are both needed to fool the Tracks 113 // A ChildProcess and a MessageLoopForUI are both needed to fool the Tracks
78 // and Sources in |registry_| into believing they are on the right threads. 114 // and Sources in |registry_| into believing they are on the right threads.
79 const base::MessageLoopForUI message_loop_; 115 const base::MessageLoopForUI message_loop_;
80 const ChildProcess child_process_; 116 const ChildProcess child_process_;
81 MockMediaStreamRegistry registry_; 117 MockMediaStreamRegistry registry_;
82 118
83 // The Class under test. Needs to be scoped_ptr to force its destruction. 119 // The Class under test. Needs to be scoped_ptr to force its destruction.
84 scoped_ptr<MediaRecorderHandler> media_recorder_handler_; 120 scoped_ptr<MediaRecorderHandler> media_recorder_handler_;
85 121
122 // For generating test AudioBuses
123 media::SineWaveAudioSource audio_source_;
124
86 private: 125 private:
87 DISALLOW_COPY_AND_ASSIGN(MediaRecorderHandlerTest); 126 DISALLOW_COPY_AND_ASSIGN(MediaRecorderHandlerTest);
88 }; 127 };
89 128
90 // Checks that canSupportMimeType() works as expected. 129 // Checks that canSupportMimeType() works as expected.
91 // TODO(mcasas): revisit this when canSupportMimeType() is fully implemented. 130 // TODO(mcasas): revisit this when canSupportMimeType() is fully implemented.
92 TEST_F(MediaRecorderHandlerTest, CanSupportMimeType) { 131 TEST_P(MediaRecorderHandlerTest, CanSupportMimeType) {
mcasas 2015/11/19 00:49:52 Hmm this should not be parameterised, right? Keep
ajose 2015/11/19 22:17:19 Done.
93 const WebString good_mime_type_vp8(base::UTF8ToUTF16("video/vp8")); 132 const WebString good_mime_type_vp8(base::UTF8ToUTF16("video/vp8"));
94 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type_vp8)); 133 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type_vp8));
95 134
96 const WebString good_mime_type_vp9(base::UTF8ToUTF16("video/vp9")); 135 const WebString good_mime_type_vp9(base::UTF8ToUTF16("video/vp9"));
97 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type_vp9)); 136 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(good_mime_type_vp9));
98 137
138 const WebString audio_mime_type(base::UTF8ToUTF16("audio/opus"));
139 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(audio_mime_type));
140
99 const WebString bad_mime_type(base::UTF8ToUTF16("video/unsupportedcodec")); 141 const WebString bad_mime_type(base::UTF8ToUTF16("video/unsupportedcodec"));
100 EXPECT_FALSE(media_recorder_handler_->canSupportMimeType(bad_mime_type)); 142 EXPECT_FALSE(media_recorder_handler_->canSupportMimeType(bad_mime_type));
101 143
102 const WebString empty_mime_type(base::UTF8ToUTF16("")); 144 const WebString empty_mime_type(base::UTF8ToUTF16(""));
103 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(empty_mime_type)); 145 EXPECT_TRUE(media_recorder_handler_->canSupportMimeType(empty_mime_type));
104 } 146 }
mcasas 2015/11/19 00:49:52 Guess this test should at least try an OK combinat
ajose 2015/11/19 22:17:19 Done.
105 147
106 // Checks that the initialization-destruction sequence works fine. 148 // Checks that the initialization-destruction sequence works fine.
107 TEST_P(MediaRecorderHandlerTest, InitializeStartStop) { 149 TEST_P(MediaRecorderHandlerTest, InitializeStartStop) {
108 const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type)); 150 const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type));
109 EXPECT_TRUE(media_recorder_handler_->initialize(this, 151 EXPECT_TRUE(media_recorder_handler_->initialize(this,
110 registry_.test_stream(), 152 registry_.test_stream(),
111 mime_type)); 153 mime_type));
112 EXPECT_FALSE(recording()); 154 EXPECT_FALSE(recording());
113 EXPECT_FALSE(hasVideoRecorders()); 155 EXPECT_FALSE(hasVideoRecorders());
156 EXPECT_FALSE(hasAudioRecorders());
114 157
115 EXPECT_TRUE(media_recorder_handler_->start()); 158 EXPECT_TRUE(media_recorder_handler_->start());
116 EXPECT_TRUE(recording()); 159 EXPECT_TRUE(recording());
117 EXPECT_TRUE(hasVideoRecorders()); 160
161 if (GetParam().has_video)
162 EXPECT_TRUE(hasVideoRecorders());
163 else
164 EXPECT_FALSE(hasVideoRecorders());
mcasas 2015/11/19 00:49:52 EXPECT_TRUE(hasVideoRecorders() || !GetParam().has
ajose 2015/11/19 22:17:19 Done.
165
166 if (GetParam().has_audio)
167 EXPECT_TRUE(hasAudioRecorders());
168 else
169 EXPECT_FALSE(hasAudioRecorders());
118 170
119 media_recorder_handler_->stop(); 171 media_recorder_handler_->stop();
120 EXPECT_FALSE(recording()); 172 EXPECT_FALSE(recording());
121 EXPECT_FALSE(hasVideoRecorders()); 173 EXPECT_FALSE(hasVideoRecorders());
174 EXPECT_FALSE(hasAudioRecorders());
122 175
123 // Expect a last call on destruction. 176 // Expect a last call on destruction.
124 EXPECT_CALL(*this, writeData(_, _, true)).Times(1); 177 EXPECT_CALL(*this, writeData(_, _, true)).Times(1);
125 media_recorder_handler_.reset(); 178 media_recorder_handler_.reset();
126 } 179 }
127 180
128 // Sends 2 frames and expect them as WebM contained encoded data in writeData(). 181 // Sends 2 frames and expect them as WebM contained encoded data in writeData().
129 TEST_P(MediaRecorderHandlerTest, EncodeVideoFrames) { 182 TEST_P(MediaRecorderHandlerTest, EncodeVideoFrames) {
183 // Video-only test.
184 if (GetParam().has_audio) {
mcasas 2015/11/19 00:49:52 no {}
ajose 2015/11/19 22:17:19 Done.
185 return;
186 }
187
130 const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type)); 188 const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type));
131 EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(), 189 EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(),
132 mime_type)); 190 mime_type));
133 EXPECT_TRUE(media_recorder_handler_->start()); 191 EXPECT_TRUE(media_recorder_handler_->start());
134 192
135 InSequence s; 193 InSequence s;
136 const scoped_refptr<media::VideoFrame> video_frame = 194 const scoped_refptr<media::VideoFrame> video_frame =
137 media::VideoFrame::CreateBlackFrame(gfx::Size(160, 80)); 195 media::VideoFrame::CreateBlackFrame(gfx::Size(160, 80));
138 196
139 { 197 {
140 base::RunLoop run_loop; 198 base::RunLoop run_loop;
141 base::Closure quit_closure = run_loop.QuitClosure(); 199 base::Closure quit_closure = run_loop.QuitClosure();
142 // writeData() is pinged a number of times as the WebM header is written; 200 // writeData() is pinged a number of times as the WebM header is written;
143 // the last time it is called it has the encoded data. 201 // the last time it is called it has the encoded data.
144 const size_t encoded_data_size = GetParam().first_encoded_frame_size; 202 const size_t encoded_data_size = GetParam().first_encoded_video_frame_size;
145 EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _)) 203 EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _))
146 .Times(AtLeast(1)); 204 .Times(AtLeast(1));
147 EXPECT_CALL(*this, writeData(_, encoded_data_size, _)) 205 EXPECT_CALL(*this, writeData(_, encoded_data_size, _))
148 .Times(1) 206 .Times(1)
149 .WillOnce(RunClosure(quit_closure)); 207 .WillOnce(RunClosure(quit_closure));
150 208
151 OnVideoFrameForTesting(video_frame); 209 OnVideoFrameForTesting(video_frame);
152 run_loop.Run(); 210 run_loop.Run();
153 } 211 }
154 212
155 { 213 {
156 base::RunLoop run_loop; 214 base::RunLoop run_loop;
157 base::Closure quit_closure = run_loop.QuitClosure(); 215 base::Closure quit_closure = run_loop.QuitClosure();
158 // The second time around writeData() is called a number of times to write 216 // The second time around writeData() is called a number of times to write
159 // the WebM frame header, and then is pinged with the encoded data. 217 // the WebM frame header, and then is pinged with the encoded data.
160 const size_t encoded_data_size = GetParam().second_encoded_frame_size; 218 const size_t encoded_data_size = GetParam().second_encoded_video_frame_size;
161 EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _)) 219 EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _))
162 .Times(AtLeast(1)); 220 .Times(AtLeast(1));
163 EXPECT_CALL(*this, writeData(_, encoded_data_size, _)) 221 EXPECT_CALL(*this, writeData(_, encoded_data_size, _))
164 .Times(1) 222 .Times(1)
165 .WillOnce(RunClosure(quit_closure)); 223 .WillOnce(RunClosure(quit_closure));
166 224
167 OnVideoFrameForTesting(video_frame); 225 OnVideoFrameForTesting(video_frame);
168 run_loop.Run(); 226 run_loop.Run();
169 } 227 }
170 228
171 media_recorder_handler_->stop(); 229 media_recorder_handler_->stop();
172 230
173 // Expect a last call on destruction, with size 0 and |lastInSlice| true. 231 // Expect a last call on destruction, with size 0 and |lastInSlice| true.
174 EXPECT_CALL(*this, writeData(nullptr, 0, true)).Times(1); 232 EXPECT_CALL(*this, writeData(nullptr, 0, true)).Times(1);
175 media_recorder_handler_.reset(); 233 media_recorder_handler_.reset();
176 } 234 }
177 235
178 INSTANTIATE_TEST_CASE_P(, 236 INSTANTIATE_TEST_CASE_P(,
179 MediaRecorderHandlerTest, 237 MediaRecorderHandlerTest,
180 ValuesIn(kMediaRecorderTestParams)); 238 ValuesIn(kMediaRecorderTestParams));
181 239
240 // Sends 2 frames and expect them as WebM contained encoded data in writeData().
241 TEST_P(MediaRecorderHandlerTest, EncodeAudioFrames) {
242 // Audio-only test.
243 if (GetParam().has_video) {
244 return;
245 }
mcasas 2015/11/19 00:49:52 no {}
ajose 2015/11/19 22:17:19 Done.
246
247 const WebString mime_type(base::UTF8ToUTF16("audio/opus"));
248 EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(),
249 mime_type));
250 EXPECT_TRUE(media_recorder_handler_->start());
251
252 InSequence s;
253 const scoped_ptr<media::AudioBus> audio_bus1 = NextAudioBus();
254 const scoped_ptr<media::AudioBus> audio_bus2 = NextAudioBus();
255
256 media::AudioParameters params(
257 media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO,
258 kTestAudioSampleRate, kTestAudioBitsPerSample,
259 kTestAudioSampleRate * kTestAudioBufferDurationMS / 1000);
260 SetAudioFormatForTesting(params);
261
262 {
263 base::RunLoop run_loop;
264 base::Closure quit_closure = run_loop.QuitClosure();
265 // writeData() is pinged a number of times as the WebM header is written;
266 // the last time it is called it has the encoded data.
267 const size_t kEncodedDataSize = GetParam().first_encoded_audio_frame_size;
268 EXPECT_CALL(*this, writeData(_, Lt(kEncodedDataSize), _)).Times(AtLeast(1));
269 EXPECT_CALL(*this, writeData(_, kEncodedDataSize, _))
270 .Times(1)
271 .WillOnce(RunClosure(quit_closure));
272
273 OnAudioBusForTesting(*audio_bus1);
274 run_loop.Run();
275 }
276
277 {
278 base::RunLoop run_loop;
279 base::Closure quit_closure = run_loop.QuitClosure();
280 // The second time around writeData() is called a number of times to write
281 // the WebM frame header, and then is pinged with the encoded data.
282 const size_t kSecondEncodedDataSize =
283 GetParam().second_encoded_audio_frame_size;
284 EXPECT_CALL(*this, writeData(_, Lt(kSecondEncodedDataSize), _))
285 .Times(AtLeast(1));
286 EXPECT_CALL(*this, writeData(_, kSecondEncodedDataSize, _))
287 .Times(1)
288 .WillOnce(RunClosure(quit_closure));
289
290 OnAudioBusForTesting(*audio_bus2);
291 run_loop.Run();
292 }
293
294 media_recorder_handler_->stop();
295
296 // Expect a last call on destruction, with size 0 and |lastInSlice| true.
297 EXPECT_CALL(*this, writeData(nullptr, 0, true)).Times(1);
298 media_recorder_handler_.reset();
299 }
300
182 } // namespace content 301 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698