diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /dom/media/systemservices/VideoEngine.cpp | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/systemservices/VideoEngine.cpp')
-rw-r--r-- | dom/media/systemservices/VideoEngine.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/dom/media/systemservices/VideoEngine.cpp b/dom/media/systemservices/VideoEngine.cpp new file mode 100644 index 0000000000..5aec39b638 --- /dev/null +++ b/dom/media/systemservices/VideoEngine.cpp @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VideoEngine.h" +#include "libwebrtcglue/SystemTime.h" +#include "system_wrappers/include/clock.h" +#include "video_engine/video_capture_factory.h" + +#ifdef MOZ_WIDGET_ANDROID +# include "mozilla/jni/Utils.h" +#endif + +#if defined(ANDROID) +namespace webrtc { +int32_t SetCaptureAndroidVM(JavaVM* javaVM); +} +#endif + +namespace mozilla::camera { + +#undef LOG +#undef LOG_ENABLED +mozilla::LazyLogModule gVideoEngineLog("VideoEngine"); +#define LOG(args) MOZ_LOG(gVideoEngineLog, mozilla::LogLevel::Debug, args) +#define LOG_ENABLED() MOZ_LOG_TEST(gVideoEngineLog, mozilla::LogLevel::Debug) + +#if defined(ANDROID) +int VideoEngine::SetAndroidObjects() { + LOG(("%s", __PRETTY_FUNCTION__)); + + JavaVM* const javaVM = mozilla::jni::GetVM(); + if (!javaVM || webrtc::SetCaptureAndroidVM(javaVM) != 0) { + LOG(("Could not set capture Android VM")); + return -1; + } +# ifdef WEBRTC_INCLUDE_INTERNAL_VIDEO_RENDER + if (webrtc::SetRenderAndroidVM(javaVM) != 0) { + LOG(("Could not set render Android VM")); + return -1; + } +# endif + return 0; +} +#endif + +int32_t VideoEngine::CreateVideoCapture(const char* aDeviceUniqueIdUTF8) { + LOG(("%s", __PRETTY_FUNCTION__)); + MOZ_ASSERT(aDeviceUniqueIdUTF8); + + int32_t id = GenerateId(); + LOG(("CaptureDeviceInfo.type=%s id=%d", mCaptureDevInfo.TypeName(), id)); + + for (auto& it : mCaps) { + if (it.second.VideoCapture() && + it.second.VideoCapture()->CurrentDeviceName() && + strcmp(it.second.VideoCapture()->CurrentDeviceName(), + aDeviceUniqueIdUTF8) == 0) { + mIdMap.emplace(id, it.first); + return id; + } + } + + CaptureEntry entry = {-1, nullptr}; + + entry = CaptureEntry(id, mVideoCaptureFactory->CreateVideoCapture( + id, aDeviceUniqueIdUTF8, mCaptureDevInfo.type)); + + mCaps.emplace(id, std::move(entry)); + mIdMap.emplace(id, id); + return id; +} + +int VideoEngine::ReleaseVideoCapture(const int32_t aId) { + bool found = false; + +#ifdef DEBUG + { + auto it = mIdMap.find(aId); + MOZ_ASSERT(it != mIdMap.end()); + Unused << it; + } +#endif + + for (auto& it : mIdMap) { + if (it.first != aId && it.second == mIdMap[aId]) { + // There are other tracks still using this hardware. + found = true; + } + } + + if (!found) { + WithEntry(aId, [&found](CaptureEntry& cap) { + cap.mVideoCaptureModule = nullptr; + found = true; + }); + MOZ_ASSERT(found); + if (found) { + auto it = mCaps.find(mIdMap[aId]); + MOZ_ASSERT(it != mCaps.end()); + mCaps.erase(it); + } + } + + mIdMap.erase(aId); + return found ? 0 : (-1); +} + +std::shared_ptr<webrtc::VideoCaptureModule::DeviceInfo> +VideoEngine::GetOrCreateVideoCaptureDeviceInfo() { + LOG(("%s", __PRETTY_FUNCTION__)); + webrtc::Timestamp currentTime = webrtc::Timestamp::Micros(0); + + const char* capDevTypeName = + CaptureDeviceInfo(mCaptureDevInfo.type).TypeName(); + + if (mDeviceInfo) { + LOG(("Device cache available.")); + // Camera cache is invalidated by HW change detection elsewhere + if (mCaptureDevInfo.type == CaptureDeviceType::Camera) { + LOG(("returning cached CaptureDeviceInfo of type %s", capDevTypeName)); + return mDeviceInfo; + } + // Screen sharing cache is invalidated after the expiration time + currentTime = WebrtcSystemTime(); + LOG(("Checking expiry, fetched current time of: %" PRId64, + currentTime.ms())); + LOG(("device cache expiration is %" PRId64, mExpiryTime.ms())); + if (currentTime <= mExpiryTime) { + LOG(("returning cached CaptureDeviceInfo of type %s", capDevTypeName)); + return mDeviceInfo; + } + } + + if (currentTime.IsZero()) { + currentTime = WebrtcSystemTime(); + LOG(("Fetched current time of: %" PRId64, currentTime.ms())); + } + mExpiryTime = currentTime + webrtc::TimeDelta::Millis(kCacheExpiryPeriodMs); + LOG(("new device cache expiration is %" PRId64, mExpiryTime.ms())); + LOG(("creating a new VideoCaptureDeviceInfo of type %s", capDevTypeName)); + +#ifdef MOZ_WIDGET_ANDROID + if (mCaptureDevInfo.type == CaptureDeviceType::Camera) { + if (SetAndroidObjects()) { + LOG(("VideoEngine::SetAndroidObjects Failed")); + return mDeviceInfo; + } + } +#endif + + mDeviceInfo = + mVideoCaptureFactory->CreateDeviceInfo(mId, mCaptureDevInfo.type); + + LOG(("EXIT %s", __PRETTY_FUNCTION__)); + return mDeviceInfo; +} + +void VideoEngine::ClearVideoCaptureDeviceInfo() { + LOG(("%s", __PRETTY_FUNCTION__)); + mDeviceInfo.reset(); +} + +already_AddRefed<VideoEngine> VideoEngine::Create( + const CaptureDeviceType& aCaptureDeviceType, + RefPtr<VideoCaptureFactory> aVideoCaptureFactory) { + LOG(("%s", __PRETTY_FUNCTION__)); + return do_AddRef( + new VideoEngine(aCaptureDeviceType, std::move(aVideoCaptureFactory))); +} + +VideoEngine::CaptureEntry::CaptureEntry( + int32_t aCapnum, rtc::scoped_refptr<webrtc::VideoCaptureModule> aCapture) + : mCapnum(aCapnum), mVideoCaptureModule(aCapture) {} + +rtc::scoped_refptr<webrtc::VideoCaptureModule> +VideoEngine::CaptureEntry::VideoCapture() { + return mVideoCaptureModule; +} + +int32_t VideoEngine::CaptureEntry::Capnum() const { return mCapnum; } + +bool VideoEngine::WithEntry( + const int32_t entryCapnum, + const std::function<void(CaptureEntry& entry)>&& fn) { +#ifdef DEBUG + { + auto it = mIdMap.find(entryCapnum); + MOZ_ASSERT(it != mIdMap.end()); + Unused << it; + } +#endif + + auto it = mCaps.find(mIdMap[entryCapnum]); + MOZ_ASSERT(it != mCaps.end()); + if (it == mCaps.end()) { + return false; + } + fn(it->second); + return true; +} + +int32_t VideoEngine::GenerateId() { + // XXX Something better than this (a map perhaps, or a simple boolean TArray, + // given the number in-use is O(1) normally!) + static int sId = 0; + return mId = sId++; +} + +VideoEngine::VideoEngine(const CaptureDeviceType& aCaptureDeviceType, + RefPtr<VideoCaptureFactory> aVideoCaptureFactory) + : mId(0), + mCaptureDevInfo(aCaptureDeviceType), + mVideoCaptureFactory(std::move(aVideoCaptureFactory)), + mDeviceInfo(nullptr) { + MOZ_ASSERT(mVideoCaptureFactory); + LOG(("%s", __PRETTY_FUNCTION__)); + LOG(("Creating new VideoEngine with CaptureDeviceType %s", + mCaptureDevInfo.TypeName())); +} + +VideoEngine::~VideoEngine() { + MOZ_ASSERT(mCaps.empty()); + MOZ_ASSERT(mIdMap.empty()); +} + +} // namespace mozilla::camera |