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