Chromium Code Reviews| Index: media/video/capture/win/video_capture_device_win.cc |
| diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc |
| index c0bd9d27ca51880574fb7a6158932c7c7d873f1f..1dd96d9b9a66eef60cd41adab61f57d70c5d3527 100644 |
| --- a/media/video/capture/win/video_capture_device_win.cc |
| +++ b/media/video/capture/win/video_capture_device_win.cc |
| @@ -150,6 +150,31 @@ void DeleteMediaType(AM_MEDIA_TYPE* mt) { |
| } |
| } |
| +VideoPixelFormat TranslateMediaSubtypeToPixelFormat(GUID subtype) { |
|
tommi (sloooow) - chröme
2014/02/17 12:58:29
sub_type? Also, pass by const&?
mcasas
2014/02/17 14:56:20
Done.
|
| + // We can't use a GUID in a switch-case, this applies to |subtype|. |
| + if (subtype == kMediaSubTypeI420) { |
|
tommi (sloooow) - chröme
2014/02/17 12:58:29
I would like to see this data driven instead of mu
mcasas
2014/02/17 14:56:20
Done.
|
| + return PIXEL_FORMAT_I420; |
| + } else if (subtype == MEDIASUBTYPE_IYUV) { |
| + // This is identical to PIXEL_FORMAT_I420. |
| + return PIXEL_FORMAT_I420; |
| + } else if (subtype == MEDIASUBTYPE_RGB24) { |
| + return PIXEL_FORMAT_RGB24; |
| + } else if (subtype == MEDIASUBTYPE_YUY2) { |
| + return PIXEL_FORMAT_YUY2; |
| + } else if (subtype == MEDIASUBTYPE_MJPG) { |
| + return PIXEL_FORMAT_MJPEG; |
| + } else if (subtype == MEDIASUBTYPE_UYVY) { |
| + return PIXEL_FORMAT_UYVY; |
| + } else if (subtype == MEDIASUBTYPE_ARGB32) { |
| + return PIXEL_FORMAT_ARGB; |
| + } else { |
| + WCHAR guid_str[128]; |
| + StringFromGUID2(subtype, guid_str, arraysize(guid_str)); |
|
tommi (sloooow) - chröme
2014/02/17 12:58:29
(I know this is just moved code)
This should be in
mcasas
2014/02/17 14:56:20
Done.
|
| + DVLOG(2) << "Device supports (also) an unknown media type " << guid_str; |
| + return PIXEL_FORMAT_UNKNOWN; |
| + } |
| +} |
| + |
| } // namespace |
| // static |
| @@ -254,7 +279,7 @@ void VideoCaptureDeviceWin::GetDeviceNames(Names* device_names) { |
| if (SUCCEEDED(hr) && name.type() == VT_BSTR) { |
| // Ignore all VFW drivers and the special Google Camera Adapter. |
| // Google Camera Adapter is not a real DirectShow camera device. |
| - // VFW is very old Video for Windows drivers that can not be used. |
| + // VFW are very old Video for Windows drivers that can not be used. |
| const wchar_t* str_ptr = V_BSTR(&name); |
| const int name_length = arraysize(kGoogleCameraAdapter) - 1; |
| @@ -283,7 +308,107 @@ void VideoCaptureDeviceWin::GetDeviceNames(Names* device_names) { |
| // static |
| void VideoCaptureDeviceWin::GetDeviceSupportedFormats(const Name& device, |
| VideoCaptureFormats* formats) { |
| - NOTIMPLEMENTED(); |
| + DVLOG(1) << "GetDeviceSupportedFormats for " << device.name(); |
| + ScopedComPtr<ICreateDevEnum> dev_enum; |
| + HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, |
| + CLSCTX_INPROC); |
| + if (FAILED(hr)) |
| + return; |
| + |
| + ScopedComPtr<IEnumMoniker> enum_moniker; |
| + hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, |
| + enum_moniker.Receive(), 0); |
| + // CreateClassEnumerator returns S_FALSE on some Windows OS when no camera |
| + // exists. Therefore the FAILED macro can't be used. |
| + if (hr != S_OK) |
| + return; |
| + |
| + // Walk the capture devices. No need to check for "google camera adapter". |
|
tommi (sloooow) - chröme
2014/02/17 12:58:29
maybe elaborate on why not?
mcasas
2014/02/17 14:56:20
Done.
|
| + ScopedComPtr<IMoniker> moniker; |
| + int index = 0; |
| + ScopedVariant device_id; |
| + while (enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK) { |
| + ScopedComPtr<IPropertyBag> prop_bag; |
| + hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid()); |
| + if (FAILED(hr)) { |
| + moniker.Release(); |
| + continue; |
| + } |
| + |
| + device_id.Reset(); |
| + hr = prop_bag->Read(L"DevicePath", device_id.Receive(), 0); |
| + if (FAILED(hr)) { |
| + DVLOG(1) << "Couldn't read a device's DevicePath."; |
| + return; |
| + } |
| + if (device.id() == base::SysWideToUTF8(V_BSTR(&device_id))) |
| + break; |
| + moniker.Release(); |
| + } |
| + |
| + if (moniker.get()) { |
| + base::win::ScopedComPtr<IBaseFilter> capture_filter; |
| + hr = GetDeviceFilter(device, capture_filter.Receive()); |
| + if (!capture_filter) { |
| + DVLOG(2) << "Failed to create capture filter."; |
| + return; |
| + } |
| + |
| + base::win::ScopedComPtr<IPin> output_capture_pin; |
| + hr = GetPin(capture_filter, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, |
| + output_capture_pin.Receive()); |
| + if (!output_capture_pin) { |
| + DVLOG(2) << "Failed to get capture output pin"; |
| + return; |
| + } |
| + |
| + ScopedComPtr<IAMStreamConfig> stream_config; |
| + hr = output_capture_pin.QueryInterface(stream_config.Receive()); |
| + if (FAILED(hr)) { |
| + DVLOG(2) << "Failed to get IAMStreamConfig interface from " |
| + "capture device"; |
| + return; |
| + } |
| + |
| + int count, size; |
| + hr = stream_config->GetNumberOfCapabilities(&count, &size); |
| + if (FAILED(hr)) { |
| + DVLOG(2) << "Failed to GetNumberOfCapabilities"; |
| + return; |
| + } |
| + |
| + AM_MEDIA_TYPE* media_type = NULL; |
| + VIDEO_STREAM_CONFIG_CAPS caps; |
| + for (int i = 0; i < count; ++i) { |
| + hr = stream_config->GetStreamCaps(i, &media_type, |
| + reinterpret_cast<BYTE*>(&caps)); |
| + // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() |
| + // macros here since they'll trigger incorrectly. |
| + if (hr != S_OK) { |
| + DVLOG(2) << "Failed to GetStreamCaps"; |
| + return; |
| + } |
| + |
| + if (media_type->majortype == MEDIATYPE_Video && |
| + media_type->formattype == FORMAT_VideoInfo) { |
| + VIDEOINFOHEADER* h = |
| + reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); |
| + VideoCaptureFormat format; |
| + format.frame_size.SetSize(h->bmiHeader.biWidth, |
| + h->bmiHeader.biHeight); |
| + // Trust the frame rate from the VIDEOINFOHEADER. |
| + format.frame_rate = (h->AvgTimePerFrame > 0) |
| + ? static_cast<int>(kSecondsToReferenceTime / h->AvgTimePerFrame) |
|
tommi (sloooow) - chröme
2014/02/17 12:58:29
nit: I think the convention is to have the operato
mcasas
2014/02/17 14:56:20
Done.
|
| + : 0; |
| + format.pixel_format = |
| + TranslateMediaSubtypeToPixelFormat(media_type->subtype); |
| + formats->push_back(format); |
| + DVLOG(1) << device.name() << " resolution: " |
| + << format.frame_size.ToString() << ", fps: " << format.frame_rate |
| + << ", pixel format: " << format.pixel_format; |
| + } |
| + } |
| + } |
| } |
| VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name) |
| @@ -582,28 +707,8 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() { |
| capability.frame_rate_numerator = capability.supported_format.frame_rate; |
| capability.frame_rate_denominator = 1; |
| - // We can't switch MEDIATYPE :~(. |
| - if (media_type->subtype == kMediaSubTypeI420) { |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_I420; |
| - } else if (media_type->subtype == MEDIASUBTYPE_IYUV) { |
| - // This is identical to PIXEL_FORMAT_I420. |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_I420; |
| - } else if (media_type->subtype == MEDIASUBTYPE_RGB24) { |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_RGB24; |
| - } else if (media_type->subtype == MEDIASUBTYPE_YUY2) { |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_YUY2; |
| - } else if (media_type->subtype == MEDIASUBTYPE_MJPG) { |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_MJPEG; |
| - } else if (media_type->subtype == MEDIASUBTYPE_UYVY) { |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_UYVY; |
| - } else if (media_type->subtype == MEDIASUBTYPE_ARGB32) { |
| - capability.supported_format.pixel_format = PIXEL_FORMAT_ARGB; |
| - } else { |
| - WCHAR guid_str[128]; |
| - StringFromGUID2(media_type->subtype, guid_str, arraysize(guid_str)); |
| - DVLOG(2) << "Device supports (also) an unknown media type " << guid_str; |
| - continue; |
| - } |
| + capability.supported_format.pixel_format = |
| + TranslateMediaSubtypeToPixelFormat(media_type->subtype); |
| capabilities_.Add(capability); |
| } |
| DeleteMediaType(media_type); |