Bug 1297337 - implement mediaDevices.ondevicechange for Linux; r=jesup
MozReview-Commit-ID: 6cEq7xVUkhf
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -36,17 +36,17 @@ skip-if = toolkit == 'gonk' || buildapp
[test_dataChannel_basicVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g(Bug 960442, video support for WebRTC is disabled on b2g), android(Bug 1189784, timeouts on 4.3 emulator)
[test_dataChannel_bug1013809.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
[test_dataChannel_noOffer.html]
[test_enumerateDevices.html]
skip-if = buildapp == 'mulet'
[test_ondevicechange.html]
-skip-if = toolkit == 'gonk' || buildapp == 'mulet' || os == 'linux' || os == 'win' || os == 'android'
+skip-if = toolkit == 'gonk' || buildapp == 'mulet' || os == 'win' || os == 'android'
[test_getUserMedia_audioCapture.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g emulator seems to be too slow (Bug 1016498 and 1008080), android(Bug 1189784, timeouts on 4.3 emulator)
[test_getUserMedia_addTrackRemoveTrack.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure
[test_getUserMedia_addtrack_removetrack_events.html]
[test_getUserMedia_basicAudio.html]
skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure
[test_getUserMedia_basicVideo.html]
--- a/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc
@@ -24,16 +24,18 @@
#include <sys/videodev2.h>
#else
#include <linux/videodev2.h>
#endif
#include "webrtc/system_wrappers/interface/ref_count.h"
#include "webrtc/system_wrappers/interface/trace.h"
+#define EVENT_SIZE ( sizeof (struct inotify_event) )
+#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
namespace webrtc
{
namespace videocapturemodule
{
VideoCaptureModule::DeviceInfo*
VideoCaptureImpl::CreateDeviceInfo(const int32_t id)
{
@@ -42,28 +44,153 @@ VideoCaptureImpl::CreateDeviceInfo(const
if (!deviceInfo)
{
deviceInfo = NULL;
}
return deviceInfo;
}
+void DeviceInfoLinux::HandleEvent(inotify_event* event)
+{
+ switch (event->mask) {
+ case IN_CREATE:
+ DeviceChange();
+ break;
+ case IN_DELETE:
+ DeviceChange();
+ break;
+ default:
+ 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,
+ "UNKNOWN EVENT OCCURRED for file \"%s\" on WD #%i\n",
+ cur_event_filename, cur_event_wd);
+ break;
+ }
+}
+
+int DeviceInfoLinux::EventCheck()
+{
+ struct timeval timeout;
+ fd_set rfds;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 100000;
+
+ FD_ZERO(&rfds);
+ FD_SET(_fd, &rfds);
+
+ return select(_fd+1, &rfds, NULL, NULL, &timeout);
+}
+
+int DeviceInfoLinux::HandleEvents()
+{
+ char buffer[BUF_LEN];
+
+ ssize_t r = read(_fd, buffer, BUF_LEN);
+
+ if (r <= 0) {
+ return r;
+ }
+
+ ssize_t buffer_i = 0;
+ inotify_event* pevent;
+ size_t eventSize;
+ int count = 0;
+
+ while (buffer_i < r)
+ {
+ pevent = (inotify_event *) (&buffer[buffer_i]);
+ eventSize = sizeof(inotify_event) + pevent->len;
+ char event[sizeof(inotify_event) + FILENAME_MAX + 1] // null-terminated
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+
+ memcpy(event, pevent, eventSize);
+
+ HandleEvent((inotify_event*)(event));
+
+ buffer_i += eventSize;
+ count++;
+ }
+
+ return count;
+}
+
+int DeviceInfoLinux::ProcessInotifyEvents()
+{
+ while (0 == _isShutdown.Value()) {
+ if (EventCheck() > 0) {
+ if (HandleEvents() < 0) {
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+bool DeviceInfoLinux::InotifyEventThread(void* obj)
+{
+ return static_cast<DeviceInfoLinux*> (obj)->InotifyProcess();
+}
+
+bool DeviceInfoLinux::InotifyProcess()
+{
+ _fd = inotify_init();
+ if (_fd >= 0) {
+ _wd_v4l = inotify_add_watch(_fd, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE);
+ _wd_snd = inotify_add_watch(_fd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE);
+ ProcessInotifyEvents();
+
+ if (_wd_v4l >= 0) {
+ inotify_rm_watch(_fd, _wd_v4l);
+ }
+
+ if (_wd_snd >= 0) {
+ inotify_rm_watch(_fd, _wd_snd);
+ }
+
+ close(_fd);
+ return true;
+ } else {
+ return false;
+ }
+}
+
DeviceInfoLinux::DeviceInfoLinux(const int32_t id)
: DeviceInfoImpl(id)
+ , _isShutdown(0)
{
+ _inotifyEventThread = ThreadWrapper::CreateThread(
+ InotifyEventThread, this, "InotifyEventThread");
+
+ if (_inotifyEventThread)
+ {
+ _inotifyEventThread->Start();
+ _inotifyEventThread->SetPriority(kHighPriority);
+ }
}
int32_t DeviceInfoLinux::Init()
{
return 0;
}
DeviceInfoLinux::~DeviceInfoLinux()
{
+ ++_isShutdown;
+
+ if (_inotifyEventThread) {
+ _inotifyEventThread->Stop();
+ _inotifyEventThread.reset();
+ }
}
uint32_t DeviceInfoLinux::NumberOfDevices()
{
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideoCapture, _id, "%s", __FUNCTION__);
uint32_t count = 0;
char device[20];
--- a/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.h
@@ -8,16 +8,19 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_LINUX_DEVICE_INFO_LINUX_H_
#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_LINUX_DEVICE_INFO_LINUX_H_
#include "webrtc/modules/video_capture/device_info_impl.h"
#include "webrtc/modules/video_capture/video_capture_impl.h"
+#include "webrtc/system_wrappers/interface/thread_wrapper.h"
+#include "webrtc/system_wrappers/interface/atomic32.h"
+#include <sys/inotify.h>
namespace webrtc
{
namespace videocapturemodule
{
class DeviceInfoLinux: public DeviceInfoImpl
{
public:
@@ -42,12 +45,22 @@ public:
void* /*parentWindow*/,
uint32_t /*positionX*/,
uint32_t /*positionY*/) { return -1;}
int32_t FillCapabilities(int fd);
int32_t Init();
private:
bool IsDeviceNameMatches(const char* name, const char* deviceUniqueIdUTF8);
+
+ void HandleEvent(inotify_event* event);
+ int EventCheck();
+ int HandleEvents();
+ int ProcessInotifyEvents();
+ rtc::scoped_ptr<ThreadWrapper> _inotifyEventThread;
+ static bool InotifyEventThread(void*);
+ bool InotifyProcess();
+ int _fd, _wd_v4l, _wd_snd; /* accessed on InotifyEventThread thread */
+ Atomic32 _isShutdown;
};
} // namespace videocapturemodule
} // namespace webrtc
#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_LINUX_DEVICE_INFO_LINUX_H_