14ee2ad04344446e610172a0e73949212923014dfSebastian Redl/* 22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * 42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Use of this source code is governed by a BSD-style license 52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * that can be found in the LICENSE file in the root of the source 62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * tree. An additional intellectual property rights grant can be found 72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * in the file PATENTS. All contributing project authors may 82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * be found in the AUTHORS file in the root of the source tree. 92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor */ 10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl 112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "webrtc/modules/video_capture/linux/device_info_linux.h" 122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <errno.h> 147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl#include <fcntl.h> 1589d9980bbc2e4a4ac86673e6ec16fb9f5babb63bDouglas Gregor#include <stdio.h> 160eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis#include <stdlib.h> 17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include <sys/ioctl.h> 18e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include <sys/stat.h> 192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <unistd.h> 202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor//v4l includes 212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <linux/videodev2.h> 222a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall 2389eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis#include "webrtc/system_wrappers/interface/ref_count.h" 240b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor#include "webrtc/system_wrappers/interface/trace.h" 257a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall 262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 27a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallnamespace webrtc 286ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl{ 297c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattnernamespace videocapturemodule 306a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor{ 317c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris LattnerVideoCaptureModule::DeviceInfo* 3283d63c78810556d26b62ac4cbae2eda6cdd2570cSteve NaroffVideoCaptureImpl::CreateDeviceInfo(const int32_t id) 3314f79002e58556798e86168c63e48d533287eda5Douglas Gregor{ 3410e286aa8d39fb51a21412850265d9dae74613eeChris Lattner videocapturemodule::DeviceInfoLinux *deviceInfo = 353251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor new videocapturemodule::DeviceInfoLinux(id); 3614f79002e58556798e86168c63e48d533287eda5Douglas Gregor if (!deviceInfo) 37bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor { 382bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor deviceInfo = NULL; 39ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor } 400a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor 4117fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor return deviceInfo; 4217fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor} 432596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar 442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorDeviceInfoLinux::DeviceInfoLinux(const int32_t id) 45fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer : DeviceInfoImpl(id) 4614f79002e58556798e86168c63e48d533287eda5Douglas Gregor{ 4703013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer} 48f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor 493c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattnerint32_t DeviceInfoLinux::Init() 50cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor{ 51f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor return 0; 522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 538538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas GregorDeviceInfoLinux::~DeviceInfoLinux() 55ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl{ 565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner} 575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner 585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattneruint32_t DeviceInfoLinux::NumberOfDevices() 596e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer{ 60ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCapture, _id, "%s", __FUNCTION__); 616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer 626e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer uint32_t count = 0; 635f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner char device[20]; 645f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner int fd = -1; 656e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer 66ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl /* detect /dev/video [0-63]VideoCaptureModule entries */ 67ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl for (int n = 0; n < 64; n++) 682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor sprintf(device, "/dev/video%d", n); 702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if ((fd = open(device, O_RDONLY)) != -1) 7112b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner { 722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor close(fd); 733397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl count++; 74a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl } 7589eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis } 762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return count; 782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 798538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorint32_t DeviceInfoLinux::GetDeviceName( 8189eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis uint32_t deviceNumber, 828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl char* deviceNameUTF8, 832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor uint32_t deviceNameLength, 842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor char* deviceUniqueIdUTF8, 852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor uint32_t deviceUniqueIdUTF8Length, 862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor char* /*productUniqueIdUTF8*/, 872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor uint32_t /*productUniqueIdUTF8Length*/) 882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor{ 892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCapture, _id, "%s", __FUNCTION__); 902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Travel through /dev/video [0-63] 922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor uint32_t count = 0; 932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor char device[20]; 943397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl int fd = -1; 952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor bool found = false; 962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor for (int n = 0; n < 64; n++) 972cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 983397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl sprintf(device, "/dev/video%d", n); 992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if ((fd = open(device, O_RDONLY)) != -1) 1008538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl { 1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (count == deviceNumber) { 1022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // Found the device 1033397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl found = true; 1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor break; 1058538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl } else { 1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor close(fd); 1072cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor count++; 1083397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl } 1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1108538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl } 1112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!found) 1133397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl return -1; 114df1550fc59b51681d37225934fe4e3acac321621Richard Smith 115df1550fc59b51681d37225934fe4e3acac321621Richard Smith // query device capabilities 1168538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl struct v4l2_capability cap; 1172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) 1182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 1193397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 120df1550fc59b51681d37225934fe4e3acac321621Richard Smith "error in querying the device capability for device %s. errno = %d", 1218538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl device, errno); 1222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor close(fd); 1232cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return -1; 1243397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl } 1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump close(fd); 1278538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 1282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor char cameraName[64]; 1292cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor memset(deviceNameUTF8, 0, deviceNameLength); 1303397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl memcpy(cameraName, cap.card, sizeof(cap.card)); 1312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1322cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (deviceNameLength >= strlen(cameraName)) 1330953e767ff7817f97b3ab20896b229891eeff45bJohn McCall { 1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor memcpy(deviceNameUTF8, cameraName, strlen(cameraName)); 1352cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1363397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl else 1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 1382cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "buffer passed is too small"); 1398538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl return -1; 1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1412cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1423397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl if (cap.bus_info[0] != 0) // may not available in all drivers 1432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 1448538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // copy device id 1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (deviceUniqueIdUTF8Length >= strlen((const char*) cap.bus_info)) 1462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 1473397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl memset(deviceUniqueIdUTF8, 0, deviceUniqueIdUTF8Length); 1482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor memcpy(deviceUniqueIdUTF8, cap.bus_info, 1497e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor strlen((const char*) cap.bus_info)); 1507e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor } 151c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor else 1528538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl { 1532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 1542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor "buffer passed is too small"); 1553397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl return -1; 1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 158e86d78cf4754a6aef2cf9a33d847aa15338e276fBob Wilson 1598538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl return 0; 1602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 1612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1623397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlint32_t DeviceInfoLinux::CreateCapabilityMap( 1632cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const char* deviceUniqueIdUTF8) 1648538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl{ 1652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor int fd; 1662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor char device[32]; 1673397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl bool found = false; 1682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 169264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola const int32_t deviceUniqueIdUTF8Length = 170264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola (int32_t) strlen((char*) deviceUniqueIdUTF8); 171a49218e17bcbb1acde0245773173e2c0c42f4f19Eli Friedman if (deviceUniqueIdUTF8Length > kVideoCaptureUniqueNameLength) 172425ef72306d4ff6b3698b744353e5f0e56b4b884Rafael Espindola { 173ab8bbf4ebd3e3e6eab913cb044772a62b7581941Douglas Gregor WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "Device name too long"); 174264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola return -1; 175f85e193739c953358c865005855253af4f68a497John McCall } 1762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, 1772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor "CreateCapabilityMap called for device %s", deviceUniqueIdUTF8); 1783397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 1792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor /* detect /dev/video [0-63] entries */ 1808538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl for (int n = 0; n < 64; ++n) 1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 1822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor sprintf(device, "/dev/video%d", n); 1833397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl fd = open(device, O_RDONLY); 1842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (fd == -1) 1852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor continue; 1862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // query device capabilities 1882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor struct v4l2_capability cap; 1892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) 190c938c1668b4fd12af154e965dd935a89e4801a70Douglas Gregor { 19160618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl if (cap.bus_info[0] != 0) 19260618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl { 19360618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl if (strncmp((const char*) cap.bus_info, 19460618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl (const char*) deviceUniqueIdUTF8, 19560618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl strlen((const char*) deviceUniqueIdUTF8)) == 0) //match with device id 19660618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl { 19760618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl found = true; 19860618fa7f88d5162bb5b40988b6b38d4d75d6fc6Sebastian Redl break; // fd matches with device unique id supplied 1998538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl } 2002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 2012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor else //match for device name 2023397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl { 203ed97649e9574b9d854fa4d6109c9333ae0993554John McCall if (IsDeviceNameMatches((const char*) cap.card, 2048538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl (const char*) deviceUniqueIdUTF8)) 205ed97649e9574b9d854fa4d6109c9333ae0993554John McCall { 206ed97649e9574b9d854fa4d6109c9333ae0993554John McCall found = true; 2073397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl break; 2082cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 2099763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis } 2109763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis } 2118538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl close(fd); // close since this is not the matching device 2122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 2132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2143397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl if (!found) 215c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor { 2168538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "no matching device found"); 2172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return -1; 2182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 2193397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 2202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor // now fd will point to the matching device 2218538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // reset old capability list. 2222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor _captureCapabilities.clear(); 2232cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2243397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl int size = FillCapabilities(fd); 225395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson close(fd); 2268538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 227395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson // Store the new used device name 228395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson _lastUsedDeviceNameLength = deviceUniqueIdUTF8Length; 229ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt _lastUsedDeviceName = (char*) realloc(_lastUsedDeviceName, 230ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt _lastUsedDeviceNameLength + 1); 231ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8, _lastUsedDeviceNameLength + 1); 232ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt 233ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt WEBRTC_TRACE(webrtc::kTraceInfo, 234ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt webrtc::kTraceVideoCapture, 235ca63c200346c0ca9e00194ec6e34a5a7b0ed9321Sean Hunt _id, 23634b41d939a1328f484511c6002ba2456db879a29Richard Smith "CreateCapabilityMap %u", 23734b41d939a1328f484511c6002ba2456db879a29Richard Smith static_cast<unsigned int>(_captureCapabilities.size())); 23834b41d939a1328f484511c6002ba2456db879a29Richard Smith 23934b41d939a1328f484511c6002ba2456db879a29Richard Smith return size; 24034b41d939a1328f484511c6002ba2456db879a29Richard Smith} 2413397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 242be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidisbool DeviceInfoLinux::IsDeviceNameMatches(const char* name, 2432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const char* deviceUniqueIdUTF8) 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{ 2452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (strncmp(deviceUniqueIdUTF8, name, strlen(name)) == 0) 2462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return true; 2472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return false; 2483397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 2492cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2508538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlint32_t DeviceInfoLinux::FillCapabilities(int fd) 2512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor{ 2522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2533397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // set image format 2542cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor struct v4l2_format video_fmt; 2558538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl memset(&video_fmt, 0, sizeof(struct v4l2_format)); 2562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 2572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 2589d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall video_fmt.fmt.pix.sizeimage = 0; 2599d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall 2609d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall int totalFmts = 3; 2619d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall unsigned int videoFormats[] = { 2629d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall V4L2_PIX_FMT_MJPEG, 2639d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall V4L2_PIX_FMT_YUV420, 2649d156a7b1b2771e191f2f5a45a7b7a694129463bJohn McCall V4L2_PIX_FMT_YUYV }; 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2663397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl int sizes = 13; 26749a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall unsigned int size[][2] = { { 128, 96 }, { 160, 120 }, { 176, 144 }, 26849a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall { 320, 240 }, { 352, 288 }, { 640, 480 }, 26949a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall { 704, 576 }, { 800, 600 }, { 960, 720 }, 2708538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl { 1280, 720 }, { 1024, 768 }, { 1440, 1080 }, 27149a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall { 1920, 1080 } }; 27249a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall 27349a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall int index = 0; 274c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor for (int fmts = 0; fmts < totalFmts; fmts++) 275c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor { 276c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor for (int i = 0; i < sizes; i++) 277c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor { 278c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor video_fmt.fmt.pix.pixelformat = videoFormats[fmts]; 279c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor video_fmt.fmt.pix.width = size[i][0]; 280c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor video_fmt.fmt.pix.height = size[i][1]; 281c3069d618f4661d923cb1b5c4525b082fce73b04Douglas Gregor 2823397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl if (ioctl(fd, VIDIOC_TRY_FMT, &video_fmt) >= 0) 2832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor { 284be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis if ((video_fmt.fmt.pix.width == size[i][0]) 28590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis && (video_fmt.fmt.pix.height == size[i][1])) 28690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis { 28790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis VideoCaptureCapability cap; 28890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis cap.width = video_fmt.fmt.pix.width; 28990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis cap.height = video_fmt.fmt.pix.height; 2903e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith cap.expectedCaptureDelay = 120; 2913e4c6c4c79a03f5cb0c4671d7c282d623c6dc35eRichard Smith if (videoFormats[fmts] == V4L2_PIX_FMT_YUYV) 2929763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis { 2939763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis cap.rawType = kVideoYUY2; 2948538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl } 29590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis else if (videoFormats[fmts] == V4L2_PIX_FMT_YUV420) 29690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis { 29790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis cap.rawType = kVideoI420; 2983397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl } 299ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis else if (videoFormats[fmts] == V4L2_PIX_FMT_MJPEG) 300ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis { 301ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis cap.rawType = kVideoMJPEG; 3028538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl } 30390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 30490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // get fps of current camera mode 30590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis // V4l2 does not have a stable method of knowing so we just guess. 3063397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl if(cap.width >= 800 && cap.rawType != kVideoMJPEG) 30790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis { 30890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis cap.maxFPS = 15; 30990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis } 31090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis else 31190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis { 31290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis cap.maxFPS = 30; 3133397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl } 31490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 31590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis _captureCapabilities.push_back(cap); 31690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis index++; 3174fb86f8c4585e53c21c847ad3de9e3b2de123cd9Chandler Carruth WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, 3188538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl "Camera capability, width:%d height:%d type:%d fps:%d", 31990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis cap.width, cap.height, cap.rawType, cap.maxFPS); 32090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis } 32190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis } 3223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl } 3238dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis } 3248dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis 3258dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis WEBRTC_TRACE(webrtc::kTraceInfo, 326f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis webrtc::kTraceVideoCapture, 327f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis _id, 328f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis "CreateCapabilityMap %u", 3298538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl static_cast<unsigned int>(_captureCapabilities.size())); 33090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis return _captureCapabilities.size(); 33190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis} 33290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis 3333397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} // namespace videocapturemodule 33490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis} // namespace webrtc 3353acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis