refs #177, #175, #131 Update Examples

This commit is contained in:
shogo4405 2017-02-11 17:45:32 +09:00
parent eb82538d7b
commit ecd7e4a2af
14 changed files with 90 additions and 42 deletions

View File

@ -23,14 +23,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
fileLevel: nil
)
do {
try AVAudioSession.sharedInstance().setPreferredSampleRate(44_100)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
try AVAudioSession.sharedInstance().setMode(AVAudioSessionModeDefault)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
}
return true

View File

@ -42,8 +42,6 @@ final class LiveViewController: UIViewController {
rtmpStream.audioSettings = [
"sampleRate": sampleRate
]
rtmpStream.addObserver(self, forKeyPath: "currentFPS", options: NSKeyValueObservingOptions.new, context: nil)
videoBitrateSlider?.value = Float(RTMPStream.defaultVideoBitrate) / 1024
audioBitrateSlider?.value = Float(RTMPStream.defaultAudioBitrate) / 1024
@ -54,12 +52,15 @@ final class LiveViewController: UIViewController {
super.viewWillAppear(animated)
rtmpStream.attachAudio(AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
rtmpStream.attachCamera(DeviceUtil.device(withPosition: currentPosition))
rtmpStream.addObserver(self, forKeyPath: "currentFPS", options: NSKeyValueObservingOptions.new, context: nil)
lfView?.attachStream(rtmpStream)
}
override func viewWillDisappear(_ animated: Bool) {
logger.info("viewWillDisappear")
super.viewWillDisappear(animated)
rtmpStream.removeObserver(self, forKeyPath: "currentFPS")
rtmpStream.close()
rtmpStream.dispose()
}
@ -92,6 +93,10 @@ final class LiveViewController: UIViewController {
rtmpStream.togglePause()
}
@IBAction func on(close:UIButton) {
self.dismiss(animated: true, completion: nil)
}
@IBAction func on(publish:UIButton) {
if (publish.isSelected) {
UIApplication.shared.isIdleTimerDisabled = false

View File

@ -13,7 +13,7 @@
<!--First-->
<scene sceneID="hNz-n2-bh7">
<objects>
<viewController id="9pv-A4-QxB" customClass="LiveViewController" customModule="Example_iOS" customModuleProvider="target" sceneMemberID="viewController">
<viewController storyboardIdentifier="PopUpLive" 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"/>
@ -32,14 +32,14 @@
<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"/>
<rect key="frame" x="209" 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"/>
<rect key="frame" x="286" 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"/>
@ -125,14 +125,21 @@
<action selector="onSlider:" destination="9pv-A4-QxB" eventType="valueChanged" id="IS3-vj-jFX"/>
</connections>
</slider>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yIo-MW-aK8">
<rect key="frame" x="337" y="24" width="30" height="30"/>
<state key="normal" title="❌"/>
<connections>
<action selector="onClose:" destination="9pv-A4-QxB" eventType="touchDown" id="d0Y-4e-dGf"/>
</connections>
</button>
</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="oVn-9L-n2U" firstAttribute="leading" secondItem="LTk-1V-jZa" secondAttribute="trailing" constant="23" id="6Vg-1x-anx"/>
<constraint firstItem="oVn-9L-n2U" firstAttribute="trailing" secondItem="Gme-VA-sgd" secondAttribute="trailingMargin" constant="-42" 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"/>
@ -147,8 +154,10 @@
<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="oVn-9L-n2U" firstAttribute="trailing" secondItem="2Sy-na-foy" secondAttribute="trailing" constant="-42" id="QWk-gv-Pl5"/>
<constraint firstAttribute="trailing" secondItem="yIo-MW-aK8" secondAttribute="trailing" constant="8" id="Uqv-T7-tDV"/>
<constraint firstItem="2Sy-na-foy" firstAttribute="leading" secondItem="fbC-rC-wNg" secondAttribute="leading" id="XWv-od-GU0"/>
<constraint firstItem="yIo-MW-aK8" firstAttribute="top" secondItem="Gme-VA-sgd" secondAttribute="top" constant="24" id="ZEM-uL-Va0"/>
<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"/>
@ -216,15 +225,27 @@
<outlet property="delegate" destination="8rJ-Kc-sve" id="LBu-SL-u7B"/>
</connections>
</textField>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q77-wA-cY7">
<rect key="frame" x="8" y="580" width="359" height="30"/>
<color key="backgroundColor" red="0.012865800950000001" green="0.0" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<state key="normal" title="Open Window"/>
<connections>
<action selector="onOpen:" destination="8rJ-Kc-sve" eventType="touchDown" id="MhK-qi-afU"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Q77-wA-cY7" firstAttribute="trailing" secondItem="QS5-Rx-YEW" secondAttribute="trailingMargin" constant="8" id="1a0-JV-nZh"/>
<constraint firstItem="A5Y-FA-epc" firstAttribute="leading" secondItem="Hiy-yh-Bwn" secondAttribute="leading" id="CJJ-BH-Gde"/>
<constraint firstItem="Hiy-yh-Bwn" firstAttribute="top" secondItem="L7p-HK-0SC" secondAttribute="bottom" constant="8" id="CVs-CB-ZGl"/>
<constraint firstItem="A5Y-FA-epc" firstAttribute="top" secondItem="Hiy-yh-Bwn" secondAttribute="bottom" constant="8" symbolic="YES" id="Nvl-et-opI"/>
<constraint firstItem="Djb-ko-YwX" firstAttribute="top" secondItem="Q77-wA-cY7" secondAttribute="bottom" constant="8" symbolic="YES" id="PUC-5i-7iv"/>
<constraint firstItem="Hiy-yh-Bwn" firstAttribute="leading" secondItem="QS5-Rx-YEW" secondAttribute="leading" constant="8" id="UR1-Hr-4D4"/>
<constraint firstAttribute="trailing" secondItem="A5Y-FA-epc" secondAttribute="trailing" constant="160" id="buc-rb-JnR"/>
<constraint firstItem="Hiy-yh-Bwn" firstAttribute="trailing" secondItem="QS5-Rx-YEW" secondAttribute="trailingMargin" constant="8" id="kGk-2F-Qtn"/>
<constraint firstItem="Q77-wA-cY7" firstAttribute="leading" secondItem="QS5-Rx-YEW" secondAttribute="leading" constant="8" id="uKo-hV-Ipd"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Second" image="second" id="cPa-gy-q4n"/>

View File

@ -10,6 +10,12 @@ final class PreferenceViewController: UIViewController {
urlField?.text = Preference.defaultInstance.uri
streamNameField?.text = Preference.defaultInstance.streamName
}
@IBAction func on(open:UIButton) {
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let controller:UIViewController = storyboard.instantiateViewController(withIdentifier: "PopUpLive")
present(controller, animated: true, completion: nil)
}
}
extension PreferenceViewController: UITextFieldDelegate {

View File

@ -80,18 +80,25 @@ final class LiveViewController: NSViewController {
view.frame = NSMakeRect(0, 0, 640, 360)
}
override func viewWillAppear() {
super.viewWillAppear()
rtmpStream.attachAudio(DeviceUtil.device(withLocalizedName: audioPopUpButton.itemTitles[audioPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeAudio))
rtmpStream.attachCamera(DeviceUtil.device(withLocalizedName: cameraPopUpButton.itemTitles[cameraPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeVideo))
lfView.attachStream(rtmpStream)
}
override func viewWillDisappear() {
super.viewWillDisappear()
rtmpStream.dispose()
}
override func viewDidLoad() {
super.viewDidLoad()
audioPopUpButton.target = self
cameraPopUpButton.target = self
rtmpStream = RTMPStream(connection: rtmpConnection)
rtmpStream.attachAudio(DeviceUtil.device(withLocalizedName: audioPopUpButton.itemTitles[audioPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeAudio))
rtmpStream.attachCamera(DeviceUtil.device(withLocalizedName: cameraPopUpButton.itemTitles[cameraPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeVideo))
rtmpStream.addObserver(self, forKeyPath: "currentFPS", options: .new, context: nil)
publishButton.target = self
lfView.attachStream(rtmpStream)
view.addSubview(lfView)
view.addSubview(fpsPopUpButton)
view.addSubview(cameraPopUpButton)

View File

@ -11,8 +11,8 @@ open class GLLFView: GLKView {
open var videoGravity:String = AVLayerVideoGravityResizeAspect
var position:AVCaptureDevicePosition = .back
var orientation:AVCaptureVideoOrientation = .portrait
var position:AVCaptureDevicePosition = .front
fileprivate var ciContext:CIContext!
fileprivate var displayImage:CIImage?
@ -60,7 +60,9 @@ open class GLLFView: GLKView {
open func attachStream(_ stream:NetStream?) {
if let stream:NetStream = stream {
stream.lockQueue.async {
self.position = stream.mixer.videoIO.position
stream.mixer.videoIO.drawable = self
stream.mixer.startRunning()
}
}
currentStream = stream

View File

@ -65,10 +65,13 @@ open class LFView: UIView {
return
}
stream.lockQueue.async {
stream.mixer.session.beginConfiguration()
self.layer.session = stream.mixer.session
stream.mixer.videoIO.drawable = self
self.orientation = stream.mixer.videoIO.orientation
self.currentStream = stream
stream.mixer.session.commitConfiguration()
stream.mixer.startRunning()
}
}
}

View File

@ -95,7 +95,10 @@ open class GLLFView: NSOpenGLView {
currentStream.mixer.videoIO.drawable = nil
}
if let stream:NetStream = stream {
stream.mixer.videoIO.drawable = self
stream.lockQueue.async {
stream.mixer.videoIO.drawable = self
stream.mixer.startRunning()
}
}
currentStream = stream
}

View File

@ -45,9 +45,16 @@ open class LFView: NSView {
}
open func attachStream(_ stream:NetStream?) {
layer?.setValue(stream?.mixer.session, forKey: "session")
stream?.mixer.videoIO.drawable = self
currentStream = stream
guard let stream:NetStream = stream else {
layer?.setValue(nil, forKey: "session")
return
}
stream.lockQueue.async {
self.layer?.setValue(stream.mixer.session, forKey: "session")
stream.mixer.videoIO.drawable = self
stream.mixer.startRunning()
}
}
}

View File

@ -93,7 +93,9 @@ extension AVMixer: Runnable {
guard !running else {
return
}
session.startRunning()
DispatchQueue.global(qos: .userInteractive).async {
self.session.startRunning()
}
}
final func stopRunning() {

View File

@ -42,6 +42,8 @@ final class VideoIOComponent: IOComponent {
}
}
var position:AVCaptureDevicePosition = .back
var videoSettings:[NSObject:AnyObject] = AVMixer.defaultVideoSettings {
didSet {
output.videoSettings = videoSettings
@ -53,7 +55,7 @@ final class VideoIOComponent: IOComponent {
guard orientation != oldValue else {
return
}
drawable?.orientation = orientation
for connection in output.connections {
if let connection:AVCaptureConnection = connection as? AVCaptureConnection {
if (connection.isVideoOrientationSupported) {
@ -61,6 +63,7 @@ final class VideoIOComponent: IOComponent {
}
}
}
drawable?.orientation = orientation
}
}
@ -223,11 +226,6 @@ final class VideoIOComponent: IOComponent {
super.init(mixer: mixer)
encoder.lockQueue = lockQueue
decoder.delegate = self
#if os(iOS)
if let orientation:AVCaptureVideoOrientation = DeviceUtil.videoOrientation(by: UIDevice.current.orientation) {
self.orientation = orientation
}
#endif
}
func attachCamera(_ camera:AVCaptureDevice?) {
@ -258,6 +256,7 @@ final class VideoIOComponent: IOComponent {
}
fps = fps * 1
position = camera.position
drawable?.position = camera.position
do {

View File

@ -41,18 +41,11 @@ open class NetStream: NSObject {
#if os(iOS)
open var orientation:AVCaptureVideoOrientation {
get {
var orientation:AVCaptureVideoOrientation!
DispatchQueue.main.sync {
orientation = self.mixer.videoIO.orientation
}
return orientation
return mixer.videoIO.orientation
}
set {
DispatchQueue.main.async {
self.mixer.videoIO.orientation = newValue
}
self.mixer.videoIO.orientation = newValue
}
}
open var syncOrientation:Bool = false {
didSet {
@ -131,7 +124,6 @@ open class NetStream: NSObject {
open func attachCamera(_ camera:AVCaptureDevice?) {
lockQueue.async {
self.mixer.videoIO.attachCamera(camera)
self.mixer.startRunning()
}
}
@ -192,11 +184,7 @@ open class NetStream: NSObject {
#if os(iOS)
@objc private func on(uiDeviceOrientationDidChange:Notification) {
var deviceOrientation:UIDeviceOrientation = .unknown
if let device:UIDevice = uiDeviceOrientationDidChange.object as? UIDevice {
deviceOrientation = device.orientation
}
if let orientation:AVCaptureVideoOrientation = DeviceUtil.videoOrientation(by: deviceOrientation) {
if let orientation:AVCaptureVideoOrientation = DeviceUtil.videoOrientation(by: uiDeviceOrientationDidChange) {
self.orientation = orientation
}
}

View File

@ -456,7 +456,7 @@ open class RTMPStream: NetStream {
}
open func close() {
if (self.readyState == .closed) {
if (readyState == .closed || readyState == .initilized) {
return
}
play()

View File

@ -9,6 +9,13 @@ public final class DeviceUtil {
}
#if os(iOS)
static public func videoOrientation(by notification:Notification) -> AVCaptureVideoOrientation? {
guard let device:UIDevice = notification.object as? UIDevice else {
return nil
}
return videoOrientation(by: device.orientation)
}
static public func videoOrientation(by orientation:UIDeviceOrientation) -> AVCaptureVideoOrientation? {
switch orientation {
case .portrait: