Skip to content

Instantly share code, notes, and snippets.

@akovalov
Created December 14, 2016 08:50
Show Gist options
  • Save akovalov/af414171f93238603cc43704e75e10fc to your computer and use it in GitHub Desktop.
Save akovalov/af414171f93238603cc43704e75e10fc to your computer and use it in GitHub Desktop.
import Foundation
import UIKit
import AVFoundation
import lf
struct RTMPStreamSettings {
var uri: String!
var name: String!
var videoWidth: Int!
var videoHeight: Int!
var videoBitrate: Int!
}
class RTMPStreamController: NSObject {
// MARK: Properties
var rtmpSettings: RTMPStreamSettings! {
didSet {
if oldValue == nil {
updateRTMPStreamSettings()
}
}
}
var glLFView: GLLFView = {
return GLLFView(frame: CGRect.zero)
}()
var syncOrientation: Bool = true
fileprivate var rtmpConnection: RTMPConnection = RTMPConnection()
fileprivate var rtmpStream: RTMPStream!
fileprivate var cameraPosition: AVCaptureDevicePosition = .back
// MARK: Lifecycle
override init() {
super.init()
setupAudioSession()
createRTMPStream()
observeDeviceOrientationChanges()
}
}
// MARK: Setup
extension RTMPStreamController {
func setupAudioSession() {
let sampleRate: Double = 44_100
do {
try AVAudioSession.sharedInstance().setPreferredSampleRate(sampleRate)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
}
}
func createRTMPStream() {
rtmpStream = RTMPStream(connection: rtmpConnection)
rtmpStream.syncOrientation = true
rtmpStream.attachAudio(AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio), automaticallyConfiguresApplicationAudioSession: false)
rtmpStream.attachCamera(DeviceUtil.device(withPosition: cameraPosition))
rtmpStream.captureSettings = [
"sessionPreset": AVCaptureSessionPreset1280x720,
"continuousAutofocus": true,
"continuousExposure": true,
]
glLFView.attachStream(rtmpStream)
}
func updateRTMPStreamSettings() {
if syncOrientation {
configureRTMPSettingsForCurrentOrientation()
}
var videoSettings = rtmpStream.videoSettings
videoSettings["width"] = rtmpSettings.videoWidth
videoSettings["height"] = rtmpSettings.videoHeight
videoSettings["bitrate"] = rtmpSettings.videoBitrate
rtmpStream.videoSettings = videoSettings
}
}
// MARK: Actions
extension RTMPStreamController {
func rotateCamera() {
cameraPosition = cameraPosition == .back ? .front : .back
rtmpStream.attachCamera(DeviceUtil.device(withPosition: cameraPosition))
}
func toggleTorch() {
rtmpStream.torch = !rtmpStream.torch
}
func pause() {
rtmpStream.togglePause()
}
func close() {
rtmpConnection.close()
}
func connect() {
rtmpConnection.addEventListener(Event.RTMP_STATUS, selector:#selector(RTMPStreamController.rtmpStatusHandler(_:)), observer: self)
rtmpConnection.connect(rtmpSettings.uri)
}
func setPointOfInterest(point: CGPoint) {
rtmpStream.setPointOfInterest(point, exposure: point)
}
func toggleMicMute() {
var audioSettings = rtmpStream.audioSettings
audioSettings["muted"] = !micMuted()
rtmpStream.audioSettings = audioSettings
}
func micMuted() -> Bool {
return rtmpStream.audioSettings["muted"] as? Bool ?? false
}
}
// MARK: Event Listener
extension RTMPStreamController {
func rtmpStatusHandler(_ notification:Notification) {
let event = Event.from(notification)
if let data: ASObject = event.data as? ASObject , let code:String = data["code"] as? String {
switch code {
case RTMPConnection.Code.connectSuccess.rawValue:
rtmpStream.publish(rtmpSettings.name)
default:
break
}
}
}
}
// MARK: Rotation
extension RTMPStreamController {
func observeDeviceOrientationChanges() {
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
func deviceOrientationDidChange() {
if !syncOrientation {
return
}
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight, .portrait, .portraitUpsideDown:
updateRTMPStreamSettings()
case .unknown, .faceDown, .faceUp:
break
}
}
func configureRTMPSettingsForCurrentOrientation() {
let minVideoSize = min(rtmpSettings.videoWidth, rtmpSettings.videoHeight)
let maxVideoSize = max(rtmpSettings.videoWidth, rtmpSettings.videoHeight)
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight:
rtmpSettings.videoWidth = maxVideoSize
rtmpSettings.videoHeight = minVideoSize
case .portrait, .portraitUpsideDown:
rtmpSettings.videoWidth = minVideoSize
rtmpSettings.videoHeight = maxVideoSize
case .unknown, .faceDown, .faceUp:
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment