-
Notifications
You must be signed in to change notification settings - Fork 29
/
SubscribeAudioDelayTest.swift
106 lines (90 loc) · 4.59 KB
/
SubscribeAudioDelayTest.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//
// SubscribeAudioManipTest.swift
// R5ProTestbed
//
// Created by David Heimann on 4/30/18.
// Copyright © 2015 Infrared5, Inc. All rights reserved.
//
// The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code")
// is licensed to you by Infrared5 Inc. in consideration of your agreement to the following
// license terms and conditions. Access, use, modification, or redistribution of the accompanying
// code constitutes your acceptance of the following license terms and conditions.
//
// Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation
// files (collectively, the "Software") without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end
// user license agreement (the "EULA"), which must be executed with Infrared5, Inc.
// An example of the EULA can be found on our website at: https://account.red5pro.com/assets/LICENSE.txt.
//
// The above copyright notice and this license shall be included in all copies or portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
import UIKit
import R5Streaming
@objc(SubscribeAudioDelayTest)
class SubscribeAudioDelayTest: SubscribeTest {
var sampleBuffer: [SampleHolder]? = []
var sampleDelay = 1000.0
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
subscribeStream!.setPlaybackAudioHandler({ (sampleData, samples, timeMillis) in
if(sampleData == nil || self.sampleBuffer == nil){
return // we can't manipulate data if we haven't been pointed to any
}
let newSample = SampleHolder.init()
newSample.sampleData = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(samples))
newSample.samples = samples
newSample.timeStamp = timeMillis
newSample.sampleData!.initialize(from: sampleData!, count: Int(samples))
self.sampleBuffer!.append(newSample)
if(self.sampleBuffer![0].timeStamp <= timeMillis - self.sampleDelay){
// each call will likely have the a different number of samples
// so we run checks to prevent overflow and discarded information
var samplesPassed: Int32 = 0
while(samplesPassed < samples){
let pastSample = self.sampleBuffer![0]
let passing = min(pastSample.samples - pastSample.offset, samples - samplesPassed)
sampleData!.advanced(by: Int(samplesPassed)).initialize(
from: pastSample.sampleData!.advanced(by: Int(pastSample.offset)),
count: Int(passing)
)
samplesPassed += passing
if(pastSample.offset + passing < pastSample.samples){
pastSample.offset += passing
}
else{
self.sampleBuffer!.removeFirst()
pastSample.sampleData!.deallocate(capacity: Int(pastSample.samples))
}
}
}
else{
sampleData!.initialize(to: 0, count: Int(samples))
}
})
}
override func closeTest() {
super.closeTest()
//We're handling raw memory, release everything
for s in sampleBuffer! {
s.sampleData?.deallocate(capacity: Int(s.samples))
}
//nullify the array to end processing, just in case
sampleBuffer = nil
}
}
@objc(SampleHolder)
class SampleHolder: NSObject {
var sampleData: UnsafeMutablePointer<UInt8>? = nil
var samples: Int32 = 0
var offset: Int32 = 0
var timeStamp: Double = 0.0
}