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

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

Issue 83633008: Reland: Reorganize media::VideoCapture* types (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « media/video/capture/win/video_capture_device_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm> 7 #include <algorithm>
8 #include <list> 8 #include <list>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 hr = graph_builder_->AddFilter(sink_filter_, NULL); 334 hr = graph_builder_->AddFilter(sink_filter_, NULL);
335 if (FAILED(hr)) { 335 if (FAILED(hr)) {
336 DVLOG(2)<< "Failed to add the send filter to the graph."; 336 DVLOG(2)<< "Failed to add the send filter to the graph.";
337 return false; 337 return false;
338 } 338 }
339 339
340 return CreateCapabilityMap(); 340 return CreateCapabilityMap();
341 } 341 }
342 342
343 void VideoCaptureDeviceWin::AllocateAndStart( 343 void VideoCaptureDeviceWin::AllocateAndStart(
344 const VideoCaptureCapability& capture_format, 344 const VideoCaptureParams& params,
345 scoped_ptr<VideoCaptureDevice::Client> client) { 345 scoped_ptr<VideoCaptureDevice::Client> client) {
346 DCHECK(CalledOnValidThread()); 346 DCHECK(CalledOnValidThread());
347 if (state_ != kIdle) 347 if (state_ != kIdle)
348 return; 348 return;
349 349
350 client_ = client.Pass(); 350 client_ = client.Pass();
351 351
352 // Get the camera capability that best match the requested resolution. 352 // Get the camera capability that best match the requested resolution.
353 const VideoCaptureCapabilityWin& found_capability = 353 const VideoCaptureCapabilityWin& found_capability =
354 capabilities_.GetBestMatchedCapability(capture_format.width, 354 capabilities_.GetBestMatchedFormat(
355 capture_format.height, 355 params.requested_format.frame_size.width(),
356 capture_format.frame_rate); 356 params.requested_format.frame_size.height(),
357 VideoCaptureCapability capability = found_capability; 357 params.requested_format.frame_rate);
358 VideoCaptureFormat format = found_capability.supported_format;
358 359
359 // Reduce the frame rate if the requested frame rate is lower 360 // Reduce the frame rate if the requested frame rate is lower
360 // than the capability. 361 // than the capability.
361 if (capability.frame_rate > capture_format.frame_rate) 362 if (format.frame_rate > params.requested_format.frame_rate)
362 capability.frame_rate = capture_format.frame_rate; 363 format.frame_rate = params.requested_format.frame_rate;
363 364
364 AM_MEDIA_TYPE* pmt = NULL; 365 AM_MEDIA_TYPE* pmt = NULL;
365 VIDEO_STREAM_CONFIG_CAPS caps; 366 VIDEO_STREAM_CONFIG_CAPS caps;
366 367
367 ScopedComPtr<IAMStreamConfig> stream_config; 368 ScopedComPtr<IAMStreamConfig> stream_config;
368 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); 369 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
369 if (FAILED(hr)) { 370 if (FAILED(hr)) {
370 SetErrorState("Can't get the Capture format settings"); 371 SetErrorState("Can't get the Capture format settings");
371 return; 372 return;
372 } 373 }
373 374
374 // Get the windows capability from the capture device. 375 // Get the windows capability from the capture device.
375 hr = stream_config->GetStreamCaps(found_capability.stream_index, &pmt, 376 hr = stream_config->GetStreamCaps(found_capability.stream_index, &pmt,
376 reinterpret_cast<BYTE*>(&caps)); 377 reinterpret_cast<BYTE*>(&caps));
377 if (SUCCEEDED(hr)) { 378 if (SUCCEEDED(hr)) {
378 if (pmt->formattype == FORMAT_VideoInfo) { 379 if (pmt->formattype == FORMAT_VideoInfo) {
379 VIDEOINFOHEADER* h = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat); 380 VIDEOINFOHEADER* h = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);
380 if (capability.frame_rate > 0) 381 if (format.frame_rate > 0)
381 h->AvgTimePerFrame = kSecondsToReferenceTime / capability.frame_rate; 382 h->AvgTimePerFrame = kSecondsToReferenceTime / format.frame_rate;
382 } 383 }
383 // Set the sink filter to request this capability. 384 // Set the sink filter to request this format.
384 sink_filter_->SetRequestedMediaCapability(capability); 385 sink_filter_->SetRequestedMediaFormat(format);
385 // Order the capture device to use this capability. 386 // Order the capture device to use this format.
386 hr = stream_config->SetFormat(pmt); 387 hr = stream_config->SetFormat(pmt);
387 } 388 }
388 389
389 if (FAILED(hr)) 390 if (FAILED(hr))
390 SetErrorState("Failed to set capture device output format"); 391 SetErrorState("Failed to set capture device output format");
391 392
392 if (capability.color == PIXEL_FORMAT_MJPEG && 393 if (format.pixel_format == PIXEL_FORMAT_MJPEG && !mjpg_filter_.get()) {
393 !mjpg_filter_.get()) {
394 // Create MJPG filter if we need it. 394 // Create MJPG filter if we need it.
395 hr = mjpg_filter_.CreateInstance(CLSID_MjpegDec, NULL, CLSCTX_INPROC); 395 hr = mjpg_filter_.CreateInstance(CLSID_MjpegDec, NULL, CLSCTX_INPROC);
396 396
397 if (SUCCEEDED(hr)) { 397 if (SUCCEEDED(hr)) {
398 GetPin(mjpg_filter_, PINDIR_INPUT, GUID_NULL, input_mjpg_pin_.Receive()); 398 GetPin(mjpg_filter_, PINDIR_INPUT, GUID_NULL, input_mjpg_pin_.Receive());
399 GetPin(mjpg_filter_, PINDIR_OUTPUT, GUID_NULL, 399 GetPin(mjpg_filter_, PINDIR_OUTPUT, GUID_NULL,
400 output_mjpg_pin_.Receive()); 400 output_mjpg_pin_.Receive());
401 hr = graph_builder_->AddFilter(mjpg_filter_, NULL); 401 hr = graph_builder_->AddFilter(mjpg_filter_, NULL);
402 } 402 }
403 403
404 if (FAILED(hr)) { 404 if (FAILED(hr)) {
405 mjpg_filter_.Release(); 405 mjpg_filter_.Release();
406 input_mjpg_pin_.Release(); 406 input_mjpg_pin_.Release();
407 output_mjpg_pin_.Release(); 407 output_mjpg_pin_.Release();
408 } 408 }
409 } 409 }
410 410
411 if (capability.color == PIXEL_FORMAT_MJPEG && 411 if (format.pixel_format == PIXEL_FORMAT_MJPEG && mjpg_filter_.get()) {
412 mjpg_filter_.get()) {
413 // Connect the camera to the MJPEG decoder. 412 // Connect the camera to the MJPEG decoder.
414 hr = graph_builder_->ConnectDirect(output_capture_pin_, input_mjpg_pin_, 413 hr = graph_builder_->ConnectDirect(output_capture_pin_, input_mjpg_pin_,
415 NULL); 414 NULL);
416 // Connect the MJPEG filter to the Capture filter. 415 // Connect the MJPEG filter to the Capture filter.
417 hr += graph_builder_->ConnectDirect(output_mjpg_pin_, input_sink_pin_, 416 hr += graph_builder_->ConnectDirect(output_mjpg_pin_, input_sink_pin_,
418 NULL); 417 NULL);
419 } else { 418 } else {
420 hr = graph_builder_->ConnectDirect(output_capture_pin_, input_sink_pin_, 419 hr = graph_builder_->ConnectDirect(output_capture_pin_, input_sink_pin_,
421 NULL); 420 NULL);
422 } 421 }
423 422
424 if (FAILED(hr)) { 423 if (FAILED(hr)) {
425 SetErrorState("Failed to connect the Capture graph."); 424 SetErrorState("Failed to connect the Capture graph.");
426 return; 425 return;
427 } 426 }
428 427
429 hr = media_control_->Pause(); 428 hr = media_control_->Pause();
430 if (FAILED(hr)) { 429 if (FAILED(hr)) {
431 SetErrorState("Failed to Pause the Capture device. " 430 SetErrorState("Failed to Pause the Capture device. "
432 "Is it already occupied?"); 431 "Is it already occupied?");
433 return; 432 return;
434 } 433 }
435 434
436 // Get the capability back from the sink filter after the filter have been 435 // Get the format back from the sink filter after the filter have been
437 // connected. 436 // connected.
438 current_setting_ = sink_filter_->ResultingCapability(); 437 capture_format_ = sink_filter_->ResultingFormat();
439 438
440 // Start capturing. 439 // Start capturing.
441 hr = media_control_->Run(); 440 hr = media_control_->Run();
442 if (FAILED(hr)) { 441 if (FAILED(hr)) {
443 SetErrorState("Failed to start the Capture device."); 442 SetErrorState("Failed to start the Capture device.");
444 return; 443 return;
445 } 444 }
446 445
447 state_ = kCapturing; 446 state_ = kCapturing;
448 } 447 }
(...skipping 23 matching lines...) Expand all
472 return; 471 return;
473 } 472 }
474 client_.reset(); 473 client_.reset();
475 state_ = kIdle; 474 state_ = kIdle;
476 } 475 }
477 476
478 // Implements SinkFilterObserver::SinkFilterObserver. 477 // Implements SinkFilterObserver::SinkFilterObserver.
479 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, 478 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer,
480 int length) { 479 int length) {
481 client_->OnIncomingCapturedFrame( 480 client_->OnIncomingCapturedFrame(
482 buffer, length, base::Time::Now(), 0, false, false, current_setting_); 481 buffer, length, base::Time::Now(), 0, false, false, capture_format_);
483 } 482 }
484 483
485 bool VideoCaptureDeviceWin::CreateCapabilityMap() { 484 bool VideoCaptureDeviceWin::CreateCapabilityMap() {
486 DCHECK(CalledOnValidThread()); 485 DCHECK(CalledOnValidThread());
487 ScopedComPtr<IAMStreamConfig> stream_config; 486 ScopedComPtr<IAMStreamConfig> stream_config;
488 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); 487 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
489 if (FAILED(hr)) { 488 if (FAILED(hr)) {
490 DVLOG(2) << "Failed to get IAMStreamConfig interface from " 489 DVLOG(2) << "Failed to get IAMStreamConfig interface from "
491 "capture device"; 490 "capture device";
492 return false; 491 return false;
(...skipping 22 matching lines...) Expand all
515 if (hr != S_OK) { 514 if (hr != S_OK) {
516 DVLOG(2) << "Failed to GetStreamCaps"; 515 DVLOG(2) << "Failed to GetStreamCaps";
517 return false; 516 return false;
518 } 517 }
519 518
520 if (media_type->majortype == MEDIATYPE_Video && 519 if (media_type->majortype == MEDIATYPE_Video &&
521 media_type->formattype == FORMAT_VideoInfo) { 520 media_type->formattype == FORMAT_VideoInfo) {
522 VideoCaptureCapabilityWin capability(i); 521 VideoCaptureCapabilityWin capability(i);
523 VIDEOINFOHEADER* h = 522 VIDEOINFOHEADER* h =
524 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); 523 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
525 capability.width = h->bmiHeader.biWidth; 524 capability.supported_format.frame_size.SetSize(h->bmiHeader.biWidth,
526 capability.height = h->bmiHeader.biHeight; 525 h->bmiHeader.biHeight);
527 526
528 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use 527 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use
529 // the value from VIDEOINFOHEADER. 528 // the value from VIDEOINFOHEADER.
530 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; 529 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame;
531 if (video_control) { 530 if (video_control) {
532 ScopedCoMem<LONGLONG> max_fps; 531 ScopedCoMem<LONGLONG> max_fps;
533 LONG list_size = 0; 532 LONG list_size = 0;
534 SIZE size = { capability.width, capability.height }; 533 SIZE size = {capability.supported_format.frame_size.width(),
534 capability.supported_format.frame_size.height()};
535 535
536 // GetFrameRateList doesn't return max frame rate always 536 // GetFrameRateList doesn't return max frame rate always
537 // eg: Logitech Notebook. This may be due to a bug in that API 537 // eg: Logitech Notebook. This may be due to a bug in that API
538 // because GetFrameRateList array is reversed in the above camera. So 538 // because GetFrameRateList array is reversed in the above camera. So
539 // a util method written. Can't assume the first value will return 539 // a util method written. Can't assume the first value will return
540 // the max fps. 540 // the max fps.
541 hr = video_control->GetFrameRateList(output_capture_pin_, i, size, 541 hr = video_control->GetFrameRateList(output_capture_pin_, i, size,
542 &list_size, &max_fps); 542 &list_size, &max_fps);
543 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some 543 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some
544 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates 544 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates
545 // into success, so explicitly check S_OK. See http://crbug.com/306237. 545 // into success, so explicitly check S_OK. See http://crbug.com/306237.
546 if (hr == S_OK && list_size > 0 && max_fps) { 546 if (hr == S_OK && list_size > 0 && max_fps) {
547 time_per_frame = *std::min_element(max_fps.get(), 547 time_per_frame = *std::min_element(max_fps.get(),
548 max_fps.get() + list_size); 548 max_fps.get() + list_size);
549 } 549 }
550 } 550 }
551 551
552 capability.frame_rate = (time_per_frame > 0) ? 552 capability.supported_format.frame_rate =
553 static_cast<int>(kSecondsToReferenceTime / time_per_frame) : 0; 553 (time_per_frame > 0)
554 ? static_cast<int>(kSecondsToReferenceTime / time_per_frame)
555 : 0;
554 556
555 // DirectShow works at the moment only on integer frame_rate but the 557 // DirectShow works at the moment only on integer frame_rate but the
556 // best capability matching class works on rational frame rates. 558 // best capability matching class works on rational frame rates.
557 capability.frame_rate_numerator = capability.frame_rate; 559 capability.frame_rate_numerator = capability.supported_format.frame_rate;
558 capability.frame_rate_denominator = 1; 560 capability.frame_rate_denominator = 1;
559 561
560 // We can't switch MEDIATYPE :~(. 562 // We can't switch MEDIATYPE :~(.
561 if (media_type->subtype == kMediaSubTypeI420) { 563 if (media_type->subtype == kMediaSubTypeI420) {
562 capability.color = PIXEL_FORMAT_I420; 564 capability.supported_format.pixel_format = PIXEL_FORMAT_I420;
563 } else if (media_type->subtype == MEDIASUBTYPE_IYUV) { 565 } else if (media_type->subtype == MEDIASUBTYPE_IYUV) {
564 // This is identical to PIXEL_FORMAT_I420. 566 // This is identical to PIXEL_FORMAT_I420.
565 capability.color = PIXEL_FORMAT_I420; 567 capability.supported_format.pixel_format = PIXEL_FORMAT_I420;
566 } else if (media_type->subtype == MEDIASUBTYPE_RGB24) { 568 } else if (media_type->subtype == MEDIASUBTYPE_RGB24) {
567 capability.color = PIXEL_FORMAT_RGB24; 569 capability.supported_format.pixel_format = PIXEL_FORMAT_RGB24;
568 } else if (media_type->subtype == MEDIASUBTYPE_YUY2) { 570 } else if (media_type->subtype == MEDIASUBTYPE_YUY2) {
569 capability.color = PIXEL_FORMAT_YUY2; 571 capability.supported_format.pixel_format = PIXEL_FORMAT_YUY2;
570 } else if (media_type->subtype == MEDIASUBTYPE_MJPG) { 572 } else if (media_type->subtype == MEDIASUBTYPE_MJPG) {
571 capability.color = PIXEL_FORMAT_MJPEG; 573 capability.supported_format.pixel_format = PIXEL_FORMAT_MJPEG;
572 } else if (media_type->subtype == MEDIASUBTYPE_UYVY) { 574 } else if (media_type->subtype == MEDIASUBTYPE_UYVY) {
573 capability.color = PIXEL_FORMAT_UYVY; 575 capability.supported_format.pixel_format = PIXEL_FORMAT_UYVY;
574 } else if (media_type->subtype == MEDIASUBTYPE_ARGB32) { 576 } else if (media_type->subtype == MEDIASUBTYPE_ARGB32) {
575 capability.color = PIXEL_FORMAT_ARGB; 577 capability.supported_format.pixel_format = PIXEL_FORMAT_ARGB;
576 } else { 578 } else {
577 WCHAR guid_str[128]; 579 WCHAR guid_str[128];
578 StringFromGUID2(media_type->subtype, guid_str, arraysize(guid_str)); 580 StringFromGUID2(media_type->subtype, guid_str, arraysize(guid_str));
579 DVLOG(2) << "Device supports (also) an unknown media type " << guid_str; 581 DVLOG(2) << "Device supports (also) an unknown media type " << guid_str;
580 continue; 582 continue;
581 } 583 }
582 capabilities_.Add(capability); 584 capabilities_.Add(capability);
583 } 585 }
584 DeleteMediaType(media_type); 586 DeleteMediaType(media_type);
585 media_type = NULL; 587 media_type = NULL;
586 } 588 }
587 589
588 return !capabilities_.empty(); 590 return !capabilities_.empty();
589 } 591 }
590 592
591 void VideoCaptureDeviceWin::SetErrorState(const char* reason) { 593 void VideoCaptureDeviceWin::SetErrorState(const char* reason) {
592 DCHECK(CalledOnValidThread()); 594 DCHECK(CalledOnValidThread());
593 DVLOG(1) << reason; 595 DVLOG(1) << reason;
594 state_ = kError; 596 state_ = kError;
595 client_->OnError(); 597 client_->OnError();
596 } 598 }
597 } // namespace media 599 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/win/video_capture_device_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698