Redesign RTMPConnecitonDelegate and RTMPStreamDelegate.

This commit is contained in:
shogo4405
2023-03-20 17:36:17 +09:00
parent b4ae19fc2a
commit bb54f7ada3
4 changed files with 65 additions and 78 deletions
+22 -40
View File
@@ -31,6 +31,8 @@ final class LiveViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
rtmpConnection.delegate = self
pipIntentView.layer.borderWidth = 1.0
pipIntentView.layer.borderColor = UIColor.white.cgColor
pipIntentView.bounds = MultiCamCaptureSettings.default.regionOfInterest
@@ -41,7 +43,6 @@ final class LiveViewController: UIViewController {
if let orientation = DeviceUtil.videoOrientation(by: UIApplication.shared.statusBarOrientation) {
rtmpStream.videoOrientation = orientation
}
rtmpStream.delegate = self
rtmpStream.videoSettings.videoSize = .init(width: 720, height: 1280)
rtmpStream.mixer.recorder.delegate = self
videoBitrateSlider?.value = Float(VideoCodecSettings.default.bitRate) / 1000
@@ -280,6 +281,26 @@ final class LiveViewController: UIViewController {
}
}
extension LiveViewController: RTMPConnectionDelegate {
func connection(_ connection: RTMPConnection, publishInsufficientBWOccured stream: RTMPStream) {
// Adaptive bitrate streaming exsample. Please feedback me your good algorithm. :D
videoBitRate -= 32 * 1000
stream.videoSettings.bitRate = max(videoBitRate, 64 * 1000)
}
func connection(_ connection: RTMPConnection, publishSufficientBWOccured stream: RTMPStream) {
videoBitRate += 32 * 1000
stream.videoSettings.bitRate = min(videoBitRate, VideoCodecSettings.default.bitRate)
}
func connection(_ connection: RTMPConnection, updateStats stream: RTMPStream) {
}
func connection(_ connection: RTMPConnection, didClear stream: RTMPStream) {
videoBitRate = VideoCodecSettings.default.bitRate
}
}
extension LiveViewController: IORecorderDelegate {
// MARK: IORecorderDelegate
func recorder(_ recorder: IORecorder, errorOccured error: IORecorder.Error) {
@@ -298,42 +319,3 @@ extension LiveViewController: IORecorderDelegate {
})
}
}
extension LiveViewController: RTMPStreamDelegate {
// MARK: RTMPStreamDelegate
func rtmpStream(_ stream: RTMPStream, publishInsufficientBWOccured connection: RTMPConnection) {
// Adaptive bitrate streaming exsample. Please feedback me your good algorithm. :D
videoBitRate -= 32 * 1000
stream.videoSettings.bitRate = max(videoBitRate, 64 * 1000)
}
func rtmpStream(_ stream: RTMPStream, publishSufficientBWOccured connection: RTMPConnection) {
videoBitRate += 32 * 1000
stream.videoSettings.bitRate = min(videoBitRate, VideoCodecSettings.default.bitRate)
}
func rtmpStream(_ stream: RTMPStream, didOutput audio: AVAudioBuffer, presentationTimeStamp: CMTime) {
}
func rtmpStream(_ stream: RTMPStream, didOutput video: CMSampleBuffer) {
}
func rtmpStream(_ stream: RTMPStream, updatedStats connection: RTMPConnection) {
}
func rtmpStream(_ stream: RTMPStream, sessionWasInterrupted session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason) {
}
func rtmpStream(_ stream: RTMPStream, sessionInterruptionEnded session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason) {
}
func rtmpStream(_ stream: RTMPStream, audioCodecErrorOccurred error: HaishinKit.AudioCodec.Error) {
}
func rtmpStream(_ stream: RTMPStream, videoCodecErrorOccurred error: VideoCodec.Error) {
}
func rtmpStreamDidClear(_ stream: RTMPStream) {
videoBitRate = VideoCodecSettings.default.bitRate
}
}
+20
View File
@@ -5,6 +5,24 @@ import CoreMedia
import ScreenCaptureKit
#endif
/// The interface a NetStream uses to inform its delegate.
public protocol NetStreamDelegate: AnyObject {
/// Tells the receiver to playback an audio packet incoming.
func stream(_ stream: NetStream, didOutput audio: AVAudioBuffer, presentationTimeStamp: CMTime)
/// Tells the receiver to playback a video packet incoming.
func stream(_ stream: NetStream, didOutput video: CMSampleBuffer)
#if os(iOS)
/// Tells the receiver to session was interrupted.
func stream(_ stream: NetStream, sessionWasInterrupted session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason)
/// Tells the receiver to session interrupted ended.
func stream(_ stream: NetStream, sessionInterruptionEnded session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason)
#endif
/// Tells the receiver to video codec error occured.
func stream(_ stream: NetStream, videoCodecErrorOccurred error: VideoCodec.Error)
/// Tells the receiver to audio codec error occured.
func stream(_ stream: NetStream, audioCodecErrorOccurred error: AudioCodec.Error)
}
/// The `NetStream` class is the foundation of a RTMPStream, HTTPStream.
open class NetStream: NSObject {
/// The lockQueue.
@@ -19,6 +37,8 @@ open class NetStream: NSObject {
/// The mixer object.
public private(set) var mixer = IOMixer()
/// Specifies the delegate of the NetStream.
public weak var delegate: NetStreamDelegate?
/// Specifies the context object.
public var context: CIContext {
+17 -3
View File
@@ -25,6 +25,18 @@ open class RTMPResponder {
}
}
/// The interface a RTMPConnectionDelegate uses to inform its delegate.
public protocol RTMPConnectionDelegate: AnyObject {
/// Tells the receiver to publish insufficient bandwidth occured.
func connection(_ connection: RTMPConnection, publishInsufficientBWOccured stream: RTMPStream)
/// Tells the receiver to publish sufficient bandwidth occured.
func connection(_ connection: RTMPConnection, publishSufficientBWOccured stream: RTMPStream)
/// Tells the receiver to update statistics.
func connection(_ connection: RTMPConnection, updateStats stream: RTMPStream)
/// Tells the receiver to the stream opend.
func connection(_ connection: RTMPConnection, didClear stream: RTMPStream)
}
// MARK: -
/// The RTMPConneciton class create a two-way RTMP connection.
open class RTMPConnection: EventDispatcher {
@@ -203,6 +215,8 @@ open class RTMPConnection: EventDispatcher {
public var totalStreamsCount: Int {
streams.count
}
/// Specifies the delegate of the NetStream.
public weak var delegate: RTMPConnectionDelegate?
/// The statistics of outgoing queue bytes per second.
@objc open private(set) dynamic var previousQueueBytesOut: [Int64] = []
/// The statistics of incoming bytes per second.
@@ -469,17 +483,17 @@ open class RTMPConnection: EventDispatcher {
}
if total == measureInterval - 1 {
for stream in streams {
stream.delegate?.rtmpStream(stream, publishInsufficientBWOccured: self)
delegate?.connection(self, publishInsufficientBWOccured: stream)
}
} else if total == 0 {
for stream in streams {
stream.delegate?.rtmpStream(stream, publishSufficientBWOccured: self)
delegate?.connection(self, publishSufficientBWOccured: stream)
}
}
previousQueueBytesOut.removeFirst()
}
for stream in streams {
stream.delegate?.rtmpStream(stream, updatedStats: self)
delegate?.connection(self, didClear: stream)
}
}
}
+6 -35
View File
@@ -1,31 +1,5 @@
import AVFoundation
/// The interface a RTMPStream uses to inform its delegate.
public protocol RTMPStreamDelegate: AnyObject {
/// Tells the receiver to publish insufficient bandwidth occured.
func rtmpStream(_ stream: RTMPStream, publishInsufficientBWOccured connection: RTMPConnection)
/// Tells the receiver to publish sufficient bandwidth occured.
func rtmpStream(_ stream: RTMPStream, publishSufficientBWOccured connection: RTMPConnection)
/// Tells the receiver to playback an audio packet incoming.
func rtmpStream(_ stream: RTMPStream, didOutput audio: AVAudioBuffer, presentationTimeStamp: CMTime)
/// Tells the receiver to playback a video packet incoming.
func rtmpStream(_ stream: RTMPStream, didOutput video: CMSampleBuffer)
/// Tells the receiver to update statistics.
func rtmpStream(_ stream: RTMPStream, updatedStats connection: RTMPConnection)
#if os(iOS)
/// Tells the receiver to session was interrupted.
func rtmpStream(_ stream: RTMPStream, sessionWasInterrupted session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason)
/// Tells the receiver to session interrupted ended.
func rtmpStream(_ stream: RTMPStream, sessionInterruptionEnded session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason)
#endif
/// Tells the receiver to video codec error occured.
func rtmpStream(_ stream: RTMPStream, videoCodecErrorOccurred error: VideoCodec.Error)
/// Tells the receiver to audio codec error occured.
func rtmpStream(_ stream: RTMPStream, audioCodecErrorOccurred error: AudioCodec.Error)
/// Tells the receiver to the stream opend.
func rtmpStreamDidClear(_ stream: RTMPStream)
}
/// An object that provides the interface to control a one-way channel over a RtmpConnection.
open class RTMPStream: NetStream {
/// NetStatusEvent#info.code for NetStream
@@ -185,8 +159,6 @@ open class RTMPStream: NetStream {
}
static let defaultID: UInt32 = 0
/// Specifies the delegate of the RTMPStream.
public weak var delegate: RTMPStreamDelegate?
/// The NetStreamInfo object whose properties contain data.
public internal(set) var info = RTMPStreamInfo()
/// The object encoding (AMF). Framework supports AMF0 only.
@@ -479,7 +451,6 @@ open class RTMPStream: NetStream {
currentFPS = 0
frameCount = 0
info.clear()
delegate?.rtmpStreamDidClear(self)
for message in messages {
rtmpConnection.currentTransactionId += 1
message.streamId = id
@@ -618,11 +589,11 @@ extension RTMPStream: RTMPMuxerDelegate {
}
func muxer(_ muxer: RTMPMuxer, videoCodecErrorOccurred error: VideoCodec.Error) {
delegate?.rtmpStream(self, videoCodecErrorOccurred: error)
delegate?.stream(self, videoCodecErrorOccurred: error)
}
func muxer(_ muxer: RTMPMuxer, audioCodecErrorOccurred error: AudioCodec.Error) {
delegate?.rtmpStream(self, audioCodecErrorOccurred: error)
delegate?.stream(self, audioCodecErrorOccurred: error)
}
}
@@ -630,20 +601,20 @@ extension RTMPStream: IOMixerDelegate {
// MARK: IOMixerDelegate
func mixer(_ mixer: IOMixer, didOutput video: CMSampleBuffer) {
frameCount += 1
delegate?.rtmpStream(self, didOutput: video)
delegate?.stream(self, didOutput: video)
}
func mixer(_ mixer: IOMixer, didOutput audio: AVAudioPCMBuffer, presentationTimeStamp: CMTime) {
delegate?.rtmpStream(self, didOutput: audio, presentationTimeStamp: presentationTimeStamp)
delegate?.stream(self, didOutput: audio, presentationTimeStamp: presentationTimeStamp)
}
#if os(iOS)
func mixer(_ mixer: IOMixer, sessionWasInterrupted session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason) {
delegate?.rtmpStream(self, sessionWasInterrupted: session, reason: reason)
delegate?.stream(self, sessionWasInterrupted: session, reason: reason)
}
func mixer(_ mixer: IOMixer, sessionInterruptionEnded session: AVCaptureSession, reason: AVCaptureSession.InterruptionReason) {
delegate?.rtmpStream(self, sessionInterruptionEnded: session, reason: reason)
delegate?.stream(self, sessionInterruptionEnded: session, reason: reason)
}
#endif
}