Update Example

This commit is contained in:
shogo4405 2017-02-04 21:48:55 +09:00
parent 1a2e18884c
commit 9fe037b6bf
16 changed files with 334 additions and 370 deletions

View File

@ -1,22 +1,12 @@
import UIKit
import XCGLogger
let logger:XCGLogger = XCGLogger.default
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window:UIWindow?
var rootViewController:UINavigationController = {
let controller:UINavigationController = UINavigationController()
controller.setViewControllers([LiveViewController()], animated: true)
controller.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
controller.navigationBar.isTranslucent = true
controller.navigationBar.titleTextAttributes = [
NSForegroundColorAttributeName: UIColor.white
]
controller.navigationBar.tintColor = UIColor.white
controller.navigationBar.shadowImage = UIImage()
return controller
}()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
XCGLogger.default.setup(
@ -31,11 +21,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
writeToFile: nil,
fileLevel: nil
)
window = UIWindow(frame: UIScreen.main.bounds)
window?.backgroundColor = UIColor.white
window?.rootViewController = rootViewController
window?.makeKeyAndVisible()
return true
}
}

View File

@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
@ -14,9 +18,9 @@
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>

View File

@ -2,17 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPhotoLibraryUsageDescription</key>
<string></string>
<key>NSCameraUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
@ -33,8 +22,21 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSPhotoLibraryUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>

View File

