OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/video/capture/win/video_capture_device_mf_win.h" | 5 #include "media/video/capture/win/video_capture_device_mf_win.h" |
6 | 6 |
7 #include <mfapi.h> | 7 #include <mfapi.h> |
8 #include <mferror.h> | 8 #include <mferror.h> |
9 | 9 |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 for (int i = 0; i < arraysize(kFormatMap); ++i) { | 87 for (int i = 0; i < arraysize(kFormatMap); ++i) { |
88 if (kFormatMap[i].guid == guid) { | 88 if (kFormatMap[i].guid == guid) { |
89 *format = kFormatMap[i].format; | 89 *format = kFormatMap[i].format; |
90 return true; | 90 return true; |
91 } | 91 } |
92 } | 92 } |
93 | 93 |
94 return false; | 94 return false; |
95 } | 95 } |
96 | 96 |
97 bool GetFrameSize(IMFMediaType* type, gfx::Size* frame_size) { | 97 bool GetFrameSize(IMFMediaType* type, int* width, int* height) { |
98 UINT32 width32, height32; | 98 UINT32 width32, height32; |
99 if (FAILED(MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width32, &height32))) | 99 if (FAILED(MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width32, &height32))) |
100 return false; | 100 return false; |
101 frame_size->SetSize(width32, height32); | 101 *width = width32; |
| 102 *height = height32; |
102 return true; | 103 return true; |
103 } | 104 } |
104 | 105 |
105 bool GetFrameRate(IMFMediaType* type, | 106 bool GetFrameRate(IMFMediaType* type, |
106 int* frame_rate_numerator, | 107 int* frame_rate_numerator, |
107 int* frame_rate_denominator) { | 108 int* frame_rate_denominator) { |
108 UINT32 numerator, denominator; | 109 UINT32 numerator, denominator; |
109 if (FAILED(MFGetAttributeRatio(type, MF_MT_FRAME_RATE, &numerator, | 110 if (FAILED(MFGetAttributeRatio(type, MF_MT_FRAME_RATE, &numerator, |
110 &denominator))|| | 111 &denominator))|| |
111 !denominator) { | 112 !denominator) { |
112 return false; | 113 return false; |
113 } | 114 } |
114 *frame_rate_numerator = numerator; | 115 *frame_rate_numerator = numerator; |
115 *frame_rate_denominator = denominator; | 116 *frame_rate_denominator = denominator; |
116 return true; | 117 return true; |
117 } | 118 } |
118 | 119 |
119 bool FillCapabilitiesFromType(IMFMediaType* type, | 120 bool FillCapabilitiesFromType(IMFMediaType* type, |
120 VideoCaptureCapabilityWin* capability) { | 121 VideoCaptureCapabilityWin* capability) { |
121 GUID type_guid; | 122 GUID type_guid; |
122 if (FAILED(type->GetGUID(MF_MT_SUBTYPE, &type_guid)) || | 123 if (FAILED(type->GetGUID(MF_MT_SUBTYPE, &type_guid)) || |
123 !GetFrameSize(type, &capability->supported_format.frame_size) || | 124 !FormatFromGuid(type_guid, &capability->color) || |
| 125 !GetFrameSize(type, &capability->width, &capability->height) || |
124 !GetFrameRate(type, | 126 !GetFrameRate(type, |
125 &capability->frame_rate_numerator, | 127 &capability->frame_rate_numerator, |
126 &capability->frame_rate_denominator) || | 128 &capability->frame_rate_denominator)) { |
127 !FormatFromGuid(type_guid, &capability->supported_format.pixel_format)) { | |
128 return false; | 129 return false; |
129 } | 130 } |
130 // Keep the integer version of the frame_rate for (potential) returns. | 131 // Keep the integer version of the frame_rate for (potential) returns. |
131 capability->supported_format.frame_rate = | 132 capability->frame_rate = |
132 capability->frame_rate_numerator / capability->frame_rate_denominator; | 133 capability->frame_rate_numerator / capability->frame_rate_denominator; |
133 | 134 |
134 return true; | 135 return true; |
135 } | 136 } |
136 | 137 |
137 HRESULT FillCapabilities(IMFSourceReader* source, | 138 HRESULT FillCapabilities(IMFSourceReader* source, |
138 CapabilityList* capabilities) { | 139 CapabilityList* capabilities) { |
139 DWORD stream_index = 0; | 140 DWORD stream_index = 0; |
140 ScopedComPtr<IMFMediaType> type; | 141 ScopedComPtr<IMFMediaType> type; |
141 HRESULT hr; | 142 HRESULT hr; |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 DCHECK(attributes); | 330 DCHECK(attributes); |
330 | 331 |
331 callback_ = new MFReaderCallback(this); | 332 callback_ = new MFReaderCallback(this); |
332 attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback_.get()); | 333 attributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, callback_.get()); |
333 | 334 |
334 return SUCCEEDED(MFCreateSourceReaderFromMediaSource(source, attributes, | 335 return SUCCEEDED(MFCreateSourceReaderFromMediaSource(source, attributes, |
335 reader_.Receive())); | 336 reader_.Receive())); |
336 } | 337 } |
337 | 338 |
338 void VideoCaptureDeviceMFWin::AllocateAndStart( | 339 void VideoCaptureDeviceMFWin::AllocateAndStart( |
339 const VideoCaptureParams& params, | 340 const VideoCaptureCapability& capture_format, |
340 scoped_ptr<VideoCaptureDevice::Client> client) { | 341 scoped_ptr<VideoCaptureDevice::Client> client) { |
341 DCHECK(CalledOnValidThread()); | 342 DCHECK(CalledOnValidThread()); |
342 | 343 |
343 base::AutoLock lock(lock_); | 344 base::AutoLock lock(lock_); |
344 | 345 |
345 client_ = client.Pass(); | 346 client_ = client.Pass(); |
346 DCHECK_EQ(capture_, false); | 347 DCHECK_EQ(capture_, false); |
347 | 348 |
348 CapabilityList capabilities; | 349 CapabilityList capabilities; |
349 HRESULT hr = S_OK; | 350 HRESULT hr = S_OK; |
350 if (!reader_ || FAILED(hr = FillCapabilities(reader_, &capabilities))) { | 351 if (!reader_ || FAILED(hr = FillCapabilities(reader_, &capabilities))) { |
351 OnError(hr); | 352 OnError(hr); |
352 return; | 353 return; |
353 } | 354 } |
354 | 355 |
355 VideoCaptureCapabilityWin found_capability = | 356 VideoCaptureCapabilityWin found_capability = |
356 capabilities.GetBestMatchedFormat( | 357 capabilities.GetBestMatchedCapability(capture_format.width, |
357 params.requested_format.frame_size.width(), | 358 capture_format.height, |
358 params.requested_format.frame_size.height(), | 359 capture_format.frame_rate); |
359 params.requested_format.frame_rate); | 360 DLOG(INFO) << "Chosen capture format= (" << found_capability.width << "x" |
| 361 << found_capability.height << ")@(" |
| 362 << found_capability.frame_rate_numerator << "/" |
| 363 << found_capability.frame_rate_denominator << ")fps"; |
360 | 364 |
361 ScopedComPtr<IMFMediaType> type; | 365 ScopedComPtr<IMFMediaType> type; |
362 if (FAILED(hr = reader_->GetNativeMediaType( | 366 if (FAILED(hr = reader_->GetNativeMediaType( |
363 MF_SOURCE_READER_FIRST_VIDEO_STREAM, found_capability.stream_index, | 367 MF_SOURCE_READER_FIRST_VIDEO_STREAM, found_capability.stream_index, |
364 type.Receive())) || | 368 type.Receive())) || |
365 FAILED(hr = reader_->SetCurrentMediaType( | 369 FAILED(hr = reader_->SetCurrentMediaType( |
366 MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, type))) { | 370 MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, type))) { |
367 OnError(hr); | 371 OnError(hr); |
368 return; | 372 return; |
369 } | 373 } |
370 | 374 |
371 if (FAILED(hr = reader_->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, | 375 if (FAILED(hr = reader_->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, |
372 NULL, NULL, NULL, NULL))) { | 376 NULL, NULL, NULL, NULL))) { |
373 OnError(hr); | 377 OnError(hr); |
374 return; | 378 return; |
375 } | 379 } |
376 capture_format_ = found_capability.supported_format; | 380 current_setting_ = found_capability; |
377 capture_ = true; | 381 capture_ = true; |
378 } | 382 } |
379 | 383 |
380 void VideoCaptureDeviceMFWin::StopAndDeAllocate() { | 384 void VideoCaptureDeviceMFWin::StopAndDeAllocate() { |
381 DCHECK(CalledOnValidThread()); | 385 DCHECK(CalledOnValidThread()); |
382 base::WaitableEvent flushed(false, false); | 386 base::WaitableEvent flushed(false, false); |
383 const int kFlushTimeOutInMs = 1000; | 387 const int kFlushTimeOutInMs = 1000; |
384 bool wait = false; | 388 bool wait = false; |
385 { | 389 { |
386 base::AutoLock lock(lock_); | 390 base::AutoLock lock(lock_); |
(...skipping 26 matching lines...) Expand all Loading... |
413 bool flip_vert, | 417 bool flip_vert, |
414 bool flip_horiz) { | 418 bool flip_horiz) { |
415 base::AutoLock lock(lock_); | 419 base::AutoLock lock(lock_); |
416 if (data && client_.get()) | 420 if (data && client_.get()) |
417 client_->OnIncomingCapturedFrame(data, | 421 client_->OnIncomingCapturedFrame(data, |
418 length, | 422 length, |
419 time_stamp, | 423 time_stamp, |
420 rotation, | 424 rotation, |
421 flip_vert, | 425 flip_vert, |
422 flip_horiz, | 426 flip_horiz, |
423 capture_format_); | 427 current_setting_); |
424 | 428 |
425 if (capture_) { | 429 if (capture_) { |
426 HRESULT hr = reader_->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, | 430 HRESULT hr = reader_->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, |
427 NULL, NULL, NULL, NULL); | 431 NULL, NULL, NULL, NULL); |
428 if (FAILED(hr)) { | 432 if (FAILED(hr)) { |
429 // If running the *VideoCap* unit tests on repeat, this can sometimes | 433 // If running the *VideoCap* unit tests on repeat, this can sometimes |
430 // fail with HRESULT_FROM_WINHRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION). | 434 // fail with HRESULT_FROM_WINHRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION). |
431 // It's not clear to me why this is, but it is possible that it has | 435 // It's not clear to me why this is, but it is possible that it has |
432 // something to do with this bug: | 436 // something to do with this bug: |
433 // http://support.microsoft.com/kb/979567 | 437 // http://support.microsoft.com/kb/979567 |
434 OnError(hr); | 438 OnError(hr); |
435 } | 439 } |
436 } | 440 } |
437 } | 441 } |
438 | 442 |
439 void VideoCaptureDeviceMFWin::OnError(HRESULT hr) { | 443 void VideoCaptureDeviceMFWin::OnError(HRESULT hr) { |
440 DLOG(ERROR) << "VideoCaptureDeviceMFWin: " << std::hex << hr; | 444 DLOG(ERROR) << "VideoCaptureDeviceMFWin: " << std::hex << hr; |
441 if (client_.get()) | 445 if (client_.get()) |
442 client_->OnError(); | 446 client_->OnError(); |
443 } | 447 } |
444 | 448 |
445 } // namespace media | 449 } // namespace media |
OLD | NEW |