fix MP4Reader

This commit is contained in:
shogo4405 2016-12-11 11:41:08 +09:00
parent daabefc352
commit 523b92f401
15 changed files with 102 additions and 48 deletions

View File

@ -10,7 +10,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Examples lf</string>
<string>HaishinKit</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>

View File

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ObA-dk-sSI">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ObA-dk-sSI">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -18,15 +21,15 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="150"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="rtmpt://192.168.179.4:1935/live" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="GKU-M2-aRK">
<frame key="frameInset" minX="16" minY="60" width="222" height="30"/>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="rtmp://192.168.179.3:1935/live" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="GKU-M2-aRK">
<rect key="frame" x="16" y="60" width="222" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4nz-OC-sf0">
<frame key="frameInset" minX="252" minY="59" width="34" height="30"/>
<rect key="frame" x="252" y="59" width="34" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Start"/>
</button>

View File

@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Examples lf</string>
<string>HaishinKit</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>

View File

@ -3,7 +3,7 @@ import Cocoa
import AVFoundation
final class LiveViewController: NSViewController {
static let defaultURL:String = "rtmp://test:test@192.168.179.4:1935/live"
static let defaultURL:String = "rtmpt://test:test@192.168.179.3:1935/live"
var enabledSharedObject:Bool = false
var rtmpConnection:RTMPConnection = RTMPConnection()
@ -85,10 +85,8 @@ final class LiveViewController: NSViewController {
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.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

View File

View File

@ -623,7 +623,7 @@ final class MP4TrakReader {
if let stss:MP4SyncSampleBox = stss as? MP4SyncSampleBox {
var keyframes:[UInt32] = stss.entries
for i in 0..<keyframes.count {
keyframe[Int(keyframes[i])] = true
keyframe[Int(keyframes[i]) - 1] = true
}
}
@ -650,11 +650,9 @@ final class MP4TrakReader {
var index:Int = 0
let count:Int = sampleToChunk.count
for i in 0..<count {
let j:Int = Int(sampleToChunk[i].firstChunk) - 1
let m:Int = (i + 1 < count) ? Int(sampleToChunk[i + 1].firstChunk) - 1 : offsets.count
for _ in j..<m {
for j in (Int(sampleToChunk[i].firstChunk) - 1)..<m {
var offset:UInt32 = offsets[j]
for _ in 0..<sampleToChunk[i].samplesPerChunk {
self.offset.append(offset)

View File

@ -18,6 +18,9 @@ final class RTMPMuxer {
fileprivate var videoTimestamp:CMTime = kCMTimeZero
func dispose() {
avcC = nil
audioDecorderSpecificConfig = nil
timestamps.removeAll()
audioTimestamp = kCMTimeZero
videoTimestamp = kCMTimeZero
}
@ -25,7 +28,6 @@ final class RTMPMuxer {
extension RTMPMuxer: AudioEncoderDelegate {
// MARK: AudioEncoderDelegate
func didSetFormatDescription(audio formatDescription: CMFormatDescription?) {
guard let formatDescription:CMFormatDescription = formatDescription else {
return
@ -105,7 +107,6 @@ extension RTMPMuxer: MP4SamplerDelegate {
if (avcC == self.avcC) {
return
}
logger.info("\(avcC)")
var buffer:Data = Data([FLVFrameType.key.rawValue << 4 | FLVVideoCodec.avc.rawValue, FLVAVCPacketType.seq.rawValue, 0, 0, 0])
buffer.append(avcC)
delegate?.sampleOutput(video: buffer, withTimestamp: 0, muxer: self)
@ -119,7 +120,7 @@ extension RTMPMuxer: MP4SamplerDelegate {
if (audioDecorderSpecificConfig == self.audioDecorderSpecificConfig) {
return
}
var buffer:Data = Data([RTMPMuxer.aac, FLVAACPacketType.raw.rawValue])
var buffer:Data = Data([RTMPMuxer.aac, FLVAACPacketType.seq.rawValue])
buffer.append(audioDecorderSpecificConfig)
delegate?.sampleOutput(audio: buffer, withTimestamp: 0, muxer: self)
self.audioDecorderSpecificConfig = audioDecorderSpecificConfig

View File

@ -27,6 +27,8 @@ protocol RTMPSocketDelegate: IEventDispatcher {
// MARK: -
final class RTMPSocket: NetSocket, RTMPSocketCompatible {
static let defaultBufferSize:Int = 1024
enum ReadyState: UInt8 {
case uninitialized = 0
case versionSent = 1
@ -36,8 +38,6 @@ final class RTMPSocket: NetSocket, RTMPSocketCompatible {
case closed = 5
}
static let defaultBufferSize:Int = 1024
var readyState:ReadyState = .uninitialized {
didSet {
delegate?.didSet(readyState: readyState)

View File

@ -6,11 +6,8 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
var timeout:Int64 = 0
var chunkSizeC:Int = RTMPChunk.defaultSize
var chunkSizeS:Int = RTMPChunk.defaultSize
var totalBytesIn:Int64 = 0
var totalBytesOut:Int64 = 0
var inputBuffer:[UInt8] = []
var securityLevel:StreamSocketSecurityLevel = .none
var objectEncoding:UInt8 = 0x00
weak var delegate:RTMPSocketDelegate? = nil
var connected:Bool = false {
didSet {
@ -20,6 +17,7 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
readyState = .versionSent
return
}
timer = nil
readyState = .closed
for event in events {
delegate?.dispatch(event: event)
@ -27,7 +25,7 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
events.removeAll()
}
}
var timestamp:TimeInterval {
return handshake.timestamp
}
@ -38,18 +36,32 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
}
}
fileprivate(set) var totalBytesIn:Int64 = 0
fileprivate(set) var totalBytesOut:Int64 = 0
fileprivate var timer:Timer? {
didSet {
if let oldValue:Timer = oldValue {
oldValue.invalidate()
}
if let timer:Timer = timer {
RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
}
}
}
private var delay:UInt8 = 1
private var index:Int64 = 0
private var events:[Event] = []
private var baseURL:URL!
private var session:URLSession!
private var request:URLRequest!
private var c2packet:[UInt8] = []
private var isPending:Bool = false
private var handshake:RTMPHandshake = RTMPHandshake()
private let outputQueue:DispatchQueue = DispatchQueue(label: "com.github.shgoo4405.lf.RTMPTSocket.output")
private var connectionID:String!
private var connectionID:String?
private var isRequesting:Bool = false
private var outputBuffer:[UInt8] = []
private var lastResponse:Date = Date()
private var handshake:RTMPHandshake = RTMPHandshake()
override init() {
super.init()
@ -63,9 +75,10 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
"User-Agent": "Shockwave Flash",
]
let scheme:String = securityLevel == .none ? "http" : "https"
session = URLSession(configuration: config)
session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
baseURL = URL(string: "\(scheme)://\(withName):\(port)")!
doRequest("/fcs/ident2", Data([0x00]), didIdent2)
timer = Timer(timeInterval: 0.1, target: self, selector: #selector(RTMPTSocket.on(timer:)), userInfo: nil, repeats: true)
}
@discardableResult
@ -77,8 +90,7 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
}
outputQueue.sync {
self.outputBuffer.append(contentsOf: bytes)
if (!self.isPending) {
self.isPending = true
if (!self.isRequesting) {
self.doOutput(bytes: self.outputBuffer)
self.outputBuffer.removeAll()
}
@ -103,6 +115,9 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
}
private func listen(data:Data?, response:URLResponse?, error:Error?) {
lastResponse = Date()
if (logger.isEnabledFor(level: .verbose)) {
logger.verbose("\(data):\(response):\(error)")
}
@ -112,10 +127,9 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
return
}
lastResponse = Date()
outputQueue.sync {
if (self.outputBuffer.isEmpty) {
self.isPending = false
self.isRequesting = false
} else {
self.doOutput(bytes: outputBuffer)
self.outputBuffer.removeAll()
@ -130,6 +144,7 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
}
var buffer:[UInt8] = data.bytes
OSAtomicAdd64(Int64(buffer.count), &totalBytesIn)
delay = buffer.remove(at: 0)
inputBuffer.append(contentsOf: buffer)
@ -178,13 +193,13 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
return
}
connectionID = String(data: data, encoding: String.Encoding.utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
doRequest("/idel/\(connectionID!)/0", Data([0x00]), didIdel0)
doRequest("/idle/\(connectionID!)/0", Data([0x00]), didIdle0)
if (logger.isEnabledFor(level: .verbose)) {
logger.verbose("\(data.bytes):\(response)")
}
}
private func didIdel0(data:Data?, response:URLResponse?, error:Error?) {
private func didIdle0(data:Data?, response:URLResponse?, error:Error?) {
if let error:Error = error {
logger.error("\(error)")
}
@ -204,17 +219,23 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
}
}
private func idel() {
private func idle() {
guard let connectionID:String = connectionID, connected else {
return
}
let index:Int64 = OSAtomicIncrement64(&self.index)
doRequest("/idel/\(connectionID)/\(index)", Data([0x00]), didIdel)
doRequest("/idle/\(connectionID)/\(index)", Data([0x00]), didIdle)
}
private func didIdel(data:Data?, response:URLResponse?, error:Error?) {
private func didIdle(data:Data?, response:URLResponse?, error:Error?) {
listen(data: data, response: response, error: error)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: idel)
}
@objc private func on(timer:Timer) {
guard (Double(delay) / 60) < abs(lastResponse.timeIntervalSinceNow), !isRequesting else {
return
}
idle()
}
@discardableResult
@ -229,11 +250,19 @@ final class RTMPTSocket: NSObject, RTMPSocketCompatible {
}
private func doRequest(_ pathComonent: String,_ data:Data,_ completionHandler: @escaping ((Data?, URLResponse?, Error?) -> Void)) {
var request:URLRequest = URLRequest(url: baseURL.appendingPathComponent(pathComonent))
isRequesting = true
request = URLRequest(url: baseURL.appendingPathComponent(pathComonent))
request.httpMethod = "POST"
session.uploadTask(with: request, from: data, completionHandler: completionHandler).resume()
if (logger.isEnabledFor(level: .verbose)) {
logger.verbose("\(request)")
logger.verbose("\(self.request)")
}
}
}
// MARK: -
extension RTMPTSocket: URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
OSAtomicAdd64(bytesSent, &totalBytesOut)
}
}

View File

@ -4,7 +4,7 @@ import XCTest
@testable import lf
final class MP4SamplerTests: XCTestCase {
func testMain() {
func main() {
let bundle:Bundle = Bundle(for: type(of: self))
let url:URL = URL(fileURLWithPath: bundle.path(forResource: "SampleVideo_360x240_5mb", ofType: "mp4")!)
let sampler:MP4Sampler = MP4Sampler()

View File

@ -0,0 +1,17 @@
import Foundation
import XCTest
@testable import lf
final class RTMPConnectionTests: XCTestCase {
func testPublish() {
let bundle:Bundle = Bundle(for: type(of: self))
let url:URL = URL(fileURLWithPath: bundle.path(forResource: "SampleVideo_360x240_5mb-base", ofType: "mp4")!)
let connection:RTMPConnection = RTMPConnection()
let stream:RTMPStream = RTMPStream(connection: connection)
connection.connect("rtmp://localhost:1935/live")
stream.appendFile(url)
stream.publish("live")
sleep(10000)
}
}

Binary file not shown.

View File

@ -4,7 +4,7 @@ import XCTest
@testable import lf
final class TimerDriverTests: XCTestCase {
func testMain() {
func main() {
let timerDriver:TimerDriver = TimerDriver()
let delegate:TimerDriverDelegate = LoggerTimerDriverDelegate()
timerDriver.delegate = delegate

View File

@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
2901A4EE1D437170002BBD23 /* ClockedQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2901A4ED1D437170002BBD23 /* ClockedQueue.swift */; };
2901A4EF1D437662002BBD23 /* ClockedQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2901A4ED1D437170002BBD23 /* ClockedQueue.swift */; };
290686031DFDB7A7008EB7ED /* RTMPConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290686021DFDB7A6008EB7ED /* RTMPConnectionTests.swift */; };
290686051DFDC19B008EB7ED /* SampleVideo_360x240_5mb-base.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 290686041DFDC19B008EB7ED /* SampleVideo_360x240_5mb-base.mp4 */; };
290EA8901DFB616000053022 /* Foundation+ExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290EA88E1DFB616000053022 /* Foundation+ExtensionTests.swift */; };
290EA8911DFB616000053022 /* SwiftCore+ExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290EA88F1DFB616000053022 /* SwiftCore+ExtensionTests.swift */; };
290EA8931DFB617800053022 /* HTTPRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290EA8921DFB617800053022 /* HTTPRequestTests.swift */; };
@ -100,7 +102,7 @@
299B131D1D35272D00A1E8F5 /* ScreenCaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299B131C1D35272D00A1E8F5 /* ScreenCaptureSession.swift */; };
299B13271D3B751400A1E8F5 /* LFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299B13261D3B751400A1E8F5 /* LFView.swift */; };
29A39C8E1D85BF6F007C27E9 /* BroadcastViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A39C831D85BF21007C27E9 /* BroadcastViewController.swift */; };
29A39C921D85CF5F007C27E9 /* RTMPSampleHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A39C911D85CF5E007C27E9 /* RTMPSampleHandler.swift */; };
29A39C921D85CF5F007C27E9 /* RTMPMP4ClipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A39C911D85CF5E007C27E9 /* RTMPMP4ClipHandler.swift */; };
29AF3FCF1D7C744C00E41212 /* NetStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AF3FCE1D7C744C00E41212 /* NetStream.swift */; };
29AF3FD01D7C745200E41212 /* NetStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29AF3FCE1D7C744C00E41212 /* NetStream.swift */; };
29B8765B1CD70A7900FC07DA /* AACEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29B876571CD70A7900FC07DA /* AACEncoder.swift */; };
@ -301,6 +303,8 @@
/* Begin PBXFileReference section */
2901A4ED1D437170002BBD23 /* ClockedQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ClockedQueue.swift; path = Sources/Util/ClockedQueue.swift; sourceTree = SOURCE_ROOT; };
290686021DFDB7A6008EB7ED /* RTMPConnectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTMPConnectionTests.swift; path = RTMP/RTMPConnectionTests.swift; sourceTree = "<group>"; };
290686041DFDC19B008EB7ED /* SampleVideo_360x240_5mb-base.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SampleVideo_360x240_5mb-base.mp4"; sourceTree = "<group>"; };
290EA88E1DFB616000053022 /* Foundation+ExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Foundation+ExtensionTests.swift"; path = "Core/Foundation+ExtensionTests.swift"; sourceTree = "<group>"; };
290EA88F1DFB616000053022 /* SwiftCore+ExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "SwiftCore+ExtensionTests.swift"; path = "Core/SwiftCore+ExtensionTests.swift"; sourceTree = "<group>"; };
290EA8921DFB617800053022 /* HTTPRequestTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPRequestTests.swift; path = HTTP/HTTPRequestTests.swift; sourceTree = "<group>"; };
@ -378,7 +382,7 @@
29A39C831D85BF21007C27E9 /* BroadcastViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BroadcastViewController.swift; path = Examples/iOS/ScreencastUI/BroadcastViewController.swift; sourceTree = "<group>"; };
29A39C841D85BF21007C27E9 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Examples/iOS/ScreencastUI/Info.plist; sourceTree = "<group>"; };
29A39C881D85BF30007C27E9 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Examples/iOS/Screencast/Info.plist; sourceTree = "<group>"; };
29A39C911D85CF5E007C27E9 /* RTMPSampleHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTMPSampleHandler.swift; path = Platforms/iOS/RTMPSampleHandler.swift; sourceTree = "<group>"; };
29A39C911D85CF5E007C27E9 /* RTMPMP4ClipHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RTMPMP4ClipHandler.swift; path = Platforms/iOS/RTMPMP4ClipHandler.swift; sourceTree = "<group>"; };
29AF3FCE1D7C744C00E41212 /* NetStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NetStream.swift; path = Sources/Net/NetStream.swift; sourceTree = SOURCE_ROOT; };
29B8761B1CD701F900FC07DA /* lf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = lf.framework; sourceTree = BUILT_PRODUCTS_DIR; };
29B876571CD70A7900FC07DA /* AACEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AACEncoder.swift; path = Sources/Codec/AACEncoder.swift; sourceTree = SOURCE_ROOT; };
@ -572,6 +576,7 @@
290EA89C1DFB61B100053022 /* AMF0SerializerTests.swift */,
290EA89D1DFB61B100053022 /* ASClassTests.swift */,
290EA89E1DFB61B100053022 /* RTMPChunkTests.swift */,
290686021DFDB7A6008EB7ED /* RTMPConnectionTests.swift */,
);
name = RTMP;
sourceTree = "<group>";
@ -603,6 +608,7 @@
isa = PBXGroup;
children = (
29B876D71CD70CE700FC07DA /* SampleVideo_360x240_5mb */,
290686041DFDC19B008EB7ED /* SampleVideo_360x240_5mb-base.mp4 */,
29B876D81CD70CE700FC07DA /* SampleVideo_360x240_5mb.m3u8 */,
29B876D91CD70CE700FC07DA /* SampleVideo_360x240_5mb.mp4 */,
);
@ -823,7 +829,7 @@
299F7E3A1CD71A97001E7272 /* Info.plist */,
299F7E3B1CD71A97001E7272 /* lf.h */,
299B13261D3B751400A1E8F5 /* LFView.swift */,
29A39C911D85CF5E007C27E9 /* RTMPSampleHandler.swift */,
29A39C911D85CF5E007C27E9 /* RTMPMP4ClipHandler.swift */,
299B131C1D35272D00A1E8F5 /* ScreenCaptureSession.swift */,
);
name = iOS;
@ -1179,6 +1185,7 @@
files = (
29798E751CE614FE00F5CBD0 /* SampleVideo_360x240_5mb in Resources */,
29798E761CE614FE00F5CBD0 /* SampleVideo_360x240_5mb.m3u8 in Resources */,
290686051DFDC19B008EB7ED /* SampleVideo_360x240_5mb-base.mp4 in Resources */,
29798E771CE614FE00F5CBD0 /* SampleVideo_360x240_5mb.mp4 in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1329,7 +1336,7 @@
29B876841CD70AE800FC07DA /* H264+AVC.swift in Sources */,
296242621D8DB86500C451A3 /* TSWriter.swift in Sources */,
29B8769B1CD70B1100FC07DA /* MIME.swift in Sources */,
29A39C921D85CF5F007C27E9 /* RTMPSampleHandler.swift in Sources */,
29A39C921D85CF5F007C27E9 /* RTMPMP4ClipHandler.swift in Sources */,
29B8769C1CD70B1100FC07DA /* NetClient.swift in Sources */,
29B876871CD70AE800FC07DA /* ProgramSpecific.swift in Sources */,
298BCF331DD4C44A007FF86A /* AnyUtil.swift in Sources */,
@ -1395,6 +1402,7 @@
290EA8A11DFB61B100053022 /* RTMPChunkTests.swift in Sources */,
290EA89F1DFB61B100053022 /* AMF0SerializerTests.swift in Sources */,
290EA8AA1DFB61E700053022 /* CRC32Tests.swift in Sources */,
290686031DFDB7A7008EB7ED /* RTMPConnectionTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};