Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: media/video/capture/win/video_capture_device_win.cc

Issue 558623002: Video capture: Refactor GetBestMatchedFormat from Win to OS independent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix mac syntax error Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_win.h" 5 #include "media/video/capture/win/video_capture_device_win.h"
6 6
7 #include <ks.h> 7 #include <ks.h>
8 #include <ksmedia.h> 8 #include <ksmedia.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 280
281 void VideoCaptureDeviceWin::AllocateAndStart( 281 void VideoCaptureDeviceWin::AllocateAndStart(
282 const VideoCaptureParams& params, 282 const VideoCaptureParams& params,
283 scoped_ptr<VideoCaptureDevice::Client> client) { 283 scoped_ptr<VideoCaptureDevice::Client> client) {
284 DCHECK(CalledOnValidThread()); 284 DCHECK(CalledOnValidThread());
285 if (state_ != kIdle) 285 if (state_ != kIdle)
286 return; 286 return;
287 287
288 client_ = client.Pass(); 288 client_ = client.Pass();
289 289
290 // Get the camera capability that best match the requested resolution. 290 // Get the camera capability that best match the requested format.
291 const VideoCaptureCapabilityWin& found_capability = 291 const VideoCaptureCapabilityWin& found_capability =
292 capabilities_.GetBestMatchedFormat( 292 *GetBestMatchedFormat(params.requested_format, capabilities_);
293 params.requested_format.frame_size.width(), 293 VideoCaptureFormat format = found_capability.second;
294 params.requested_format.frame_size.height(),
295 params.requested_format.frame_rate);
296 VideoCaptureFormat format = found_capability.supported_format;
297 294
298 // Reduce the frame rate if the requested frame rate is lower 295 // Reduce the frame rate if the requested frame rate is lower
299 // than the capability. 296 // than the capability.
300 if (format.frame_rate > params.requested_format.frame_rate) 297 format.frame_rate =
301 format.frame_rate = params.requested_format.frame_rate; 298 std::min(format.frame_rate, params.requested_format.frame_rate);
302 299
303 ScopedComPtr<IAMStreamConfig> stream_config; 300 ScopedComPtr<IAMStreamConfig> stream_config;
304 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); 301 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
305 if (FAILED(hr)) { 302 if (FAILED(hr)) {
306 SetErrorState("Can't get the Capture format settings"); 303 SetErrorState("Can't get the Capture format settings");
307 return; 304 return;
308 } 305 }
309 306
310 int count = 0, size = 0; 307 int count = 0, size = 0;
311 hr = stream_config->GetNumberOfCapabilities(&count, &size); 308 hr = stream_config->GetNumberOfCapabilities(&count, &size);
312 if (FAILED(hr)) { 309 if (FAILED(hr)) {
313 SetErrorState("Failed to GetNumberOfCapabilities"); 310 SetErrorState("Failed to GetNumberOfCapabilities");
314 return; 311 return;
315 } 312 }
316 313
317 scoped_ptr<BYTE[]> caps(new BYTE[size]); 314 scoped_ptr<BYTE[]> caps(new BYTE[size]);
318 ScopedMediaType media_type; 315 ScopedMediaType media_type;
319 316
320 // Get the windows capability from the capture device. 317 // Get the windows capability from the capture device.
321 // GetStreamCaps can return S_FALSE which we consider an error. Therefore the 318 // GetStreamCaps can return S_FALSE which we consider an error. Therefore the
322 // FAILED macro can't be used. 319 // FAILED macro can't be used.
323 hr = stream_config->GetStreamCaps( 320 hr = stream_config->GetStreamCaps(
324 found_capability.stream_index, media_type.Receive(), caps.get()); 321 found_capability.first, media_type.Receive(), caps.get());
325 if (hr != S_OK) { 322 if (hr != S_OK) {
326 SetErrorState("Failed to get capture device capabilities"); 323 SetErrorState("Failed to get capture device capabilities");
327 return; 324 return;
328 } else { 325 } else {
329 if (media_type->formattype == FORMAT_VideoInfo) { 326 if (media_type->formattype == FORMAT_VideoInfo) {
330 VIDEOINFOHEADER* h = 327 VIDEOINFOHEADER* h =
331 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); 328 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
332 if (format.frame_rate > 0) 329 if (format.frame_rate > 0)
333 h->AvgTimePerFrame = kSecondsToReferenceTime / format.frame_rate; 330 h->AvgTimePerFrame = kSecondsToReferenceTime / format.frame_rate;
334 } 331 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 454
458 int count = 0, size = 0; 455 int count = 0, size = 0;
459 hr = stream_config->GetNumberOfCapabilities(&count, &size); 456 hr = stream_config->GetNumberOfCapabilities(&count, &size);
460 if (FAILED(hr)) { 457 if (FAILED(hr)) {
461 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: " 458 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: "
462 << logging::SystemErrorCodeToString(hr); 459 << logging::SystemErrorCodeToString(hr);
463 return false; 460 return false;
464 } 461 }
465 462
466 scoped_ptr<BYTE[]> caps(new BYTE[size]); 463 scoped_ptr<BYTE[]> caps(new BYTE[size]);
467 for (int i = 0; i < count; ++i) { 464 for (int stream_index = 0; stream_index < count; ++stream_index) {
468 ScopedMediaType media_type; 465 ScopedMediaType media_type;
469 hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); 466 hr = stream_config->GetStreamCaps(
467 stream_index, media_type.Receive(), caps.get());
470 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() 468 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED()
471 // macros here since they'll trigger incorrectly. 469 // macros here since they'll trigger incorrectly.
472 if (hr != S_OK) { 470 if (hr != S_OK) {
473 DLOG(ERROR) << "Failed to GetStreamCaps: " 471 DLOG(ERROR) << "Failed to GetStreamCaps: "
474 << logging::SystemErrorCodeToString(hr); 472 << logging::SystemErrorCodeToString(hr);
475 return false; 473 return false;
476 } 474 }
477 475
478 if (media_type->majortype == MEDIATYPE_Video && 476 if (media_type->majortype == MEDIATYPE_Video &&
479 media_type->formattype == FORMAT_VideoInfo) { 477 media_type->formattype == FORMAT_VideoInfo) {
480 VideoCaptureCapabilityWin capability(i); 478 VideoCaptureFormat format;
481 capability.supported_format.pixel_format = 479 format.pixel_format =
482 TranslateMediaSubtypeToPixelFormat(media_type->subtype); 480 TranslateMediaSubtypeToPixelFormat(media_type->subtype);
483 if (capability.supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) 481 if (format.pixel_format == PIXEL_FORMAT_UNKNOWN)
484 continue; 482 continue;
485 483
486 VIDEOINFOHEADER* h = 484 VIDEOINFOHEADER* h =
487 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); 485 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
488 capability.supported_format.frame_size.SetSize(h->bmiHeader.biWidth, 486 format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight);
489 h->bmiHeader.biHeight);
490 487
491 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use 488 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use
492 // the value from VIDEOINFOHEADER. 489 // the value from VIDEOINFOHEADER.
493 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; 490 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame;
494 if (video_control) { 491 if (video_control) {
495 ScopedCoMem<LONGLONG> max_fps; 492 ScopedCoMem<LONGLONG> max_fps;
496 LONG list_size = 0; 493 LONG list_size = 0;
497 SIZE size = {capability.supported_format.frame_size.width(), 494 const SIZE size = {format.frame_size.width(),
498 capability.supported_format.frame_size.height()}; 495 format.frame_size.height()};
499
500 // GetFrameRateList doesn't return max frame rate always 496 // GetFrameRateList doesn't return max frame rate always
501 // eg: Logitech Notebook. This may be due to a bug in that API 497 // eg: Logitech Notebook. This may be due to a bug in that API
502 // because GetFrameRateList array is reversed in the above camera. So 498 // because GetFrameRateList array is reversed in the above camera. So
503 // a util method written. Can't assume the first value will return 499 // a util method written. Can't assume the first value will return
504 // the max fps. 500 // the max fps.
505 hr = video_control->GetFrameRateList(output_capture_pin_, i, size, 501 hr = video_control->GetFrameRateList(
506 &list_size, &max_fps); 502 output_capture_pin_, stream_index, size, &list_size, &max_fps);
507 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some 503 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some
508 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates 504 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates
509 // into success, so explicitly check S_OK. See http://crbug.com/306237. 505 // into success, so explicitly check S_OK. See http://crbug.com/306237.
510 if (hr == S_OK && list_size > 0 && max_fps) { 506 if (hr == S_OK && list_size > 0 && max_fps) {
511 time_per_frame = *std::min_element(max_fps.get(), 507 time_per_frame = *std::min_element(max_fps.get(),
512 max_fps.get() + list_size); 508 max_fps.get() + list_size);
513 } 509 }
514 } 510 }
515 511
516 capability.supported_format.frame_rate = 512 format.frame_rate =
517 (time_per_frame > 0) 513 (time_per_frame > 0)
518 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) 514 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame))
519 : 0.0; 515 : 0.0;
520 516
521 // DirectShow works at the moment only on integer frame_rate but the 517 capabilities_.push_back(VideoCaptureCapabilityWin(stream_index, format));
522 // best capability matching class works on rational frame rates.
523 capability.frame_rate_numerator = capability.supported_format.frame_rate;
524 capability.frame_rate_denominator = 1;
525
526 capabilities_.Add(capability);
527 } 518 }
528 } 519 }
529 520
530 return !capabilities_.empty(); 521 return !capabilities_.empty();
531 } 522 }
532 523
533 // Set the power line frequency removal in |capture_filter_| if available. 524 // Set the power line frequency removal in |capture_filter_| if available.
534 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { 525 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() {
535 const int power_line_frequency = GetPowerLineFrequencyForLocation(); 526 const int power_line_frequency = GetPowerLineFrequencyForLocation();
536 if (power_line_frequency != kPowerLine50Hz && 527 if (power_line_frequency != kPowerLine50Hz &&
(...skipping 23 matching lines...) Expand all
560 DVLOG(2) << "Anti-flicker setting not supported."; 551 DVLOG(2) << "Anti-flicker setting not supported.";
561 } 552 }
562 } 553 }
563 554
564 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { 555 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) {
565 DCHECK(CalledOnValidThread()); 556 DCHECK(CalledOnValidThread());
566 state_ = kError; 557 state_ = kError;
567 client_->OnError(reason); 558 client_->OnError(reason);
568 } 559 }
569 } // namespace media 560 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698