CameraVideoCapturer
public final class CameraVideoCapturer : Sendable
カメラをキャプチャするクラスです。
解像度やフレームレートなどの設定は start 実行時に指定します。
カメラはパブリッシャーまたはグループの接続時に自動的に起動 (起動済みなら再起動) されます。
カメラの設定を変更したい場合は、 change を実行します。
共有状態は CameraStateOwner が、device は instance ごとの lock 付き storage が、
handlers は型全体で共有する lock 付き storage (private static let handlersStorage) が
保持します。この型が持つ instance の stored property は次の 3 つだけです。
id: instance を識別する IDdeviceStorage:AVCaptureDeviceを保持する lock 付き storagenativeStorage:RTCCameraVideoCapturerとその delegate を保持する storage
不変条件は次のとおりです。RTCCameraVideoCapturer の start / stop と
AVCaptureDevice の使用は libwebrtc の capture session queue 上でのみ行います。
camera queue への hop は CameraQueueExecutor に閉じ込めており、start / stop /
restart / change / flip はすべてこの queue を経由します。
frame callback (CameraVideoCapturerDelegate.capturer(_:didCapture:)) も
libwebrtc の capture session queue 上で発火する前提とします (upstream の実装を
確認できないため、現行の挙動を前提とします)。
一方で current / isRunning / format / frameRate は owner の snapshot と
resource テーブルから、stream は owner の resource テーブルから (弱参照のため
capturer は MediaStream を保持しません)、device / position は instance の lock 付き
storage から、handlers は型全体で共有する lock 付き storage から、captureSession は
init で確定して以後差し替えない storage から読むため、任意のスレッドから呼べます。
device の setter も任意のスレッドから呼べるため、command の実行中に device を差し替えると、
その command が読む device は差し替え前後で変わり得ます。
handlers の get / set が排他するのは参照だけであり、返した CameraVideoCapturerHandlers が
持つイベントハンドラのプロパティは、その instance がプロパティごとに持つ HandlerStorage が
排他します。
どちらも任意のスレッドから読み書きできます。
Sendable に準拠するのは、共有状態を owner が、non-Sendable な実資源を
lock 付き storage が保持しているためです。
-
利用可能なデバイスのリスト RTCCameraVideoCapturer.captureDevices を返します。
Declaration
Swift
public static var devices: [AVCaptureDevice] { get } -
前面のカメラに対応するデバイス
owner が instance を 1 つだけ遅延生成して強参照で保持し、2 回目以降は同じ instance を 返します。
public static letのままだと@unchecked Sendableの除去後に non-Sendable 型の static let になり Swift 6 でエラーになるため computed property と しています。Declaration
Swift
public static var front: CameraVideoCapturer? { get } -
背面のカメラに対応するデバイス
Declaration
Swift
public static var back: CameraVideoCapturer? { get } -
起動中のデバイス
owner の snapshot を読みます。書き込みは owner の publish へ一本化するため setter は設けません (外部からは従来どおり読み取り専用)。
Declaration
Swift
public static var current: CameraVideoCapturer? { get } -
RTCCameraVideoCapturer が保持している AVCaptureSession
Declaration
Swift
public var captureSession: AVCaptureSession { get } -
指定したカメラ位置にマッチした最初のデバイスを返します。 captureDevice(for: .back) とすれば背面カメラを取得できます。
Declaration
Swift
public static func device(for position: AVCaptureDevice.Position) -> AVCaptureDevice? -
指定された設定に最も近い AVCaptureDevice.Format? を返します。
Declaration
Swift
public static func format( width: Int32, height: Int32, for device: AVCaptureDevice, frameRate: Int? = nil ) -> AVCaptureDevice.Format? -
指定された FPS 値をサポートしているレンジが存在すれば、その値を返します。 存在しない場合はサポートされているレンジの中で最大の値を返します。
Declaration
Swift
public static func maxFrameRate(_ frameRate: Int, for format: AVCaptureDevice.Format) -> Int? -
引数に指定された capturer を停止し、反対の position を持つ CameraVideoCapturer を起動します。 CameraVideoCapturer の起動には、 capturer と近い設定のフォーマットとフレームレートが利用されます。 また、起動された CameraVideoCapturer には capturer の保持する MediaStream が設定されます。
切り替え先の stream は start より前に設定します。RTCCameraVideoCapturer は start の completion より前から frame callback を発生させることがあり、静的に再利用される front / back capturer に前回利用時の stream が残っていると、旧 stream へ frame が 送信されるためです。stream を先行設定し、start 失敗時は元の stream へ rollback します。 連続実行時の競合は owner の state が持つ flip 実行中フラグで防ぎます。 引数には CameraVideoCapturer.current を渡してください。
Declaration
Swift
public static func flip( _ capturer: CameraVideoCapturer, completionHandler: @escaping ((Error?) -> Void) )
-
出力先のストリーム
owner の resource テーブルへ同期で読み書きします。owner の queue を 同期 wait しないため、libwebrtc の capture session queue 上からの代入でも deadlock しません。
Declaration
Swift
public var stream: MediaStream? { get set } -
カメラが起動中であれば
trueowner の snapshot から読みます。更新は owner の reducer 経由で行います。
Declaration
Swift
public var isRunning: Bool { get } -
イベントハンドラ
lock 付き storage から同一インスタンスを返します。利用者の
CameraVideoCapturer.handlers.onCapture = ...という in-place 変更を維持します。Declaration
Swift
public static var handlers: CameraVideoCapturerHandlers { get set } -
カメラの位置
Declaration
Swift
public var position: AVCaptureDevice.Position { get } -
使用中のデバイス
lock 付き storage から同期で読み書きします。owner の queue を同期 wait しません。
Declaration
Swift
public var device: AVCaptureDevice { get set } -
フレームレート
owner の snapshot から読みます。更新は owner の reducer 経由で行います。
Declaration
Swift
public var frameRate: Int? { get } -
フォーマット
AVCaptureDevice.Formatは non-Sendable のため owner の resource テーブルが 保持し、ここから lock 付きで読み出します。更新はカメラ操作が resource テーブルへ 同期で行います (frameRateは reducer の state が保持します)。Declaration
Swift
public var format: AVCaptureDevice.Format? { get } -
引数に指定した device を利用して CameraVideoCapturer を初期化します。 自動的に初期化される静的プロパティ、 front/back を定義しています。 上記以外のデバイスを利用したい場合のみ CameraVideoCapturer を生成してください。
Declaration
Swift
public init(device: AVCaptureDevice)
-
カメラを起動します。
このメソッドを実行すると、
UIDeviceのbeginGeneratingDeviceOrientationNotifications()が実行されます。beginGeneratingDeviceOrientationNotifications()またはendGeneratingDeviceOrientationNotifications()を使う際は 必ず対に実行するように注意してください。Declaration
Swift
public func start( format: AVCaptureDevice.Format, frameRate: Int, completionHandler: @escaping ((Error?) -> Void) ) -
カメラを停止します。
このメソッドを実行すると、
UIDeviceのendGeneratingDeviceOrientationNotifications()が実行されます。beginGeneratingDeviceOrientationNotifications()またはendGeneratingDeviceOrientationNotifications()を使う際は 必ず対に実行するように注意してください。Declaration
Swift
public func stop(completionHandler: @escaping ((Error?) -> Void)) -
停止前と同じ設定でカメラを再起動します。
Declaration
Swift
public func restart(completionHandler: @escaping ((Error?) -> Void)) -
カメラを停止後、指定されたパラメーターで起動します。
Declaration
Swift
public func change( format: AVCaptureDevice.Format? = nil, frameRate: Int? = nil, completionHandler: @escaping ((Error?) -> Void) )
View on GitHub
Install in Dash