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

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

Issue 11418307: Revert 170912 - need more delayloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years 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/string_util.h" 10 #include "base/string_util.h"
11 #include "base/sys_string_conversions.h" 11 #include "base/sys_string_conversions.h"
12 #include "base/win/scoped_variant.h" 12 #include "base/win/scoped_variant.h"
13 #include "base/win/windows_version.h"
14 #include "media/video/capture/win/video_capture_device_mf_win.h"
15 13
16 using base::win::ScopedComPtr; 14 using base::win::ScopedComPtr;
17 using base::win::ScopedVariant; 15 using base::win::ScopedVariant;
18 16
19 namespace { 17 namespace {
20 18
21 // Finds and creates a DirectShow Video Capture filter matching the device_name. 19 // Finds and creates a DirectShow Video Capture filter matching the device_name.
22 HRESULT GetDeviceFilter(const media::VideoCaptureDevice::Name& device_name, 20 HRESULT GetDeviceFilter(const media::VideoCaptureDevice::Name& device_name,
23 IBaseFilter** filter) { 21 IBaseFilter** filter) {
24 DCHECK(filter); 22 DCHECK(filter);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 135
138 // Delete a media type structure that was allocated on the heap. 136 // Delete a media type structure that was allocated on the heap.
139 // http://msdn.microsoft.com/en-us/library/dd375432(VS.85).aspx 137 // http://msdn.microsoft.com/en-us/library/dd375432(VS.85).aspx
140 void DeleteMediaType(AM_MEDIA_TYPE* mt) { 138 void DeleteMediaType(AM_MEDIA_TYPE* mt) {
141 if (mt != NULL) { 139 if (mt != NULL) {
142 FreeMediaType(mt); 140 FreeMediaType(mt);
143 CoTaskMemFree(mt); 141 CoTaskMemFree(mt);
144 } 142 }
145 } 143 }
146 144
145 // Help structure used for comparing video capture capabilities.
146 struct ResolutionDiff {
147 int capability_index;
148 int diff_height;
149 int diff_width;
150 int diff_frame_rate;
151 media::VideoCaptureCapability::Format color;
152 };
153
154 bool CompareHeight(const ResolutionDiff& item1, const ResolutionDiff& item2) {
155 return abs(item1.diff_height) < abs(item2.diff_height);
156 }
157
158 bool CompareWidth(const ResolutionDiff& item1, const ResolutionDiff& item2) {
159 return abs(item1.diff_width) < abs(item2.diff_width);
160 }
161
162 bool CompareFrameRate(const ResolutionDiff& item1,
163 const ResolutionDiff& item2) {
164 return abs(item1.diff_frame_rate) < abs(item2.diff_frame_rate);
165 }
166
167 bool CompareColor(const ResolutionDiff& item1, const ResolutionDiff& item2) {
168 return (item1.color < item2.color);
169 }
170
147 } // namespace 171 } // namespace
148 172
149 namespace media { 173 namespace media {
150 174
151 // static 175 // Name of a fake DirectShow filter that exist on computers with
176 // GTalk installed.
177 static const char kGoogleCameraAdapter[] = "google camera adapter";
178
179 // Gets the names of all video capture devices connected to this computer.
152 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { 180 void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
153 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
154 VideoCaptureDeviceMFWin::GetDeviceNames(device_names);
155 } else {
156 VideoCaptureDeviceWin::GetDeviceNames(device_names);
157 }
158 }
159
160 // static
161 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
162 VideoCaptureDevice* ret = NULL;
163 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
164 scoped_ptr<VideoCaptureDeviceMFWin> device(
165 new VideoCaptureDeviceMFWin(device_name));
166 if (device->Init())
167 ret = device.release();
168 } else {
169 scoped_ptr<VideoCaptureDeviceWin> device(
170 new VideoCaptureDeviceWin(device_name));
171 if (device->Init())
172 ret = device.release();
173 }
174
175 return ret;
176 }
177
178 // static
179 void VideoCaptureDeviceWin::GetDeviceNames(Names* device_names) {
180 DCHECK(device_names); 181 DCHECK(device_names);
181 182
182 ScopedComPtr<ICreateDevEnum> dev_enum; 183 ScopedComPtr<ICreateDevEnum> dev_enum;
183 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, 184 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL,
184 CLSCTX_INPROC); 185 CLSCTX_INPROC);
185 if (FAILED(hr)) 186 if (FAILED(hr))
186 return; 187 return;
187 188
188 ScopedComPtr<IEnumMoniker> enum_moniker; 189 ScopedComPtr<IEnumMoniker> enum_moniker;
189 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, 190 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
190 enum_moniker.Receive(), 0); 191 enum_moniker.Receive(), 0);
191 // CreateClassEnumerator returns S_FALSE on some Windows OS 192 // CreateClassEnumerator returns S_FALSE on some Windows OS
192 // when no camera exist. Therefore the FAILED macro can't be used. 193 // when no camera exist. Therefore the FAILED macro can't be used.
193 if (hr != S_OK) 194 if (hr != S_OK)
194 return; 195 return;
195 196
196 device_names->clear(); 197 device_names->clear();
197 198
198 // Name of a fake DirectShow filter that exist on computers with
199 // GTalk installed.
200 static const char kGoogleCameraAdapter[] = "google camera adapter";
201
202 // Enumerate all video capture devices. 199 // Enumerate all video capture devices.
203 ScopedComPtr<IMoniker> moniker; 200 ScopedComPtr<IMoniker> moniker;
204 int index = 0; 201 int index = 0;
205 while (enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK) { 202 while (enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK) {
206 Name device; 203 Name device;
207 ScopedComPtr<IPropertyBag> prop_bag; 204 ScopedComPtr<IPropertyBag> prop_bag;
208 hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid()); 205 hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid());
209 if (FAILED(hr)) { 206 if (FAILED(hr)) {
210 moniker.Release(); 207 moniker.Release();
211 continue; 208 continue;
(...skipping 25 matching lines...) Expand all
237 device.unique_id = base::SysWideToUTF8(V_BSTR(&name)); 234 device.unique_id = base::SysWideToUTF8(V_BSTR(&name));
238 } 235 }
239 236
240 device_names->push_back(device); 237 device_names->push_back(device);
241 } 238 }
242 } 239 }
243 moniker.Release(); 240 moniker.Release();
244 } 241 }
245 } 242 }
246 243
244 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
245 VideoCaptureDeviceWin* self = new VideoCaptureDeviceWin(device_name);
246 if (self && self->Init())
247 return self;
248
249 delete self;
250 return NULL;
251 }
252
247 VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name) 253 VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name)
248 : device_name_(device_name), 254 : device_name_(device_name),
249 state_(kIdle), 255 state_(kIdle),
250 observer_(NULL) { 256 observer_(NULL) {
251 DetachFromThread(); 257 DetachFromThread();
252 } 258 }
253 259
254 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { 260 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() {
255 DCHECK(CalledOnValidThread()); 261 DCHECK(CalledOnValidThread());
256 if (media_control_) 262 if (media_control_)
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 void VideoCaptureDeviceWin::Allocate( 331 void VideoCaptureDeviceWin::Allocate(
326 int width, 332 int width,
327 int height, 333 int height,
328 int frame_rate, 334 int frame_rate,
329 VideoCaptureDevice::EventHandler* observer) { 335 VideoCaptureDevice::EventHandler* observer) {
330 DCHECK(CalledOnValidThread()); 336 DCHECK(CalledOnValidThread());
331 if (state_ != kIdle) 337 if (state_ != kIdle)
332 return; 338 return;
333 339
334 observer_ = observer; 340 observer_ = observer;
335
336 // Get the camera capability that best match the requested resolution. 341 // Get the camera capability that best match the requested resolution.
337 const VideoCaptureCapabilityWin& found_capability = 342 const int capability_index = GetBestMatchedCapability(width, height,
338 capabilities_.GetBestMatchedCapability(width, height, frame_rate); 343 frame_rate);
339 VideoCaptureCapability capability = found_capability; 344 VideoCaptureCapability capability = capabilities_[capability_index];
340 345
341 // Reduce the frame rate if the requested frame rate is lower 346 // Reduce the frame rate if the requested frame rate is lower
342 // than the capability. 347 // than the capability.
343 if (capability.frame_rate > frame_rate) 348 if (capability.frame_rate > frame_rate)
344 capability.frame_rate = frame_rate; 349 capability.frame_rate = frame_rate;
345 350
346 AM_MEDIA_TYPE* pmt = NULL; 351 AM_MEDIA_TYPE* pmt = NULL;
347 VIDEO_STREAM_CONFIG_CAPS caps; 352 VIDEO_STREAM_CONFIG_CAPS caps;
348 353
349 ScopedComPtr<IAMStreamConfig> stream_config; 354 ScopedComPtr<IAMStreamConfig> stream_config;
350 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); 355 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
351 if (FAILED(hr)) { 356 if (FAILED(hr)) {
352 SetErrorState("Can't get the Capture format settings"); 357 SetErrorState("Can't get the Capture format settings");
353 return; 358 return;
354 } 359 }
355 360
356 // Get the windows capability from the capture device. 361 // Get the windows capability from the capture device.
357 hr = stream_config->GetStreamCaps(found_capability.stream_index, &pmt, 362 hr = stream_config->GetStreamCaps(capability_index, &pmt,
358 reinterpret_cast<BYTE*>(&caps)); 363 reinterpret_cast<BYTE*>(&caps));
359 if (SUCCEEDED(hr)) { 364 if (SUCCEEDED(hr)) {
360 if (pmt->formattype == FORMAT_VideoInfo) { 365 if (pmt->formattype == FORMAT_VideoInfo) {
361 VIDEOINFOHEADER* h = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat); 366 VIDEOINFOHEADER* h = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);
362 if (capability.frame_rate > 0) 367 if (capability.frame_rate > 0)
363 h->AvgTimePerFrame = kSecondsToReferenceTime / capability.frame_rate; 368 h->AvgTimePerFrame = kSecondsToReferenceTime / capability.frame_rate;
364 } 369 }
365 // Set the sink filter to request this capability. 370 // Set the sink filter to request this capability.
366 sink_filter_->SetRequestedMediaCapability(capability); 371 sink_filter_->SetRequestedMediaCapability(capability);
367 // Order the capture device to use this capability. 372 // Order the capture device to use this capability.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 for (int i = 0; i < count; ++i) { 519 for (int i = 0; i < count; ++i) {
515 hr = stream_config->GetStreamCaps(i, &media_type, 520 hr = stream_config->GetStreamCaps(i, &media_type,
516 reinterpret_cast<BYTE*>(&caps)); 521 reinterpret_cast<BYTE*>(&caps));
517 if (FAILED(hr)) { 522 if (FAILED(hr)) {
518 DVLOG(2) << "Failed to GetStreamCaps"; 523 DVLOG(2) << "Failed to GetStreamCaps";
519 return false; 524 return false;
520 } 525 }
521 526
522 if (media_type->majortype == MEDIATYPE_Video && 527 if (media_type->majortype == MEDIATYPE_Video &&
523 media_type->formattype == FORMAT_VideoInfo) { 528 media_type->formattype == FORMAT_VideoInfo) {
524 VideoCaptureCapabilityWin capability(i); 529 VideoCaptureCapability capability;
525 REFERENCE_TIME time_per_frame = 0; 530 REFERENCE_TIME time_per_frame = 0;
526 531
527 VIDEOINFOHEADER* h = 532 VIDEOINFOHEADER* h =
528 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); 533 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
529 capability.width = h->bmiHeader.biWidth; 534 capability.width = h->bmiHeader.biWidth;
530 capability.height = h->bmiHeader.biHeight; 535 capability.height = h->bmiHeader.biHeight;
531 time_per_frame = h->AvgTimePerFrame; 536 time_per_frame = h->AvgTimePerFrame;
532 537
533 // Try to get the max frame rate from IAMVideoControl. 538 // Try to get the max frame rate from IAMVideoControl.
534 if (video_control.get()) { 539 if (video_control.get()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 } else if (media_type->subtype == MEDIASUBTYPE_YUY2) { 579 } else if (media_type->subtype == MEDIASUBTYPE_YUY2) {
575 capability.color = VideoCaptureCapability::kYUY2; 580 capability.color = VideoCaptureCapability::kYUY2;
576 } else if (media_type->subtype == MEDIASUBTYPE_MJPG) { 581 } else if (media_type->subtype == MEDIASUBTYPE_MJPG) {
577 capability.color = VideoCaptureCapability::kMJPEG; 582 capability.color = VideoCaptureCapability::kMJPEG;
578 } else { 583 } else {
579 WCHAR guid_str[128]; 584 WCHAR guid_str[128];
580 StringFromGUID2(media_type->subtype, guid_str, arraysize(guid_str)); 585 StringFromGUID2(media_type->subtype, guid_str, arraysize(guid_str));
581 DVLOG(2) << "Device support unknown media type " << guid_str; 586 DVLOG(2) << "Device support unknown media type " << guid_str;
582 continue; 587 continue;
583 } 588 }
584 capabilities_.Add(capability); 589 capabilities_[i] = capability;
585 } 590 }
586 DeleteMediaType(media_type); 591 DeleteMediaType(media_type);
587 media_type = NULL; 592 media_type = NULL;
588 } 593 }
589 594
590 return !capabilities_.empty(); 595 return capabilities_.size() > 0;
596 }
597
598 // Loops through the list of capabilities and returns an index of the best
599 // matching capability.
600 // The algorithm prioritize height, width, frame rate and color format in that
601 // order.
602 int VideoCaptureDeviceWin::GetBestMatchedCapability(int requested_width,
603 int requested_height,
604 int requested_frame_rate) {
605 DCHECK(CalledOnValidThread());
606 std::list<ResolutionDiff> diff_list;
607
608 // Loop through the candidates to create a list of differentials between the
609 // requested resolution and the camera capability.
610 for (CapabilityMap::iterator iterator = capabilities_.begin();
611 iterator != capabilities_.end();
612 ++iterator) {
613 VideoCaptureCapability capability = iterator->second;
614
615 ResolutionDiff diff;
616 diff.capability_index = iterator->first;
617 diff.diff_width = capability.width - requested_width;
618 diff.diff_height = capability.height - requested_height;
619 diff.diff_frame_rate = capability.frame_rate - requested_frame_rate;
620 diff.color = capability.color;
621 diff_list.push_back(diff);
622 }
623
624 // Sort the best height candidates.
625 diff_list.sort(&CompareHeight);
626 int best_diff = diff_list.front().diff_height;
627 for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
628 it != diff_list.end(); ++it) {
629 if (it->diff_height != best_diff) {
630 // Remove all candidates but the best.
631 diff_list.erase(it, diff_list.end());
632 break;
633 }
634 }
635
636 // Sort the best width candidates.
637 diff_list.sort(&CompareWidth);
638 best_diff = diff_list.front().diff_width;
639 for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
640 it != diff_list.end(); ++it) {
641 if (it->diff_width != best_diff) {
642 // Remove all candidates but the best.
643 diff_list.erase(it, diff_list.end());
644 break;
645 }
646 }
647
648 // Sort the best frame rate candidates.
649 diff_list.sort(&CompareFrameRate);
650 best_diff = diff_list.front().diff_frame_rate;
651 for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
652 it != diff_list.end(); ++it) {
653 if (it->diff_frame_rate != best_diff) {
654 diff_list.erase(it, diff_list.end());
655 break;
656 }
657 }
658
659 // Decide the best color format.
660 diff_list.sort(&CompareColor);
661 return diff_list.front().capability_index;
591 } 662 }
592 663
593 void VideoCaptureDeviceWin::SetErrorState(const char* reason) { 664 void VideoCaptureDeviceWin::SetErrorState(const char* reason) {
594 DCHECK(CalledOnValidThread()); 665 DCHECK(CalledOnValidThread());
595 DVLOG(1) << reason; 666 DVLOG(1) << reason;
596 state_ = kError; 667 state_ = kError;
597 observer_->OnError(); 668 observer_->OnError();
598 } 669 }
599 670
600 } // namespace media 671 } // 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