HaishinKit.swift/Examples/macOS/LiveViewController.swift

244 lines
9.4 KiB
Swift

import lf
import Cocoa
import AVFoundation
final class LiveViewController: NSViewController {
static let defaultURL:String = "rtmpt://test:test@192.168.179.3:1935/live"
var enabledSharedObject:Bool = false
var rtmpConnection:RTMPConnection = RTMPConnection()
var rtmpStream:RTMPStream!
var sharedObject:RTMPSharedObject!
var httpService:HTTPService = HTTPService(
domain: "localhost", type: HTTPService.type, name: "", port: HTTPService.defaultPort
)
var httpStream:HTTPStream = HTTPStream()
var lfView:GLLFView = GLLFView(frame: NSZeroRect)
var urlField:NSTextField = {
let field:NSTextField = NSTextField()
field.stringValue = LiveViewController.defaultURL
return field
}()
var publishButton:NSButton = {
let button:NSButton = NSButton()
button.title = "Publish"
button.action = #selector(LiveViewController.publishOrStop(_:))
return button
}()
var fpsPopUpButton:NSPopUpButton = {
let button:NSPopUpButton = NSPopUpButton()
button.action = #selector(LiveViewController.selectFPS(_:))
button.addItem(withTitle: "30")
button.addItem(withTitle: "60")
button.addItem(withTitle: "15")
button.addItem(withTitle: "1")
return button
}()
var audioPopUpButton:NSPopUpButton = {
let button:NSPopUpButton = NSPopUpButton()
button.action = #selector(LiveViewController.selectAudio(_:))
let audios:[Any]! = AVCaptureDevice.devices(withMediaType: AVMediaTypeAudio)
for audio in audios {
if let audio:AVCaptureDevice = audio as? AVCaptureDevice {
button.addItem(withTitle: audio.localizedName)
}
}
return button
}()
var cameraPopUpButton:NSPopUpButton = {
let button:NSPopUpButton = NSPopUpButton()
button.action = #selector(LiveViewController.selectCamera(_:))
let cameras:[Any]! = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo)
for camera in cameras {
if let camera:AVCaptureDevice = camera as? AVCaptureDevice {
button.addItem(withTitle: camera.localizedName)
}
}
return button
}()
var segmentedControl:NSSegmentedControl = {
let segmented:NSSegmentedControl = NSSegmentedControl()
segmented.segmentCount = 2
segmented.action = #selector(LiveViewController.modeChanged(_:))
segmented.setLabel("RTMP", forSegment: 0)
segmented.setLabel("HTTP", forSegment: 1)
segmented.selectedSegment = 0
return segmented
}()
override func loadView() {
view = NSView()
view.wantsLayer = true
view.frame = NSMakeRect(0, 0, 640, 360)
}
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.addSubview(audioPopUpButton)
view.addSubview(publishButton)
view.addSubview(segmentedControl)
view.addSubview(urlField)
}
override func viewWillLayout() {
super.viewWillLayout()
urlField.frame = NSMakeRect(20, 20, 300, 20)
lfView.frame = NSMakeRect(0, 0, view.frame.width, view.frame.height)
segmentedControl.frame = NSMakeRect(20, view.frame.height - 40, 200, 20)
fpsPopUpButton.frame = NSMakeRect(20, view.frame.height - 70, 120, 20)
publishButton.frame = NSMakeRect(view.frame.width - 120, view.frame.height - 40, 100, 20)
cameraPopUpButton.frame = NSMakeRect(view.frame.width - 220, 50, 200, 20)
audioPopUpButton.frame = NSMakeRect(view.frame.width - 220, 20, 200, 20)
}
func publishOrStop(_ sender:NSButton) {
// Publish
if (sender.title == "Publish") {
sender.title = "Stop"
segmentedControl.isEnabled = false
switch segmentedControl.selectedSegment {
case 0:
rtmpConnection.addEventListener(Event.RTMP_STATUS, selector:#selector(LiveViewController.rtmpStatusHandler(_:)), observer: self)
rtmpConnection.connect(urlField.stringValue)
case 1:
httpStream.publish("hello")
httpService.addHTTPStream(httpStream)
httpService.startRunning()
default:
break
}
return
}
// Stop
sender.title = "Publish"
segmentedControl.isEnabled = true
switch segmentedControl.selectedSegment {
case 0:
rtmpConnection.removeEventListener(Event.RTMP_STATUS, selector:#selector(LiveViewController.rtmpStatusHandler(_:)), observer: self)
rtmpConnection.close()
case 1:
httpService.removeHTTPStream(httpStream)
httpService.stopRunning()
httpStream.publish(nil)
default:
break
}
return
}
func modeChanged(_ sender:NSSegmentedControl) {
switch sender.selectedSegment {
case 0:
httpStream.attachAudio(nil)
httpStream.attachCamera(nil)
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)
urlField.stringValue = LiveViewController.defaultURL
case 1:
rtmpStream.attachAudio(nil)
rtmpStream.attachCamera(nil)
httpStream.attachAudio(DeviceUtil.device(withLocalizedName: audioPopUpButton.itemTitles[audioPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeAudio))
httpStream.attachCamera(DeviceUtil.device(withLocalizedName: cameraPopUpButton.itemTitles[cameraPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeVideo))
lfView.attachStream(httpStream)
urlField.stringValue = "http://{ipAddress}:8080/hello/playlist.m3u8"
default:
break
}
}
func selectAudio(_ sender:AnyObject) {
let device:AVCaptureDevice? = DeviceUtil.device(withLocalizedName:
audioPopUpButton.itemTitles[audioPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeAudio
)
switch segmentedControl.selectedSegment {
case 0:
rtmpStream.attachAudio(device)
httpStream.attachAudio(nil)
case 1:
rtmpStream.attachAudio(nil)
httpStream.attachAudio(device)
default:
break
}
}
func selectCamera(_ sender:AnyObject) {
let device:AVCaptureDevice? = DeviceUtil.device(withLocalizedName:
cameraPopUpButton.itemTitles[cameraPopUpButton.indexOfSelectedItem], mediaType: AVMediaTypeVideo
)
switch segmentedControl.selectedSegment {
case 0:
rtmpStream.attachCamera(device)
httpStream.attachCamera(nil)
case 1:
rtmpStream.attachCamera(nil)
httpStream.attachCamera(device)
default:
break
}
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let keyPath:String = keyPath , Thread.isMainThread else {
return
}
switch keyPath {
case "currentFPS":
view.window!.title = "lf - lIVE fRAMEWORK(FPS:\(rtmpStream.currentFPS):totalBytesIn:\(rtmpConnection.totalBytesIn):totalBytesOut:\(rtmpConnection.totalBytesOut)"
default:
break
}
}
func selectFPS(_ sender:AnyObject) {
let value:String = fpsPopUpButton.itemTitles[fpsPopUpButton.indexOfSelectedItem]
rtmpStream.captureSettings["fps"] = value
httpStream.captureSettings["fps"] = value
}
func rtmpStatusHandler(_ notification:Notification) {
let e:Event = Event.from(notification)
if let data:ASObject = e.data as? ASObject , let code:String = data["code"] as? String {
switch code {
case RTMPConnection.Code.connectSuccess.rawValue:
rtmpStream!.publish("live")
if (enabledSharedObject) {
sharedObject = RTMPSharedObject.getRemote(withName: "test", remotePath: urlField.stringValue, persistence: false)
sharedObject.connect(rtmpConnection)
sharedObject.setProperty("Hello", "World!!")
}
default:
break
}
}
}
}
extension LiveViewController: NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
NSApp.terminate(self)
}
}