| 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 |