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

Unified Diff: media/video/capture/win/video_capture_device_win.cc

Issue 156583004: Add GetDeviceSupportedFormats to Win DirectShow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tommi@s comments Created 6 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..d747a1a009f2a1bebf570184ebb74b83a3f04ddc 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(const GUID& sub_type) {
+ static struct {
+ const GUID& sub_type;
+ VideoPixelFormat format;
+ } pixel_formats[] = {
+ { kMediaSubTypeI420, PIXEL_FORMAT_I420 },
+ { MEDIASUBTYPE_IYUV, PIXEL_FORMAT_I420 },
+ { MEDIASUBTYPE_RGB24, PIXEL_FORMAT_RGB24 },
+ { MEDIASUBTYPE_YUY2, PIXEL_FORMAT_YUY2 },
+ { MEDIASUBTYPE_MJPG, PIXEL_FORMAT_MJPEG },
+ { MEDIASUBTYPE_UYVY, PIXEL_FORMAT_UYVY },
+ { MEDIASUBTYPE_ARGB32, PIXEL_FORMAT_ARGB },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(pixel_formats); ++i) {
+ if (sub_type == pixel_formats[i].sub_type)
+ return pixel_formats[i].format;
+ }
+#ifndef NDEBUG
+ WCHAR guid_str[128];
+ StringFromGUID2(sub_type, guid_str, arraysize(guid_str));
+ DVLOG(2) << "Device (also) supports an unknown media type " << guid_str;
+#endif
+ 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,108 @@ 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",
+ // since this is already skipped in the enumeration of GetDeviceNames().
+ 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) :
+ 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 +708,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);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698