@ -1,215 +1,86 @@
import lf
import UIKit
import XCGLogger
import AVFoundation
struct Preference {
static let defaultInstance:Preference = Preference()
var uri:String? = "rtmp://test:test@192.168.11.2/live"
var streamName:String? = "live"
}
let sampleRate:Double = 44_100
final class LiveViewController: UIViewController {
/*
var rtmpConnection:RTMPConnection = RTMPConnection()
var rtmpStream:RTMPStream!
var sharedObject:RTMPSharedObject!
var currentEffect:VisualEffect? = nil
var httpService:HTTPService!
var httpStream:HTTPStream!
let touchView: UIView! = UIView()
let lfView:GLLFView = GLLFView(frame: CGRect.zero)
var currentFPSLabel:UILabel = {
let label:UILabel = UILabel()
label.textColor = UIColor.white
return label
}()
var publishButton:UIButton = {
let button:UIButton = UIButton()
button.backgroundColor = UIColor.blue
button.setTitle("", for: UIControlState())
button.layer.masksToBounds = true
return button
}()
var pauseButton:UIButton = {
let button:UIButton = UIButton()
button.backgroundColor = UIColor.blue
button.setTitle("P", for: UIControlState())
button.layer.masksToBounds = true
return button
}()
var videoBitrateLabel:UILabel = {
let label:UILabel = UILabel()
label.textColor = UIColor.white
return label
}()
var videoBitrateSlider:UISlider = {
let slider:UISlider = UISlider()
slider.minimumValue = 32
slider.maximumValue = 1024
return slider
}()
var audioBitrateLabel:UILabel = {
let label:UILabel = UILabel()
label.textColor = UIColor.white
return label
}()
var zoomSlider:UISlider = {
let slider:UISlider = UISlider()
slider.minimumValue = 0.0
slider.maximumValue = 5.0
return slider
}()
var audioBitrateSlider:UISlider = {
let slider:UISlider = UISlider()
slider.minimumValue = 16
slider.maximumValue = 120
return slider
}()
var fpsControl:UISegmentedControl = {
let segment:UISegmentedControl = UISegmentedControl(items: ["15.0", "30.0", "60.0"])
segment.tintColor = UIColor.white
return segment
}()
var effectSegmentControl:UISegmentedControl = {
let segment:UISegmentedControl = UISegmentedControl(items: ["None", "Monochrome", "Pronama"])
segment.tintColor = UIColor.white
return segment
}()
@IBOutlet var lfView:LFView?
@IBOutlet var currentFPSLabel:UILabel?
@IBOutlet var publishButton:UIButton?
@IBOutlet var pauseButton:UIButton?
@IBOutlet var videoBitrateLabel:UILabel?
@IBOutlet var videoBitrateSlider:UISlider?
@IBOutlet var audioBitrateLabel:UILabel?
@IBOutlet var zoomSlider:UISlider?
@IBOutlet var audioBitrateSlider:UISlider?
@IBOutlet var fpsControl:UISegmentedControl?
@IBOutlet var effectSegmentControl:UISegmentedControl?
var currentPosition:AVCaptureDevicePosition = AVCaptureDevicePosition.back
override func viewDidLoad() {
super.viewDidLoad()
let sampleRate:Double = 44_100
do {
try AVAudioSession.sharedInstance().setPreferredSampleRate(sampleRate)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
try AVAudioSession.sharedInstance().setMode(AVAudioSessionModeDefault)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
}
currentFPSLabel.text = "FPS"
zoomSlider.addTarget(self, action: #selector(LiveViewController.onSliderValueChanged(_:)), for: .valueChanged)
videoBitrateSlider.addTarget(self, action: #selector(LiveViewController.onSliderValueChanged(_:)), for: .valueChanged)
audioBitrateSlider.addTarget(self, action: #selector(LiveViewController.onSliderValueChanged(_:)), for: .valueChanged)
fpsControl.addTarget(self, action: #selector(LiveViewController.onFPSValueChanged(_:)), for: .valueChanged)
effectSegmentControl.addTarget(self, action: #selector(LiveViewController.onEffectValueChanged(_:)), for: .valueChanged)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(title: "Torch", style: .plain, target: self, action: #selector(LiveViewController.toggleTorch(_:))),
UIBarButtonItem(title: "Camera", style: .plain, target: self, action: #selector(LiveViewController.rotateCamera(_:)))
]
rtmpStream = RTMPStream(connection: rtmpConnection)
rtmpStream.syncOrientation = true
rtmpStream.attachAudio(AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
rtmpStream.attachCamera(DeviceUtil.device(withPosition: .back))
rtmpStream.addObserver(self, forKeyPath: "currentFPS", options: NSKeyValueObservingOptions.new, context: nil)
rtmpStream.captureSettings = [
"sessionPreset": AVCaptureSessionPreset1280x720,
"continuousAutofocus": true,
"continuousExposure": true,
]
rtmpStream.videoSettings = [
"width": 1280,
"height": 720,
]
rtmpStream.audioSettings = [
"sampleRate": sampleRate
]
rtmpStream.addObserver(self, forKeyPath: "currentFPS", options: NSKeyValueObservingOptions.new, context: nil)
publishButton.addTarget(self, action: #selector(LiveViewController.on(publish:)), for: .touchUpInside)
pauseButton.addTarget(self, action: #selector(LiveViewController.on(pause:)), for: .touchUpInside)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(LiveViewController.tapScreen(_:)))
touchView.addGestureRecognizer(tapGesture)
touchView.frame = view.frame
touchView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
videoBitrateSlider.value = Float(RTMPStream.defaultVideoBitrate) / 1024
audioBitrateSlider.value = Float(RTMPStream.defaultAudioBitrate) / 1024
lfView.attachStream(rtmpStream)
view.addSubview(lfView)
view.addSubview(touchView)
view.addSubview(videoBitrateLabel)
view.addSubview(videoBitrateSlider)
view.addSubview(audioBitrateLabel)
view.addSubview(audioBitrateSlider)
view.addSubview(zoomSlider)
view.addSubview(fpsControl)
view.addSubview(currentFPSLabel)
view.addSubview(effectSegmentControl)
view.addSubview(pauseButton)
view.addSubview(publishButton)
videoBitrateSlider?.value = Float(RTMPStream.defaultVideoBitrate) / 1024
audioBitrateSlider?.value = Float(RTMPStream.defaultAudioBitrate) / 1024
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let navigationHeight:CGFloat = 66
lfView.frame = view.bounds
fpsControl.frame = CGRect(x: view.bounds.width - 200 - 10 , y: navigationHeight + 40, width: 200, height: 30)
effectSegmentControl.frame = CGRect(x: view.bounds.width - 200 - 10 , y: navigationHeight, width: 200, height: 30)
pauseButton.frame = CGRect(x: view.bounds.width - 44 - 20, y: view.bounds.height - 44 * 2 - 20 * 2, width: 44, height: 44)
publishButton.frame = CGRect(x: view.bounds.width - 44 - 20, y: view.bounds.height - 44 - 20, width: 44, height: 44)
currentFPSLabel.frame = CGRect(x: 10, y: 10, width: 40, height: 40)
zoomSlider.frame = CGRect(x: 20, y: view.frame.height - 44 * 3 - 22, width: view.frame.width - 44 - 60, height: 44)
videoBitrateLabel.text = "video \(Int(videoBitrateSlider.value))/kbps"
videoBitrateLabel.frame = CGRect(x: view.frame.width - 150 - 60, y: view.frame.height - 44 * 2 - 22, width: 150, height: 44)
videoBitrateSlider.frame = CGRect(x: 20, y: view.frame.height - 44 * 2, width: view.frame.width - 44 - 60, height: 44)
audioBitrateLabel.text = "audio \(Int(audioBitrateSlider.value))/kbps"
audioBitrateLabel.frame = CGRect(x: view.frame.width - 150 - 60, y: view.frame.height - 44 - 22, width: 150, height: 44)
audioBitrateSlider.frame = CGRect(x: 20, y: view.frame.height - 44, width: view.frame.width - 44 - 60, height: 44)
override func viewWillAppear(_ animated: Bool) {
logger.info("viewWillAppear")
super.viewWillAppear(animated)
rtmpStream.attachAudio(AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
rtmpStream.attachCamera(DeviceUtil.device(withPosition: currentPosition))
lfView?.attachStream(rtmpStream)
}
func rotateCamera(_ sender:UIBarButtonItem) {
override func viewWillDisappear(_ animated: Bool) {
logger.info("viewWillDisappear")
super.viewWillDisappear(animated)
rtmpStream.dispose()
}
@IBAction func rotateCamera(_ sender:UIButton) {
logger.info("rotateCamera")
let position:AVCaptureDevicePosition = currentPosition == .back ? .front : .back
rtmpStream.attachCamera(DeviceUtil.device(withPosition: position))
currentPosition = position
}
func toggleTorch(_ sender:UIBarButtonItem) {
@IBAction func toggleTorch(_ sender:UIButton) {
rtmpStream.torch = !rtmpStream.torch
}
func showPreference(_ sender:UIBarButtonItem) {
let preference:PreferenceController = PreferenceController()
preference.view.backgroundColor = UIColor(colorLiteralRed: 1.0, green: 1.0, blue: 1.0, alpha: 0.25)
preference.view.frame = view.frame
preference.modalPresentationStyle = .overCurrentContext
preference.modalTransitionStyle = .crossDissolve
present(preference, animated: true, completion: nil)
}
func onSliderValueChanged(_ slider:UISlider) {
@IBAction func on(slider:UISlider) {
if (slider == audioBitrateSlider) {
audioBitrateLabel.text = "audio \(Int(slider.value))/kbps"
audioBitrateLabel?.text = "audio \(Int(slider.value))/kbps"
rtmpStream.audioSettings["bitrate"] = slider.value * 1024
}
if (slider == videoBitrateSlider) {
videoBitrateLabel.text = "video \(Int(slider.value))/kbsp"
videoBitrateLabel?.text = "video \(Int(slider.value))/kbsp"
rtmpStream.videoSettings["bitrate"] = slider.value * 1024
}
if (slider == zoomSlider) {
@ -217,12 +88,11 @@ final class LiveViewController: UIViewController {
}
}
func on(pause:UIButton) {
print("pause")
@IBAction func on(pause:UIButton) {
rtmpStream.togglePause()
}
func on(publish:UIButton) {
@IBAction func on(publish:UIButton) {
if (publish.isSelected) {
UIApplication.shared.isIdleTimerDisabled = false
rtmpConnection.close()
@ -260,7 +130,7 @@ final class LiveViewController: UIViewController {
}
}
func onFPSValueChanged(_ segment:UISegmentedControl) {
@IBAction func onFPSValueChanged(_ segment:UISegmentedControl) {
switch segment.selectedSegmentIndex {
case 0:
rtmpStream.captureSettings["fps"] = 15.0
@ -273,7 +143,7 @@ final class LiveViewController: UIViewController {
}
}
func onEffectValueChanged(_ segment:UISegmentedControl) {
@IBAction func onEffectValueChanged(_ segment:UISegmentedControl) {
if let currentEffect:VisualEffect = currentEffect {
let _:Bool = rtmpStream.unregisterEffect(video: currentEffect)
}
@ -291,23 +161,7 @@ final class LiveViewController: UIViewController {
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if (Thread.isMainThread) {
currentFPSLabel.text = "\(rtmpStream.currentFPS)"
currentFPSLabel?.text = "\(rtmpStream.currentFPS)"
}
}
*/
override func viewDidLoad() {
super.viewDidLoad()
let nextButton = UIButton()
nextButton.setTitle("toLfViewController", for: UIControlState.normal)
nextButton.frame = CGRect(x: 130, y: 200, width: 180, height: 100)
nextButton.setTitleColor(UIColor.red, for: UIControlState.normal)
nextButton.addTarget(self, action: #selector(LiveViewController.toLfViewController), for: UIControlEvents.touchUpInside)
self.view.addSubview(nextButton)
}
dynamic private func toLfViewController() {
let publisherViewController = LfViewController()
self.present(publisherViewController, animated: true, completion: nil)
}
}

View File

@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="49e-Tb-3d3">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--First-->
<scene sceneID="hNz-n2-bh7">
<objects>
<viewController id="9pv-A4-QxB" customClass="LiveViewController" customModule="Example_iOS" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ia1-K6-d13"/>
<viewControllerLayoutGuide type="bottom" id="4ug-Mw-9AY"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="tsR-hK-woN">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Gme-VA-sgd" customClass="LFView" customModule="lf">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="FPS" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YMl-Xb-JZb">
<rect key="frame" x="8" y="24" width="31" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LTk-1V-jZa">
<rect key="frame" x="266" y="24" width="54" height="30"/>
<state key="normal" title="Camera"/>
<connections>
<action selector="rotateCamera:" destination="9pv-A4-QxB" eventType="touchDown" id="516-MC-1k2"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oVn-9L-n2U">
<rect key="frame" x="328" y="24" width="39" height="30"/>
<state key="normal" title="Torch"/>
<connections>
<action selector="toggleTorch:" destination="9pv-A4-QxB" eventType="touchDown" id="gY1-x2-YlF"/>
</connections>
</button>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="2Sy-na-foy">
<rect key="frame" x="166" y="62" width="201" height="29"/>
<constraints>
<constraint firstAttribute="width" constant="201" id="RrQ-qe-7IF"/>
</constraints>
<segments>
<segment title="None"/>
<segment title="Monochrome"/>
<segment title="Pronama"/>
</segments>
<connections>
<action selector="onEffectValueChanged:" destination="9pv-A4-QxB" eventType="valueChanged" id="ES6-Gg-Wri"/>
</connections>
</segmentedControl>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="fbC-rC-wNg">
<rect key="frame" x="166" y="98" width="201" height="29"/>
<segments>
<segment title="15.0"/>
<segment title="30.0"/>
<segment title="60.0"/>
</segments>
<connections>
<action selector="onFPSValueChanged:" destination="9pv-A4-QxB" eventType="valueChanged" id="Kbk-b2-4D9"/>
</connections>
</segmentedControl>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kaV-Nf-KmS">
<rect key="frame" x="337" y="568" width="30" height="30"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<state key="normal" title="●"/>
<connections>
<action selector="onPublish:" destination="9pv-A4-QxB" eventType="touchDown" id="c2R-AY-2Rc"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ioi-3B-kK8">
<rect key="frame" x="337" y="530" width="30" height="30"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<state key="normal" title="P"/>
<connections>
<action selector="onPause:" destination="9pv-A4-QxB" eventType="touchDown" id="0LP-Df-9W3"/>
</connections>
</button>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="32" minValue="15" maxValue="120" translatesAutoresizingMaskIntoConstraints="NO" id="aKS-oc-LrT">
<rect key="frame" x="6" y="581" width="325" height="31"/>
<connections>
<action selector="onSlider:" destination="9pv-A4-QxB" eventType="valueChanged" id="ICf-sz-Jsg"/>
<action selector="onSlider:" destination="9pv-A4-QxB" eventType="editingChanged" id="no0-Fi-g9d"/>
</connections>
</slider>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="160" minValue="32" maxValue="1024" translatesAutoresizingMaskIntoConstraints="NO" id="4s5-OW-qAO">
<rect key="frame" x="6" y="543" width="325" height="31"/>
<connections>
<action selector="onSlider:" destination="9pv-A4-QxB" eventType="valueChanged" id="Nm5-Xr-jcw"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="audio 32/kbps" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gR3-9k-qhK">
<rect key="frame" x="182" y="568" width="147" height="21"/>
<constraints>
<constraint firstAttribute="width" constant="147" id="8BA-lG-1iM"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="video 160/kbps" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dLf-ee-K3I">
<rect key="frame" x="182" y="530" width="147" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="1" maxValue="5" translatesAutoresizingMaskIntoConstraints="NO" id="Qnn-SP-eWm">
<rect key="frame" x="6" y="498" width="184" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="180" id="j7E-LA-DzC"/>
</constraints>
<connections>
<action selector="onSlider:" destination="9pv-A4-QxB" eventType="valueChanged" id="IS3-vj-jFX"/>
</connections>
</slider>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="aKS-oc-LrT" firstAttribute="top" secondItem="4s5-OW-qAO" secondAttribute="bottom" constant="8" symbolic="YES" id="2m5-eb-CoG"/>
<constraint firstItem="gR3-9k-qhK" firstAttribute="top" secondItem="kaV-Nf-KmS" secondAttribute="top" id="3N7-Qc-9t6"/>
<constraint firstItem="gR3-9k-qhK" firstAttribute="top" secondItem="dLf-ee-K3I" secondAttribute="bottom" constant="17" id="68w-uX-tfn"/>
<constraint firstItem="oVn-9L-n2U" firstAttribute="leading" secondItem="LTk-1V-jZa" secondAttribute="trailing" constant="8" symbolic="YES" id="6Vg-1x-anx"/>
<constraint firstItem="oVn-9L-n2U" firstAttribute="trailing" secondItem="Gme-VA-sgd" secondAttribute="trailingMargin" id="6rr-bb-7YM"/>
<constraint firstItem="Qnn-SP-eWm" firstAttribute="leading" secondItem="4s5-OW-qAO" secondAttribute="leading" id="7pQ-g5-nsB"/>
<constraint firstItem="aKS-oc-LrT" firstAttribute="trailing" secondItem="dLf-ee-K3I" secondAttribute="trailing" id="95T-z2-og9"/>
<constraint firstItem="LTk-1V-jZa" firstAttribute="baseline" secondItem="oVn-9L-n2U" secondAttribute="baseline" id="9rQ-Pd-sIs"/>
<constraint firstItem="kaV-Nf-KmS" firstAttribute="leading" secondItem="aKS-oc-LrT" secondAttribute="trailing" constant="8" id="9xN-e6-8l1"/>
<constraint firstAttribute="trailing" secondItem="kaV-Nf-KmS" secondAttribute="trailing" constant="8" id="Aic-J2-vWn"/>
<constraint firstItem="YMl-Xb-JZb" firstAttribute="top" secondItem="LTk-1V-jZa" secondAttribute="top" id="CB3-nR-J9w"/>
<constraint firstItem="aKS-oc-LrT" firstAttribute="leading" secondItem="YMl-Xb-JZb" secondAttribute="leading" id="DB8-CU-CVt"/>
<constraint firstAttribute="trailing" secondItem="ioi-3B-kK8" secondAttribute="trailing" constant="8" id="EG2-1j-EOW"/>
<constraint firstItem="fbC-rC-wNg" firstAttribute="top" secondItem="2Sy-na-foy" secondAttribute="bottom" constant="8" symbolic="YES" id="FYR-nO-ITz"/>
<constraint firstItem="YMl-Xb-JZb" firstAttribute="top" secondItem="Gme-VA-sgd" secondAttribute="top" constant="24" id="Fln-Xa-IfS"/>
<constraint firstAttribute="bottom" secondItem="kaV-Nf-KmS" secondAttribute="bottom" constant="69" id="Htu-b5-tkc"/>
<constraint firstItem="2Sy-na-foy" firstAttribute="top" secondItem="LTk-1V-jZa" secondAttribute="bottom" constant="8" symbolic="YES" id="IHI-kR-YLk"/>
<constraint firstItem="aKS-oc-LrT" firstAttribute="leading" secondItem="4s5-OW-qAO" secondAttribute="leading" id="Jn2-73-2k2"/>
<constraint firstItem="aKS-oc-LrT" firstAttribute="trailing" secondItem="gR3-9k-qhK" secondAttribute="trailing" id="NoE-xi-abm"/>
<constraint firstItem="oVn-9L-n2U" firstAttribute="trailing" secondItem="2Sy-na-foy" secondAttribute="trailing" id="QWk-gv-Pl5"/>
<constraint firstItem="2Sy-na-foy" firstAttribute="leading" secondItem="fbC-rC-wNg" secondAttribute="leading" id="XWv-od-GU0"/>
<constraint firstItem="gR3-9k-qhK" firstAttribute="leading" secondItem="dLf-ee-K3I" secondAttribute="leading" id="fUu-mz-saR"/>
<constraint firstItem="dLf-ee-K3I" firstAttribute="top" secondItem="Qnn-SP-eWm" secondAttribute="bottom" constant="2" id="jei-Q0-cS1"/>
<constraint firstItem="aKS-oc-LrT" firstAttribute="trailing" secondItem="4s5-OW-qAO" secondAttribute="trailing" id="nd7-Gv-Mns"/>
<constraint firstItem="YMl-Xb-JZb" firstAttribute="leading" secondItem="Gme-VA-sgd" secondAttribute="leadingMargin" id="qng-pg-fcu"/>
<constraint firstItem="kaV-Nf-KmS" firstAttribute="top" secondItem="ioi-3B-kK8" secondAttribute="bottom" constant="8" id="r7p-mb-URS"/>
<constraint firstItem="2Sy-na-foy" firstAttribute="trailing" secondItem="fbC-rC-wNg" secondAttribute="trailing" id="s7N-3Y-aku"/>
<constraint firstAttribute="bottom" secondItem="aKS-oc-LrT" secondAttribute="bottom" constant="56" id="wE5-l2-Ga1"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Gme-VA-sgd" firstAttribute="leading" secondItem="tsR-hK-woN" secondAttribute="leading" id="8ZZ-DN-0QJ"/>
<constraint firstAttribute="bottom" secondItem="Gme-VA-sgd" secondAttribute="bottom" id="ioL-vG-JZf"/>
<constraint firstAttribute="trailing" secondItem="Gme-VA-sgd" secondAttribute="trailing" id="tLi-SX-6vy"/>
<constraint firstItem="Gme-VA-sgd" firstAttribute="top" secondItem="tsR-hK-woN" secondAttribute="top" id="y74-3d-5OK"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="First" image="first" id="acW-dT-cKf"/>
<connections>
<outlet property="audioBitrateLabel" destination="gR3-9k-qhK" id="KH8-U9-YKe"/>
<outlet property="audioBitrateSlider" destination="aKS-oc-LrT" id="b72-LB-0BW"/>
<outlet property="currentFPSLabel" destination="YMl-Xb-JZb" id="k4n-rH-YcZ"/>
<outlet property="effectSegmentControl" destination="2Sy-na-foy" id="25f-W4-fWk"/>
<outlet property="fpsControl" destination="fbC-rC-wNg" id="t4h-VS-Pmd"/>
<outlet property="lfView" destination="Gme-VA-sgd" id="lgg-bN-G69"/>
<outlet property="pauseButton" destination="ioi-3B-kK8" id="Afy-2V-jam"/>
<outlet property="publishButton" destination="kaV-Nf-KmS" id="6yv-vb-8Vp"/>
<outlet property="videoBitrateLabel" destination="dLf-ee-K3I" id="hto-Gs-HwU"/>
<outlet property="videoBitrateSlider" destination="4s5-OW-qAO" id="IKu-cc-gGp"/>
<outlet property="zoomSlider" destination="Qnn-SP-eWm" id="FjO-E6-f1K"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="W5J-7L-Pyd" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="749.60000000000002" y="-320.68965517241384"/>
</scene>
<!--Second-->
<scene sceneID="wg7-f3-ORb">
<objects>
<viewController id="8rJ-Kc-sve" customClass="PreferenceViewController" customModule="Example_iOS" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="L7p-HK-0SC"/>
<viewControllerLayoutGuide type="bottom" id="Djb-ko-YwX"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="QS5-Rx-YEW">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<tabBarItem key="tabBarItem" title="Second" image="second" id="cPa-gy-q4n"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4Nw-L8-lE0" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="750" y="360"/>
</scene>
<!--Tab Bar Controller-->
<scene sceneID="yl2-sM-qoP">
<objects>
<tabBarController id="49e-Tb-3d3" sceneMemberID="viewController">
<nil key="simulatedBottomBarMetrics"/>
<tabBar key="tabBar" contentMode="scaleToFill" id="W28-zg-YXA">
<rect key="frame" x="0.0" y="975" width="768" height="49"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</tabBar>
<connections>
<segue destination="9pv-A4-QxB" kind="relationship" relationship="viewControllers" id="u7Y-xg-7CH"/>
<segue destination="8rJ-Kc-sve" kind="relationship" relationship="viewControllers" id="lzU-1b-eKA"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="HuB-VB-40B" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="0.0" y="0.0"/>
</scene>
</scenes>
<resources>
<image name="first" width="30" height="30"/>
<image name="second" width="30" height="30"/>
</resources>
</document>

View File

@ -1,31 +0,0 @@
import UIKit
import Foundation
import AVFoundation
final class PreferenceController: UIViewController {
let closeButton:UIButton = {
let button:UIButton = UIButton()
button.layer.cornerRadius = 22
button.setTitle("X", for: UIControlState())
button.backgroundColor = UIColor.gray
return button
}()
let scrollView:UIScrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
closeButton.addTarget(self, action: #selector(PreferenceController.closePreference), for: .touchDown)
view.addSubview(closeButton)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
closeButton.frame = CGRect(x: view.frame.width - 44 - 20 , y: 20, width: 44, height: 44)
}
func closePreference() {
dismiss(animated: true, completion: nil)
}
}

View File

@ -0,0 +1,6 @@
import UIKit
import Foundation
final class PreferenceViewController: UIViewController {
}

View File

@ -1,105 +0,0 @@
//
// LfViewController.swift
// lf
//
// Created by Shogo Endo on 2017/01/29.
// Copyright © 2017 Shogo Endo. All rights reserved.
//
import UIKit
import lf
import AVFoundation
import VideoToolbox
class LfViewController: UIViewController {
private var rtmpConnection: RTMPConnection!
private var rtmpStream: RTMPStream!
private var lfView:LFView?
override func viewDidLoad() {
super.viewDidLoad()
// let lfView = LFView(frame: view.bounds)
lfView = LFView(frame: view.bounds)
lfView?.videoGravity = AVLayerVideoGravityResizeAspectFill
// add ViewController#view
let closeButton = UIButton(frame: CGRect(x: 150, y: 200, width: 100, height: 100))
closeButton.setTitle("Close", for: UIControlState.normal)
closeButton.setTitleColor(UIColor.red, for: UIControlState.normal)
closeButton.addTarget(self, action: #selector(LfViewController.close), for: UIControlEvents.touchUpInside)
let tButton = UIButton(frame: CGRect(x: 150, y: 500, width: 100, height: 100))
tButton.setTitle("T", for: UIControlState.normal)
tButton.setTitleColor(UIColor.red, for: UIControlState.normal)
tButton.addTarget(self, action: #selector(LfViewController.toggle), for: UIControlEvents.touchUpInside)
lfView?.addSubview(tButton)
lfView?.addSubview(closeButton)
view.addSubview(lfView!)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.setCameraStream()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
rtmpStream.dispose()
}
private func setCameraStream() {
rtmpConnection = RTMPConnection()
rtmpStream = RTMPStream(connection: rtmpConnection)
rtmpStream.syncOrientation = true
let sampleRate:Double = 48_000 // or 44_100
do {
try AVAudioSession.sharedInstance().setPreferredSampleRate(sampleRate)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
try AVAudioSession.sharedInstance().setMode(AVAudioSessionModeVideoChat)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
}
rtmpStream.captureSettings = [
"fps": 30, // FPS
"sessionPreset": AVCaptureSessionPresetMedium, // input video width/height
"continuousAutofocus": false, // use camera autofocus mode
"continuousExposure": false, // use camera exposure mode
]
rtmpStream.audioSettings = [
"muted": false, // mute audio
"bitrate": 32 * 1024,
"sampleRate": sampleRate,
]
rtmpStream.videoSettings = [
"width": 360, // video output width
"height": 640, // video output height
"bitrate": 160 * 1024, // video output bitrate
//"bitrate": 512 * 1024, // video output bitrate
"profileLevel": kVTProfileLevel_H264_High_4_2, // H264 Profile require "import VideoToolbox"
"maxKeyFrameIntervalDuration": 2, // key frame / sec
]
rtmpStream.attachAudio(AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
rtmpStream.attachCamera(DeviceUtil.device(withPosition: .back))
lfView?.attachStream(rtmpStream)
}
var cameraPosition:AVCaptureDevicePosition = AVCaptureDevicePosition.back
dynamic private func toggle() {
cameraPosition = cameraPosition == .back ? .front : .back
rtmpStream.attachCamera(DeviceUtil.device(withPosition: cameraPosition))
}
dynamic private func close() {
self.dismiss(animated: true, completion: nil)
}
}

View File

@ -4,7 +4,8 @@ import AVFoundation
open class GLLFView: GLKView {
static let defaultOptions:[String: AnyObject] = [
kCIContextWorkingColorSpace: NSNull()
kCIContextWorkingColorSpace: NSNull(),
kCIContextUseSoftwareRenderer: NSNumber(value: false),
]
open static var defaultBackgroundColor:UIColor = UIColor.black
@ -42,6 +43,7 @@ open class GLLFView: GLKView {
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.context = EAGLContext(api: .openGLES2)
}
open override func awakeFromNib() {

View File

@ -67,6 +67,7 @@ open class LFView: UIView {
stream.lockQueue.async {
self.layer.session = stream.mixer.session
stream.mixer.videoIO.drawable = self
self.orientation = stream.mixer.videoIO.orientation
self.currentStream = stream
}
}

8
Preference.swift Normal file
View File

@ -0,0 +1,8 @@
import Foundation
struct Preference {
static let defaultInstance:Preference = Preference()
var uri:String? = "rtmp://test:test@192.168.11.9/live"
var streamName:String? = "live"
}

View File

@ -96,8 +96,6 @@ do {
#endif
var rtmpStream:RTMPStream = RTMPStream(connection: rtmpConnection)
// 2nd arguemnt set false
rtmpStream.attachAudio(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
rtmpStream.captureSettings = [
"fps": 30, // FPS
@ -139,6 +137,10 @@ rtmpStream.recorderSettings = [
*/
],
]
// 2nd arguemnt set false
rtmpStream.attachAudio(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
```
### Authentication
```swift

View File

@ -71,7 +71,6 @@ final public class AVMixer: NSObject {
}
audioIO.dispose()
videoIO.dispose()
print(session)
}
}
@ -94,7 +93,6 @@ extension AVMixer: Runnable {
guard !running else {
return
}
print("startRunning")
session.startRunning()
}

View File

@ -357,6 +357,7 @@ final class VideoIOComponent: IOComponent {
#endif
func dispose() {
drawable?.attachStream(nil)
input = nil
output = nil
}

View File

@ -10,6 +10,7 @@ protocol NetStreamDrawable: class {
var position:AVCaptureDevicePosition { get set }
func draw(image:CIImage)
func attachStream(_ stream:NetStream?)
func render(image: CIImage, to toCVPixelBuffer: CVPixelBuffer)
}

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 48;
objects = {
/* Begin PBXBuildFile section */
@ -58,11 +58,13 @@
2931204F1D4529F900B14211 /* RTSPRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2931204B1D4522CF00B14211 /* RTSPRequest.swift */; };
293120501D4529FB00B14211 /* RTSPResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2931204D1D4522E400B14211 /* RTSPResponse.swift */; };
293C74371D85D56D001ED43C /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 293C74361D85D56D001ED43C /* MainInterface.storyboard */; };
2940D8811E3E32950081C5AC /* LfViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2940D87F1E3E32480081C5AC /* LfViewController.swift */; };
2942424D1CF4C01300D65DCB /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2942424C1CF4C01300D65DCB /* MD5.swift */; };
2942EF841DFF4D06008E620C /* lf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2945CBBD1B4BE66000104112 /* lf.framework */; };
2942EF861DFF4D3C008E620C /* lf.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2945CBBD1B4BE66000104112 /* lf.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
294852571D852499002DE492 /* RTMPTSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294852551D84BFAD002DE492 /* RTMPTSocket.swift */; };
295074301E4620FF007F15A4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29205CBD1E461F4E009D3FFF /* Main.storyboard */; };
295074311E462105007F15A4 /* PreferenceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2950742E1E4620B7007F15A4 /* PreferenceViewController.swift */; };
295074341E462146007F15A4 /* Preference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295074321E46211D007F15A4 /* Preference.swift */; };
2955F51F1D09EBAD004CC995 /* VisualEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296897461CDB01D20074D5F0 /* VisualEffect.swift */; };
2957473E1E34F3DB00EF056E /* RTMPBroadcaster.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2957473B1E34F30300EF056E /* RTMPBroadcaster.swift */; };
295747911E37AC1000EF056E /* RTMPStreamQoSStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295747901E37AC1000EF056E /* RTMPStreamQoSStrategy.swift */; };
@ -81,7 +83,6 @@
296897661CDB028C0074D5F0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2968974D1CDB01DD0074D5F0 /* LaunchScreen.storyboard */; };
296897671CDB02940074D5F0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296897411CDB01D20074D5F0 /* AppDelegate.swift */; };
296897681CDB02940074D5F0 /* LiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296897441CDB01D20074D5F0 /* LiveViewController.swift */; };
296897691CDB02940074D5F0 /* PreferenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 296897451CDB01D20074D5F0 /* PreferenceController.swift */; };
2975EF6F1D6096FB00DABA5A /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2975EF6E1D6096FB00DABA5A /* Mutex.swift */; };
2975EF701D60B32600DABA5A /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2975EF6E1D6096FB00DABA5A /* Mutex.swift */; };
2976A47E1D48C5C700B53EF2 /* AVMixerRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2976A47D1D48C5C700B53EF2 /* AVMixerRecorder.swift */; };
@ -333,6 +334,7 @@
2915EC5F1D85BDF100621092 /* ScreencastUI.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ScreencastUI.appex; sourceTree = BUILT_PRODUCTS_DIR; };
2915EC611D85BDF100621092 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
291F4E361CF206E200F59C51 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon.png; path = Examples/iOS/Icon.png; sourceTree = "<group>"; };
29205CBD1E461F4E009D3FFF /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Examples/iOS/Main.storyboard; sourceTree = "<group>"; };
2923A1FA1D63011E0019FBCD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Examples/macOS/Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
29245AEC1D3233EB00AFFB9A /* VideoGravityUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VideoGravityUtil.swift; path = Sources/Util/VideoGravityUtil.swift; sourceTree = SOURCE_ROOT; };
2926A9EB1DE6B71D0074E3D2 /* MachUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MachUtil.swift; path = Sources/Util/MachUtil.swift; sourceTree = SOURCE_ROOT; };
@ -344,10 +346,11 @@
2931204B1D4522CF00B14211 /* RTSPRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTSPRequest.swift; path = Sources/RTSP/RTSPRequest.swift; sourceTree = SOURCE_ROOT; };
2931204D1D4522E400B14211 /* RTSPResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTSPResponse.swift; path = Sources/RTSP/RTSPResponse.swift; sourceTree = SOURCE_ROOT; };
293C74361D85D56D001ED43C /* MainInterface.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = MainInterface.storyboard; path = Examples/iOS/ScreencastUI/Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
2940D87F1E3E32480081C5AC /* LfViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LfViewController.swift; sourceTree = "<group>"; };
2942424C1CF4C01300D65DCB /* MD5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MD5.swift; path = Sources/Util/MD5.swift; sourceTree = SOURCE_ROOT; };
2945CBBD1B4BE66000104112 /* lf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = lf.framework; sourceTree = BUILT_PRODUCTS_DIR; };
294852551D84BFAD002DE492 /* RTMPTSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTMPTSocket.swift; path = Sources/RTMP/RTMPTSocket.swift; sourceTree = SOURCE_ROOT; };
2950742E1E4620B7007F15A4 /* PreferenceViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferenceViewController.swift; path = Examples/iOS/PreferenceViewController.swift; sourceTree = "<group>"; };
295074321E46211D007F15A4 /* Preference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Preference.swift; sourceTree = "<group>"; };
2957473B1E34F30300EF056E /* RTMPBroadcaster.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTMPBroadcaster.swift; path = Examples/iOS/Screencast/RTMPBroadcaster.swift; sourceTree = "<group>"; };
295747901E37AC1000EF056E /* RTMPStreamQoSStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTMPStreamQoSStrategy.swift; path = Sources/RTMP/RTMPStreamQoSStrategy.swift; sourceTree = SOURCE_ROOT; };
2962425F1D8DB86500C451A3 /* TSReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TSReader.swift; path = Sources/ISO/TSReader.swift; sourceTree = SOURCE_ROOT; };
@ -368,7 +371,6 @@
296897421CDB01D20074D5F0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Examples/iOS/Assets.xcassets; sourceTree = "<group>"; };
296897431CDB01D20074D5F0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Examples/iOS/Info.plist; sourceTree = "<group>"; };
296897441CDB01D20074D5F0 /* LiveViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LiveViewController.swift; path = Examples/iOS/LiveViewController.swift; sourceTree = "<group>"; };
296897451CDB01D20074D5F0 /* PreferenceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PreferenceController.swift; path = Examples/iOS/PreferenceController.swift; sourceTree = "<group>"; };
296897461CDB01D20074D5F0 /* VisualEffect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VisualEffect.swift; path = Examples/iOS/VisualEffect.swift; sourceTree = "<group>"; };
2968974E1CDB01DD0074D5F0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Examples/iOS/Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
2975EF6E1D6096FB00DABA5A /* Mutex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Mutex.swift; path = Sources/Util/Mutex.swift; sourceTree = SOURCE_ROOT; };
@ -767,11 +769,12 @@
296897431CDB01D20074D5F0 /* Info.plist */,
2968974D1CDB01DD0074D5F0 /* LaunchScreen.storyboard */,
296897441CDB01D20074D5F0 /* LiveViewController.swift */,
296897451CDB01D20074D5F0 /* PreferenceController.swift */,
29205CBD1E461F4E009D3FFF /* Main.storyboard */,
295074321E46211D007F15A4 /* Preference.swift */,
2950742E1E4620B7007F15A4 /* PreferenceViewController.swift */,
29A39C801D85BEFA007C27E9 /* Screencast */,
29A39C811D85BF07007C27E9 /* ScreencastUI */,
296897461CDB01D20074D5F0 /* VisualEffect.swift */,
2940D87F1E3E32480081C5AC /* LfViewController.swift */,
);
name = iOS;
sourceTree = "<group>";
@ -1150,7 +1153,7 @@
};
};
buildConfigurationList = 2945CBB71B4BE66000104112 /* Build configuration list for PBXProject "lf" */;
compatibilityVersion = "Xcode 3.2";
compatibilityVersion = "Xcode 8.0";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
@ -1229,6 +1232,7 @@
291F4E381CF206E600F59C51 /* Icon.png in Resources */,
296897651CDB028C0074D5F0 /* Assets.xcassets in Resources */,
296897661CDB028C0074D5F0 /* LaunchScreen.storyboard in Resources */,
295074301E4620FF007F15A4 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1521,11 +1525,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
295074341E462146007F15A4 /* Preference.swift in Sources */,
296897671CDB02940074D5F0 /* AppDelegate.swift in Sources */,
2940D8811E3E32950081C5AC /* LfViewController.swift in Sources */,
296897681CDB02940074D5F0 /* LiveViewController.swift in Sources */,
2955F51F1D09EBAD004CC995 /* VisualEffect.swift in Sources */,
296897691CDB02940074D5F0 /* PreferenceController.swift in Sources */,
295074311E462105007F15A4 /* PreferenceViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};