зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1331648 - detect device connection for the case /dev/v4l hasn't existed; r=jesup
MozReview-Commit-ID: 1erqrFScjr --HG-- extra : rebase_source : ad4a4adde64f479a84a3f7fa093f71eef319436b
This commit is contained in:
Родитель
0f5f625a1a
Коммит
a50658a789
|
@ -52,30 +52,57 @@ VideoCaptureImpl::CreateDeviceInfo(const int32_t id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WEBRTC_LINUX
|
#ifdef WEBRTC_LINUX
|
||||||
void DeviceInfoLinux::HandleEvent(inotify_event* event)
|
void DeviceInfoLinux::HandleEvent(inotify_event* event, int fd)
|
||||||
{
|
{
|
||||||
switch (event->mask) {
|
if (event->mask & IN_CREATE) {
|
||||||
case IN_CREATE:
|
if (fd == _fd_v4l || fd == _fd_snd) {
|
||||||
DeviceChange();
|
DeviceChange();
|
||||||
break;
|
} else if ((event->mask & IN_ISDIR) && (fd == _fd_dev)) {
|
||||||
case IN_DELETE:
|
if (_wd_v4l < 0) {
|
||||||
DeviceChange();
|
// Sometimes inotify_add_watch failed if we call it immediately after receiving this event
|
||||||
break;
|
// Adding 5ms delay to let file system settle down
|
||||||
default:
|
usleep(5*1000);
|
||||||
char* cur_event_filename = NULL;
|
_wd_v4l = inotify_add_watch(_fd_v4l, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF);
|
||||||
int cur_event_wd = event->wd;
|
if (_wd_v4l >= 0) {
|
||||||
if (event->len) {
|
DeviceChange();
|
||||||
cur_event_filename = event->name;
|
}
|
||||||
}
|
}
|
||||||
|
if (_wd_snd < 0) {
|
||||||
|
usleep(5*1000);
|
||||||
|
_wd_snd = inotify_add_watch(_fd_snd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF);
|
||||||
|
if (_wd_snd >= 0) {
|
||||||
|
DeviceChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event->mask & IN_DELETE) {
|
||||||
|
if (fd == _fd_v4l || fd == _fd_snd) {
|
||||||
|
DeviceChange();
|
||||||
|
}
|
||||||
|
} else if (event->mask & IN_DELETE_SELF) {
|
||||||
|
if (fd == _fd_v4l) {
|
||||||
|
inotify_rm_watch(_fd_v4l, _wd_v4l);
|
||||||
|
_wd_v4l = -1;
|
||||||
|
} else if (fd == _fd_snd) {
|
||||||
|
inotify_rm_watch(_fd_snd, _wd_snd);
|
||||||
|
_wd_snd = -1;
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char* cur_event_filename = NULL;
|
||||||
|
int cur_event_wd = event->wd;
|
||||||
|
if (event->len) {
|
||||||
|
cur_event_filename = event->name;
|
||||||
|
}
|
||||||
|
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
|
||||||
"UNKNOWN EVENT OCCURRED for file \"%s\" on WD #%i\n",
|
"UNKNOWN EVENT OCCURRED for file \"%s\" on WD #%i\n",
|
||||||
cur_event_filename, cur_event_wd);
|
cur_event_filename, cur_event_wd);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceInfoLinux::EventCheck()
|
int DeviceInfoLinux::EventCheck(int fd)
|
||||||
{
|
{
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
|
@ -84,16 +111,16 @@ int DeviceInfoLinux::EventCheck()
|
||||||
timeout.tv_usec = 100000;
|
timeout.tv_usec = 100000;
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(_fd, &rfds);
|
FD_SET(fd, &rfds);
|
||||||
|
|
||||||
return select(_fd+1, &rfds, NULL, NULL, &timeout);
|
return select(fd+1, &rfds, NULL, NULL, &timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceInfoLinux::HandleEvents()
|
int DeviceInfoLinux::HandleEvents(int fd)
|
||||||
{
|
{
|
||||||
char buffer[BUF_LEN];
|
char buffer[BUF_LEN];
|
||||||
|
|
||||||
ssize_t r = read(_fd, buffer, BUF_LEN);
|
ssize_t r = read(fd, buffer, BUF_LEN);
|
||||||
|
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
return r;
|
return r;
|
||||||
|
@ -113,7 +140,7 @@ int DeviceInfoLinux::HandleEvents()
|
||||||
|
|
||||||
memcpy(event, pevent, eventSize);
|
memcpy(event, pevent, eventSize);
|
||||||
|
|
||||||
HandleEvent((inotify_event*)(event));
|
HandleEvent((inotify_event*)(event), fd);
|
||||||
|
|
||||||
buffer_i += eventSize;
|
buffer_i += eventSize;
|
||||||
count++;
|
count++;
|
||||||
|
@ -125,8 +152,18 @@ int DeviceInfoLinux::HandleEvents()
|
||||||
int DeviceInfoLinux::ProcessInotifyEvents()
|
int DeviceInfoLinux::ProcessInotifyEvents()
|
||||||
{
|
{
|
||||||
while (0 == _isShutdown.Value()) {
|
while (0 == _isShutdown.Value()) {
|
||||||
if (EventCheck() > 0) {
|
if (EventCheck(_fd_dev) > 0) {
|
||||||
if (HandleEvents() < 0) {
|
if (HandleEvents(_fd_dev) < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (EventCheck(_fd_v4l) > 0) {
|
||||||
|
if (HandleEvents(_fd_v4l) < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (EventCheck(_fd_snd) > 0) {
|
||||||
|
if (HandleEvents(_fd_snd) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,21 +178,30 @@ bool DeviceInfoLinux::InotifyEventThread(void* obj)
|
||||||
|
|
||||||
bool DeviceInfoLinux::InotifyProcess()
|
bool DeviceInfoLinux::InotifyProcess()
|
||||||
{
|
{
|
||||||
_fd = inotify_init();
|
_fd_v4l = inotify_init();
|
||||||
if (_fd >= 0) {
|
_fd_snd = inotify_init();
|
||||||
_wd_v4l = inotify_add_watch(_fd, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE);
|
_fd_dev = inotify_init();
|
||||||
_wd_snd = inotify_add_watch(_fd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE);
|
if (_fd_v4l >= 0 && _fd_snd >= 0 && _fd_dev >= 0) {
|
||||||
|
_wd_v4l = inotify_add_watch(_fd_v4l, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF);
|
||||||
|
_wd_snd = inotify_add_watch(_fd_snd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF);
|
||||||
|
_wd_dev = inotify_add_watch(_fd_dev, "/dev/", IN_CREATE);
|
||||||
ProcessInotifyEvents();
|
ProcessInotifyEvents();
|
||||||
|
|
||||||
if (_wd_v4l >= 0) {
|
if (_wd_v4l >= 0) {
|
||||||
inotify_rm_watch(_fd, _wd_v4l);
|
inotify_rm_watch(_fd_v4l, _wd_v4l);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_wd_snd >= 0) {
|
if (_wd_snd >= 0) {
|
||||||
inotify_rm_watch(_fd, _wd_snd);
|
inotify_rm_watch(_fd_snd, _wd_snd);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(_fd);
|
if (_wd_dev >= 0) {
|
||||||
|
inotify_rm_watch(_fd_dev, _wd_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(_fd_v4l);
|
||||||
|
close(_fd_snd);
|
||||||
|
close(_fd_dev);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -55,14 +55,14 @@ private:
|
||||||
bool IsDeviceNameMatches(const char* name, const char* deviceUniqueIdUTF8);
|
bool IsDeviceNameMatches(const char* name, const char* deviceUniqueIdUTF8);
|
||||||
|
|
||||||
#ifdef WEBRTC_LINUX
|
#ifdef WEBRTC_LINUX
|
||||||
void HandleEvent(inotify_event* event);
|
void HandleEvent(inotify_event* event, int fd);
|
||||||
int EventCheck();
|
int EventCheck(int fd);
|
||||||
int HandleEvents();
|
int HandleEvents(int fd);
|
||||||
int ProcessInotifyEvents();
|
int ProcessInotifyEvents();
|
||||||
rtc::scoped_ptr<rtc::PlatformThread> _inotifyEventThread;
|
rtc::scoped_ptr<rtc::PlatformThread> _inotifyEventThread;
|
||||||
static bool InotifyEventThread(void*);
|
static bool InotifyEventThread(void*);
|
||||||
bool InotifyProcess();
|
bool InotifyProcess();
|
||||||
int _fd, _wd_v4l, _wd_snd; /* accessed on InotifyEventThread thread */
|
int _fd_v4l, _fd_snd, _fd_dev, _wd_v4l, _wd_snd, _wd_dev; /* accessed on InotifyEventThread thread */
|
||||||
Atomic32 _isShutdown;
|
Atomic32 _isShutdown;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче