Skip to content
This repository was archived by the owner on Jul 8, 2024. It is now read-only.

Commit 4fdf0e2

Browse files
committed
update
2 parents df8c7cc + 0e095a1 commit 4fdf0e2

72 files changed

Lines changed: 1840 additions & 1128 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Examples/iOS/AudioCapture.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import AVFoundation
2+
import Foundation
3+
import HaishinKit
4+
5+
protocol AudioCaptureDelegate: AnyObject {
6+
func audioCapture(_ audioCapture: AudioCapture, buffer: AVAudioBuffer, time: AVAudioTime)
7+
}
8+
9+
final class AudioCapture {
10+
var isRunning: Atomic<Bool> = .init(false)
11+
var delegate: (any AudioCaptureDelegate)?
12+
private let audioEngine = AVAudioEngine()
13+
}
14+
15+
extension AudioCapture: Running {
16+
func startRunning() {
17+
guard !isRunning.value else {
18+
return
19+
}
20+
let input = audioEngine.inputNode
21+
let mixer = audioEngine.mainMixerNode
22+
audioEngine.connect(input, to: mixer, format: input.inputFormat(forBus: 0))
23+
input.installTap(onBus: 0, bufferSize: 1024, format: input.inputFormat(forBus: 0)) { buffer, when in
24+
self.delegate?.audioCapture(self, buffer: buffer, time: when)
25+
}
26+
do {
27+
try audioEngine.start()
28+
isRunning.mutate { $0 = true }
29+
} catch {
30+
logger.error(error)
31+
}
32+
}
33+
34+
func stopRunning() {
35+
guard isRunning.value else {
36+
return
37+
}
38+
audioEngine.stop()
39+
isRunning.mutate { $0 = false }
40+
}
41+
}

Examples/iOS/LiveViewController.swift

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,32 @@ final class LiveViewController: UIViewController {
2727
private var currentEffect: VideoEffect?
2828
private var currentPosition: AVCaptureDevice.Position = .back
2929
private var retryCount: Int = 0
30-
private var videoBitRate = VideoCodecSettings.default.bitRate
3130
private var preferedStereo = false
31+
private lazy var audioCapture: AudioCapture = {
32+
let audioCapture = AudioCapture()
33+
audioCapture.delegate = self
34+
return audioCapture
35+
}()
3236

3337
override func viewDidLoad() {
3438
super.viewDidLoad()
3539

36-
rtmpConnection.delegate = self
37-
3840
pipIntentView.layer.borderWidth = 1.0
3941
pipIntentView.layer.borderColor = UIColor.white.cgColor
4042
pipIntentView.bounds = MultiCamCaptureSettings.default.regionOfInterest
4143
pipIntentView.isUserInteractionEnabled = true
4244
view.addSubview(pipIntentView)
4345

46+
rtmpConnection.delegate = self
47+
4448
rtmpStream = RTMPStream(connection: rtmpConnection)
4549
if let orientation = DeviceUtil.videoOrientation(by: UIApplication.shared.statusBarOrientation) {
4650
rtmpStream.videoOrientation = orientation
4751
}
4852

4953
rtmpStream.isMonitoringEnabled = DeviceUtil.isHeadphoneConnected()
50-
51-
rtmpStream.audioSettings = AudioCodecSettings(
52-
bitRate: 64 * 1000
53-
)
54-
55-
rtmpStream.videoSettings = VideoCodecSettings(
56-
videoSize: .init(width: 854, height: 480),
57-
profileLevel: kVTProfileLevel_H264_Baseline_3_1 as String,
58-
bitRate: 640 * 1000,
59-
maxKeyFrameIntervalDuration: 2,
60-
scalingMode: .trim,
61-
bitRateMode: .average,
62-
allowFrameReordering: nil,
63-
isHardwareEncoderEnabled: true
64-
)
65-
54+
rtmpStream.audioSettings.bitRate = 64 * 1000
55+
rtmpStream.bitrateStrategy = VideoAdaptiveNetBitRateStrategy(mamimumVideoBitrate: VideoCodecSettings.default.bitRate)
6656
rtmpStream.mixer.recorder.delegate = self
6757
videoBitrateSlider?.value = Float(VideoCodecSettings.default.bitRate) / 1000
6858
audioBitrateSlider?.value = Float(AudioCodecSettings.default.bitRate) / 1000
@@ -163,7 +153,7 @@ final class LiveViewController: UIViewController {
163153
}
164154
if slider == videoBitrateSlider {
165155
videoBitrateLabel?.text = "video \(Int(slider.value))/kbps"
166-
rtmpStream.videoSettings.bitRate = UInt32(slider.value * 1000)
156+
rtmpStream.bitrateStrategy = VideoAdaptiveNetBitRateStrategy(mamimumVideoBitrate: Int(slider.value * 1000))
167157
}
168158
if slider == zoomSlider {
169159
let zoomFactor = CGFloat(slider.value)
@@ -348,21 +338,15 @@ final class LiveViewController: UIViewController {
348338

349339
extension LiveViewController: RTMPConnectionDelegate {
350340
func connection(_ connection: RTMPConnection, publishInsufficientBWOccured stream: RTMPStream) {
351-
// Adaptive bitrate streaming exsample. Please feedback me your good algorithm. :D
352-
videoBitRate -= 32 * 1000
353-
stream.videoSettings.bitRate = max(videoBitRate, 64 * 1000)
354341
}
355342

356343
func connection(_ connection: RTMPConnection, publishSufficientBWOccured stream: RTMPStream) {
357-
videoBitRate += 32 * 1000
358-
stream.videoSettings.bitRate = min(videoBitRate, VideoCodecSettings.default.bitRate)
359344
}
360345

361346
func connection(_ connection: RTMPConnection, updateStats stream: RTMPStream) {
362347
}
363348

364349
func connection(_ connection: RTMPConnection, didClear stream: RTMPStream) {
365-
videoBitRate = VideoCodecSettings.default.bitRate
366350
}
367351
}
368352

@@ -385,6 +369,13 @@ extension LiveViewController: IORecorderDelegate {
385369
}
386370
}
387371

372+
extension LiveViewController: AudioCaptureDelegate {
373+
// MARK: AudioCaptureDelegate
374+
func audioCapture(_ audioCapture: AudioCapture, buffer: AVAudioBuffer, time: AVAudioTime) {
375+
rtmpStream.appendAudioBuffer(buffer, when: time)
376+
}
377+
}
378+
388379
extension LiveViewController: UIPickerViewDelegate {
389380
// MARK: UIPickerViewDelegate
390381
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

Examples/iOS/MemoryUsage.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import Foundation
2+
3+
private let kMemoryUsage_count = mach_msg_type_number_t(MemoryLayout<task_vm_info_data_t>.size / MemoryLayout<UInt32>.size)
4+
5+
final class MemoryUsage {
6+
static let MB1 = 1000 * 1000 * 1
7+
static let MB5 = 1000 * 1000 * 5
8+
static let MB10 = 1000 * 10000 * 10
9+
10+
static let shared = MemoryUsage()
11+
12+
private let step: Int = 512000000
13+
private var data: [UnsafeMutablePointer<Int8>] = []
14+
15+
func toEmpty() {
16+
let available = available()
17+
allocateAavailable(available)
18+
}
19+
20+
func available() -> Int {
21+
return os_proc_available_memory()
22+
}
23+
24+
func allocate(_ size: Int) {
25+
let value = UnsafeMutablePointer<Int8>.allocate(capacity: size)
26+
value.update(repeating: 0, count: size)
27+
data.append(value)
28+
}
29+
30+
private func allocateAavailable(_ size: Int) {
31+
if step < size {
32+
for _ in 0..<(size / step) - 1 {
33+
let value = UnsafeMutablePointer<Int8>.allocate(capacity: step)
34+
value.update(repeating: 0, count: step)
35+
data.append(value)
36+
}
37+
sleep(3)
38+
allocate(available())
39+
} else {
40+
if MemoryUsage.MB5 < size {
41+
let value = UnsafeMutablePointer<Int8>.allocate(capacity: size - MemoryUsage.MB5)
42+
value.update(repeating: 0, count: size - MemoryUsage.MB5)
43+
data.append(value)
44+
}
45+
}
46+
}
47+
}

Examples/iOS/PlaybackViewController.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ extension PlaybackViewController: AVPictureInPictureSampleBufferPlaybackDelegate
123123

124124
extension PlaybackViewController: NetStreamDelegate {
125125
// MARK: NetStreamDelegate
126-
func stream(_ stream: NetStream, didOutput audio: AVAudioBuffer, presentationTimeStamp: CMTime) {
126+
func stream(_ stream: NetStream, didOutput audio: AVAudioBuffer, when: AVAudioTime) {
127127
}
128128

129129
func stream(_ stream: NetStream, didOutput video: CMSampleBuffer) {
@@ -141,10 +141,6 @@ extension PlaybackViewController: NetStreamDelegate {
141141
func stream(_ stream: NetStream, audioCodecErrorOccurred error: HaishinKit.AudioCodec.Error) {
142142
}
143143

144-
func streamWillDropFrame(_ stream: NetStream) -> Bool {
145-
return false
146-
}
147-
148144
func streamDidOpen(_ stream: NetStream) {
149145
}
150146
}

Examples/iOS/Screencast/SampleHandler.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Logboard
33
import ReplayKit
44
import VideoToolbox
55

6-
let logger = LBLogger.with("com.haishinkit.Exsample.iOS.Screencast")
6+
let logger = LBLogger.with(HaishinKitIdentifier)
77

88
@available(iOS 10.0, *)
99
open class SampleHandler: RPBroadcastSampleHandler {
@@ -27,13 +27,12 @@ open class SampleHandler: RPBroadcastSampleHandler {
2727

2828
override open func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) {
2929
/*
30-
let logger = Logboard.with(HaishinKitIdentifier)
3130
let socket = SocketAppender()
32-
socket.connect("192.168.11.15", port: 22222)
31+
socket.connect("192.168.1.9", port: 22222)
3332
logger.level = .debug
3433
logger.appender = socket
34+
logger.level = .debug
3535
*/
36-
logger.level = .debug
3736
LBLogger.with(HaishinKitIdentifier).level = .info
3837
rtmpConnection.connect(Preference.defaultInstance.uri!, arguments: nil)
3938
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Foundation
2+
import HaishinKit
3+
4+
public final class VideoAdaptiveNetBitRateStrategy: NetBitRateStrategyConvertible {
5+
public weak var stream: NetStream?
6+
public let mamimumVideoBitRate: Int
7+
public let mamimumAudioBitRate: Int = 0
8+
private var zeroBytesOutPerSecondCounts: Int = 0
9+
10+
public init(mamimumVideoBitrate: Int) {
11+
self.mamimumVideoBitRate = mamimumVideoBitrate
12+
}
13+
14+
public func setUp() {
15+
zeroBytesOutPerSecondCounts = 0
16+
stream?.videoSettings.bitRate = mamimumVideoBitRate
17+
}
18+
19+
public func sufficientBWOccured(_ stats: NetBitRateStats) {
20+
guard let stream else {
21+
return
22+
}
23+
stream.videoSettings.bitRate = min(stream.videoSettings.bitRate + 64 * 1000, mamimumVideoBitRate)
24+
}
25+
26+
public func insufficientBWOccured(_ stats: NetBitRateStats) {
27+
guard let stream, 0 < stats.currentBytesOutPerSecond else {
28+
return
29+
}
30+
if 0 < stats.currentBytesOutPerSecond {
31+
let bitRate = Int(stats.currentBytesOutPerSecond * 8) / (zeroBytesOutPerSecondCounts + 1)
32+
stream.videoSettings.bitRate = max(bitRate - stream.audioSettings.bitRate, 64 * 1000)
33+
zeroBytesOutPerSecondCounts = 0
34+
} else {
35+
zeroBytesOutPerSecondCounts += 1
36+
}
37+
}
38+
}

Examples/macOS/Base.lproj/Main.storyboard

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="4Lp-xV-zxC">
2+
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="22154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="4Lp-xV-zxC">
33
<dependencies>
4-
<deployment identifier="macosx"/>
5-
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
4+
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22154"/>
65
<capability name="NSView safe area layout guides" minToolsVersion="12.0"/>
76
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
87
</dependencies>
@@ -95,7 +94,7 @@
9594
<action selector="modeChanged:" target="XfG-lQ-9wD" id="Yy2-YF-Uce"/>
9695
</connections>
9796
</segmentedControl>
98-
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lB9-7R-daQ">
97+
<textField focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lB9-7R-daQ">
9998
<rect key="frame" x="20" y="20" width="300" height="21"/>
10099
<constraints>
101100
<constraint firstAttribute="width" constant="300" id="beN-tf-ecK"/>
@@ -224,13 +223,13 @@
224223
<autoresizingMask key="autoresizingMask"/>
225224
<subviews>
226225
<scrollView autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="U7X-zB-Ct9">
227-
<rect key="frame" x="0.0" y="0.0" width="154" height="1684"/>
226+
<rect key="frame" x="0.0" y="0.0" width="154" height="1888"/>
228227
<clipView key="contentView" id="TC0-20-xwt">
229-
<rect key="frame" x="1" y="1" width="152" height="1682"/>
228+
<rect key="frame" x="1" y="1" width="152" height="1886"/>
230229
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
231230
<subviews>
232231
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" rowSizeStyle="automatic" viewBased="YES" id="Zf5-MB-jdh">
233-
<rect key="frame" x="0.0" y="0.0" width="152" height="1682"/>
232+
<rect key="frame" x="0.0" y="0.0" width="152" height="1886"/>
234233
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
235234
<size key="intercellSpacing" width="17" height="0.0"/>
236235
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -252,7 +251,7 @@
252251
<rect key="frame" x="8" y="0.0" width="135" height="24"/>
253252
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
254253
<subviews>
255-
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="nKL-O8-0aU">
254+
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="nKL-O8-0aU">
256255
<rect key="frame" x="0.0" y="4" width="135" height="16"/>
257256
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="Lf1-hH-841">
258257
<font key="font" usesAppearanceFont="YES"/>
@@ -281,7 +280,7 @@
281280
</subviews>
282281
</clipView>
283282
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="5e8-aJ-U5N">
284-
<rect key="frame" x="1" y="1565" width="152" height="16"/>
283+
<rect key="frame" x="1" y="1769" width="152" height="16"/>
285284
<autoresizingMask key="autoresizingMask"/>
286285
</scroller>
287286
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="eRz-M7-DJS">
@@ -395,7 +394,7 @@
395394
<action selector="selectCamera:" target="dhX-nT-Doa" id="F16-Nj-MQi"/>
396395
</connections>
397396
</popUpButton>
398-
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EUe-gL-Kfw">
397+
<textField focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EUe-gL-Kfw">
399398
<rect key="frame" x="20" y="20" width="300" height="21"/>
400399
<constraints>
401400
<constraint firstAttribute="width" constant="300" id="zUM-Oo-BRX"/>
@@ -434,7 +433,7 @@
434433
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
435434
<autoresizingMask key="autoresizingMask"/>
436435
<subviews>
437-
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="muK-Fu-lNp">
436+
<textField focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="muK-Fu-lNp">
438437
<rect key="frame" x="16" y="419" width="300" height="21"/>
439438
<constraints>
440439
<constraint firstAttribute="width" constant="300" id="onn-Pa-e0H"/>
@@ -448,23 +447,23 @@
448447
<outlet property="delegate" destination="9vk-iW-BZX" id="TTT-Ka-3O4"/>
449448
</connections>
450449
</textField>
451-
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y43-vh-quB">
450+
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="y43-vh-quB">
452451
<rect key="frame" x="14" y="448" width="73" height="16"/>
453452
<textFieldCell key="cell" lineBreakMode="clipping" title="RTMP URL:" id="a0O-iB-hpy">
454453
<font key="font" metaFont="system"/>
455454
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
456455
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
457456
</textFieldCell>
458457
</textField>
459-
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WSq-ak-6dS">
458+
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WSq-ak-6dS">
460459
<rect key="frame" x="14" y="395" width="87" height="16"/>
461460
<textFieldCell key="cell" lineBreakMode="clipping" title="StreamName:" id="2cu-1b-UVj">
462461
<font key="font" metaFont="system"/>
463462
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
464463
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
465464
</textFieldCell>
466465
</textField>
467-
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YII-qB-iiW">
466+
<textField focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YII-qB-iiW">
468467
<rect key="frame" x="16" y="366" width="300" height="21"/>
469468
<constraints>
470469
<constraint firstAttribute="width" constant="300" id="03D-Ul-Uui"/>

Examples/macOS/MainSplitViewController.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,4 @@ import AppKit
22
import Foundation
33

44
final class MainSplitViewController: NSSplitViewController {
5-
override func viewDidLoad() {
6-
super.viewDidLoad()
7-
}
85
}
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
import Cocoa
22

33
final class MainWindowController: NSWindowController {
4-
override func windowDidLoad() {
5-
super.windowDidLoad()
6-
}
74
}

0 commit comments

Comments
 (0)