Skip to content

Commit

Permalink
Merge pull request #1642 from shogo4405/feature/manual-capture-start
Browse files Browse the repository at this point in the history
Add an option to start capture manually.
  • Loading branch information
shogo4405 authored Dec 15, 2024
2 parents 6555357 + c8ba890 commit e22de14
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 24 deletions.
8 changes: 4 additions & 4 deletions Examples/iOS/IngestViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ final class IngestViewController: UIViewController {
private var retryCount: Int = 0
private var preferedStereo = false
private let netStreamSwitcher: HKStreamSwitcher = .init()
private lazy var mixer = MediaMixer()
private lazy var mixer = MediaMixer(multiCamSessionEnabled: true, multiTrackAudioMixingEnabled: false, useManualCapture: true)
private lazy var audioCapture: AudioCapture = {
let audioCapture = AudioCapture()
audioCapture.delegate = self
Expand All @@ -37,9 +37,7 @@ final class IngestViewController: UIViewController {
super.viewDidLoad()
Task {
// If you want to use the multi-camera feature, please make create a MediaMixer with a multiCamSession mode.
// ```
// let mixer = MediaMixer(multiCamSessionEnabled: true, multiTrackAudioMixingEnabled: false)
// ```
// let mixer = MediaMixer(multiCamSessionEnabled: true)
if let orientation = DeviceUtil.videoOrientation(by: UIApplication.shared.statusBarOrientation) {
await mixer.setVideoOrientation(orientation)
}
Expand Down Expand Up @@ -83,6 +81,7 @@ final class IngestViewController: UIViewController {
try? await mixer.attachVideo(front, track: 1) { videoUnit in
videoUnit.isVideoMirrored = true
}
await mixer.startRunning()
}
NotificationCenter.default.addObserver(self, selector: #selector(on(_:)), name: UIDevice.orientationDidChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didInterruptionNotification(_:)), name: AVAudioSession.interruptionNotification, object: nil)
Expand All @@ -94,6 +93,7 @@ final class IngestViewController: UIViewController {
super.viewWillDisappear(animated)
Task {
await netStreamSwitcher.close()
await mixer.stopRunning()
try? await mixer.attachAudio(nil)
try? await mixer.attachVideo(nil, track: 0)
try? await mixer.attachVideo(nil, track: 1)
Expand Down
50 changes: 30 additions & 20 deletions HaishinKit/Sources/Mixer/MediaMixer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,11 @@ public final actor MediaMixer {

public private(set) var isRunning = false
private var outputs: [any MediaMixerOutput] = []
private var cancellables: Set<AnyCancellable> = []
private let useManualCapture: Bool
private lazy var audioIO = AudioCaptureUnit(session)
private lazy var videoIO = VideoCaptureUnit(session)
private lazy var session = CaptureSession()
private var cancellables: Set<AnyCancellable> = []
@ScreenActor
private lazy var displayLink = DisplayLinkChoreographer()

Expand All @@ -105,21 +106,35 @@ public final actor MediaMixer {
/// - Parameters:
/// - multiCamSessionEnabled: Specifies the AVCaptureMultiCamSession enabled.
/// - multiTrackAudioMixingEnabled: Specifies the feature to mix multiple audio tracks. For example, it is possible to mix .appAudio and .micAudio from ReplayKit.
public init(multiCamSessionEnabled: Bool = true, multiTrackAudioMixingEnabled: Bool = false) {
/// - useManualCapture: Specifies whether to start capturing manually. #1642
public init(
multiCamSessionEnabled: Bool = true,
multiTrackAudioMixingEnabled: Bool = false,
useManualCapture: Bool = false
) {
self.useManualCapture = useManualCapture
Task {
await setMultiCamSessionEnabled(multiCamSessionEnabled)
await setMultiTrackAudioMixingEnabled(multiTrackAudioMixingEnabled)
await startRunning()
await session.isMultiCamSessionEnabled = true
await audioIO.isMultiTrackAudioMixingEnabled = multiCamSessionEnabled
if !useManualCapture {
await startRunning()
}
}
}

#else
/// Creates a new instance.
///
/// - Parameters:
/// - multiTrackAudioMixingEnabled: Specifies the feature to mix multiple audio tracks. For example, it is possible to mix .appAudio and .micAudio from ReplayKit.
public init(multiTrackAudioMixingEnabled: Bool = false) {
/// - useManualCapture: Specifies whether to start capturing manually. #1642
public init(
multiTrackAudioMixingEnabled: Bool = false,
useManualCapture: Bool = false
) {
self.useManualCapture = useManualCapture
Task {
await setMultiTrackAudioMixingEnabled(multiTrackAudioMixingEnabled)
await audioIO.isMultiTrackAudioMixingEnabled = multiTrackAudioMixingEnabled
await startRunning()
}
}
Expand All @@ -128,9 +143,8 @@ public final actor MediaMixer {
/// Attaches a video device.
///
/// If you want to use the multi-camera feature, please make create a MediaMixer with a multiCamSession mode for iOS.
/// ```
/// let mixer = MediaMixer(multiCamSessionEnabled: true, multiTrackAudioMixingEnabled: false)
/// ```
///
@available(tvOS 17.0, *)
public func attachVideo(_ device: AVCaptureDevice?, track: UInt8 = 0, configuration: VideoDeviceConfigurationBlock? = nil) async throws {
return try await withCheckedThrowingContinuation { continuation in
Expand Down Expand Up @@ -294,7 +308,7 @@ public final actor MediaMixer {
}
outputs.append(output)
if #available(tvOS 17.0, *) {
if !isCapturing {
if !isCapturing && !useManualCapture {
startCapturing()
}
}
Expand All @@ -307,16 +321,6 @@ public final actor MediaMixer {
}
}

#if os(iOS) || os(tvOS)
func setMultiCamSessionEnabled(_ multiCamSessionEnabled: Bool) {
session.isMultiCamSessionEnabled = multiCamSessionEnabled
}
#endif

func setMultiTrackAudioMixingEnabled(_ multiTrackAudioMixingEnabled: Bool) {
audioIO.isMultiTrackAudioMixingEnabled = multiTrackAudioMixingEnabled
}

func setVideoRenderingMode(_ mode: VideoMixerSettings.Mode) {
switch mode {
case .passthrough:
Expand Down Expand Up @@ -391,6 +395,9 @@ extension MediaMixer: AsyncRunner {
}
}
setVideoRenderingMode(videoMixerSettings.mode)
if useManualCapture {
session.startRunning()
}
#if os(iOS) || os(tvOS) || os(visionOS)
NotificationCenter
.Publisher(center: .default, name: UIApplication.didEnterBackgroundNotification, object: nil)
Expand All @@ -416,6 +423,9 @@ extension MediaMixer: AsyncRunner {
return
}
isRunning = false
if useManualCapture {
session.stopRunning()
}
cancellables.forEach { $0.cancel() }
cancellables.removeAll()
Task { @ScreenActor in
Expand Down

0 comments on commit e22de14

Please sign in to comment.