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