OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <map> | 5 #include <map> |
6 #include <string> | 6 #include <string> |
7 | 7 |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
22 | 22 |
23 using ::testing::_; | 23 using ::testing::_; |
24 using ::testing::AtLeast; | 24 using ::testing::AtLeast; |
25 using ::testing::AnyNumber; | 25 using ::testing::AnyNumber; |
26 using ::testing::DoAll; | 26 using ::testing::DoAll; |
27 using ::testing::InSequence; | 27 using ::testing::InSequence; |
28 using ::testing::Mock; | 28 using ::testing::Mock; |
29 using ::testing::Return; | 29 using ::testing::Return; |
30 | 30 |
31 // IPC::Msg.routing_id. | |
32 static const int32 kRouteId = 200; | |
33 // Id used to identify the capture session between renderer and | 31 // Id used to identify the capture session between renderer and |
34 // video_capture_host. | 32 // video_capture_host. |
35 static const int kDeviceId = 1; | 33 static const int kDeviceId = 1; |
36 // Id of a video capture device | 34 // Id of a video capture device |
37 static const media::VideoCaptureSessionId kTestFakeDeviceId = | 35 static const media::VideoCaptureSessionId kTestFakeDeviceId = |
38 media_stream::VideoCaptureManager::kStartOpenSessionId; | 36 media_stream::VideoCaptureManager::kStartOpenSessionId; |
39 | 37 |
40 // Define to enable test where video is dumped to file. | 38 // Define to enable test where video is dumped to file. |
41 // #define DUMP_VIDEO | 39 // #define DUMP_VIDEO |
42 | 40 |
(...skipping 27 matching lines...) Expand all Loading... |
70 | 68 |
71 class MockVideoCaptureHost : public VideoCaptureHost { | 69 class MockVideoCaptureHost : public VideoCaptureHost { |
72 public: | 70 public: |
73 MockVideoCaptureHost() : return_buffers_(false), dump_video_(false) {} | 71 MockVideoCaptureHost() : return_buffers_(false), dump_video_(false) {} |
74 virtual ~MockVideoCaptureHost() { | 72 virtual ~MockVideoCaptureHost() { |
75 STLDeleteContainerPairSecondPointers(filled_dib_.begin(), | 73 STLDeleteContainerPairSecondPointers(filled_dib_.begin(), |
76 filled_dib_.end()); | 74 filled_dib_.end()); |
77 } | 75 } |
78 | 76 |
79 // A list of mock methods. | 77 // A list of mock methods. |
80 MOCK_METHOD5(OnNewBufferCreated, | 78 MOCK_METHOD4(OnNewBufferCreated, |
81 void(int routing_id, int device_id, | 79 void(int device_id, base::SharedMemoryHandle handle, |
82 base::SharedMemoryHandle handle, | |
83 int length, int buffer_id)); | 80 int length, int buffer_id)); |
84 MOCK_METHOD3(OnBufferFilled, | 81 MOCK_METHOD3(OnBufferFilled, |
85 void(int routing_id, int device_id, int buffer_id)); | 82 void(int device_id, int buffer_id, base::Time timestamp)); |
86 MOCK_METHOD3(OnStateChanged, | 83 MOCK_METHOD2(OnStateChanged, |
87 void(int routing_id, int device_id, | 84 void(int device_id, media::VideoCapture::State state)); |
88 media::VideoCapture::State state)); | 85 MOCK_METHOD1(OnDeviceInfo, void(int device_id)); |
89 MOCK_METHOD2(OnDeviceInfo, void(int routing_id, int device_id)); | |
90 | 86 |
91 // Use class DumpVideo to write I420 video to file. | 87 // Use class DumpVideo to write I420 video to file. |
92 void SetDumpVideo(bool enable) { | 88 void SetDumpVideo(bool enable) { |
93 dump_video_ = enable; | 89 dump_video_ = enable; |
94 } | 90 } |
95 void SetReturnReceviedDibs(bool enable) { | 91 void SetReturnReceviedDibs(bool enable) { |
96 return_buffers_ = enable; | 92 return_buffers_ = enable; |
97 } | 93 } |
98 | 94 |
99 // Return Dibs we currently have received. | 95 // Return Dibs we currently have received. |
100 void ReturnReceivedDibs(int device_id) { | 96 void ReturnReceivedDibs(int device_id) { |
101 int handle = GetReceivedDib(); | 97 int handle = GetReceivedDib(); |
102 while (handle) { | 98 while (handle) { |
103 IPC::Message msg; | 99 this->OnReceiveEmptyBuffer(device_id, handle); |
104 msg.set_routing_id(kRouteId); | |
105 this->OnReceiveEmptyBuffer(msg, device_id, handle); | |
106 handle = GetReceivedDib(); | 100 handle = GetReceivedDib(); |
107 } | 101 } |
108 } | 102 } |
109 int GetReceivedDib() { | 103 int GetReceivedDib() { |
110 if (filled_dib_.empty()) | 104 if (filled_dib_.empty()) |
111 return 0; | 105 return 0; |
112 std::map<int, base::SharedMemory*>::iterator it = filled_dib_.begin(); | 106 std::map<int, base::SharedMemory*>::iterator it = filled_dib_.begin(); |
113 int h = it->first; | 107 int h = it->first; |
114 delete it->second; | 108 delete it->second; |
115 filled_dib_.erase(it); | 109 filled_dib_.erase(it); |
116 | 110 |
117 return h; | 111 return h; |
118 } | 112 } |
119 | 113 |
120 private: | 114 private: |
121 // This method is used to dispatch IPC messages to the renderer. We intercept | 115 // This method is used to dispatch IPC messages to the renderer. We intercept |
122 // these messages here and dispatch to our mock methods to verify the | 116 // these messages here and dispatch to our mock methods to verify the |
123 // conversation between this object and the renderer. | 117 // conversation between this object and the renderer. |
124 virtual bool Send(IPC::Message* message) { | 118 virtual bool Send(IPC::Message* message) { |
125 CHECK(message); | 119 CHECK(message); |
126 | 120 |
127 // In this method we dispatch the messages to the according handlers as if | 121 // In this method we dispatch the messages to the according handlers as if |
128 // we are the renderer. | 122 // we are the renderer. |
129 bool handled = true; | 123 bool handled = true; |
130 IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message) | 124 IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message) |
131 IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreated) | 125 IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreatedDispatch) |
132 IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilled) | 126 IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilledDispatch) |
133 IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChanged) | 127 IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChangedDispatch) |
134 IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfo) | 128 IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfoDispatch) |
135 IPC_MESSAGE_UNHANDLED(handled = false) | 129 IPC_MESSAGE_UNHANDLED(handled = false) |
136 IPC_END_MESSAGE_MAP() | 130 IPC_END_MESSAGE_MAP() |
137 EXPECT_TRUE(handled); | 131 EXPECT_TRUE(handled); |
138 | 132 |
139 delete message; | 133 delete message; |
140 return true; | 134 return true; |
141 } | 135 } |
142 | 136 |
143 // These handler methods do minimal things and delegate to the mock methods. | 137 // These handler methods do minimal things and delegate to the mock methods. |
144 void OnNewBufferCreated(const IPC::Message& msg, int device_id, | 138 void OnNewBufferCreatedDispatch(int device_id, |
145 base::SharedMemoryHandle handle, | 139 base::SharedMemoryHandle handle, |
146 int length, int buffer_id) { | 140 int length, int buffer_id) { |
147 OnNewBufferCreated(msg.routing_id(), device_id, handle, length, buffer_id); | 141 OnNewBufferCreated(device_id, handle, length, buffer_id); |
148 base::SharedMemory* dib = new base::SharedMemory(handle, false); | 142 base::SharedMemory* dib = new base::SharedMemory(handle, false); |
149 dib->Map(length); | 143 dib->Map(length); |
150 filled_dib_[buffer_id] = dib; | 144 filled_dib_[buffer_id] = dib; |
151 } | 145 } |
152 | 146 |
153 void OnBufferFilled(const IPC::Message& msg, int device_id, | 147 void OnBufferFilledDispatch(int device_id, int buffer_id, |
154 int buffer_id) { | 148 base::Time timestamp) { |
155 if (dump_video_) { | 149 if (dump_video_) { |
156 base::SharedMemory* dib = filled_dib_[buffer_id]; | 150 base::SharedMemory* dib = filled_dib_[buffer_id]; |
157 ASSERT_TRUE(dib != NULL); | 151 ASSERT_TRUE(dib != NULL); |
158 dumper_.NewVideoFrame(dib->memory()); | 152 dumper_.NewVideoFrame(dib->memory()); |
159 } | 153 } |
160 | 154 |
161 OnBufferFilled(msg.routing_id(), device_id, buffer_id); | 155 OnBufferFilled(device_id, buffer_id, timestamp); |
162 if (return_buffers_) { | 156 if (return_buffers_) { |
163 VideoCaptureHost::OnReceiveEmptyBuffer(msg, device_id, buffer_id); | 157 VideoCaptureHost::OnReceiveEmptyBuffer(device_id, buffer_id); |
164 } | 158 } |
165 } | 159 } |
166 | 160 |
167 void OnStateChanged(const IPC::Message& msg, int device_id, | 161 void OnStateChangedDispatch(int device_id, |
168 media::VideoCapture::State state) { | 162 media::VideoCapture::State state) { |
169 OnStateChanged(msg.routing_id(), device_id, state); | 163 OnStateChanged(device_id, state); |
170 } | 164 } |
171 | 165 |
172 void OnDeviceInfo(const IPC::Message& msg, int device_id, | 166 void OnDeviceInfoDispatch(int device_id, |
173 media::VideoCaptureParams params) { | 167 media::VideoCaptureParams params) { |
174 if (dump_video_) { | 168 if (dump_video_) { |
175 dumper_.StartDump(params.width, params.height); | 169 dumper_.StartDump(params.width, params.height); |
176 } | 170 } |
177 OnDeviceInfo(msg.routing_id(), device_id); | 171 OnDeviceInfo(device_id); |
178 } | 172 } |
179 | 173 |
180 std::map<int, base::SharedMemory*> filled_dib_; | 174 std::map<int, base::SharedMemory*> filled_dib_; |
181 bool return_buffers_; | 175 bool return_buffers_; |
182 bool dump_video_; | 176 bool dump_video_; |
183 DumpVideo dumper_; | 177 DumpVideo dumper_; |
184 }; | 178 }; |
185 | 179 |
186 ACTION_P(ExitMessageLoop, message_loop) { | 180 ACTION_P(ExitMessageLoop, message_loop) { |
187 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | 181 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
(...skipping 18 matching lines...) Expand all Loading... |
206 | 200 |
207 // Simulate IPC channel connected. | 201 // Simulate IPC channel connected. |
208 host_->OnChannelConnected(base::GetCurrentProcId()); | 202 host_->OnChannelConnected(base::GetCurrentProcId()); |
209 } | 203 } |
210 | 204 |
211 virtual void TearDown() { | 205 virtual void TearDown() { |
212 // Verifies and removes the expectations on host_ and | 206 // Verifies and removes the expectations on host_ and |
213 // returns true iff successful. | 207 // returns true iff successful. |
214 Mock::VerifyAndClearExpectations(host_); | 208 Mock::VerifyAndClearExpectations(host_); |
215 | 209 |
216 EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId, | 210 EXPECT_CALL(*host_, OnStateChanged(kDeviceId, |
217 media::VideoCapture::kStopped)) | 211 media::VideoCapture::kStopped)) |
218 .Times(AnyNumber()); | 212 .Times(AnyNumber()); |
219 | 213 |
220 // Simulate closing the IPC channel. | 214 // Simulate closing the IPC channel. |
221 host_->OnChannelClosing(); | 215 host_->OnChannelClosing(); |
222 | 216 |
223 // Release the reference to the mock object. The object will be destructed | 217 // Release the reference to the mock object. The object will be destructed |
224 // on message_loop_. | 218 // on message_loop_. |
225 host_ = NULL; | 219 host_ = NULL; |
226 | 220 |
(...skipping 22 matching lines...) Expand all Loading... |
249 void SyncWithVideoCaptureManagerThread() { | 243 void SyncWithVideoCaptureManagerThread() { |
250 message_loop_->PostTask( | 244 message_loop_->PostTask( |
251 FROM_HERE, NewRunnableFunction(&PostQuitOnVideoCaptureManagerThread, | 245 FROM_HERE, NewRunnableFunction(&PostQuitOnVideoCaptureManagerThread, |
252 message_loop_.get())); | 246 message_loop_.get())); |
253 message_loop_->Run(); | 247 message_loop_->Run(); |
254 } | 248 } |
255 | 249 |
256 void StartCapture() { | 250 void StartCapture() { |
257 InSequence s; | 251 InSequence s; |
258 // 1. Newly created buffers will arrive. | 252 // 1. Newly created buffers will arrive. |
259 EXPECT_CALL(*host_, OnNewBufferCreated(kRouteId, kDeviceId, _, _, _)) | 253 EXPECT_CALL(*host_, OnNewBufferCreated(kDeviceId, _, _, _)) |
260 .Times(AnyNumber()) | 254 .Times(AnyNumber()) |
261 .WillRepeatedly(Return()); | 255 .WillRepeatedly(Return()); |
262 | 256 |
263 // 2. First - get info about the new resolution | 257 // 2. First - get info about the new resolution |
264 EXPECT_CALL(*host_, OnDeviceInfo(kRouteId, kDeviceId)); | 258 EXPECT_CALL(*host_, OnDeviceInfo(kDeviceId)); |
265 | 259 |
266 // 3. Change state to started | 260 // 3. Change state to started |
267 EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId, | 261 EXPECT_CALL(*host_, OnStateChanged(kDeviceId, |
268 media::VideoCapture::kStarted)); | 262 media::VideoCapture::kStarted)); |
269 | 263 |
270 // 4. First filled buffer will arrive. | 264 // 4. First filled buffer will arrive. |
271 EXPECT_CALL(*host_, OnBufferFilled(kRouteId, kDeviceId, _)) | 265 EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _)) |
272 .Times(AnyNumber()) | 266 .Times(AnyNumber()) |
273 .WillOnce(ExitMessageLoop(message_loop_.get())); | 267 .WillOnce(ExitMessageLoop(message_loop_.get())); |
274 | 268 |
275 IPC::Message msg; | |
276 msg.set_routing_id(kRouteId); | |
277 | |
278 media::VideoCaptureParams params; | 269 media::VideoCaptureParams params; |
279 params.width = 352; | 270 params.width = 352; |
280 params.height = 288; | 271 params.height = 288; |
281 params.frame_per_second = 30; | 272 params.frame_per_second = 30; |
282 params.session_id = kTestFakeDeviceId; | 273 params.session_id = kTestFakeDeviceId; |
283 host_->OnStartCapture(msg, kDeviceId, params); | 274 host_->OnStartCapture(kDeviceId, params); |
284 message_loop_->Run(); | 275 message_loop_->Run(); |
285 } | 276 } |
286 | 277 |
287 void CaptureAndDumpVideo(int width, int heigt, int frame_rate) { | 278 void CaptureAndDumpVideo(int width, int heigt, int frame_rate) { |
288 InSequence s; | 279 InSequence s; |
289 // 1. First - get info about the new resolution | 280 // 1. First - get info about the new resolution |
290 EXPECT_CALL(*host_, OnDeviceInfo(kRouteId, kDeviceId)); | 281 EXPECT_CALL(*host_, OnDeviceInfo(kDeviceId)); |
291 | 282 |
292 // 2. Change state to started | 283 // 2. Change state to started |
293 EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId, | 284 EXPECT_CALL(*host_, OnStateChanged(kDeviceId, |
294 media::VideoCapture::kStarted)); | 285 media::VideoCapture::kStarted)); |
295 | 286 |
296 // 3. First filled buffer will arrive. | 287 // 3. First filled buffer will arrive. |
297 EXPECT_CALL(*host_, OnBufferFilled(kRouteId, kDeviceId, _)) | 288 EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _)) |
298 .Times(AnyNumber()) | 289 .Times(AnyNumber()) |
299 .WillOnce(ExitMessageLoop(message_loop_.get())); | 290 .WillOnce(ExitMessageLoop(message_loop_.get())); |
300 | 291 |
301 IPC::Message msg; | |
302 msg.set_routing_id(kRouteId); | |
303 | |
304 media::VideoCaptureParams params; | 292 media::VideoCaptureParams params; |
305 params.width = width; | 293 params.width = width; |
306 params.height = heigt; | 294 params.height = heigt; |
307 params.frame_per_second = frame_rate; | 295 params.frame_per_second = frame_rate; |
308 params.session_id = kTestFakeDeviceId; | 296 params.session_id = kTestFakeDeviceId; |
309 host_->SetDumpVideo(true); | 297 host_->SetDumpVideo(true); |
310 host_->OnStartCapture(msg, kDeviceId, params); | 298 host_->OnStartCapture(kDeviceId, params); |
311 message_loop_->Run(); | 299 message_loop_->Run(); |
312 } | 300 } |
313 | 301 |
314 void StopCapture() { | 302 void StopCapture() { |
315 EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId, | 303 EXPECT_CALL(*host_, OnStateChanged(kDeviceId, |
316 media::VideoCapture::kStopped)) | 304 media::VideoCapture::kStopped)) |
317 .Times(AtLeast(1)); | 305 .Times(AtLeast(1)); |
318 | 306 |
319 IPC::Message msg; | 307 host_->OnStopCapture(kDeviceId); |
320 msg.set_routing_id(kRouteId); | |
321 host_->OnStopCapture(msg, kDeviceId); | |
322 host_->SetReturnReceviedDibs(true); | 308 host_->SetReturnReceviedDibs(true); |
323 host_->ReturnReceivedDibs(kDeviceId); | 309 host_->ReturnReceivedDibs(kDeviceId); |
324 | 310 |
325 SyncWithVideoCaptureManagerThread(); | 311 SyncWithVideoCaptureManagerThread(); |
326 host_->SetReturnReceviedDibs(false); | 312 host_->SetReturnReceviedDibs(false); |
327 // Expect the VideoCaptureDevice has been stopped | 313 // Expect the VideoCaptureDevice has been stopped |
328 EXPECT_EQ(0u, host_->entries_.size()); | 314 EXPECT_EQ(0u, host_->entries_.size()); |
329 } | 315 } |
330 | 316 |
331 void NotifyPacketReady() { | 317 void NotifyPacketReady() { |
332 EXPECT_CALL(*host_, OnBufferFilled(kRouteId, kDeviceId, _)) | 318 EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _)) |
333 .Times(AnyNumber()) | 319 .Times(AnyNumber()) |
334 .WillOnce(ExitMessageLoop(message_loop_.get())) | 320 .WillOnce(ExitMessageLoop(message_loop_.get())) |
335 .RetiresOnSaturation(); | 321 .RetiresOnSaturation(); |
336 message_loop_->Run(); | 322 message_loop_->Run(); |
337 } | 323 } |
338 | 324 |
339 void ReturnReceivedPackets() { | 325 void ReturnReceivedPackets() { |
340 host_->ReturnReceivedDibs(kDeviceId); | 326 host_->ReturnReceivedDibs(kDeviceId); |
341 } | 327 } |
342 | 328 |
343 void SimulateError() { | 329 void SimulateError() { |
344 // Expect a change state to error state sent through IPC. | 330 // Expect a change state to error state sent through IPC. |
345 EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId, | 331 EXPECT_CALL(*host_, OnStateChanged(kDeviceId, |
346 media::VideoCapture::kError)) | 332 media::VideoCapture::kError)) |
347 .Times(1); | 333 .Times(1); |
348 VideoCaptureControllerID id(kRouteId, kDeviceId); | 334 VideoCaptureControllerID id(kDeviceId); |
349 host_->OnError(id); | 335 host_->OnError(id); |
350 SyncWithVideoCaptureManagerThread(); | 336 SyncWithVideoCaptureManagerThread(); |
351 } | 337 } |
352 | 338 |
353 scoped_refptr<MockVideoCaptureHost> host_; | 339 scoped_refptr<MockVideoCaptureHost> host_; |
354 private: | 340 private: |
355 scoped_ptr<MessageLoop> message_loop_; | 341 scoped_ptr<MessageLoop> message_loop_; |
356 scoped_ptr<BrowserThread> io_thread_; | 342 scoped_ptr<BrowserThread> io_thread_; |
357 | 343 |
358 DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest); | 344 DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest); |
(...skipping 11 matching lines...) Expand all Loading... |
370 StopCapture(); | 356 StopCapture(); |
371 } | 357 } |
372 | 358 |
373 TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) { | 359 TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) { |
374 StartCapture(); | 360 StartCapture(); |
375 SimulateError(); | 361 SimulateError(); |
376 StopCapture(); | 362 StopCapture(); |
377 } | 363 } |
378 | 364 |
379 TEST_F(VideoCaptureHostTest, StartCaptureError) { | 365 TEST_F(VideoCaptureHostTest, StartCaptureError) { |
380 EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId, | 366 EXPECT_CALL(*host_, OnStateChanged(kDeviceId, |
381 media::VideoCapture::kStopped)) | 367 media::VideoCapture::kStopped)) |
382 .Times(0); | 368 .Times(0); |
383 StartCapture(); | 369 StartCapture(); |
384 NotifyPacketReady(); | 370 NotifyPacketReady(); |
385 SimulateError(); | 371 SimulateError(); |
386 base::PlatformThread::Sleep(200); | 372 base::PlatformThread::Sleep(200); |
387 } | 373 } |
388 | 374 |
389 #ifdef DUMP_VIDEO | 375 #ifdef DUMP_VIDEO |
390 TEST_F(VideoCaptureHostTest, CaptureAndDumpVideoVga) { | 376 TEST_F(VideoCaptureHostTest, CaptureAndDumpVideoVga) { |
391 CaptureAndDumpVideo(640, 480, 30); | 377 CaptureAndDumpVideo(640, 480, 30); |
392 } | 378 } |
393 TEST_F(VideoCaptureHostTest, CaptureAndDump720P) { | 379 TEST_F(VideoCaptureHostTest, CaptureAndDump720P) { |
394 CaptureAndDumpVideo(1280, 720, 30); | 380 CaptureAndDumpVideo(1280, 720, 30); |
395 } | 381 } |
396 #endif | 382 #endif |
OLD | NEW |