forked from mirrors/gecko-dev
For some reason, its value in the Google style we use is 80... except for Objective-C, where it's 100, which led to things like: https://hg.mozilla.org/mozilla-central/rev/31bf68247e6e https://hg.mozilla.org/mozilla-central/rev/64ceb33533a4. There's probably a discussion to have about whether 80 is the right limit, but since it's what's used for everything except ObjC, let's roll with it. # ignore-this-changeset Differential Revision: https://phabricator.services.mozilla.com/D187409
223 lines
7.2 KiB
Text
223 lines
7.2 KiB
Text
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
/* 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 "device_info_avfoundation.h"
|
|
#include <CoreVideo/CVPixelBuffer.h>
|
|
|
|
#include <string>
|
|
|
|
#include "components/capturer/RTCCameraVideoCapturer.h"
|
|
#import "helpers/NSString+StdString.h"
|
|
#include "media/base/video_common.h"
|
|
#include "modules/video_capture/video_capture_defines.h"
|
|
#include "rtc_base/logging.h"
|
|
|
|
namespace webrtc::videocapturemodule {
|
|
/* static */
|
|
int32_t DeviceInfoAvFoundation::ConvertAVFrameRateToCapabilityFPS(
|
|
Float64 aRate) {
|
|
return static_cast<int32_t>(aRate);
|
|
}
|
|
|
|
/* static */
|
|
webrtc::VideoType DeviceInfoAvFoundation::ConvertFourCCToVideoType(
|
|
FourCharCode aCode) {
|
|
switch (aCode) {
|
|
case kCVPixelFormatType_420YpCbCr8Planar:
|
|
case kCVPixelFormatType_420YpCbCr8PlanarFullRange:
|
|
return webrtc::VideoType::kI420;
|
|
case kCVPixelFormatType_24BGR:
|
|
return webrtc::VideoType::kRGB24;
|
|
case kCVPixelFormatType_32ABGR:
|
|
return webrtc::VideoType::kABGR;
|
|
case kCMPixelFormat_32ARGB:
|
|
return webrtc::VideoType::kBGRA;
|
|
case kCMPixelFormat_32BGRA:
|
|
return webrtc::VideoType::kARGB;
|
|
case kCMPixelFormat_16LE565:
|
|
return webrtc::VideoType::kRGB565;
|
|
case kCMPixelFormat_16LE555:
|
|
case kCMPixelFormat_16LE5551:
|
|
return webrtc::VideoType::kARGB1555;
|
|
case kCMPixelFormat_422YpCbCr8_yuvs:
|
|
return webrtc::VideoType::kYUY2;
|
|
case kCMPixelFormat_422YpCbCr8:
|
|
return webrtc::VideoType::kUYVY;
|
|
case kCMVideoCodecType_JPEG:
|
|
case kCMVideoCodecType_JPEG_OpenDML:
|
|
return webrtc::VideoType::kMJPEG;
|
|
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
|
|
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
|
|
return webrtc::VideoType::kNV12;
|
|
default:
|
|
RTC_LOG(LS_WARNING) << "Unhandled FourCharCode" << aCode;
|
|
return webrtc::VideoType::kUnknown;
|
|
}
|
|
}
|
|
|
|
DeviceInfoAvFoundation::DeviceInfoAvFoundation()
|
|
: mInvalidateCapabilities(false),
|
|
mDeviceChangeCaptureInfo([[DeviceInfoIosObjC alloc] init]) {
|
|
[mDeviceChangeCaptureInfo registerOwner:this];
|
|
}
|
|
|
|
DeviceInfoAvFoundation::~DeviceInfoAvFoundation() {
|
|
[mDeviceChangeCaptureInfo registerOwner:nil];
|
|
}
|
|
|
|
void DeviceInfoAvFoundation::DeviceChange() {
|
|
mInvalidateCapabilities = true;
|
|
DeviceInfo::DeviceChange();
|
|
}
|
|
|
|
uint32_t DeviceInfoAvFoundation::NumberOfDevices() {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
EnsureCapabilitiesMap();
|
|
return mDevicesAndCapabilities.size();
|
|
}
|
|
|
|
int32_t DeviceInfoAvFoundation::GetDeviceName(
|
|
uint32_t aDeviceNumber, char* aDeviceNameUTF8, uint32_t aDeviceNameLength,
|
|
char* aDeviceUniqueIdUTF8, uint32_t aDeviceUniqueIdUTF8Length,
|
|
char* /* aProductUniqueIdUTF8 */, uint32_t /* aProductUniqueIdUTF8Length */,
|
|
pid_t* /* aPid */) {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
// Don't EnsureCapabilitiesMap() here, since:
|
|
// 1) That might invalidate the capabilities map
|
|
// 2) This function depends on the device index
|
|
|
|
if (aDeviceNumber >= mDevicesAndCapabilities.size()) {
|
|
return -1;
|
|
}
|
|
|
|
const auto& [uniqueId, name, _] = mDevicesAndCapabilities[aDeviceNumber];
|
|
|
|
strncpy(aDeviceUniqueIdUTF8, uniqueId.c_str(), aDeviceUniqueIdUTF8Length);
|
|
aDeviceUniqueIdUTF8[aDeviceUniqueIdUTF8Length - 1] = '\0';
|
|
|
|
strncpy(aDeviceNameUTF8, name.c_str(), aDeviceNameLength);
|
|
aDeviceNameUTF8[aDeviceNameLength - 1] = '\0';
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t DeviceInfoAvFoundation::NumberOfCapabilities(
|
|
const char* aDeviceUniqueIdUTF8) {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
|
|
std::string deviceUniqueId(aDeviceUniqueIdUTF8);
|
|
const auto* tup = FindDeviceAndCapabilities(deviceUniqueId);
|
|
if (!tup) {
|
|
return 0;
|
|
}
|
|
|
|
const auto& [_, __, capabilities] = *tup;
|
|
return static_cast<int32_t>(capabilities.size());
|
|
}
|
|
|
|
int32_t DeviceInfoAvFoundation::GetCapability(
|
|
const char* aDeviceUniqueIdUTF8, const uint32_t aDeviceCapabilityNumber,
|
|
VideoCaptureCapability& aCapability) {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
|
|
std::string deviceUniqueId(aDeviceUniqueIdUTF8);
|
|
const auto* tup = FindDeviceAndCapabilities(deviceUniqueId);
|
|
if (!tup) {
|
|
return -1;
|
|
}
|
|
|
|
const auto& [_, __, capabilities] = *tup;
|
|
if (aDeviceCapabilityNumber >= capabilities.size()) {
|
|
return -1;
|
|
}
|
|
|
|
aCapability = capabilities[aDeviceCapabilityNumber];
|
|
return 0;
|
|
}
|
|
|
|
int32_t DeviceInfoAvFoundation::CreateCapabilityMap(
|
|
const char* aDeviceUniqueIdUTF8) {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
|
|
const size_t deviceUniqueIdUTF8Length = strlen(aDeviceUniqueIdUTF8);
|
|
if (deviceUniqueIdUTF8Length > kVideoCaptureUniqueNameLength) {
|
|
RTC_LOG(LS_INFO) << "Device name too long";
|
|
return -1;
|
|
}
|
|
RTC_LOG(LS_INFO) << "CreateCapabilityMap called for device "
|
|
<< aDeviceUniqueIdUTF8;
|
|
std::string deviceUniqueId(aDeviceUniqueIdUTF8);
|
|
const auto* tup = FindDeviceAndCapabilities(deviceUniqueId);
|
|
if (!tup) {
|
|
RTC_LOG(LS_INFO) << "no matching device found";
|
|
return -1;
|
|
}
|
|
|
|
// Store the new used device name
|
|
_lastUsedDeviceNameLength = deviceUniqueIdUTF8Length;
|
|
_lastUsedDeviceName = static_cast<char*>(
|
|
realloc(_lastUsedDeviceName, _lastUsedDeviceNameLength + 1));
|
|
memcpy(_lastUsedDeviceName, aDeviceUniqueIdUTF8,
|
|
_lastUsedDeviceNameLength + 1);
|
|
|
|
const auto& [_, __, capabilities] = *tup;
|
|
_captureCapabilities = capabilities;
|
|
return static_cast<int32_t>(_captureCapabilities.size());
|
|
}
|
|
|
|
auto DeviceInfoAvFoundation::FindDeviceAndCapabilities(
|
|
const std::string& aDeviceUniqueId) const
|
|
-> const std::tuple<std::string, std::string, VideoCaptureCapabilities>* {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
for (const auto& tup : mDevicesAndCapabilities) {
|
|
if (std::get<0>(tup) == aDeviceUniqueId) {
|
|
return &tup;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void DeviceInfoAvFoundation::EnsureCapabilitiesMap() {
|
|
RTC_DCHECK_RUN_ON(&mChecker);
|
|
|
|
if (mInvalidateCapabilities.exchange(false)) {
|
|
mDevicesAndCapabilities.clear();
|
|
}
|
|
|
|
if (!mDevicesAndCapabilities.empty()) {
|
|
return;
|
|
}
|
|
|
|
for (AVCaptureDevice* device in [RTCCameraVideoCapturer captureDevices]) {
|
|
std::string uniqueId = [NSString stdStringForString:device.uniqueID];
|
|
std::string name = [NSString stdStringForString:device.localizedName];
|
|
auto& [_, __, capabilities] = mDevicesAndCapabilities.emplace_back(
|
|
uniqueId, name, VideoCaptureCapabilities());
|
|
|
|
for (AVCaptureDeviceFormat* format in
|
|
[RTCCameraVideoCapturer supportedFormatsForDevice:device]) {
|
|
VideoCaptureCapability cap;
|
|
FourCharCode fourcc =
|
|
CMFormatDescriptionGetMediaSubType(format.formatDescription);
|
|
cap.videoType = ConvertFourCCToVideoType(fourcc);
|
|
CMVideoDimensions dimensions =
|
|
CMVideoFormatDescriptionGetDimensions(format.formatDescription);
|
|
cap.width = dimensions.width;
|
|
cap.height = dimensions.height;
|
|
|
|
for (AVFrameRateRange* range in format.videoSupportedFrameRateRanges) {
|
|
cap.maxFPS = ConvertAVFrameRateToCapabilityFPS(range.maxFrameRate);
|
|
capabilities.push_back(cap);
|
|
}
|
|
|
|
if (capabilities.empty()) {
|
|
cap.maxFPS = 30;
|
|
capabilities.push_back(cap);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // namespace webrtc::videocapturemodule
|