Files
haikuports/media-libs/tg_owt/patches/tg_owt-0.0.20260409.patchset
Gerasim Troeglazov fe1a18df22 tg_owt: bump version
2026-04-13 16:56:32 +10:00

1737 lines
52 KiB
Plaintext

From 85c4f122585172f2aee5d993247596e3e1e880e1 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Thu, 1 Aug 2024 20:17:51 +1000
Subject: Add Haiku support
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a36752b..28dd4a6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1453,6 +1453,9 @@ PRIVATE
modules/video_capture/linux/video_capture_pipewire.h
modules/video_capture/linux/video_capture_v4l2.cc
modules/video_capture/linux/video_capture_v4l2.h
+ modules/video_capture/haiku/device_info_haiku.cc
+ modules/video_capture/haiku/video_capture_haiku.cc
+ modules/video_capture/haiku/video_consumer.cc
modules/video_capture/windows/device_info_ds.cc
modules/video_capture/windows/device_info_ds.h
modules/video_capture/windows/help_functions_ds.cc
@@ -2212,6 +2215,7 @@ PRIVATE
modules/desktop_capture/mouse_cursor.h
modules/desktop_capture/mouse_cursor_monitor.h
modules/desktop_capture/mouse_cursor_monitor_linux.cc
+ modules/desktop_capture/mouse_cursor_monitor_haiku.cc
modules/desktop_capture/mouse_cursor_monitor_mac.mm
modules/desktop_capture/mouse_cursor_monitor_win.cc
modules/desktop_capture/resolution_tracker.cc
@@ -2223,8 +2227,10 @@ PRIVATE
modules/desktop_capture/screen_capturer_helper.h
modules/desktop_capture/screen_capturer_darwin.mm
modules/desktop_capture/screen_capturer_linux.cc
+ modules/desktop_capture/screen_capturer_haiku.cc
modules/desktop_capture/screen_capturer_win.cc
modules/desktop_capture/window_capturer_linux.cc
+ modules/desktop_capture/window_capturer_haiku.cc
modules/desktop_capture/window_capturer_mac.mm
modules/desktop_capture/window_capturer_win.cc
modules/desktop_capture/window_finder.cc
@@ -2239,6 +2245,10 @@ PRIVATE
modules/desktop_capture/screen_capturer_null.cc
modules/desktop_capture/window_capturer_null.cc
+ # haiku specific
+ modules/desktop_capture/haiku/screen_capturer_haiku.cc
+ modules/desktop_capture/haiku/screen_capturer_haiku.h
+
# linux specific
modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc
modules/desktop_capture/linux/wayland/base_capturer_pipewire.h
diff --git a/cmake/libwebrtcbuild.cmake b/cmake/libwebrtcbuild.cmake
index 4838e03..c15cef1 100644
--- a/cmake/libwebrtcbuild.cmake
+++ b/cmake/libwebrtcbuild.cmake
@@ -64,6 +64,12 @@ if (WIN32)
WEBRTC_WIN
RTC_ENABLE_WIN_WGC
)
+elseif (HAIKU)
+ target_compile_definitions(libwebrtcbuild
+ INTERFACE
+ WEBRTC_POSIX
+ WEBRTC_HAIKU
+ )
else()
target_compile_definitions(libwebrtcbuild
INTERFACE
diff --git a/cmake/nice_target_sources.cmake b/cmake/nice_target_sources.cmake
index cfc6aeb..699d0e6 100644
--- a/cmake/nice_target_sources.cmake
+++ b/cmake/nice_target_sources.cmake
@@ -15,6 +15,7 @@ function(nice_target_sources target_name src_loc)
set(not_win_sources "")
set(not_mac_sources "")
set(not_linux_sources "")
+ set(not_haiku_sources "")
foreach (entry ${list})
if (${entry} STREQUAL "PRIVATE" OR ${entry} STREQUAL "PUBLIC" OR ${entry} STREQUAL "INTERFACE")
set(writing_now ${entry})
@@ -23,12 +24,19 @@ function(nice_target_sources target_name src_loc)
if (${entry} MATCHES "(^|/)win/" OR ${entry} MATCHES "(^|/)winrc/" OR ${entry} MATCHES "(^|/)windows/" OR ${entry} MATCHES "[_\\/]win\\.")
list(APPEND not_mac_sources ${full_name})
list(APPEND not_linux_sources ${full_name})
+ list(APPEND not_haiku_sources ${full_name})
elseif (${entry} MATCHES "(^|/)mac/" OR ${entry} MATCHES "(^|/)darwin/" OR ${entry} MATCHES "(^|/)osx/" OR ${entry} MATCHES "[_\\/]mac\\." OR ${entry} MATCHES "[_\\/]darwin\\." OR ${entry} MATCHES "[_\\/]osx\\.")
list(APPEND not_win_sources ${full_name})
list(APPEND not_linux_sources ${full_name})
+ list(APPEND not_haiku_sources ${full_name})
elseif (${entry} MATCHES "(^|/)linux/" OR ${entry} MATCHES "[_\\/]linux\\.")
list(APPEND not_win_sources ${full_name})
list(APPEND not_mac_sources ${full_name})
+ list(APPEND not_haiku_sources ${full_name})
+ elseif (${entry} MATCHES "(^|/)haiku/" OR ${entry} MATCHES "[_\\/]haiku\\.")
+ list(APPEND not_win_sources ${full_name})
+ list(APPEND not_mac_sources ${full_name})
+ list(APPEND not_linux_sources ${full_name})
elseif (${entry} MATCHES "(^|/)posix/" OR ${entry} MATCHES "[_\\/]posix\\.")
list(APPEND not_win_sources ${full_name})
endif()
@@ -64,6 +72,9 @@ function(nice_target_sources target_name src_loc)
elseif (APPLE)
set_source_files_properties(${not_mac_sources} PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties(${not_mac_sources} PROPERTIES SKIP_AUTOGEN TRUE)
+ elseif (HAIKU)
+ set_source_files_properties(${not_haiku_sources} PROPERTIES HEADER_FILE_ONLY TRUE)
+ set_source_files_properties(${not_haiku_sources} PROPERTIES SKIP_AUTOGEN TRUE)
else()
set_source_files_properties(${not_linux_sources} PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties(${not_linux_sources} PROPERTIES SKIP_AUTOGEN TRUE)
diff --git a/src/api/task_queue/BUILD.gn b/src/api/task_queue/BUILD.gn
index 1b9425d..ff93aea 100644
--- a/src/api/task_queue/BUILD.gn
+++ b/src/api/task_queue/BUILD.gn
@@ -95,7 +95,7 @@ rtc_library("default_task_queue_factory") {
"../../rtc_base/memory:always_valid_pointer",
]
- if (rtc_enable_libevent) {
+ if (rtc_enable_libevent && !is_haiku) {
if (is_android) {
sources +=
[ "default_task_queue_factory_stdlib_or_libevent_experiment.cc" ]
diff --git a/src/modules/audio_coding/neteq/reorder_optimizer.cc b/src/modules/audio_coding/neteq/reorder_optimizer.cc
index f6e073f..ed71751 100644
--- a/src/modules/audio_coding/neteq/reorder_optimizer.cc
+++ b/src/modules/audio_coding/neteq/reorder_optimizer.cc
@@ -12,6 +12,7 @@
#include <algorithm>
#include <limits>
+#include <cstdint>
#include <vector>
namespace webrtc {
diff --git a/src/modules/desktop_capture/haiku/screen_capturer_haiku.cc b/src/modules/desktop_capture/haiku/screen_capturer_haiku.cc
new file mode 100644
index 0000000..b6f4d24
--- /dev/null
+++ b/src/modules/desktop_capture/haiku/screen_capturer_haiku.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/desktop_capture/haiku/screen_capturer_haiku.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+#include <utility>
+
+#include "modules/desktop_capture/desktop_capture_options.h"
+#include "modules/desktop_capture/desktop_capturer.h"
+#include "modules/desktop_capture/desktop_frame.h"
+#include "modules/desktop_capture/desktop_geometry.h"
+#include "modules/desktop_capture/screen_capture_frame_queue.h"
+#include "modules/desktop_capture/screen_capturer_helper.h"
+#include "modules/desktop_capture/shared_desktop_frame.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/sanitizer.h"
+#include "rtc_base/time_utils.h"
+#include "rtc_base/trace_event.h"
+
+namespace webrtc {
+
+ScreenCapturerHaiku::ScreenCapturerHaiku() {
+ screen_ = new BScreen(B_MAIN_SCREEN_ID);
+ screen_->GetBitmap(&bitmap_);
+}
+
+ScreenCapturerHaiku::~ScreenCapturerHaiku() {
+ delete screen_;
+ delete bitmap_;
+}
+
+bool ScreenCapturerHaiku::Init(const DesktopCaptureOptions& options) {
+ options_ = options;
+ return true;
+}
+
+void ScreenCapturerHaiku::Start(Callback* callback) {
+ RTC_DCHECK(!callback_);
+ RTC_DCHECK(callback);
+ callback_ = callback;
+ lastShot_ = system_time();
+}
+
+void ScreenCapturerHaiku::CaptureFrame() {
+ int64_t capture_start_time_nanos = rtc::TimeNanos();
+ bigtime_t now_ = system_time();
+ if (now_ - lastShot_ > 1000000) {
+ screen_->ReadBitmap(bitmap_);
+ lastShot_ = now_;
+ }
+ DesktopRect r = DesktopRect::MakeXYWH(0, 0, bitmap_->Bounds().Width() + 1, bitmap_->Bounds().Height() + 1);
+ std::unique_ptr<DesktopFrame> frame(new BasicDesktopFrame(r.size()));
+ frame->CopyPixelsFrom((const uint8_t*)bitmap_->Bits(), bitmap_->BytesPerRow(), r);
+ frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) / rtc::kNumNanosecsPerMillisec);
+ callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
+}
+
+bool ScreenCapturerHaiku::GetSourceList(SourceList* sources) {
+ sources->push_back({kFullDesktopScreenId, "Active Desktop"});
+ return true;
+}
+
+bool ScreenCapturerHaiku::SelectSource(SourceId id) {
+ return id == kFullDesktopScreenId;
+}
+
+
+// static
+std::unique_ptr<DesktopCapturer> ScreenCapturerHaiku::CreateRawScreenCapturer(
+ const DesktopCaptureOptions& options) {
+ std::unique_ptr<ScreenCapturerHaiku> capturer(new ScreenCapturerHaiku());
+ if (!capturer.get()->Init(options)) {
+ return nullptr;
+ }
+
+ return std::move(capturer);
+}
+
+} // namespace webrtc
diff --git a/src/modules/desktop_capture/haiku/screen_capturer_haiku.h b/src/modules/desktop_capture/haiku/screen_capturer_haiku.h
new file mode 100644
index 0000000..b24160e
--- /dev/null
+++ b/src/modules/desktop_capture/haiku/screen_capturer_haiku.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
+#define MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
+
+#include <memory>
+
+#include "modules/desktop_capture/desktop_capture_options.h"
+#include "modules/desktop_capture/desktop_capturer.h"
+#include "modules/desktop_capture/desktop_frame.h"
+#include "modules/desktop_capture/desktop_region.h"
+#include "modules/desktop_capture/screen_capture_frame_queue.h"
+#include "modules/desktop_capture/screen_capturer_helper.h"
+#include "modules/desktop_capture/shared_desktop_frame.h"
+
+#include <OS.h>
+#include <InterfaceKit.h>
+
+namespace webrtc {
+
+class ScreenCapturerHaiku : public DesktopCapturer {
+ public:
+ ScreenCapturerHaiku();
+ ~ScreenCapturerHaiku() override;
+
+ static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer(
+ const DesktopCaptureOptions& options);
+
+ bool Init(const DesktopCaptureOptions& options);
+
+ void Start(Callback* delegate) override;
+ void CaptureFrame() override;
+ bool GetSourceList(SourceList* sources) override;
+ bool SelectSource(SourceId id) override;
+
+ private:
+ BScreen* screen_;
+ BBitmap* bitmap_;
+ bigtime_t lastShot_;
+
+ DesktopCaptureOptions options_;
+ Callback* callback_ = nullptr;
+};
+
+}
+
+#endif // MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
diff --git a/src/modules/desktop_capture/mouse_cursor_monitor_haiku.cc b/src/modules/desktop_capture/mouse_cursor_monitor_haiku.cc
new file mode 100644
index 0000000..8ea2aa2
--- /dev/null
+++ b/src/modules/desktop_capture/mouse_cursor_monitor_haiku.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/desktop_capture/desktop_capture_types.h"
+#include "modules/desktop_capture/mouse_cursor_monitor.h"
+//#include "modules/desktop_capture/haiku/mouse_cursor_monitor.h"
+
+namespace webrtc {
+
+// static
+MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
+ const DesktopCaptureOptions& options,
+ WindowId window) {
+ return nullptr;
+}
+
+// static
+MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
+ const DesktopCaptureOptions& options,
+ ScreenId screen) {
+ return nullptr;
+}
+
+// static
+std::unique_ptr<MouseCursorMonitor> MouseCursorMonitor::Create(
+ const DesktopCaptureOptions& options) {
+ return nullptr;
+}
+
+} // namespace webrtc
diff --git a/src/modules/desktop_capture/screen_capturer_haiku.cc b/src/modules/desktop_capture/screen_capturer_haiku.cc
new file mode 100644
index 0000000..63ceecc
--- /dev/null
+++ b/src/modules/desktop_capture/screen_capturer_haiku.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/desktop_capture/desktop_capture_options.h"
+#include "modules/desktop_capture/desktop_capturer.h"
+
+#include "modules/desktop_capture/haiku/screen_capturer_haiku.h"
+
+namespace webrtc {
+
+// static
+std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
+ const DesktopCaptureOptions& options) {
+ return ScreenCapturerHaiku::CreateRawScreenCapturer(options);
+}
+
+} // namespace webrtc
diff --git a/src/modules/desktop_capture/window_capturer_haiku.cc b/src/modules/desktop_capture/window_capturer_haiku.cc
new file mode 100644
index 0000000..a89b4a1
--- /dev/null
+++ b/src/modules/desktop_capture/window_capturer_haiku.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/desktop_capture/desktop_capturer.h"
+#include "modules/desktop_capture/desktop_frame.h"
+
+#include <assert.h>
+
+namespace webrtc {
+
+namespace {
+
+class WindowCapturerHaiku : public DesktopCapturer {
+ public:
+ WindowCapturerHaiku();
+ ~WindowCapturerHaiku() override;
+
+ void Start(Callback* callback) override;
+ void CaptureFrame() override;
+ bool GetSourceList(SourceList* sources) override;
+ bool SelectSource(SourceId id) override;
+
+ private:
+ Callback* callback_ = nullptr;
+};
+
+WindowCapturerHaiku::WindowCapturerHaiku() {}
+WindowCapturerHaiku::~WindowCapturerHaiku() {}
+
+bool WindowCapturerHaiku::GetSourceList(SourceList* sources) {
+ return false;
+}
+
+bool WindowCapturerHaiku::SelectSource(SourceId id) {
+ return false;
+}
+
+void WindowCapturerHaiku::Start(Callback* callback) {
+ assert(!callback_);
+ assert(callback);
+
+ callback_ = callback;
+}
+
+void WindowCapturerHaiku::CaptureFrame() {
+ callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
+}
+
+} // namespace
+
+// static
+std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
+ const DesktopCaptureOptions& options) {
+ return std::unique_ptr<DesktopCapturer>(new WindowCapturerHaiku());
+}
+
+} // namespace webrtc
diff --git a/src/modules/video_capture/haiku/device_info_haiku.cc b/src/modules/video_capture/haiku/device_info_haiku.cc
new file mode 100644
index 0000000..aeddaef
--- /dev/null
+++ b/src/modules/video_capture/haiku/device_info_haiku.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_capture/haiku/device_info_haiku.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include "modules/video_capture/video_capture.h"
+#include "modules/video_capture/video_capture_defines.h"
+#include "modules/video_capture/video_capture_impl.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+VideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo() {
+ return new videocapturemodule::DeviceInfoHaiku();
+}
+
+DeviceInfoHaiku::DeviceInfoHaiku() : DeviceInfoImpl() {}
+
+int32_t DeviceInfoHaiku::Init() {
+ return 0;
+}
+
+DeviceInfoHaiku::~DeviceInfoHaiku() {}
+
+uint32_t DeviceInfoHaiku::NumberOfDevices() {
+ status_t err = B_OK;
+
+ int32_t countDevices = 0;
+
+ dormant_node_info dni[30];
+ int32 ioCount = 30;
+ media_format out;
+ out.type = B_MEDIA_RAW_VIDEO;
+ err = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
+ if (err < B_OK)
+ return countDevices;
+
+ for (int ix=0; ix<ioCount; ix++) {
+ media_node_id running = -1;
+ if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
+ dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
+ media_node node;
+ BMediaRoster::CurrentRoster()->GetNodeFor(running, &node);
+ int32 count = 1;
+ media_output videoOutput;
+ BMediaRoster::CurrentRoster()->GetAllOutputsFor(node, &videoOutput, 1, &count);
+ if (count > 0)
+ countDevices++;
+ BMediaRoster::CurrentRoster()->ReleaseNode(node);
+ }
+ }
+
+ return countDevices;
+}
+
+int32_t DeviceInfoHaiku::GetDeviceName(uint32_t deviceNumber,
+ char* deviceNameUTF8,
+ uint32_t deviceNameLength,
+ char* deviceUniqueIdUTF8,
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8,
+ uint32_t productUniqueIdUTF8Length) {
+ if (deviceNumber >= NumberOfDevices())
+ return -1;
+
+ status_t err = B_OK;
+
+ int32_t countDevices = 0;
+
+ media_output videoOutput;
+
+ dormant_node_info dni[30];
+ int32 ioCount = 30;
+ media_format out;
+ out.type = B_MEDIA_RAW_VIDEO;
+ err = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
+ if (err < B_OK)
+ return countDevices;
+
+ err = B_ERROR;
+
+ for (int ix=0; ix<ioCount; ix++) {
+ media_node_id running = -1;
+ if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
+ dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
+ media_node node;
+ BMediaRoster::CurrentRoster()->GetNodeFor(running, &node);
+ int32 count = 1;
+ BMediaRoster::CurrentRoster()->GetAllOutputsFor(node, &videoOutput, 1, &count);
+ BMediaRoster::CurrentRoster()->ReleaseNode(node);
+ if (count > 0) {
+ if (countDevices == deviceNumber) {
+ if (deviceNameLength > strlen(videoOutput.name)) {
+ strncpy(deviceNameUTF8, videoOutput.name, deviceNameLength);
+ strncpy(deviceUniqueIdUTF8, videoOutput.name, deviceUniqueIdUTF8Length);
+ err = B_OK;
+ } else
+ err = B_ERROR;
+ break;
+ }
+ countDevices++;
+ }
+ BMediaRoster::CurrentRoster()->ReleaseNode(node);
+ }
+ }
+ return err == B_OK ? 0 : -1;
+}
+
+int32_t DeviceInfoHaiku::CreateCapabilityMap(const char* deviceUniqueIdUTF8) {
+ _captureCapabilities.clear();
+
+ VideoCaptureCapability cap;
+ cap.width = 640;
+ cap.height = 480;
+ cap.videoType = VideoType::kARGB;
+ cap.maxFPS = 30;
+
+ _captureCapabilities.push_back(cap);
+
+ return _captureCapabilities.size();
+}
+
+int32_t DeviceInfoHaiku::DisplayCaptureSettingsDialogBox(
+ const char* deviceUniqueIdUTF8,
+ const char* dialogTitleUTF8,
+ void* parentWindow,
+ uint32_t positionX,
+ uint32_t positionY) {
+ return -1;
+}
+
+} // namespace videocapturemodule
+} // namespace webrtc
diff --git a/src/modules/video_capture/haiku/device_info_haiku.h b/src/modules/video_capture/haiku/device_info_haiku.h
new file mode 100644
index 0000000..b5ffe94
--- /dev/null
+++ b/src/modules/video_capture/haiku/device_info_haiku.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
+#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
+
+#include <stdint.h>
+#include <MediaKit.h>
+
+#include "modules/video_capture/device_info_impl.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+class DeviceInfoHaiku : public DeviceInfoImpl {
+ public:
+ DeviceInfoHaiku();
+ ~DeviceInfoHaiku() override;
+ uint32_t NumberOfDevices() override;
+ int32_t GetDeviceName(uint32_t deviceNumber,
+ char* deviceNameUTF8,
+ uint32_t deviceNameLength,
+ char* deviceUniqueIdUTF8,
+ uint32_t deviceUniqueIdUTF8Length,
+ char* productUniqueIdUTF8 = 0,
+ uint32_t productUniqueIdUTF8Length = 0) override;
+ int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8) override;
+ int32_t DisplayCaptureSettingsDialogBox(const char*,
+ const char*,
+ void*,
+ uint32_t,
+ uint32_t) override;
+ int32_t Init() override;
+};
+} // namespace videocapturemodule
+} // namespace webrtc
+#endif // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
diff --git a/src/modules/video_capture/haiku/video_capture_haiku.cc b/src/modules/video_capture/haiku/video_capture_haiku.cc
new file mode 100644
index 0000000..86d8d20
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_capture_haiku.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_capture/haiku/video_capture_haiku.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <new>
+#include <string>
+
+#include "api/scoped_refptr.h"
+#include "media/base/video_common.h"
+#include "modules/video_capture/video_capture.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/ref_counted_object.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create(
+ const char* deviceUniqueId) {
+ rtc::scoped_refptr<VideoCaptureModuleHaiku> implementation(
+ new rtc::RefCountedObject<VideoCaptureModuleHaiku>());
+
+ if (implementation->Init(deviceUniqueId) != 0)
+ return nullptr;
+
+ return implementation;
+}
+
+VideoCaptureModuleHaiku::VideoCaptureModuleHaiku()
+ : VideoCaptureImpl(),
+ _currentWidth(-1),
+ _currentHeight(-1),
+ _currentFrameRate(-1),
+ _captureStarted(false),
+ _captureVideoType(VideoType::kARGB) {}
+
+int32_t VideoCaptureModuleHaiku::Init(const char* deviceUniqueIdUTF8) {
+ int len = strlen((const char*)deviceUniqueIdUTF8);
+ _deviceUniqueId = new (std::nothrow) char[len + 1];
+ if (_deviceUniqueId) {
+ memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
+ }
+
+ return 0;
+}
+
+VideoCaptureModuleHaiku::~VideoCaptureModuleHaiku() {
+ StopCapture();
+}
+
+int32_t VideoCaptureModuleHaiku::StartCapture(
+ const VideoCaptureCapability& capability) {
+ if (_captureStarted) {
+ if (capability.width == _currentWidth &&
+ capability.height == _currentHeight &&
+ _captureVideoType == capability.videoType) {
+ return 0;
+ } else {
+ StopCapture();
+ }
+ }
+
+ _currentWidth = 640;
+ _currentHeight = 480;
+ _currentFrameRate = 30;
+
+ status_t fStatus;
+ fMediaRoster = BMediaRoster::Roster(&fStatus);
+ if (fStatus != B_OK)
+ return -1;
+
+ media_node fTimeSource;
+ fStatus = fMediaRoster->GetTimeSource(&fTimeSource);
+ if (fStatus != B_OK)
+ return -1;
+
+ fVideoConsumer = new VideoConsumer("Telegram", NULL, 0);
+ fVideoConsumer->SetVideoCapture(this);
+
+ dormant_node_info dni[30];
+ int32 ioCount = 30;
+ media_format out;
+ out.type = B_MEDIA_RAW_VIDEO;
+ fStatus = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
+ if (fStatus < B_OK)
+ return -1;
+
+ fStatus = B_ERROR;
+ for (int ix=0; ix<ioCount; ix++) {
+ media_node_id running = -1;
+ if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
+ dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
+ BMediaRoster::CurrentRoster()->GetNodeFor(running, &fProducerNode);
+ int32 count = 1;
+ BMediaRoster::CurrentRoster()->GetFreeOutputsFor(
+ fProducerNode, &videoOutput, 1, &count, B_MEDIA_RAW_VIDEO);
+ if (count > 0) {
+ if (strcmp(videoOutput.name, _deviceUniqueId) == 0) {
+ fStatus = B_OK;
+ break;
+ }
+ }
+ BMediaRoster::CurrentRoster()->ReleaseNode(fProducerNode);
+ }
+ }
+ if (fStatus != B_OK)
+ return -1;
+
+ fStatus = fMediaRoster->RegisterNode(fVideoConsumer);
+ if (fStatus != B_OK)
+ return -1;
+ fConsumerNode = fVideoConsumer->Node();
+
+ int32 count = 1;
+ fStatus = fMediaRoster->GetFreeInputsFor(fConsumerNode, &videoInput, 1, &count, B_MEDIA_RAW_VIDEO);
+ if (fStatus != B_OK || count < 1)
+ return -1;
+
+ // connect the nodes
+ media_format format;
+ format.type = B_MEDIA_RAW_VIDEO;
+ media_raw_video_format videoFormat = {
+ 29.97f, 1, 0,
+ 639,
+ B_VIDEO_TOP_LEFT_RIGHT, 1, 1,
+ {
+ B_RGB32,
+ (uint32)(640),
+ (uint32)(480),
+ 0, 0, 0
+ }
+ };
+ format.u.raw_video = videoFormat;
+
+ fStatus = fMediaRoster->Connect(videoOutput.source, videoInput.destination,
+ &format, &videoOutput, &videoInput);
+
+ if (fStatus != B_OK)
+ return -1;
+
+ timeSource = fMediaRoster->MakeTimeSourceFor(fTimeSource);
+ bigtime_t real = BTimeSource::RealTime();
+ bigtime_t perf = timeSource->PerformanceTimeFor(real) + 3000000;
+
+ fStatus = fMediaRoster->StartNode(fConsumerNode, perf);
+ if (fStatus != B_OK)
+ return -1;
+
+ fStatus = fMediaRoster->StopNode(fProducerNode, perf, true);
+ fStatus = fMediaRoster->StartNode(fProducerNode, perf);
+ if (fStatus != B_OK)
+ return -1;
+
+ _captureStarted = true;
+ return 0;
+}
+
+int32_t VideoCaptureModuleHaiku::StopCapture() {
+ if (_captureStarted) {
+ fMediaRoster->StopNode(fProducerNode, BTimeSource::RealTime(), true);
+ fMediaRoster->Disconnect(fProducerNode.node, videoOutput.source,
+ fConsumerNode.node, videoInput.destination);
+ fMediaRoster->UnregisterNode(fVideoConsumer);
+ delete fVideoConsumer;
+ _captureStarted = false;
+ }
+
+ return 0;
+}
+
+bool VideoCaptureModuleHaiku::CaptureStarted() {
+ return _captureStarted;
+}
+
+int32_t VideoCaptureModuleHaiku::CaptureSettings(
+ VideoCaptureCapability& settings) {
+ settings.width = _currentWidth;
+ settings.height = _currentHeight;
+ settings.maxFPS = _currentFrameRate;
+ settings.videoType = _captureVideoType;
+
+ return 0;
+}
+} // namespace videocapturemodule
+} // namespace webrtc
diff --git a/src/modules/video_capture/haiku/video_capture_haiku.h b/src/modules/video_capture/haiku/video_capture_haiku.h
new file mode 100644
index 0000000..5bce5bd
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_capture_haiku.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
+#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include <MediaKit.h>
+
+#include "modules/video_capture/video_capture_defines.h"
+#include "modules/video_capture/video_capture_impl.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/synchronization/mutex.h"
+
+#include "video_consumer.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+class VideoCaptureModuleHaiku : public VideoCaptureImpl {
+ public:
+ VideoCaptureModuleHaiku();
+ ~VideoCaptureModuleHaiku() override;
+ int32_t Init(const char* deviceUniqueId);
+ int32_t StartCapture(const VideoCaptureCapability& capability) override;
+ int32_t StopCapture() override;
+ bool CaptureStarted() override;
+ int32_t CaptureSettings(VideoCaptureCapability& settings) override;
+
+ private:
+ BMediaRoster *fMediaRoster;
+ VideoConsumer *fVideoConsumer;
+ BTimeSource* timeSource;
+ media_node fProducerNode;
+ media_node fConsumerNode;
+ media_input videoInput;
+ media_output videoOutput;
+
+ int32_t _currentWidth;
+ int32_t _currentHeight;
+ int32_t _currentFrameRate;
+ bool _captureStarted;
+ VideoType _captureVideoType;
+};
+} // namespace videocapturemodule
+} // namespace webrtc
+
+#endif // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
diff --git a/src/modules/video_capture/haiku/video_consumer.cc b/src/modules/video_capture/haiku/video_consumer.cc
new file mode 100644
index 0000000..556d846
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_consumer.cc
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <Buffer.h>
+#include <BufferGroup.h>
+#include <NodeInfo.h>
+#include <Bitmap.h>
+#include <View.h>
+#include <scheduler.h>
+#include <TimeSource.h>
+#include <MediaRoster.h>
+
+#include "video_consumer.h"
+
+namespace webrtc {
+namespace videocapturemodule {
+
+VideoConsumer::VideoConsumer(const char* name, BMediaAddOn* addon,
+ const uint32 internal_id)
+ : BMediaNode(name),
+ BMediaEventLooper(),
+ BBufferConsumer(B_MEDIA_RAW_VIDEO),
+ fInternalID(internal_id),
+ fAddOn(addon),
+ fConnectionActive(false),
+ fMyLatency(3000),
+ fOurBuffers(false),
+ fBuffers(NULL),
+ fLastBufferIndex(-1),
+ fVideoCapture(NULL)
+{
+ AddNodeKind(B_PHYSICAL_OUTPUT);
+ SetEventLatency(0);
+
+ for (uint32 i = 0; i < kBufferCount; i++) {
+ fBitmap[i] = NULL;
+ fBufferMap[i] = NULL;
+ }
+
+ SetPriority(B_DISPLAY_PRIORITY);
+}
+
+
+VideoConsumer::~VideoConsumer()
+{
+ Quit();
+ DeleteBuffers();
+}
+
+
+void
+VideoConsumer::SetVideoCapture(VideoCaptureImpl *impl)
+{
+ fVideoCapture = impl;
+}
+
+
+BMediaAddOn*
+VideoConsumer::AddOn(int32* cookie) const
+{
+ *cookie = fInternalID;
+ return fAddOn;
+}
+
+
+void
+VideoConsumer::NodeRegistered()
+{
+ fIn.destination.port = ControlPort();
+ fIn.destination.id = 0;
+ fIn.source = media_source::null;
+ fIn.format.type = B_MEDIA_RAW_VIDEO;
+ // wild cards yet
+ fIn.format.u.raw_video = media_raw_video_format::wildcard;
+ fIn.format.u.raw_video.interlace = 1;
+ fIn.format.u.raw_video.display.format = B_NO_COLOR_SPACE;
+ fIn.format.u.raw_video.display.bytes_per_row = 0;
+ fIn.format.u.raw_video.display.line_width = 0;
+ fIn.format.u.raw_video.display.line_count = 0;
+
+ Run();
+}
+
+
+status_t
+VideoConsumer::RequestCompleted(const media_request_info& info)
+{
+ switch(info.what) {
+ case media_request_info::B_SET_OUTPUT_BUFFERS_FOR:
+ if (info.status != B_OK)
+ fprintf(stderr, "VideoConsumer::RequestCompleted: Not using our buffers!\n");
+ break;
+ default:
+ break;
+ }
+ return B_OK;
+}
+
+
+status_t
+VideoConsumer::HandleMessage(int32 message, const void* data, size_t size)
+{
+ return B_OK;
+}
+
+
+void
+VideoConsumer::BufferReceived(BBuffer* buffer)
+{
+ if (RunState() == B_STOPPED) {
+ buffer->Recycle();
+ return;
+ }
+ media_timed_event event(buffer->Header()->start_time,
+ BTimedEventQueue::B_HANDLE_BUFFER, buffer,
+ BTimedEventQueue::B_RECYCLE_BUFFER);
+ EventQueue()->AddEvent(event);
+}
+
+
+void
+VideoConsumer::ProducerDataStatus(const media_destination& forWhom,
+ int32 status, bigtime_t atMediaTime)
+{
+ if (forWhom != fIn.destination)
+ return;
+}
+
+
+status_t
+VideoConsumer::CreateBuffers(const media_format& format)
+{
+ DeleteBuffers();
+
+ status_t status = B_OK;
+
+ uint32 width = format.u.raw_video.display.line_width;
+ uint32 height = format.u.raw_video.display.line_count;
+ color_space colorSpace = format.u.raw_video.display.format;
+
+ fBuffers = new BBufferGroup();
+ status = fBuffers->InitCheck();
+ if (B_OK != status)
+ return status;
+
+ BRect bounds(0, 0, width - 1, height - 1);
+ for (uint32 i = 0; i < kBufferCount; i++) {
+ uint32 bitmapFlags = 0;
+ bitmapFlags = B_BITMAP_IS_LOCKED;
+
+ fBitmap[i] = new BBitmap(bounds, bitmapFlags, colorSpace);
+ status = fBitmap[i]->InitCheck();
+ if (status >= B_OK) {
+ buffer_clone_info info;
+
+ uint8* bits = (uint8*)fBitmap[i]->Bits();
+ info.area = area_for(bits);
+ area_info bitmapAreaInfo;
+ status = get_area_info(info.area, &bitmapAreaInfo);
+ if (status != B_OK) {
+ fprintf(stderr, "VideoConsumer::CreateBuffers() - "
+ "get_area_info(): %s\n", strerror(status));
+ return status;
+ }
+
+ info.offset = bits - (uint8*)bitmapAreaInfo.address;
+ info.size = (size_t)fBitmap[i]->BitsLength();
+ info.flags = 0;
+ info.buffer = 0;
+
+ BBuffer* buffer = NULL;
+ if ((status = fBuffers->AddBuffer(info, &buffer)) != B_OK) {
+ fprintf(stderr, "VideoConsumer::CreateBuffers - ERROR ADDING BUFFER "
+ "TO GROUP (%" B_PRId32 "): %s\n", i, strerror(status));
+ return status;
+ }
+ fBufferMap[i] = buffer;
+ } else {
+ fprintf(stderr, "VideoConsumer::CreateBuffers - ERROR CREATING VIDEO RING "
+ "BUFFER (Index %" B_PRId32 " Width %" B_PRId32 " Height %"
+ B_PRId32 " Colorspace %d: %s\n", i, width, height, colorSpace,
+ strerror(status));
+ return status;
+ }
+ }
+
+ return status;
+}
+
+
+void
+VideoConsumer::DeleteBuffers()
+{
+ if (fBuffers) {
+ fTargetLock.Lock();
+ if (fLastBufferIndex >= 0) {
+ fLastBufferIndex = -1;
+ }
+ fTargetLock.Unlock();
+
+ delete fBuffers;
+ fBuffers = NULL;
+
+ for (uint32 i = 0; i < kBufferCount; i++) {
+ snooze(20000);
+ delete fBitmap[i];
+ fBitmap[i] = NULL;
+ }
+ }
+}
+
+
+status_t
+VideoConsumer::Connected(const media_source& producer,
+ const media_destination& where, const media_format& format,
+ media_input* outInput)
+{
+ fIn.source = producer;
+ fIn.format = format;
+ fIn.node = Node();
+ sprintf(fIn.name, "Video Consumer");
+ *outInput = fIn;
+
+ uint32 userData = 0;
+ int32 changeTag = 1;
+ status_t ret = CreateBuffers(format);
+ if (ret == B_OK) {
+ ret = SetOutputBuffersFor(producer, fIn.destination,
+ fBuffers, &userData, &changeTag, true);
+ if (ret != B_OK)
+ fprintf(stderr, "SetOutputBuffersFor() failed: %s\n", strerror(ret));
+
+ fIn.format.u.raw_video.display.bytes_per_row
+ = fBitmap[0]->BytesPerRow();
+ } else {
+ fprintf(stderr, "VideoConsumer::Connected - COULDN'T CREATE BUFFERS\n");
+ return ret;
+ }
+
+ *outInput = fIn;
+ fConnectionActive = true;
+
+ return B_OK;
+}
+
+
+void
+VideoConsumer::Disconnected(const media_source& producer,
+ const media_destination& where)
+{
+ if (where != fIn.destination || producer != fIn.source)
+ return;
+
+ int32 changeTag = 0;
+ SetOutputBuffersFor(producer, fIn.destination, NULL, NULL, &changeTag,
+ false);
+ if (fOurBuffers) {
+ status_t reclaimError = fBuffers->ReclaimAllBuffers();
+ if (reclaimError != B_OK) {
+ fprintf(stderr, "VideoConsumer::Disconnected() - Failed to "
+ "reclaim our buffers: %s\n", strerror(reclaimError));
+ }
+ }
+ // disconnect the connection
+ fIn.source = media_source::null;
+ fConnectionActive = false;
+
+ _UnsetTargetBuffer();
+}
+
+
+status_t
+VideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
+{
+ if (dest != fIn.destination) {
+ fprintf(stderr, "VideoConsumer::AcceptFormat - BAD DESTINATION\n");
+ return B_MEDIA_BAD_DESTINATION;
+ }
+
+ if (format->type == B_MEDIA_NO_TYPE)
+ format->type = B_MEDIA_RAW_VIDEO;
+
+ if (format->type != B_MEDIA_RAW_VIDEO) {
+ fprintf(stderr, "VideoConsumer::AcceptFormat - BAD FORMAT\n");
+ return B_MEDIA_BAD_FORMAT;
+ }
+
+ if (format->u.raw_video.display.format
+ != media_raw_video_format::wildcard.display.format) {
+ uint32 flags = 0;
+ bool supported = bitmaps_support_space(
+ format->u.raw_video.display.format, &flags);
+
+ if (!supported) {
+ fprintf(stderr, "AcceptFormat - unsupported color space for BBitmaps !\n");
+ return B_MEDIA_BAD_FORMAT;
+ }
+ if (flags & B_VIEWS_SUPPORT_DRAW_BITMAP == 0) {
+ fprintf(stderr, "AcceptFormat - BViews cannot draw bitmaps in given colorspace !\n");
+ return B_MEDIA_BAD_FORMAT;
+ }
+ }
+
+ return B_OK;
+}
+
+
+status_t
+VideoConsumer::GetNextInput(int32* cookie, media_input* outInput)
+{
+ if (*cookie < 1) {
+ fIn.node = Node();
+ fIn.destination.id = *cookie;
+ sprintf(fIn.name, "Video Consumer");
+ *outInput = fIn;
+ (*cookie)++;
+ return B_OK;
+ }
+ return B_MEDIA_BAD_DESTINATION;
+}
+
+
+void
+VideoConsumer::DisposeInputCookie(int32 /*cookie*/)
+{
+}
+
+
+status_t
+VideoConsumer::GetLatencyFor(const media_destination& whom,
+ bigtime_t* _latency, media_node_id* _timeSource)
+{
+ if (whom != fIn.destination)
+ return B_MEDIA_BAD_DESTINATION;
+
+ *_latency = fMyLatency;
+ *_timeSource = TimeSource()->ID();
+ return B_OK;
+}
+
+
+status_t
+VideoConsumer::FormatChanged(const media_source& producer,
+ const media_destination& consumer, int32 fromChangeCount,
+ const media_format& format)
+{
+ if (consumer != fIn.destination)
+ return B_MEDIA_BAD_DESTINATION;
+
+ if (producer != fIn.source)
+ return B_MEDIA_BAD_SOURCE;
+
+ fIn.format = format;
+
+ return CreateBuffers(format);
+}
+
+
+void
+VideoConsumer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
+ bool realTimeEvent)
+{
+ switch (event->type) {
+ case BTimedEventQueue::B_START:
+ _SetPerformanceTimeBase(event->event_time);
+ break;
+ case BTimedEventQueue::B_WARP:
+ case BTimedEventQueue::B_SEEK:
+ _SetPerformanceTimeBase(event->bigdata);
+ break;
+ case BTimedEventQueue::B_STOP:
+ EventQueue()->FlushEvents(event->event_time, BTimedEventQueue::B_ALWAYS,
+ true, BTimedEventQueue::B_HANDLE_BUFFER);
+ _UnsetTargetBuffer();
+ break;
+ case BTimedEventQueue::B_HANDLE_BUFFER:
+ _HandleBuffer(static_cast<BBuffer*>(event->pointer));
+ break;
+ default:
+ fprintf(stderr, "VideoConsumer::HandleEvent - BAD EVENT\n");
+ break;
+ }
+}
+
+
+void
+VideoConsumer::_SetPerformanceTimeBase(bigtime_t performanceTime)
+{
+ fPerformanceTimeBase = performanceTime;
+}
+
+
+void
+VideoConsumer::_HandleBuffer(BBuffer* buffer)
+{
+ if (RunState() != B_STARTED || !fConnectionActive) {
+ buffer->Recycle();
+ return;
+ }
+
+ uint32 index = 0;
+ fOurBuffers = true;
+ while (index < kBufferCount) {
+ if (buffer->ID() == fBufferMap[index]->ID())
+ break;
+ else
+ index++;
+ }
+ if (index == kBufferCount) {
+ fOurBuffers = false;
+ index = (fLastBufferIndex + 1) % kBufferCount;
+ }
+
+ bool recycle = true;
+ bigtime_t now = TimeSource()->Now();
+
+ if (!fOurBuffers) {
+ memcpy(fBitmap[index]->Bits(), buffer->Data(),
+ fBitmap[index]->BitsLength());
+ }
+
+ bigtime_t tooEarly = buffer->Header()->start_time - now;
+ if (tooEarly > 3000)
+ snooze(tooEarly);
+
+ fTargetLock.Lock();
+
+ VideoCaptureCapability frameInfo;
+ frameInfo.width = fBitmap[index]->Bounds().Width() + 1;
+ frameInfo.height = fBitmap[index]->Bounds().Height() + 1;
+ frameInfo.videoType = VideoType::kARGB;
+
+ fVideoCapture->IncomingFrame((unsigned char*)fBitmap[index]->Bits(),
+ fBitmap[index]->BitsLength(), frameInfo);
+
+ if (fOurBuffers) {
+ if (fLastBufferIndex >= 0)
+ fBufferMap[fLastBufferIndex]->Recycle();
+ recycle = false;
+ }
+ fLastBufferIndex = index;
+
+ fTargetLock.Unlock();
+
+ if (recycle)
+ buffer->Recycle();
+}
+
+
+void
+VideoConsumer::_UnsetTargetBuffer()
+{
+ fTargetLock.Lock();
+ if (fLastBufferIndex >= 0) {
+ if (fOurBuffers)
+ fBufferMap[fLastBufferIndex]->Recycle();
+ fLastBufferIndex = -1;
+ }
+ fTargetLock.Unlock();
+}
+
+}
+}
diff --git a/src/modules/video_capture/haiku/video_consumer.h b/src/modules/video_capture/haiku/video_consumer.h
new file mode 100644
index 0000000..7308f0c
--- /dev/null
+++ b/src/modules/video_capture/haiku/video_consumer.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 Gerasim Troeglazov
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VIDEO_CONSUMER_H
+#define VIDEO_CONSUMER_H
+
+#include "modules/video_capture/video_capture_defines.h"
+#include "modules/video_capture/video_capture_impl.h"
+
+#include <BufferConsumer.h>
+#include <Locker.h>
+#include <MediaEventLooper.h>
+
+class BBitmap;
+
+namespace webrtc {
+namespace videocapturemodule {
+
+static const unsigned int kBufferCount = 4;
+
+
+class VideoConsumer : public BMediaEventLooper, public BBufferConsumer {
+public:
+ VideoConsumer(
+ const char* name,
+ BMediaAddOn* addon,
+ const uint32 internal_id);
+ ~VideoConsumer();
+public:
+ void SetVideoCapture(VideoCaptureImpl *impl);
+ // BMediaNode interface
+public:
+ virtual BMediaAddOn* AddOn(int32* cookie) const;
+
+protected:
+ virtual void NodeRegistered();
+ virtual status_t RequestCompleted(
+ const media_request_info& info);
+
+ virtual status_t HandleMessage(int32 message, const void* data,
+ size_t size);
+
+ // BMediaEventLooper interface
+protected:
+ virtual void HandleEvent(const media_timed_event* event,
+ bigtime_t lateness, bool realTimeEvent);
+
+ // BBufferConsumer interface
+public:
+ virtual status_t AcceptFormat(const media_destination& dest,
+ media_format* format);
+ virtual status_t GetNextInput(int32* cookie,
+ media_input* _input);
+
+ virtual void DisposeInputCookie(int32 cookie);
+
+protected:
+ virtual void BufferReceived(BBuffer* buffer);
+
+private:
+ virtual void ProducerDataStatus(
+ const media_destination& forWhom,
+ int32 status,
+ bigtime_t atMediaTime);
+ virtual status_t GetLatencyFor(
+ const media_destination& forWhom,
+ bigtime_t* outLatency,
+ media_node_id* outId);
+ virtual status_t Connected(const media_source& producer,
+ const media_destination& where,
+ const media_format& withFormat,
+ media_input* outInput);
+ virtual void Disconnected(const media_source& producer,
+ const media_destination& where);
+ virtual status_t FormatChanged(const media_source& producer,
+ const media_destination& consumer,
+ int32 from_change_count,
+ const media_format& format);
+
+ // VideoConsumer
+public:
+ status_t CreateBuffers(
+ const media_format& withFormat);
+
+ void DeleteBuffers();
+
+private:
+ void _SetPerformanceTimeBase(
+ bigtime_t performanceTime);
+ void _HandleBuffer(BBuffer* buffer);
+ void _UnsetTargetBuffer();
+
+private:
+ int32 fInternalID;
+ BMediaAddOn* fAddOn;
+
+ bool fConnectionActive;
+ media_input fIn;
+ bigtime_t fMyLatency;
+ bigtime_t fPerformanceTimeBase;
+
+ BBitmap* fBitmap[kBufferCount];
+ bool fOurBuffers;
+ BBufferGroup* fBuffers;
+ BBuffer* fBufferMap[kBufferCount];
+
+ BLocker fTargetLock;
+ int32 fLastBufferIndex;
+
+ VideoCaptureImpl *fVideoCapture;
+};
+
+} // namespace videocapturemodule
+} // namespace webrtc
+
+#endif // VIDEO_CONSUMER_H
diff --git a/src/rtc_base/BUILD.gn b/src/rtc_base/BUILD.gn
index 2cf9c11..cd10a6d 100644
--- a/src/rtc_base/BUILD.gn
+++ b/src/rtc_base/BUILD.gn
@@ -679,7 +679,7 @@ rtc_source_set("rtc_operations_chain") {
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
-if (rtc_enable_libevent) {
+if (rtc_enable_libevent && !is_haiku) {
rtc_library("rtc_task_queue_libevent") {
visibility = [ "../api/task_queue:default_task_queue_factory" ]
sources = [
diff --git a/src/rtc_base/byte_order.h b/src/rtc_base/byte_order.h
index 0ebaaaf..1e9566b 100644
--- a/src/rtc_base/byte_order.h
+++ b/src/rtc_base/byte_order.h
@@ -90,7 +90,7 @@
#error WEBRTC_ARCH_BIG_ENDIAN or WEBRTC_ARCH_LITTLE_ENDIAN must be defined.
#endif // defined(WEBRTC_ARCH_LITTLE_ENDIAN)
-#elif defined(WEBRTC_LINUX)
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_HAIKU)
#include <endian.h>
#elif defined(WEBRTC_FREEBSD) || defined(WEBRTC_OPENBSD)
#include <sys/endian.h>
diff --git a/src/rtc_base/ip_address.cc b/src/rtc_base/ip_address.cc
index 04fbc9b..93c7fe3 100644
--- a/src/rtc_base/ip_address.cc
+++ b/src/rtc_base/ip_address.cc
@@ -13,6 +13,9 @@
#include <sys/socket.h>
#include "absl/strings/string_view.h"
+#if defined(WEBRTC_HAIKU)
+#include <netinet6/in6.h>
+#endif
#ifdef OPENBSD
#include <netinet/in_systm.h>
#endif
@@ -31,6 +34,15 @@
namespace rtc {
// Prefixes used for categorizing IPv6 addresses.
+#if defined(WEBRTC_HAIKU)
+static const in6_addr kV4MappedPrefix = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}};
+static const in6_addr k6To4Prefix = {{0x20, 0x02, 0}};
+static const in6_addr kTeredoPrefix = {{0x20, 0x01, 0x00, 0x00}};
+static const in6_addr kV4CompatibilityPrefix = {{0}};
+static const in6_addr k6BonePrefix = {{0x3f, 0xfe, 0}};
+static const in6_addr kPrivateNetworkPrefix = {{0xFD}};
+#else
static const in6_addr kV4MappedPrefix = {
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0}}};
static const in6_addr k6To4Prefix = {{{0x20, 0x02, 0}}};
@@ -38,6 +50,7 @@ static const in6_addr kTeredoPrefix = {{{0x20, 0x01, 0x00, 0x00}}};
static const in6_addr kV4CompatibilityPrefix = {{{0}}};
static const in6_addr k6BonePrefix = {{{0x3f, 0xfe, 0}}};
static const in6_addr kPrivateNetworkPrefix = {{{0xFD}}};
+#endif
static bool IPIsHelper(const IPAddress& ip,
const in6_addr& tomatch,
diff --git a/src/rtc_base/logging.cc b/src/rtc_base/logging.cc
index 61a3c66..c61a47e 100644
--- a/src/rtc_base/logging.cc
+++ b/src/rtc_base/logging.cc
@@ -97,7 +97,7 @@ std::string LogLineRef::DefaultLogLine() const {
log_output << timestamp;
}
if (thread_id_.has_value()) {
- log_output << "[" << *thread_id_ << "] ";
+ log_output << "[" << (uint64_t)(*thread_id_) << "] ";
}
if (!filename_.empty()) {
#if defined(WEBRTC_ANDROID)
diff --git a/src/rtc_base/network.cc b/src/rtc_base/network.cc
index 4be6eed..691fb2e 100644
--- a/src/rtc_base/network.cc
+++ b/src/rtc_base/network.cc
@@ -630,8 +630,8 @@ void BasicNetworkManager::ConvertIfAddrs(
continue;
}
// Skip ones which are down.
- if (!(cursor->ifa_flags & IFF_RUNNING)) {
- RTC_LOG(LS_INFO) << "Skip interface because of not IFF_RUNNING: "
+ if (!(cursor->ifa_flags & IFF_LINK)) {
+ RTC_LOG(LS_INFO) << "Skip interface because of not IFF_LINK: "
<< ip.ToSensitiveString();
continue;
}
diff --git a/src/rtc_base/physical_socket_server.cc b/src/rtc_base/physical_socket_server.cc
index 727e200..5ce1edf 100644
--- a/src/rtc_base/physical_socket_server.cc
+++ b/src/rtc_base/physical_socket_server.cc
@@ -334,7 +334,7 @@ int PhysicalSocket::SetOption(Option opt, int value) {
value <<= 2;
#endif
}
-#if defined(WEBRTC_POSIX)
+#if defined(WEBRTC_POSIX) && !defined(WEBRTC_HAIKU)
if (sopt == IPV6_TCLASS) {
// Set the IPv4 option in all cases to support dual-stack sockets.
// Don't bother checking the return code, as this is expected to fail if
@@ -687,7 +687,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
*sopt = TCP_NODELAY;
break;
case OPT_DSCP:
-#if defined(WEBRTC_POSIX)
+#if defined(WEBRTC_POSIX) && !defined(WEBRTC_HAIKU)
if (family_ == AF_INET6) {
*slevel = IPPROTO_IPV6;
*sopt = IPV6_TCLASS;
diff --git a/src/rtc_base/platform_thread_types.h b/src/rtc_base/platform_thread_types.h
index 6046281..0a113ad 100644
--- a/src/rtc_base/platform_thread_types.h
+++ b/src/rtc_base/platform_thread_types.h
@@ -38,6 +38,9 @@ typedef DWORD PlatformThreadRef;
#elif defined(WEBRTC_FUCHSIA)
typedef zx_handle_t PlatformThreadId;
typedef zx_handle_t PlatformThreadRef;
+#elif defined(WEBRTC_HAIKU)
+typedef pthread_t PlatformThreadId;
+typedef pthread_t PlatformThreadRef;
#elif defined(WEBRTC_POSIX)
#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
typedef mach_port_t PlatformThreadId;
diff --git a/src/rtc_base/system/rtc_export.h b/src/rtc_base/system/rtc_export.h
index d1eb60a..9dc761d 100644
--- a/src/rtc_base/system/rtc_export.h
+++ b/src/rtc_base/system/rtc_export.h
@@ -28,7 +28,7 @@
#else // WEBRTC_WIN
-#if __has_attribute(visibility) && defined(WEBRTC_LIBRARY_IMPL)
+#if defined(WEBRTC_LIBRARY_IMPL)
#define RTC_EXPORT __attribute__((visibility("default")))
#endif
diff --git a/src/rtc_base/system/rtc_export_template.h b/src/rtc_base/system/rtc_export_template.h
index 4ac7043..5fe950f 100644
--- a/src/rtc_base/system/rtc_export_template.h
+++ b/src/rtc_base/system/rtc_export_template.h
@@ -185,7 +185,7 @@
RTC_EXPORT_TEMPLATE_TEST(DEFAULT, ); // NOLINT
RTC_EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default"))));
-RTC_EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
+//RTC_EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
RTC_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
#undef RTC_EXPORT_TEMPLATE_TEST
--
2.45.2
From f4560193b4024a83faa3e9ef85f6fa2ea09704ff Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Fri, 2 Aug 2024 09:49:48 +1000
Subject: Disable WebRTC-SCM-Timestamp experiment for Haiku
diff --git a/src/rtc_base/async_udp_socket.cc b/src/rtc_base/async_udp_socket.cc
index 3d258bc..f2d42bf 100644
--- a/src/rtc_base/async_udp_socket.cc
+++ b/src/rtc_base/async_udp_socket.cc
@@ -24,7 +24,11 @@ namespace rtc {
// Returns true if the experiement "WebRTC-SCM-Timestamp" is explicitly
// disabled.
static bool IsScmTimeStampExperimentDisabled() {
+#if defined(WEBRTC_HAIKU)
+ return true;
+#else
return webrtc::field_trial::IsDisabled("WebRTC-SCM-Timestamp");
+#endif
}
AsyncUDPSocket* AsyncUDPSocket::Create(Socket* socket,
diff --git a/src/rtc_base/physical_socket_server.cc b/src/rtc_base/physical_socket_server.cc
index 5ce1edf..de8c2b7 100644
--- a/src/rtc_base/physical_socket_server.cc
+++ b/src/rtc_base/physical_socket_server.cc
@@ -57,6 +57,11 @@
#include <linux/sockios.h>
#endif
+#if defined(WEBRTC_HAIKU)
+#define SO_TIMESTAMP 0
+#define SCM_TIMESTAMP 0
+#endif
+
#if defined(WEBRTC_WIN)
#define LAST_SYSTEM_ERROR (::GetLastError())
#elif defined(__native_client__) && __native_client__
@@ -123,7 +128,11 @@ class ScopedSetTrue {
// Returns true if the experiement "WebRTC-SCM-Timestamp" is explicitly
// disabled.
bool IsScmTimeStampExperimentDisabled() {
+#if defined(WEBRTC_HAIKU)
+ return true;
+#else
return webrtc::field_trial::IsDisabled("WebRTC-SCM-Timestamp");
+#endif
}
} // namespace
--
2.45.2