diff --git a/RootEncoder/.swiftpm/xcode/xcshareddata/xcschemes/RootEncoderTests.xcscheme b/RootEncoder/.swiftpm/xcode/xcshareddata/xcschemes/RootEncoderTests.xcscheme
new file mode 100644
index 0000000..a65441f
--- /dev/null
+++ b/RootEncoder/.swiftpm/xcode/xcshareddata/xcschemes/RootEncoderTests.xcscheme
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RootEncoder/Sources/RootEncoder/encoder/audio/AudioEncoder.swift b/RootEncoder/Sources/RootEncoder/encoder/audio/AudioEncoder.swift
index 2384eb4..8d1f7c6 100644
--- a/RootEncoder/Sources/RootEncoder/encoder/audio/AudioEncoder.swift
+++ b/RootEncoder/Sources/RootEncoder/encoder/audio/AudioEncoder.swift
@@ -17,14 +17,29 @@ public class AudioEncoder {
private var initTs: Int64 = 0
private let thread = DispatchQueue(label: "AudioEncoder")
private let syncQueue = SynchronizedQueue(label: "AudioEncodeQueue", size: 60)
- public var codec = AudioCodec.AAC
+ private var codec = AudioCodec.AAC
public init(callback: GetAacData) {
self.callback = callback
}
+ public func setCodec(codec: AudioCodec) {
+ self.codec = codec
+ }
+
public func prepareAudio(inputFormat: AVAudioFormat, sampleRate: Double, channels: UInt32, bitrate: Int) -> Bool {
- guard let outputFormat = getAACFormat(sampleRate: sampleRate, channels: channels) else {
+ if (codec == AudioCodec.G711 && (sampleRate != 8000 || channels != 1)) {
+ print("G711 only support samplerate 8000 and mono channel")
+ return false
+ }
+ let format: AVAudioFormat? = if codec == AudioCodec.AAC {
+ getAACFormat(sampleRate: sampleRate, channels: channels)
+ } else if codec == AudioCodec.G711 {
+ getG711AFormat(sampleRate: sampleRate, channels: channels)
+ } else {
+ nil
+ }
+ guard let outputFormat = format else {
return false
}
guard let converter = AVAudioConverter(from: inputFormat, to: outputFormat) else {
@@ -52,30 +67,51 @@ public class AudioEncoder {
let b = self.syncQueue.dequeue()
if let b = b {
var error: NSError? = nil
- guard let aacBuffer = self.convertToAAC(buffer: b, error: &error) else {
- continue
- }
- if error != nil {
- print("Encode error: \(error.debugDescription)")
- } else {
- let data = Array(UnsafeBufferPointer(start: aacBuffer.data.assumingMemoryBound(to: UInt8.self), count: Int(aacBuffer.byteLength)))
- guard let packetDescriptions = aacBuffer.packetDescriptions else {
+ if self.codec == AudioCodec.AAC {
+ guard let aacBuffer = self.convertToAAC(buffer: b, error: &error) else {
+ continue
+ }
+ if error != nil {
+ print("Encode error: \(error.debugDescription)")
+ } else {
+ let data = Array(UnsafeBufferPointer(start: aacBuffer.data.assumingMemoryBound(to: UInt8.self), count: Int(aacBuffer.byteLength)))
+ guard let packetDescriptions = aacBuffer.packetDescriptions else {
+ continue
+ }
+ for i in 0..(repeating: 0, count: Int(info.mDataByteSize))
+ mBuffer[0...mBuffer.count - 1] = data[Int(info.mStartOffset)...Int(info.mStartOffset) + Int(info.mDataByteSize - 1)]
+ let end = Date().millisecondsSince1970
+ let elapsedNanoSeconds = (end - self.initTs) * 1000
+
+ var frame = Frame()
+ frame.buffer = mBuffer
+ frame.length = UInt32(mBuffer.count)
+ frame.timeStamp = UInt64(elapsedNanoSeconds)
+ self.callback?.getAacData(frame: frame)
+ }
+ }
+ } else if self.codec == AudioCodec.G711 {
+ guard let g711Buffer = self.convertToG711(buffer: b, error: &error) else {
continue
}
- for i in 0..(repeating: 0, count: Int(info.mDataByteSize))
- mBuffer[0...mBuffer.count - 1] = data[Int(info.mStartOffset)...Int(info.mStartOffset) + Int(info.mDataByteSize - 1)]
+ if error != nil {
+ print("Encode error: \(error.debugDescription)")
+ } else {
+ let data = g711Buffer.audioBufferToBytes()
let end = Date().millisecondsSince1970
let elapsedNanoSeconds = (end - self.initTs) * 1000
var frame = Frame()
- frame.buffer = mBuffer
- frame.length = UInt32(mBuffer.count)
+ frame.buffer = data
+ frame.length = UInt32(data.count)
frame.timeStamp = UInt64(elapsedNanoSeconds)
self.callback?.getAacData(frame: frame)
+
}
}
+
}
}
}
@@ -97,6 +133,16 @@ public class AudioEncoder {
return outBuffer
}
+ private func convertToG711(buffer: AVAudioPCMBuffer, error: inout NSError?) -> AVAudioPCMBuffer? {
+ guard let outputFormat = outputFormat else {
+ return nil
+ }
+ let outBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))!
+ outBuffer.frameLength = outBuffer.frameCapacity
+ self.convert(sourceBuffer: buffer, destinationBuffer: outBuffer, error: &error)
+ return outBuffer
+ }
+
private func convert(sourceBuffer: AVAudioPCMBuffer, destinationBuffer: AVAudioBuffer, error: NSErrorPointer) {
if (running) {
sourceBuffer.frameLength = sourceBuffer.frameCapacity
@@ -118,7 +164,28 @@ public class AudioEncoder {
}
private func getAACFormat(sampleRate: Double, channels: UInt32) -> AVAudioFormat? {
- var description = AudioStreamBasicDescription(mSampleRate: sampleRate, mFormatID: kAudioFormatMPEG4AAC, mFormatFlags: 0, mBytesPerPacket: 0, mFramesPerPacket: 0, mBytesPerFrame: 0, mChannelsPerFrame: channels, mBitsPerChannel: 0, mReserved: 0)
+ var description = AudioStreamBasicDescription(mSampleRate: sampleRate,
+ mFormatID: kAudioFormatMPEG4AAC,
+ mFormatFlags: 0,
+ mBytesPerPacket: 0,
+ mFramesPerPacket: 0,
+ mBytesPerFrame: 0,
+ mChannelsPerFrame: channels,
+ mBitsPerChannel: 0,
+ mReserved: 0)
+ return AVAudioFormat(streamDescription: &description)
+ }
+
+ private func getG711AFormat(sampleRate: Double, channels: UInt32) -> AVAudioFormat? {
+ var description = AudioStreamBasicDescription(mSampleRate: sampleRate,
+ mFormatID: kAudioFormatALaw,
+ mFormatFlags: AudioFormatFlags(kAudioFormatALaw),
+ mBytesPerPacket: 1,
+ mFramesPerPacket: 1,
+ mBytesPerFrame: 1,
+ mChannelsPerFrame: channels,
+ mBitsPerChannel: 8,
+ mReserved: 0)
return AVAudioFormat(streamDescription: &description)
}
}
diff --git a/RootEncoder/Sources/RootEncoder/encoder/input/audio/MicrophoneManager.swift b/RootEncoder/Sources/RootEncoder/encoder/input/audio/MicrophoneManager.swift
index 4576671..8feb688 100644
--- a/RootEncoder/Sources/RootEncoder/encoder/input/audio/MicrophoneManager.swift
+++ b/RootEncoder/Sources/RootEncoder/encoder/input/audio/MicrophoneManager.swift
@@ -11,7 +11,7 @@ import AVFoundation
public class MicrophoneManager {
- private let thread = DispatchQueue.global()
+ private let thread = DispatchQueue(label: "MicrophoneManager")
private let audioEngine = AVAudioEngine()
private var inputNode: AVAudioInputNode?
private var inputFormat: AVAudioFormat?
diff --git a/RootEncoder/Sources/RootEncoder/encoder/utils/EncoderUtils.swift b/RootEncoder/Sources/RootEncoder/encoder/utils/EncoderUtils.swift
index b20d6ab..35227ce 100644
--- a/RootEncoder/Sources/RootEncoder/encoder/utils/EncoderUtils.swift
+++ b/RootEncoder/Sources/RootEncoder/encoder/utils/EncoderUtils.swift
@@ -34,6 +34,19 @@ public extension AVAudioPCMBuffer {
)
return sampleBuffer
}
+
+ func audioBufferToBytes() -> [UInt8] {
+ let srcLeft = self.audioBufferList.pointee.mBuffers.mData!
+ let bytesPerFrame = self.format.streamDescription.pointee.mBytesPerFrame
+ let numBytes = Int(bytesPerFrame * self.frameLength)
+ var audioByteArray = [UInt8](repeating: 0, count: numBytes)
+ srcLeft.withMemoryRebound(to: UInt8.self, capacity: numBytes) { srcByteData in
+ audioByteArray.withUnsafeMutableBufferPointer {
+ $0.baseAddress!.initialize(from: srcByteData, count: numBytes)
+ }
+ }
+ return audioByteArray
+ }
}
extension AVAudioTime {
diff --git a/RootEncoder/Sources/RootEncoder/encoder/video/VideoEncoder.swift b/RootEncoder/Sources/RootEncoder/encoder/video/VideoEncoder.swift
index 42a44fd..360a085 100644
--- a/RootEncoder/Sources/RootEncoder/encoder/video/VideoEncoder.swift
+++ b/RootEncoder/Sources/RootEncoder/encoder/video/VideoEncoder.swift
@@ -52,7 +52,6 @@ public class VideoEncoder {
codecType: codec.value, encoderSpecification: nil, imageBufferAttributes: nil,
compressedDataAllocator: nil, outputCallback: videoCallback, refcon: Unmanaged.passUnretained(self).toOpaque(),
compressionSessionOut: &session)
- print("using codec \(codec)")
self.resolution = resolution
self.fps = fps
self.bitrate = bitrate
@@ -100,8 +99,13 @@ public class VideoEncoder {
}
}
- public func setCodec(codec: CodecUtil) {
- self.codec = codec
+ public func setCodec(codec: VideoCodec) {
+ switch codec {
+ case .H264:
+ self.codec = CodecUtil.H264
+ case .H265:
+ self.codec = CodecUtil.H265
+ }
}
public func forceKeyFrame() {
diff --git a/RootEncoder/Sources/RootEncoder/library/base/CameraBase.swift b/RootEncoder/Sources/RootEncoder/library/base/CameraBase.swift
index 31ef1ba..8144331 100644
--- a/RootEncoder/Sources/RootEncoder/library/base/CameraBase.swift
+++ b/RootEncoder/Sources/RootEncoder/library/base/CameraBase.swift
@@ -164,21 +164,13 @@ public class CameraBase: GetMicrophoneData, GetCameraData, GetAacData, GetH264Da
public func setVideoCodec(codec: VideoCodec) {
setVideoCodecImp(codec: codec)
recordController.setVideoCodec(codec: codec)
- let type = switch codec {
- case .H264:
- CodecUtil.H264
- case .H265:
- CodecUtil.H265
- @unknown default:
- CodecUtil.H264
- }
- videoEncoder.setCodec(codec: type)
+ videoEncoder.setCodec(codec: codec)
}
public func setAudioCodec(codec: AudioCodec) {
setAudioCodecImp(codec: codec)
recordController.setAudioCodec(codec: codec)
- audioEncoder.codec = codec
+ audioEncoder.setCodec(codec: codec)
}
public func setVideoCodecImp(codec: VideoCodec) {}
diff --git a/RootEncoder/Sources/RootEncoder/library/base/DisplayBase.swift b/RootEncoder/Sources/RootEncoder/library/base/DisplayBase.swift
index a230ddf..ce6f68b 100644
--- a/RootEncoder/Sources/RootEncoder/library/base/DisplayBase.swift
+++ b/RootEncoder/Sources/RootEncoder/library/base/DisplayBase.swift
@@ -148,21 +148,13 @@ public class DisplayBase: GetMicrophoneData, GetCameraData, GetAacData, GetH264D
public func setVideoCodec(codec: VideoCodec) {
setVideoCodecImp(codec: codec)
recordController.setVideoCodec(codec: codec)
- let type = switch codec {
- case .H264:
- CodecUtil.H264
- case .H265:
- CodecUtil.H265
- @unknown default:
- CodecUtil.H264
- }
- videoEncoder.setCodec(codec: type)
+ videoEncoder.setCodec(codec: codec)
}
public func setAudioCodec(codec: AudioCodec) {
setAudioCodecImp(codec: codec)
recordController.setAudioCodec(codec: codec)
- audioEncoder.codec = codec
+ audioEncoder.setCodec(codec: codec)
}
public func setVideoCodecImp(codec: VideoCodec) {}
diff --git a/RootEncoder/Sources/RootEncoder/library/rtmp/DisplayRtmp.swift b/RootEncoder/Sources/RootEncoder/library/rtmp/DisplayRtmp.swift
index 5c368ca..568030c 100644
--- a/RootEncoder/Sources/RootEncoder/library/rtmp/DisplayRtmp.swift
+++ b/RootEncoder/Sources/RootEncoder/library/rtmp/DisplayRtmp.swift
@@ -18,11 +18,7 @@ public class DisplayRtmp: DisplayBase {
}
public func setAuth(user: String, password: String) {
- //client.setAuth(user: user, password: password)
- }
-
- public func setCodec(codec: CodecUtil) {
- videoEncoder.setCodec(codec: codec)
+ client.setAuth(user: user, password: password)
}
public func reTry(delay: Int, reason: String, backUrl: String? = nil) -> Bool {
diff --git a/RootEncoder/Sources/RootEncoder/library/rtsp/DisplayRtsp.swift b/RootEncoder/Sources/RootEncoder/library/rtsp/DisplayRtsp.swift
index 97993ba..2b782b5 100644
--- a/RootEncoder/Sources/RootEncoder/library/rtsp/DisplayRtsp.swift
+++ b/RootEncoder/Sources/RootEncoder/library/rtsp/DisplayRtsp.swift
@@ -22,10 +22,6 @@ public class DisplayRtsp: DisplayBase {
client.setAuth(user: user, password: password)
}
- public func setCodec(codec: CodecUtil) {
- videoEncoder.setCodec(codec: codec)
- }
-
public func reTry(delay: Int, reason: String, backUrl: String? = nil) -> Bool {
let result = client.shouldRetry(reason: reason)
if (result) {
diff --git a/RootEncoder/Sources/RootEncoder/library/rtsp/RtspCamera.swift b/RootEncoder/Sources/RootEncoder/library/rtsp/RtspCamera.swift
index 25832df..2302416 100644
--- a/RootEncoder/Sources/RootEncoder/library/rtsp/RtspCamera.swift
+++ b/RootEncoder/Sources/RootEncoder/library/rtsp/RtspCamera.swift
@@ -25,10 +25,6 @@ public class RtspCamera: CameraBase {
client.setAuth(user: user, password: password)
}
- public func setCodec(codec: CodecUtil) {
- videoEncoder.setCodec(codec: codec)
- }
-
public func reTry(delay: Int, reason: String, backUrl: String? = nil) -> Bool {
let result = client.shouldRetry(reason: reason)
if (result) {
diff --git a/RootEncoder/Sources/RootEncoder/library/utils/RecordController.swift b/RootEncoder/Sources/RootEncoder/library/utils/RecordController.swift
index 093271d..719e4fe 100644
--- a/RootEncoder/Sources/RootEncoder/library/utils/RecordController.swift
+++ b/RootEncoder/Sources/RootEncoder/library/utils/RecordController.swift
@@ -146,8 +146,6 @@ public class RecordController {
AVVideoCodecType.h264
case VideoCodec.H265:
AVVideoCodecType.hevc
- default:
- AVVideoCodecType.h264 //TODO throw error
}
}
@@ -157,8 +155,6 @@ public class RecordController {
kAudioFormatMPEG4AAC
case AudioCodec.G711:
kAudioFormatALaw
- default:
- kAudioFormatLinearPCM // TODO throw error
}
}
diff --git a/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpClient.swift b/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpClient.swift
index 05b52a1..e8b50db 100644
--- a/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpClient.swift
+++ b/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpClient.swift
@@ -67,7 +67,7 @@ public class RtmpClient {
}
if (!self.isStreaming || isRetry) {
self.isStreaming = true
- thread = Task {
+ thread = Task(priority: .high) {
guard let url = url else {
self.connectChecker.onConnectionFailed(reason: "Endpoint malformed, should be: rtmp://ip:port/appname/streamname")
return
@@ -292,7 +292,7 @@ public class RtmpClient {
connectChecker.onAuthError()
}
default:
- connectChecker.onConnectionFailed(reason: description)
+ connectChecker.onConnectionFailed(reason: description)
}
case "onStatus":
let code = ((command.data[3] as! AmfObject).getProperty(name: "code") as! AmfString).value
diff --git a/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpCommandManager.swift b/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpCommandManager.swift
index 3cb2817..0a08df6 100644
--- a/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpCommandManager.swift
+++ b/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpCommandManager.swift
@@ -160,8 +160,6 @@ public class RtmpCommandManager {
VideoFormat.AVC.rawValue
case .H265:
VideoFormat.HEVC.rawValue
- @unknown default:
- VideoFormat.AVC.rawValue
}
print("codec: \(codecValue)")
amfEcmaArray.setProperty(name: "width", data: Double(width))
@@ -176,8 +174,6 @@ public class RtmpCommandManager {
AudioFormat.AAC.rawValue
case .G711:
AudioFormat.G711_A.rawValue
- @unknown default:
- AudioFormat.AAC.rawValue
}
amfEcmaArray.setProperty(name: "audiocodecid", data: Double(codecValue))
amfEcmaArray.setProperty(name: "audiosamplerate", data: Double(sampleRate))
diff --git a/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpSender.swift b/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpSender.swift
index c93ee2d..a0320f3 100644
--- a/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpSender.swift
+++ b/RootEncoder/Sources/RootEncoder/rtmp/rtmp/RtmpSender.swift
@@ -40,10 +40,6 @@ public class RtmpSender {
let packet = RtmpH265Packet()
packet.setVideoInfo(sps: sps, pps: pps, vps: vps!)
videoPacket = packet
- @unknown default:
- let packet = RtmpH264Packet()
- packet.setVideoInfo(sps: sps, pps: pps)
- videoPacket = packet
}
}
@@ -56,10 +52,6 @@ public class RtmpSender {
case .G711:
let packet = RtmpG711Packet()
audioPacket = packet
- @unknown default:
- let packet = RtmpAacPacket()
- packet.sendAudioInfo(sampleRate: sampleRate, isStereo: isStereo)
- audioPacket = packet
}
}
@@ -94,7 +86,7 @@ public class RtmpSender {
public func start() {
queue.clear()
running = true
- thread = Task {
+ thread = Task(priority: .high) {
while (self.running) {
let flvPacket = self.queue.dequeue()
if let flvPacket = flvPacket {
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspAacPacket.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspAacPacket.swift
index f93ee4f..5fa890e 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspAacPacket.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspAacPacket.swift
@@ -9,19 +9,20 @@ public class RtspAacPacket: RtspBasePacket {
}
public override func createAndSendPacket(buffer: Array, ts: UInt64, callback: (RtpFrame) -> Void) {
- let length = buffer.count
+ var buffer = buffer
+ let naluLength = buffer.count
let dts = ts * 1000
let maxPayload = maxPacketSize - RtpConstants.rtpHeaderLength
var sum = 0
- while (sum < length) {
- let size = if (length - sum < maxPayload) {
- length - sum
+ while (sum < naluLength) {
+ let length = if (naluLength - sum < maxPayload) {
+ naluLength - sum
} else {
maxPayload
}
- var rtpBuffer = getBuffer(size: size + RtpConstants.rtpHeaderLength + 4)
- rtpBuffer[RtpConstants.rtpHeaderLength + 4...rtpBuffer.count - 1] = buffer[0...buffer.count - 1]
+ var rtpBuffer = getBuffer(size: length + RtpConstants.rtpHeaderLength + 4)
+ buffer = buffer.get(destiny: &rtpBuffer, index: RtpConstants.rtpHeaderLength + 4, length: length)
markPacket(buffer: &rtpBuffer)
let rtpTs = updateTimeStamp(buffer: &rtpBuffer, timeStamp: dts)
@@ -31,8 +32,8 @@ public class RtspAacPacket: RtspBasePacket {
rtpBuffer[RtpConstants.rtpHeaderLength] = 0x00
rtpBuffer[RtpConstants.rtpHeaderLength + 1] = 0x10
// AU-size
- rtpBuffer[RtpConstants.rtpHeaderLength + 2] = intToBytes(from: size >> 5)[0]
- rtpBuffer[RtpConstants.rtpHeaderLength + 3] = intToBytes(from: size << 3)[0]
+ rtpBuffer[RtpConstants.rtpHeaderLength + 2] = intToBytes(from: length >> 5)[0]
+ rtpBuffer[RtpConstants.rtpHeaderLength + 3] = intToBytes(from: length << 3)[0]
// AU-Index
rtpBuffer[RtpConstants.rtpHeaderLength + 3] &= 0xF8
rtpBuffer[RtpConstants.rtpHeaderLength + 3] |= 0x00
@@ -44,7 +45,7 @@ public class RtspAacPacket: RtspBasePacket {
frame.buffer = rtpBuffer
frame.channelIdentifier = channelIdentifier
- sum += size
+ sum += length
callback(frame)
}
}
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspG711Packet.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspG711Packet.swift
index 08e8e98..25253c9 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspG711Packet.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspG711Packet.swift
@@ -18,18 +18,19 @@ public class RtspG711Packet: RtspBasePacket {
}
public override func createAndSendPacket(buffer: Array, ts: UInt64, callback: (RtpFrame) -> Void) {
- let length = buffer.count
+ var buffer = buffer
+ let naluLength = buffer.count
let maxPayload = maxPacketSize - RtpConstants.rtpHeaderLength
var sum = 0
- while (sum < length) {
- let size = if (length - sum < maxPayload) {
- length - sum
+ while (sum < naluLength) {
+ let length = if (naluLength - sum < maxPayload) {
+ naluLength - sum
} else {
maxPayload
}
- var rtpBuffer = getBuffer(size: size + RtpConstants.rtpHeaderLength)
- rtpBuffer[RtpConstants.rtpHeaderLength...rtpBuffer.count - 1] = buffer[0...buffer.count - 1]
+ var rtpBuffer = getBuffer(size: length + RtpConstants.rtpHeaderLength)
+ buffer = buffer.get(destiny: &rtpBuffer, index: RtpConstants.rtpHeaderLength, length: length)
let dts = ts * 1000
markPacket(buffer: &rtpBuffer)
let rtpTs = updateTimeStamp(buffer: &rtpBuffer, timeStamp: dts)
@@ -41,7 +42,7 @@ public class RtspG711Packet: RtspBasePacket {
frame.buffer = rtpBuffer
frame.channelIdentifier = channelIdentifier
- sum += size
+ sum += length
callback(frame)
}
}
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH264Packet.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH264Packet.swift
index 0a3ab31..297aa96 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH264Packet.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH264Packet.swift
@@ -64,11 +64,10 @@ public class RtspH264Packet: RtspBasePacket {
var sum = 0
while sum < naluLength {
- var length = 0
- if (naluLength - sum > maxPacketSize - RtpConstants.rtpHeaderLength - 2) {
- length = maxPacketSize - RtpConstants.rtpHeaderLength - 2
+ let length = if (naluLength - sum > maxPacketSize - RtpConstants.rtpHeaderLength - 2) {
+ maxPacketSize - RtpConstants.rtpHeaderLength - 2
} else {
- length = buffer.count
+ buffer.count
}
var rtpBuffer = getBuffer(size: length + RtpConstants.rtpHeaderLength + 2)
rtpBuffer[RtpConstants.rtpHeaderLength] = header[0]
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH265Packet.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH265Packet.swift
index cbdf549..8c6df11 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH265Packet.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtp/packets/RtspH265Packet.swift
@@ -58,11 +58,10 @@ public class RtspH265Packet: RtspBasePacket {
var sum = 0
while sum < naluLength {
- var length = 0
- if (naluLength - sum > maxPacketSize - RtpConstants.rtpHeaderLength - 3) {
- length = maxPacketSize - RtpConstants.rtpHeaderLength - 3
+ let length = if (naluLength - sum > maxPacketSize - RtpConstants.rtpHeaderLength - 3) {
+ maxPacketSize - RtpConstants.rtpHeaderLength - 3
} else {
- length = buffer.count
+ buffer.count
}
var rtpBuffer = getBuffer(size: length + RtpConstants.rtpHeaderLength + 3)
rtpBuffer[RtpConstants.rtpHeaderLength] = header[0]
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspClient.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspClient.swift
index d50b7f4..d4aac63 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspClient.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspClient.swift
@@ -69,7 +69,7 @@ public class RtspClient {
}
if (!self.streaming || isRetry) {
self.streaming = true
- thread = Task {
+ thread = Task(priority: .background) {
guard let url = url else {
self.connectChecker.onConnectionFailed(reason: "Endpoint malformed, should be: rtsp://ip:port/appname/streamname")
return
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspSender.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspSender.swift
index 8cef780..a9b7d56 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspSender.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/RtspSender.swift
@@ -50,8 +50,6 @@ public class RtspSender {
RtspH264Packet(sps: sps, pps: pps)
case VideoCodec.H265:
RtspH265Packet()
- default:
- RtspH264Packet(sps: sps, pps: pps)
}
}
@@ -61,10 +59,7 @@ public class RtspSender {
RtspAacPacket(sampleRate: sampleRate)
case AudioCodec.G711:
RtspG711Packet(sampleRate: sampleRate)
- default:
- RtspAacPacket(sampleRate: sampleRate)
}
-
}
public func sendVideo(buffer: Array, ts: UInt64) {
@@ -103,7 +98,7 @@ public class RtspSender {
tcpReport?.setSSRC(ssrcVideo: ssrcVideo, ssrcAudio: ssrcAudio)
queue.clear()
running = true
- thread = Task {
+ thread = Task(priority: .background) {
let isTcp = self.tcpSocket is RtpSocketTcp
while (self.running) {
let frame = self.queue.dequeue()
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/RtspCommandManager.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/RtspCommandManager.swift
index 060847c..d514846 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/RtspCommandManager.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/RtspCommandManager.swift
@@ -41,8 +41,6 @@ public class RtspCommandManager {
return sps != nil && pps != nil
case VideoCodec.H265:
return sps != nil && pps != nil && vps != nil
- default:
- return false
}
}
@@ -51,8 +49,8 @@ public class RtspCommandManager {
}
private func addHeader() -> String {
- let session = sessionId != nil ? "Session: \(sessionId!)\r\n" : ""
- let auth = authorization != nil ? "Authorization: \(authorization!)\r\n" : ""
+ let session = sessionId?.isEmpty ?? true != true ? "Session: \(sessionId!)\r\n" : ""
+ let auth = authorization?.isEmpty ?? true != true ? "Authorization: \(authorization!)\r\n" : ""
let result = "CSeq: \(cSeq)\r\n\(session)\(auth)"
cSeq += 1
return result
@@ -78,8 +76,8 @@ public class RtspCommandManager {
public func createSetup(track: Int) -> String {
let ports = track == RtpConstants.trackVideo ? videoClientPorts : audioClientPorts
- let params = mProtocol == .TCP ? "TCP;interleaved=\(2 * track)-\(2 * track + 1)" : "UDP;unicast;client_port=\(ports[0])-\(ports[1])"
- let setup = "SETUP rtsp://\(host!):\(port!)\(path!)/trackID=\(track) RTSP/1.0\r\nTransport: RTP/AVP/\(params);mode=record\r\n\(addHeader())\r\n"
+ let params = mProtocol == .TCP ? "TCP;unicast;interleaved=\(2 * track)-\(2 * track + 1)" : "UDP;unicast;client_port=\(ports[0])-\(ports[1])"
+ let setup = "SETUP rtsp://\(host!):\(port!)\(path!)/streamid=\(track) RTSP/1.0\r\nTransport: RTP/AVP/\(params);mode=record\r\n\(addHeader())\r\n"
print(setup)
return setup
}
@@ -146,8 +144,6 @@ public class RtspCommandManager {
body.createAACBody(trackAudio: RtpConstants.trackAudio, sampleRate: sampleRate, isStereo: isStereo)
case .G711:
body.createG711Body(trackAudio: RtpConstants.trackAudio, sampleRate: sampleRate, isStereo: isStereo)
- default:
- ""
}
}
@@ -160,8 +156,6 @@ public class RtspCommandManager {
body.createH264Body(trackVideo: RtpConstants.trackVideo, sps: spsString, pps: ppsString)
case .H265:
body.createH265Body(trackVideo: RtpConstants.trackVideo, sps: spsString, pps: ppsString, vps: vpsString!)
- default:
- ""
}
}
diff --git a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/SdpBody.swift b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/SdpBody.swift
index 000f9d1..9c948eb 100644
--- a/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/SdpBody.swift
+++ b/RootEncoder/Sources/RootEncoder/rtsp/rtsp/commands/SdpBody.swift
@@ -27,24 +27,24 @@ public class SdpBody {
let config = (2 & 0x1F) << 11 | (sampleNum! & 0x0F) << 7 | (channel & 0x0F) << 3
let hexStringConfig = String(format:"%02X", config)
let payload = RtpConstants.payloadType + trackAudio
- return "m=audio 0 RTP/AVP \(payload)\r\na=rtpmap:\(payload) MPEG4-GENERIC/\(sampleRate)/\(channel)\r\na=fmtp:\(payload) streamtype=5; profile-level-id=15; mode=AAC-hbr; config=\(hexStringConfig); SizeLength=13; IndexLength=3; IndexDeltaLength=3;\r\na=control:trackID=\(trackAudio)\r\n"
+ return "m=audio 0 RTP/AVP \(payload)\r\na=rtpmap:\(payload) MPEG4-GENERIC/\(sampleRate)/\(channel)\r\na=fmtp:\(payload) streamtype=5; profile-level-id=15; mode=AAC-hbr; config=\(hexStringConfig); SizeLength=13; IndexLength=3; IndexDeltaLength=3;\r\na=control:streamid=\(trackAudio)\r\n"
}
public func createG711Body(trackAudio: Int, sampleRate: Int, isStereo: Bool) -> String {
let channel = isStereo ? 2 : 1
let payload = RtpConstants.payloadTypeG711
return "m=audio 0 RTP/AVP \(payload)\r\n" +
- "a=rtpmap:\(payload) PCMA/\(sampleRate)/\(channel)\r\n" +
+ "a=rtpmap:\(payload) PCMA/8000/1\r\n" +
"a=control:streamid=\(trackAudio)\r\n"
}
public func createH264Body(trackVideo: Int, sps: String, pps: String) -> String {
let payload = RtpConstants.payloadType + trackVideo
- return "m=video 0 RTP/AVP \(payload)\r\na=rtpmap:\(payload) H264/\(RtpConstants.clockVideoFrequency)\r\na=fmtp:\(payload) packetization-mode=1;sprop-parameter-sets=\(sps),\(pps);\r\na=control:trackID=\(trackVideo)\r\n"
+ return "m=video 0 RTP/AVP \(payload)\r\na=rtpmap:\(payload) H264/\(RtpConstants.clockVideoFrequency)\r\na=fmtp:\(payload) packetization-mode=1;sprop-parameter-sets=\(sps),\(pps);\r\na=control:streamid=\(trackVideo)\r\n"
}
public func createH265Body(trackVideo: Int, sps: String, pps: String, vps: String) -> String {
let payload = RtpConstants.payloadType + trackVideo
- return "m=video 0 RTP/AVP \(payload)\r\na=rtpmap:\(payload) H265/\(RtpConstants.clockVideoFrequency)\r\na=fmtp:\(payload) sprop-sps=\(sps); sprop-pps=\(pps); sprop-vps=\(vps);\r\na=control:trackID=\(trackVideo)\r\n"
+ return "m=video 0 RTP/AVP \(payload)\r\na=rtpmap:\(payload) H265/\(RtpConstants.clockVideoFrequency)\r\na=fmtp:\(payload) sprop-sps=\(sps); sprop-pps=\(pps); sprop-vps=\(vps);\r\na=control:streamid=\(trackVideo)\r\n"
}
}
diff --git a/app.xcodeproj/project.pbxproj b/app.xcodeproj/project.pbxproj
index c2c8479..28d1247 100644
--- a/app.xcodeproj/project.pbxproj
+++ b/app.xcodeproj/project.pbxproj
@@ -407,7 +407,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.6;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -464,7 +464,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 13.6;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
diff --git a/appTests/appTests.swift b/appTests/appTests.swift
index 2695446..5c49724 100644
--- a/appTests/appTests.swift
+++ b/appTests/appTests.swift
@@ -31,39 +31,4 @@ class appTests: XCTestCase {
// Put the code you want to measure the time of here.
}
}
-
- func testStapAH265() {
- let expectedStapA: [UInt8] = [128, 224, 0, 1, 0, 169, 138, 199, 7, 91, 205, 21, 96, 1, 0, 7, 0, 0, 0, 1, 2, 3, 4, 0, 7, 0, 0, 0, 1, 10, 11, 12]
- let fakeSps: [UInt8] = [0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]
- let fakePps: [UInt8] = [0x00, 0x00, 0x00, 0x01, 0x0A, 0x0B, 0x0C]
- let fakeVps: [UInt8] = [0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0F]
-
- let header: [UInt8] = [0x00, 0x00, 0x00, 0x01, 0x05, 0x00]
- let fakeH265 = header + [UInt8](repeating: 0x00, count: 2500)
-
- let packet1Size = RtpConstants.MTU - 28 - RtpConstants.rtpHeaderLength - 3
- let chunk1 = fakeH265[header.count..