Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 293e021cf6 | |||
| 340ab086d2 | |||
| f025f807f4 | |||
| 90b086c7a3 | |||
| cf56d72598 | |||
| b22f61c4e2 | |||
| 7d1311311c | |||
| a508cecc32 | |||
| 7657d27854 | |||
| 7c3aae8003 | |||
| 8c2596c23e | |||
| 681b1cd107 | |||
| 13094108e3 | |||
| abd55c5511 | |||
| fc52abe7bd | |||
| fa10e28281 | |||
| c624fbe78c | |||
| 19a355e697 | |||
| 7799f0f613 | |||
| ecf3b557cf | |||
| 58d83ed0dc | |||
| b167bda396 | |||
| 336a6e2432 | |||
| 8acddcda90 | |||
| cf2fc51fea | |||
| ae5f68661e | |||
| e30467dc13 | |||
| a217868694 | |||
| 3053a16cd3 | |||
| d2d7140312 | |||
| e93549619e | |||
| 0196b1be79 | |||
| 23ab30e668 | |||
| 42bd5c1f6b | |||
| 41393ffed8 | |||
| 2b236b2a35 | |||
| e59699b7fd | |||
| e9f3c66a3b | |||
| dc1dc18824 | |||
| 014e73f44c | |||
| ee7c25727b | |||
| 79f0ba930b | |||
| c5edbfba8e | |||
| 91c689a41f | |||
| ba48a45c0a | |||
| af09e79e74 | |||
| e4327de704 | |||
| 9760129763 | |||
| dc7f8d1d10 | |||
| 8f8bedb93d | |||
| 9428dc2c7f | |||
| e6c0d148ab | |||
| 0ca5c18c19 | |||
| cb98f0e70d | |||
| 06f1e40fba | |||
| dfbc4a51ff | |||
| f045bb14e4 | |||
| ebafc22eca | |||
| 6e3e92a6b9 | |||
| 26a47ffccc | |||
| e57d3e3806 | |||
| b73bfee6ac | |||
| 09398d0cb3 | |||
| f69b586d70 | |||
| edcb2efaa0 | |||
| 3842ff80bf | |||
| d3d5f6cb24 | |||
| 37bfd377d6 |
+2
-2
@@ -1,7 +1,7 @@
|
||||
language: objective-c
|
||||
osx_image: xcode7
|
||||
xcode_workspace: LFLiveKit.xcworkspace
|
||||
xcode_project: LFLiveKit/LFLiveKit.xcodeproj
|
||||
xcode_scheme: LFLiveKit
|
||||
|
||||
script:
|
||||
- xctool -workspace LFLiveKit.xcworkspace -scheme 'LFLiveKit' -configuration Release -sdk iphonesimulator -arch i386 build
|
||||
- xctool -project LFLiveKit/LFLiveKit.xcodeproj -scheme 'LFLiveKit' -configuration Release -sdk iphonesimulator -arch i386 build
|
||||
+4
-2
@@ -2,7 +2,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "LFLiveKit"
|
||||
s.version = "1.9.6"
|
||||
s.version = "2.2.2.6"
|
||||
s.summary = "LaiFeng ios Live. LFLiveKit."
|
||||
s.homepage = "https://github.com/chenliming777"
|
||||
s.license = { :type => "MIT", :file => "LICENSE" }
|
||||
@@ -11,11 +11,13 @@ Pod::Spec.new do |s|
|
||||
s.ios.deployment_target = "7.0"
|
||||
s.source = { :git => "https://github.com/LaiFengiOS/LFLiveKit.git", :tag => "#{s.version}" }
|
||||
s.source_files = "LFLiveKit/**/*.{h,m,mm,cpp,c}"
|
||||
s.public_header_files = "LFLiveKit/**/*.h"
|
||||
#s.public_header_files = "LFLiveKit/LFLiveKit/**/*.h"
|
||||
s.public_header_files = ['LFLiveKit/LFLiveKit/*.h', 'LFLiveKit/LFLiveKit/objects/*.h', 'LFLiveKit/LFLiveKit/configuration/*.h']
|
||||
|
||||
s.frameworks = "VideoToolbox", "AudioToolbox","AVFoundation","Foundation","UIKit"
|
||||
s.libraries = "c++", "z"
|
||||
|
||||
s.requires_arc = true
|
||||
s.ios.vendored_frameworks = 'Vendor/GPUImage.framework','Vendor/pili_rtmp.framework'
|
||||
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:LFLiveKit.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
@@ -1,155 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0730"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "48F687CDE9990BD471D7883061F7E5D4"
|
||||
BuildableName = "libCocoaAsyncSocket.a"
|
||||
BlueprintName = "CocoaAsyncSocket"
|
||||
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "6610362E50A6DE8BACCA1F2885CD9157"
|
||||
BuildableName = "libGPUImage.a"
|
||||
BlueprintName = "GPUImage"
|
||||
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "7C2BDDF89D4243C7BCA44592D146DEED"
|
||||
BuildableName = "libPods-LFLiveKit.a"
|
||||
BlueprintName = "Pods-LFLiveKit"
|
||||
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "84001F891D0015D10026C63F"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "84001F931D0015D10026C63F"
|
||||
BuildableName = "LFLiveKitTests.xctest"
|
||||
BlueprintName = "LFLiveKitTests"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "84001F931D0015D10026C63F"
|
||||
BuildableName = "LFLiveKitTests.xctest"
|
||||
BlueprintName = "LFLiveKitTests"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "84001F891D0015D10026C63F"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "84001F891D0015D10026C63F"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "84001F891D0015D10026C63F"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>LFLiveKit.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>84001F891D0015D10026C63F</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>84001F931D0015D10026C63F</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>84001F891D0015D10026C63F</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>84001F931D0015D10026C63F</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.9.6</string>
|
||||
<string>2.2.2.6</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// LFLiveKit.h
|
||||
// LFLiveKit
|
||||
//
|
||||
// Created by admin on 16/5/24.
|
||||
// Copyright © 2016年 admin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LFLiveSession.h"
|
||||
#import "LFLiveAudioConfiguration.h"
|
||||
#import "LFLiveVideoConfiguration.h"
|
||||
#import "LFAudioFrame.h"
|
||||
#import "LFFrame.h"
|
||||
#import "LFLiveStreamInfo.h"
|
||||
#import "LFVideoFrame.h"
|
||||
@@ -0,0 +1,565 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
84D8B3D21D75753300752B56 /* LFAudioCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B39C1D75753300752B56 /* LFAudioCapture.h */; };
|
||||
84D8B3D31D75753300752B56 /* LFAudioCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B39D1D75753300752B56 /* LFAudioCapture.m */; };
|
||||
84D8B3D41D75753300752B56 /* LFVideoCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B39E1D75753300752B56 /* LFVideoCapture.h */; };
|
||||
84D8B3D51D75753300752B56 /* LFVideoCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B39F1D75753300752B56 /* LFVideoCapture.m */; };
|
||||
84D8B3D61D75753300752B56 /* LFAVEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3A21D75753300752B56 /* LFAVEncoder.h */; };
|
||||
84D8B3D71D75753300752B56 /* LFAVEncoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3A31D75753300752B56 /* LFAVEncoder.mm */; };
|
||||
84D8B3D81D75753300752B56 /* LFMP4Atom.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3A41D75753300752B56 /* LFMP4Atom.h */; };
|
||||
84D8B3D91D75753300752B56 /* LFMP4Atom.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3A51D75753300752B56 /* LFMP4Atom.m */; };
|
||||
84D8B3DA1D75753300752B56 /* LFNALUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3A61D75753300752B56 /* LFNALUnit.cpp */; };
|
||||
84D8B3DB1D75753300752B56 /* LFNALUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3A71D75753300752B56 /* LFNALUnit.h */; };
|
||||
84D8B3DC1D75753300752B56 /* LFVideoEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3A81D75753300752B56 /* LFVideoEncoder.h */; };
|
||||
84D8B3DD1D75753300752B56 /* LFVideoEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3A91D75753300752B56 /* LFVideoEncoder.m */; };
|
||||
84D8B3DE1D75753300752B56 /* LFAudioEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3AA1D75753300752B56 /* LFAudioEncoding.h */; };
|
||||
84D8B3DF1D75753300752B56 /* LFH264VideoEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3AB1D75753300752B56 /* LFH264VideoEncoder.h */; };
|
||||
84D8B3E01D75753300752B56 /* LFH264VideoEncoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3AC1D75753300752B56 /* LFH264VideoEncoder.mm */; };
|
||||
84D8B3E11D75753300752B56 /* LFHardwareAudioEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3AD1D75753300752B56 /* LFHardwareAudioEncoder.h */; };
|
||||
84D8B3E21D75753300752B56 /* LFHardwareAudioEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3AE1D75753300752B56 /* LFHardwareAudioEncoder.m */; };
|
||||
84D8B3E31D75753300752B56 /* LFHardwareVideoEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3AF1D75753300752B56 /* LFHardwareVideoEncoder.h */; };
|
||||
84D8B3E41D75753300752B56 /* LFHardwareVideoEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3B01D75753300752B56 /* LFHardwareVideoEncoder.m */; };
|
||||
84D8B3E51D75753300752B56 /* LFVideoEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3B11D75753300752B56 /* LFVideoEncoding.h */; };
|
||||
84D8B3E61D75753300752B56 /* LFLiveAudioConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3B31D75753300752B56 /* LFLiveAudioConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3E71D75753300752B56 /* LFLiveAudioConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3B41D75753300752B56 /* LFLiveAudioConfiguration.m */; };
|
||||
84D8B3E81D75753300752B56 /* LFLiveVideoConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3B51D75753300752B56 /* LFLiveVideoConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3E91D75753300752B56 /* LFLiveVideoConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3B61D75753300752B56 /* LFLiveVideoConfiguration.m */; };
|
||||
84D8B3EA1D75753300752B56 /* LFGPUImageBeautyFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3B81D75753300752B56 /* LFGPUImageBeautyFilter.h */; };
|
||||
84D8B3EB1D75753300752B56 /* LFGPUImageBeautyFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3B91D75753300752B56 /* LFGPUImageBeautyFilter.m */; };
|
||||
84D8B3EC1D75753300752B56 /* LFGPUImageEmptyFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3BA1D75753300752B56 /* LFGPUImageEmptyFilter.h */; };
|
||||
84D8B3ED1D75753300752B56 /* LFGPUImageEmptyFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3BB1D75753300752B56 /* LFGPUImageEmptyFilter.m */; };
|
||||
84D8B3EE1D75753300752B56 /* LFLiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3BC1D75753300752B56 /* LFLiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3EF1D75753300752B56 /* LFLiveSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3BD1D75753300752B56 /* LFLiveSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3F01D75753300752B56 /* LFLiveSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3BE1D75753300752B56 /* LFLiveSession.m */; };
|
||||
84D8B3F11D75753300752B56 /* LFAudioFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3C01D75753300752B56 /* LFAudioFrame.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3F21D75753300752B56 /* LFAudioFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3C11D75753300752B56 /* LFAudioFrame.m */; };
|
||||
84D8B3F31D75753300752B56 /* LFFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3C21D75753300752B56 /* LFFrame.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3F41D75753300752B56 /* LFFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3C31D75753300752B56 /* LFFrame.m */; };
|
||||
84D8B3F51D75753300752B56 /* LFLiveDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3C41D75753300752B56 /* LFLiveDebug.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3F61D75753300752B56 /* LFLiveDebug.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3C51D75753300752B56 /* LFLiveDebug.m */; };
|
||||
84D8B3F71D75753300752B56 /* LFLiveStreamInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3C61D75753300752B56 /* LFLiveStreamInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3F81D75753300752B56 /* LFLiveStreamInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3C71D75753300752B56 /* LFLiveStreamInfo.m */; };
|
||||
84D8B3F91D75753300752B56 /* LFVideoFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3C81D75753300752B56 /* LFVideoFrame.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84D8B3FA1D75753300752B56 /* LFVideoFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3C91D75753300752B56 /* LFVideoFrame.m */; };
|
||||
84D8B3FB1D75753300752B56 /* LFStreamingBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3CB1D75753300752B56 /* LFStreamingBuffer.h */; };
|
||||
84D8B3FC1D75753300752B56 /* LFStreamingBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3CC1D75753300752B56 /* LFStreamingBuffer.m */; };
|
||||
84D8B3FD1D75753300752B56 /* LFStreamRTMPSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3CD1D75753300752B56 /* LFStreamRTMPSocket.h */; };
|
||||
84D8B3FE1D75753300752B56 /* LFStreamRtmpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3CE1D75753300752B56 /* LFStreamRtmpSocket.m */; };
|
||||
84D8B3FF1D75753300752B56 /* LFStreamSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3CF1D75753300752B56 /* LFStreamSocket.h */; };
|
||||
84D8B4001D75753300752B56 /* NSMutableArray+LFAdd.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D8B3D01D75753300752B56 /* NSMutableArray+LFAdd.h */; };
|
||||
84D8B4011D75753300752B56 /* NSMutableArray+LFAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B3D11D75753300752B56 /* NSMutableArray+LFAdd.m */; };
|
||||
84D8B4BF1D757EB800752B56 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D8B4BE1D757EB800752B56 /* VideoToolbox.framework */; };
|
||||
84D8B4C11D757EBE00752B56 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D8B4C01D757EBE00752B56 /* AudioToolbox.framework */; };
|
||||
84D8B4C31D757EC400752B56 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D8B4C21D757EC400752B56 /* AVFoundation.framework */; };
|
||||
84D8B4C51D757EC800752B56 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D8B4C41D757EC800752B56 /* Foundation.framework */; };
|
||||
84D8B4C71D757ECC00752B56 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D8B4C61D757ECC00752B56 /* UIKit.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
84D8B3901D7574D600752B56 /* LFLiveKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LFLiveKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
84D8B39C1D75753300752B56 /* LFAudioCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFAudioCapture.h; sourceTree = "<group>"; };
|
||||
84D8B39D1D75753300752B56 /* LFAudioCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFAudioCapture.m; sourceTree = "<group>"; };
|
||||
84D8B39E1D75753300752B56 /* LFVideoCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFVideoCapture.h; sourceTree = "<group>"; };
|
||||
84D8B39F1D75753300752B56 /* LFVideoCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFVideoCapture.m; sourceTree = "<group>"; };
|
||||
84D8B3A21D75753300752B56 /* LFAVEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFAVEncoder.h; sourceTree = "<group>"; };
|
||||
84D8B3A31D75753300752B56 /* LFAVEncoder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LFAVEncoder.mm; sourceTree = "<group>"; };
|
||||
84D8B3A41D75753300752B56 /* LFMP4Atom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFMP4Atom.h; sourceTree = "<group>"; };
|
||||
84D8B3A51D75753300752B56 /* LFMP4Atom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFMP4Atom.m; sourceTree = "<group>"; };
|
||||
84D8B3A61D75753300752B56 /* LFNALUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LFNALUnit.cpp; sourceTree = "<group>"; };
|
||||
84D8B3A71D75753300752B56 /* LFNALUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFNALUnit.h; sourceTree = "<group>"; };
|
||||
84D8B3A81D75753300752B56 /* LFVideoEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFVideoEncoder.h; sourceTree = "<group>"; };
|
||||
84D8B3A91D75753300752B56 /* LFVideoEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFVideoEncoder.m; sourceTree = "<group>"; };
|
||||
84D8B3AA1D75753300752B56 /* LFAudioEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFAudioEncoding.h; sourceTree = "<group>"; };
|
||||
84D8B3AB1D75753300752B56 /* LFH264VideoEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFH264VideoEncoder.h; sourceTree = "<group>"; };
|
||||
84D8B3AC1D75753300752B56 /* LFH264VideoEncoder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LFH264VideoEncoder.mm; sourceTree = "<group>"; };
|
||||
84D8B3AD1D75753300752B56 /* LFHardwareAudioEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFHardwareAudioEncoder.h; sourceTree = "<group>"; };
|
||||
84D8B3AE1D75753300752B56 /* LFHardwareAudioEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFHardwareAudioEncoder.m; sourceTree = "<group>"; };
|
||||
84D8B3AF1D75753300752B56 /* LFHardwareVideoEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFHardwareVideoEncoder.h; sourceTree = "<group>"; };
|
||||
84D8B3B01D75753300752B56 /* LFHardwareVideoEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFHardwareVideoEncoder.m; sourceTree = "<group>"; };
|
||||
84D8B3B11D75753300752B56 /* LFVideoEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFVideoEncoding.h; sourceTree = "<group>"; };
|
||||
84D8B3B31D75753300752B56 /* LFLiveAudioConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLiveAudioConfiguration.h; sourceTree = "<group>"; };
|
||||
84D8B3B41D75753300752B56 /* LFLiveAudioConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLiveAudioConfiguration.m; sourceTree = "<group>"; };
|
||||
84D8B3B51D75753300752B56 /* LFLiveVideoConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLiveVideoConfiguration.h; sourceTree = "<group>"; };
|
||||
84D8B3B61D75753300752B56 /* LFLiveVideoConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLiveVideoConfiguration.m; sourceTree = "<group>"; };
|
||||
84D8B3B81D75753300752B56 /* LFGPUImageBeautyFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFGPUImageBeautyFilter.h; sourceTree = "<group>"; };
|
||||
84D8B3B91D75753300752B56 /* LFGPUImageBeautyFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFGPUImageBeautyFilter.m; sourceTree = "<group>"; };
|
||||
84D8B3BA1D75753300752B56 /* LFGPUImageEmptyFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFGPUImageEmptyFilter.h; sourceTree = "<group>"; };
|
||||
84D8B3BB1D75753300752B56 /* LFGPUImageEmptyFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFGPUImageEmptyFilter.m; sourceTree = "<group>"; };
|
||||
84D8B3BC1D75753300752B56 /* LFLiveKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLiveKit.h; sourceTree = "<group>"; };
|
||||
84D8B3BD1D75753300752B56 /* LFLiveSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLiveSession.h; sourceTree = "<group>"; };
|
||||
84D8B3BE1D75753300752B56 /* LFLiveSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLiveSession.m; sourceTree = "<group>"; };
|
||||
84D8B3C01D75753300752B56 /* LFAudioFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFAudioFrame.h; sourceTree = "<group>"; };
|
||||
84D8B3C11D75753300752B56 /* LFAudioFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFAudioFrame.m; sourceTree = "<group>"; };
|
||||
84D8B3C21D75753300752B56 /* LFFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFFrame.h; sourceTree = "<group>"; };
|
||||
84D8B3C31D75753300752B56 /* LFFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFFrame.m; sourceTree = "<group>"; };
|
||||
84D8B3C41D75753300752B56 /* LFLiveDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLiveDebug.h; sourceTree = "<group>"; };
|
||||
84D8B3C51D75753300752B56 /* LFLiveDebug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLiveDebug.m; sourceTree = "<group>"; };
|
||||
84D8B3C61D75753300752B56 /* LFLiveStreamInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLiveStreamInfo.h; sourceTree = "<group>"; };
|
||||
84D8B3C71D75753300752B56 /* LFLiveStreamInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLiveStreamInfo.m; sourceTree = "<group>"; };
|
||||
84D8B3C81D75753300752B56 /* LFVideoFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFVideoFrame.h; sourceTree = "<group>"; };
|
||||
84D8B3C91D75753300752B56 /* LFVideoFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFVideoFrame.m; sourceTree = "<group>"; };
|
||||
84D8B3CB1D75753300752B56 /* LFStreamingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFStreamingBuffer.h; sourceTree = "<group>"; };
|
||||
84D8B3CC1D75753300752B56 /* LFStreamingBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFStreamingBuffer.m; sourceTree = "<group>"; };
|
||||
84D8B3CD1D75753300752B56 /* LFStreamRTMPSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFStreamRTMPSocket.h; sourceTree = "<group>"; };
|
||||
84D8B3CE1D75753300752B56 /* LFStreamRtmpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFStreamRtmpSocket.m; sourceTree = "<group>"; };
|
||||
84D8B3CF1D75753300752B56 /* LFStreamSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFStreamSocket.h; sourceTree = "<group>"; };
|
||||
84D8B3D01D75753300752B56 /* NSMutableArray+LFAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+LFAdd.h"; sourceTree = "<group>"; };
|
||||
84D8B3D11D75753300752B56 /* NSMutableArray+LFAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+LFAdd.m"; sourceTree = "<group>"; };
|
||||
84D8B4BE1D757EB800752B56 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
|
||||
84D8B4C01D757EBE00752B56 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
84D8B4C21D757EC400752B56 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
|
||||
84D8B4C41D757EC800752B56 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
84D8B4C61D757ECC00752B56 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
84D8B4C81D757ED100752B56 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
|
||||
84D8B4CA1D757ED600752B56 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
84D8B38C1D7574D600752B56 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84D8B4C71D757ECC00752B56 /* UIKit.framework in Frameworks */,
|
||||
84D8B4C51D757EC800752B56 /* Foundation.framework in Frameworks */,
|
||||
84D8B4C31D757EC400752B56 /* AVFoundation.framework in Frameworks */,
|
||||
84D8B4C11D757EBE00752B56 /* AudioToolbox.framework in Frameworks */,
|
||||
84D8B4BF1D757EB800752B56 /* VideoToolbox.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
84D8B3861D7574D600752B56 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B4CA1D757ED600752B56 /* libz.tbd */,
|
||||
84D8B4C81D757ED100752B56 /* libstdc++.tbd */,
|
||||
84D8B4C61D757ECC00752B56 /* UIKit.framework */,
|
||||
84D8B4C41D757EC800752B56 /* Foundation.framework */,
|
||||
84D8B4C21D757EC400752B56 /* AVFoundation.framework */,
|
||||
84D8B4C01D757EBE00752B56 /* AudioToolbox.framework */,
|
||||
84D8B4BE1D757EB800752B56 /* VideoToolbox.framework */,
|
||||
84D8B3921D7574D600752B56 /* LFLiveKit */,
|
||||
84D8B3911D7574D600752B56 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3911D7574D600752B56 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3901D7574D600752B56 /* LFLiveKit.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3921D7574D600752B56 /* LFLiveKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B39B1D75753300752B56 /* capture */,
|
||||
84D8B3A01D75753300752B56 /* coder */,
|
||||
84D8B3B21D75753300752B56 /* configuration */,
|
||||
84D8B3B71D75753300752B56 /* filter */,
|
||||
84D8B3BC1D75753300752B56 /* LFLiveKit.h */,
|
||||
84D8B3BD1D75753300752B56 /* LFLiveSession.h */,
|
||||
84D8B3BE1D75753300752B56 /* LFLiveSession.m */,
|
||||
84D8B3BF1D75753300752B56 /* objects */,
|
||||
84D8B3CA1D75753300752B56 /* publish */,
|
||||
);
|
||||
path = LFLiveKit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B39B1D75753300752B56 /* capture */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B39C1D75753300752B56 /* LFAudioCapture.h */,
|
||||
84D8B39D1D75753300752B56 /* LFAudioCapture.m */,
|
||||
84D8B39E1D75753300752B56 /* LFVideoCapture.h */,
|
||||
84D8B39F1D75753300752B56 /* LFVideoCapture.m */,
|
||||
);
|
||||
path = capture;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3A01D75753300752B56 /* coder */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3A11D75753300752B56 /* H264 */,
|
||||
84D8B3AA1D75753300752B56 /* LFAudioEncoding.h */,
|
||||
84D8B3AB1D75753300752B56 /* LFH264VideoEncoder.h */,
|
||||
84D8B3AC1D75753300752B56 /* LFH264VideoEncoder.mm */,
|
||||
84D8B3AD1D75753300752B56 /* LFHardwareAudioEncoder.h */,
|
||||
84D8B3AE1D75753300752B56 /* LFHardwareAudioEncoder.m */,
|
||||
84D8B3AF1D75753300752B56 /* LFHardwareVideoEncoder.h */,
|
||||
84D8B3B01D75753300752B56 /* LFHardwareVideoEncoder.m */,
|
||||
84D8B3B11D75753300752B56 /* LFVideoEncoding.h */,
|
||||
);
|
||||
path = coder;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3A11D75753300752B56 /* H264 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3A21D75753300752B56 /* LFAVEncoder.h */,
|
||||
84D8B3A31D75753300752B56 /* LFAVEncoder.mm */,
|
||||
84D8B3A41D75753300752B56 /* LFMP4Atom.h */,
|
||||
84D8B3A51D75753300752B56 /* LFMP4Atom.m */,
|
||||
84D8B3A61D75753300752B56 /* LFNALUnit.cpp */,
|
||||
84D8B3A71D75753300752B56 /* LFNALUnit.h */,
|
||||
84D8B3A81D75753300752B56 /* LFVideoEncoder.h */,
|
||||
84D8B3A91D75753300752B56 /* LFVideoEncoder.m */,
|
||||
);
|
||||
path = H264;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3B21D75753300752B56 /* configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3B31D75753300752B56 /* LFLiveAudioConfiguration.h */,
|
||||
84D8B3B41D75753300752B56 /* LFLiveAudioConfiguration.m */,
|
||||
84D8B3B51D75753300752B56 /* LFLiveVideoConfiguration.h */,
|
||||
84D8B3B61D75753300752B56 /* LFLiveVideoConfiguration.m */,
|
||||
);
|
||||
path = configuration;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3B71D75753300752B56 /* filter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3B81D75753300752B56 /* LFGPUImageBeautyFilter.h */,
|
||||
84D8B3B91D75753300752B56 /* LFGPUImageBeautyFilter.m */,
|
||||
84D8B3BA1D75753300752B56 /* LFGPUImageEmptyFilter.h */,
|
||||
84D8B3BB1D75753300752B56 /* LFGPUImageEmptyFilter.m */,
|
||||
);
|
||||
path = filter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3BF1D75753300752B56 /* objects */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3C01D75753300752B56 /* LFAudioFrame.h */,
|
||||
84D8B3C11D75753300752B56 /* LFAudioFrame.m */,
|
||||
84D8B3C21D75753300752B56 /* LFFrame.h */,
|
||||
84D8B3C31D75753300752B56 /* LFFrame.m */,
|
||||
84D8B3C41D75753300752B56 /* LFLiveDebug.h */,
|
||||
84D8B3C51D75753300752B56 /* LFLiveDebug.m */,
|
||||
84D8B3C61D75753300752B56 /* LFLiveStreamInfo.h */,
|
||||
84D8B3C71D75753300752B56 /* LFLiveStreamInfo.m */,
|
||||
84D8B3C81D75753300752B56 /* LFVideoFrame.h */,
|
||||
84D8B3C91D75753300752B56 /* LFVideoFrame.m */,
|
||||
);
|
||||
path = objects;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84D8B3CA1D75753300752B56 /* publish */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84D8B3CB1D75753300752B56 /* LFStreamingBuffer.h */,
|
||||
84D8B3CC1D75753300752B56 /* LFStreamingBuffer.m */,
|
||||
84D8B3CD1D75753300752B56 /* LFStreamRTMPSocket.h */,
|
||||
84D8B3CE1D75753300752B56 /* LFStreamRtmpSocket.m */,
|
||||
84D8B3CF1D75753300752B56 /* LFStreamSocket.h */,
|
||||
84D8B3D01D75753300752B56 /* NSMutableArray+LFAdd.h */,
|
||||
84D8B3D11D75753300752B56 /* NSMutableArray+LFAdd.m */,
|
||||
);
|
||||
path = publish;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
84D8B38D1D7574D600752B56 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84D8B3F51D75753300752B56 /* LFLiveDebug.h in Headers */,
|
||||
84D8B3E61D75753300752B56 /* LFLiveAudioConfiguration.h in Headers */,
|
||||
84D8B3F11D75753300752B56 /* LFAudioFrame.h in Headers */,
|
||||
84D8B3F71D75753300752B56 /* LFLiveStreamInfo.h in Headers */,
|
||||
84D8B3E81D75753300752B56 /* LFLiveVideoConfiguration.h in Headers */,
|
||||
84D8B3F31D75753300752B56 /* LFFrame.h in Headers */,
|
||||
84D8B3EE1D75753300752B56 /* LFLiveKit.h in Headers */,
|
||||
84D8B3EF1D75753300752B56 /* LFLiveSession.h in Headers */,
|
||||
84D8B3F91D75753300752B56 /* LFVideoFrame.h in Headers */,
|
||||
84D8B3D21D75753300752B56 /* LFAudioCapture.h in Headers */,
|
||||
84D8B3FD1D75753300752B56 /* LFStreamRTMPSocket.h in Headers */,
|
||||
84D8B3D81D75753300752B56 /* LFMP4Atom.h in Headers */,
|
||||
84D8B3EA1D75753300752B56 /* LFGPUImageBeautyFilter.h in Headers */,
|
||||
84D8B3D61D75753300752B56 /* LFAVEncoder.h in Headers */,
|
||||
84D8B3DC1D75753300752B56 /* LFVideoEncoder.h in Headers */,
|
||||
84D8B3EC1D75753300752B56 /* LFGPUImageEmptyFilter.h in Headers */,
|
||||
84D8B3DE1D75753300752B56 /* LFAudioEncoding.h in Headers */,
|
||||
84D8B4001D75753300752B56 /* NSMutableArray+LFAdd.h in Headers */,
|
||||
84D8B3E31D75753300752B56 /* LFHardwareVideoEncoder.h in Headers */,
|
||||
84D8B3D41D75753300752B56 /* LFVideoCapture.h in Headers */,
|
||||
84D8B3FF1D75753300752B56 /* LFStreamSocket.h in Headers */,
|
||||
84D8B3DB1D75753300752B56 /* LFNALUnit.h in Headers */,
|
||||
84D8B3E11D75753300752B56 /* LFHardwareAudioEncoder.h in Headers */,
|
||||
84D8B3E51D75753300752B56 /* LFVideoEncoding.h in Headers */,
|
||||
84D8B3FB1D75753300752B56 /* LFStreamingBuffer.h in Headers */,
|
||||
84D8B3DF1D75753300752B56 /* LFH264VideoEncoder.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
84D8B38F1D7574D600752B56 /* LFLiveKit */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 84D8B3981D7574D600752B56 /* Build configuration list for PBXNativeTarget "LFLiveKit" */;
|
||||
buildPhases = (
|
||||
84D8B38B1D7574D600752B56 /* Sources */,
|
||||
84D8B38C1D7574D600752B56 /* Frameworks */,
|
||||
84D8B38D1D7574D600752B56 /* Headers */,
|
||||
84D8B38E1D7574D600752B56 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = LFLiveKit;
|
||||
productName = LFLiveKit;
|
||||
productReference = 84D8B3901D7574D600752B56 /* LFLiveKit.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
84D8B3871D7574D600752B56 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0730;
|
||||
ORGANIZATIONNAME = admin;
|
||||
TargetAttributes = {
|
||||
84D8B38F1D7574D600752B56 = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 84D8B38A1D7574D600752B56 /* Build configuration list for PBXProject "LFLiveKit" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 84D8B3861D7574D600752B56;
|
||||
productRefGroup = 84D8B3911D7574D600752B56 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
84D8B38F1D7574D600752B56 /* LFLiveKit */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
84D8B38E1D7574D600752B56 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
84D8B38B1D7574D600752B56 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84D8B3EB1D75753300752B56 /* LFGPUImageBeautyFilter.m in Sources */,
|
||||
84D8B3F41D75753300752B56 /* LFFrame.m in Sources */,
|
||||
84D8B3F61D75753300752B56 /* LFLiveDebug.m in Sources */,
|
||||
84D8B3D51D75753300752B56 /* LFVideoCapture.m in Sources */,
|
||||
84D8B3F21D75753300752B56 /* LFAudioFrame.m in Sources */,
|
||||
84D8B3F81D75753300752B56 /* LFLiveStreamInfo.m in Sources */,
|
||||
84D8B3DA1D75753300752B56 /* LFNALUnit.cpp in Sources */,
|
||||
84D8B3D71D75753300752B56 /* LFAVEncoder.mm in Sources */,
|
||||
84D8B3D91D75753300752B56 /* LFMP4Atom.m in Sources */,
|
||||
84D8B3E91D75753300752B56 /* LFLiveVideoConfiguration.m in Sources */,
|
||||
84D8B3DD1D75753300752B56 /* LFVideoEncoder.m in Sources */,
|
||||
84D8B3ED1D75753300752B56 /* LFGPUImageEmptyFilter.m in Sources */,
|
||||
84D8B3F01D75753300752B56 /* LFLiveSession.m in Sources */,
|
||||
84D8B3FE1D75753300752B56 /* LFStreamRtmpSocket.m in Sources */,
|
||||
84D8B3E71D75753300752B56 /* LFLiveAudioConfiguration.m in Sources */,
|
||||
84D8B3E21D75753300752B56 /* LFHardwareAudioEncoder.m in Sources */,
|
||||
84D8B3E01D75753300752B56 /* LFH264VideoEncoder.mm in Sources */,
|
||||
84D8B3FC1D75753300752B56 /* LFStreamingBuffer.m in Sources */,
|
||||
84D8B3E41D75753300752B56 /* LFHardwareVideoEncoder.m in Sources */,
|
||||
84D8B3FA1D75753300752B56 /* LFVideoFrame.m in Sources */,
|
||||
84D8B3D31D75753300752B56 /* LFAudioCapture.m in Sources */,
|
||||
84D8B4011D75753300752B56 /* NSMutableArray+LFAdd.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
84D8B3961D7574D600752B56 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
84D8B3971D7574D600752B56 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
84D8B3991D7574D600752B56 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/../Vendor/GPUImage.framework/Headers\"",
|
||||
"\"$(SRCROOT)/../Vendor/pili_rtmp.framework/Headers\"",
|
||||
);
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MACH_O_TYPE = staticlib;
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.youku.LFLiveKit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
84D8B39A1D7574D600752B56 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"\"$(SRCROOT)/../Vendor/GPUImage.framework/Headers\"",
|
||||
"\"$(SRCROOT)/../Vendor/pili_rtmp.framework/Headers\"",
|
||||
);
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MACH_O_TYPE = staticlib;
|
||||
OTHER_LDFLAGS = "";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.youku.LFLiveKit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
84D8B38A1D7574D600752B56 /* Build configuration list for PBXProject "LFLiveKit" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
84D8B3961D7574D600752B56 /* Debug */,
|
||||
84D8B3971D7574D600752B56 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
84D8B3981D7574D600752B56 /* Build configuration list for PBXNativeTarget "LFLiveKit" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
84D8B3991D7574D600752B56 /* Debug */,
|
||||
84D8B39A1D7574D600752B56 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 84D8B3871D7574D600752B56 /* Project object */;
|
||||
}
|
||||
+17
-28
@@ -14,10 +14,10 @@
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
|
||||
BuildableName = "LFLiveKitDemo.app"
|
||||
BlueprintName = "LFLiveKitDemo"
|
||||
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
|
||||
BlueprintIdentifier = "84D8B38F1D7574D600752B56"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
@@ -29,20 +29,11 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
|
||||
BuildableName = "LFLiveKitDemo.app"
|
||||
BlueprintName = "LFLiveKitDemo"
|
||||
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
buildConfiguration = "Release"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
@@ -51,16 +42,15 @@
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
|
||||
BuildableName = "LFLiveKitDemo.app"
|
||||
BlueprintName = "LFLiveKitDemo"
|
||||
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
|
||||
BlueprintIdentifier = "84D8B38F1D7574D600752B56"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
@@ -70,16 +60,15 @@
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
|
||||
BuildableName = "LFLiveKitDemo.app"
|
||||
BlueprintName = "LFLiveKitDemo"
|
||||
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
|
||||
BlueprintIdentifier = "84D8B38F1D7574D600752B56"
|
||||
BuildableName = "LFLiveKit.framework"
|
||||
BlueprintName = "LFLiveKit"
|
||||
ReferencedContainer = "container:LFLiveKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// LFLiveKit.h
|
||||
// LFLiveKit
|
||||
//
|
||||
// Created by admin on 16/5/24.
|
||||
// Copyright © 2016年 admin. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LFLiveSession.h"
|
||||
#import "LFLiveAudioConfiguration.h"
|
||||
#import "LFLiveVideoConfiguration.h"
|
||||
#import "LFAudioFrame.h"
|
||||
#import "LFFrame.h"
|
||||
#import "LFLiveStreamInfo.h"
|
||||
#import "LFVideoFrame.h"
|
||||
#import "LFLiveDebug.h"
|
||||
|
||||
//#import <LFLiveKit/LFLiveSession.h>
|
||||
//#import <LFLiveKit/LFLiveAudioConfiguration.h>
|
||||
//#import <LFLiveKit/LFLiveVideoConfiguration.h>
|
||||
//#import <LFLiveKit/LFAudioFrame.h>
|
||||
//#import <LFLiveKit/LFFrame.h>
|
||||
//#import <LFLiveKit/LFLiveStreamInfo.h>
|
||||
//#import <LFLiveKit/LFVideoFrame.h>
|
||||
//#import <LFLiveKit/LFLiveDebug.h>
|
||||
@@ -15,6 +15,26 @@
|
||||
#import "LFLiveVideoConfiguration.h"
|
||||
#import "LFLiveDebug.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger,LFLiveCaptureType) {
|
||||
LFLiveCaptureAudio, //< capture only audio
|
||||
LFLiveCaptureVideo, //< capture onlt video
|
||||
LFLiveInputAudio, //< only audio (External input audio)
|
||||
LFLiveInputVideo, //< only video (External input video)
|
||||
};
|
||||
|
||||
|
||||
///< 用来控制采集类型(可以内部采集也可以外部传入等各种组合,支持单音频与单视频,外部输入适用于录屏,无人机等外设介入)
|
||||
typedef NS_ENUM(NSInteger,LFLiveCaptureTypeMask) {
|
||||
LFLiveCaptureMaskAudio = (1 << LFLiveCaptureAudio), ///< only inner capture audio (no video)
|
||||
LFLiveCaptureMaskVideo = (1 << LFLiveCaptureVideo), ///< only inner capture video (no audio)
|
||||
LFLiveInputMaskAudio = (1 << LFLiveInputAudio), ///< only outer input audio (no video)
|
||||
LFLiveInputMaskVideo = (1 << LFLiveInputVideo), ///< only outer input video (no audio)
|
||||
LFLiveCaptureMaskAll = (LFLiveCaptureMaskAudio | LFLiveCaptureMaskVideo), ///< inner capture audio and video
|
||||
LFLiveInputMaskAll = (LFLiveInputMaskAudio | LFLiveInputMaskVideo), ///< outer input audio and video(method see pushVideo and pushAudio)
|
||||
LFLiveCaptureMaskAudioInputVideo = (LFLiveCaptureMaskAudio | LFLiveInputMaskVideo), ///< inner capture audio and outer input video(method pushVideo and setRunning)
|
||||
LFLiveCaptureMaskVideoInputAudio = (LFLiveCaptureMaskVideo | LFLiveInputMaskAudio), ///< inner capture video and outer input audio(method pushAudio and setRunning)
|
||||
LFLiveCaptureDefaultMask = LFLiveCaptureMaskAll ///< default is inner capture audio and video
|
||||
};
|
||||
|
||||
@class LFLiveSession;
|
||||
@protocol LFLiveSessionDelegate <NSObject>
|
||||
@@ -51,10 +71,10 @@
|
||||
/** The beautyFace control capture shader filter empty or beautiy */
|
||||
@property (nonatomic, assign) BOOL beautyFace;
|
||||
|
||||
/** The beautyLevel control beautyFace Level, default 0.5, between 0.0 ~ 1.0 */
|
||||
/** The beautyLevel control beautyFace Level. Default is 0.5, between 0.0 ~ 1.0 */
|
||||
@property (nonatomic, assign) CGFloat beautyLevel;
|
||||
|
||||
/** The brightLevel control brightness Level, default 0.5, between 0.0 ~ 1.0 */
|
||||
/** The brightLevel control brightness Level, Default is 0.5, between 0.0 ~ 1.0 */
|
||||
@property (nonatomic, assign) CGFloat brightLevel;
|
||||
|
||||
/** The torch control camera zoom scale default 1.0, between 1.0 ~ 3.0 */
|
||||
@@ -69,12 +89,18 @@
|
||||
/** The muted control callbackAudioData,muted will memset 0.*/
|
||||
@property (nonatomic, assign) BOOL muted;
|
||||
|
||||
/* The adaptiveBitrate control auto adjust bitrate. Default is NO */
|
||||
@property (nonatomic, assign) BOOL adaptiveBitrate;
|
||||
|
||||
/** The stream control upload and package*/
|
||||
@property (nullable, nonatomic, strong, readonly) LFLiveStreamInfo *streamInfo;
|
||||
|
||||
/** The status of the stream .*/
|
||||
@property (nonatomic, assign, readonly) LFLiveState state;
|
||||
|
||||
/** The captureType control inner or outer audio and video .*/
|
||||
@property (nonatomic, assign, readonly) LFLiveCaptureTypeMask captureType;
|
||||
|
||||
/** The showDebugInfo control streamInfo and uploadInfo(1s) *.*/
|
||||
@property (nonatomic, assign) BOOL showDebugInfo;
|
||||
|
||||
@@ -84,6 +110,12 @@
|
||||
/** The reconnectCount control reconnect count (重连次数) *.*/
|
||||
@property (nonatomic, assign) NSUInteger reconnectCount;
|
||||
|
||||
/*** The warterMarkView control whether the watermark is displayed or not ,if set ni,will remove watermark,otherwise add.
|
||||
set alpha represent mix.Position relative to outVideoSize.
|
||||
*.*/
|
||||
@property (nonatomic, strong, nullable) UIView *warterMarkView;
|
||||
|
||||
@property (nonatomic, strong,readonly ,nullable) UIImage *currentImage;
|
||||
#pragma mark - Initializer
|
||||
///=============================================================================
|
||||
/// @name Initializer
|
||||
@@ -95,7 +127,13 @@
|
||||
The designated initializer. Multiple instances with the same configuration will make the
|
||||
capture unstable.
|
||||
*/
|
||||
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration;
|
||||
|
||||
/**
|
||||
The designated initializer. Multiple instances with the same configuration will make the
|
||||
capture unstable.
|
||||
*/
|
||||
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration captureType:(LFLiveCaptureTypeMask)captureType NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/** The start stream .*/
|
||||
- (void)startLive:(nonnull LFLiveStreamInfo *)streamInfo;
|
||||
@@ -103,6 +141,11 @@
|
||||
/** The stop stream .*/
|
||||
- (void)stopLive;
|
||||
|
||||
/** support outer input yuv or rgb video(set LFLiveCaptureTypeMask) .*/
|
||||
- (void)pushVideo:(nullable CVPixelBufferRef)pixelBuffer;
|
||||
|
||||
/** support outer input pcm audio(set LFLiveCaptureTypeMask) .*/
|
||||
- (void)pushAudio:(nullable NSData*)audioData;
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,19 +11,18 @@
|
||||
#import "LFAudioCapture.h"
|
||||
#import "LFHardwareVideoEncoder.h"
|
||||
#import "LFHardwareAudioEncoder.h"
|
||||
#import "LFH264VideoEncoder.h"
|
||||
#import "LFStreamRTMPSocket.h"
|
||||
#import "LFLiveStreamInfo.h"
|
||||
#import "LFGPUImageBeautyFilter.h"
|
||||
#import "LFH264VideoEncoder.h"
|
||||
|
||||
#define LFLiveReportKey @"com.youku.liveSessionReport"
|
||||
|
||||
@interface LFLiveSession ()<LFAudioCaptureDelegate, LFVideoCaptureDelegate, LFAudioEncodingDelegate, LFVideoEncodingDelegate, LFStreamSocketDelegate>
|
||||
{
|
||||
dispatch_semaphore_t _lock;
|
||||
}
|
||||
///音频配置
|
||||
|
||||
/// 音频配置
|
||||
@property (nonatomic, strong) LFLiveAudioConfiguration *audioConfiguration;
|
||||
///视频配置
|
||||
/// 视频配置
|
||||
@property (nonatomic, strong) LFLiveVideoConfiguration *videoConfiguration;
|
||||
/// 声音采集
|
||||
@property (nonatomic, strong) LFAudioCapture *audioCaptureSource;
|
||||
@@ -36,46 +35,63 @@
|
||||
/// 上传
|
||||
@property (nonatomic, strong) id<LFStreamSocket> socket;
|
||||
|
||||
|
||||
#pragma mark -- 内部标识
|
||||
/// 上报
|
||||
@property (nonatomic, copy) dispatch_block_t reportBlock;
|
||||
/// debugInfo
|
||||
/// 调试信息
|
||||
@property (nonatomic, strong) LFLiveDebug *debugInfo;
|
||||
/// streamInfo
|
||||
/// 流信息
|
||||
@property (nonatomic, strong) LFLiveStreamInfo *streamInfo;
|
||||
/// uploading
|
||||
/// 是否开始上传
|
||||
@property (nonatomic, assign) BOOL uploading;
|
||||
/// state
|
||||
/// 当前状态
|
||||
@property (nonatomic, assign, readwrite) LFLiveState state;
|
||||
/// 当前直播type
|
||||
@property (nonatomic, assign, readwrite) LFLiveCaptureTypeMask captureType;
|
||||
/// 时间戳锁
|
||||
@property (nonatomic, strong) dispatch_semaphore_t lock;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
/** 时间戳 */
|
||||
#define NOW (CACurrentMediaTime()*1000)
|
||||
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
|
||||
|
||||
@interface LFLiveSession ()
|
||||
|
||||
@property (nonatomic, assign) uint64_t timestamp;
|
||||
@property (nonatomic, assign) BOOL isFirstFrame;
|
||||
@property (nonatomic, assign) uint64_t currentTimestamp;
|
||||
/// 上传相对时间戳
|
||||
@property (nonatomic, assign) uint64_t relativeTimestamps;
|
||||
/// 音视频是否对齐
|
||||
@property (nonatomic, assign) BOOL AVAlignment;
|
||||
/// 当前是否采集到了音频
|
||||
@property (nonatomic, assign) BOOL hasCaptureAudio;
|
||||
/// 当前是否采集到了关键帧
|
||||
@property (nonatomic, assign) BOOL hasKeyFrameVideo;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LFLiveSession
|
||||
|
||||
#pragma mark -- LifeCycle
|
||||
- (instancetype)initWithAudioConfiguration:(LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(LFLiveVideoConfiguration *)videoConfiguration {
|
||||
if (!audioConfiguration || !videoConfiguration) @throw [NSException exceptionWithName:@"LFLiveSession init error" reason:@"audioConfiguration or videoConfiguration is nil " userInfo:nil];
|
||||
- (instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration {
|
||||
return [self initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration captureType:LFLiveCaptureDefaultMask];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration captureType:(LFLiveCaptureTypeMask)captureType{
|
||||
if((captureType & LFLiveCaptureMaskAudio || captureType & LFLiveInputMaskAudio) && !audioConfiguration) @throw [NSException exceptionWithName:@"LFLiveSession init error" reason:@"audioConfiguration is nil " userInfo:nil];
|
||||
if((captureType & LFLiveCaptureMaskVideo || captureType & LFLiveInputMaskVideo) && !videoConfiguration) @throw [NSException exceptionWithName:@"LFLiveSession init error" reason:@"videoConfiguration is nil " userInfo:nil];
|
||||
if (self = [super init]) {
|
||||
_audioConfiguration = audioConfiguration;
|
||||
_videoConfiguration = videoConfiguration;
|
||||
_lock = dispatch_semaphore_create(1);
|
||||
_adaptiveBitrate = NO;
|
||||
_captureType = captureType;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
self.audioCaptureSource.running = NO;
|
||||
self.videoCaptureSource.running = NO;
|
||||
self.audioCaptureSource.running = NO;
|
||||
}
|
||||
|
||||
#pragma mark -- CustomMethod
|
||||
@@ -84,6 +100,7 @@
|
||||
_streamInfo = streamInfo;
|
||||
_streamInfo.videoConfiguration = _videoConfiguration;
|
||||
_streamInfo.audioConfiguration = _audioConfiguration;
|
||||
_streamInfo.needDropFrame = (self.captureType & LFLiveCaptureMaskVideo || self.captureType & LFLiveInputMaskVideo) ? YES : NO;//< 有视频执行丢帧算法
|
||||
[self.socket start];
|
||||
}
|
||||
|
||||
@@ -93,33 +110,64 @@
|
||||
self.socket = nil;
|
||||
}
|
||||
|
||||
#pragma mark -- CaptureDelegate
|
||||
- (void)captureOutput:(nullable LFAudioCapture *)capture audioBuffer:(AudioBufferList)inBufferList {
|
||||
if (self.uploading) [self.audioEncoder encodeAudioData:inBufferList timeStamp:self.currentTimestamp];
|
||||
#pragma mark -- PrivateMethod
|
||||
- (void)pushSendBuffer:(LFFrame*)frame{
|
||||
if(self.relativeTimestamps == 0){
|
||||
self.relativeTimestamps = frame.timestamp;
|
||||
}
|
||||
frame.timestamp = [self uploadTimestamp:frame.timestamp];
|
||||
[self.socket sendFrame:frame];
|
||||
}
|
||||
|
||||
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVImageBufferRef)pixelBuffer {
|
||||
if (self.uploading) [self.videoEncoder encodeVideoData:pixelBuffer timeStamp:self.currentTimestamp];
|
||||
- (void)pushVideo:(nullable CVPixelBufferRef)pixelBuffer{
|
||||
if(self.captureType & LFLiveInputMaskVideo){
|
||||
if (self.uploading) [self.videoEncoder encodeVideoData:pixelBuffer timeStamp:NOW];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pushAudio:(nullable NSData*)audioData{
|
||||
if(self.captureType & LFLiveInputMaskAudio){
|
||||
if (self.uploading) [self.audioEncoder encodeAudioData:audioData timeStamp:NOW];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -- CaptureDelegate
|
||||
- (void)captureOutput:(nullable LFAudioCapture *)capture audioData:(nullable NSData*)audioData {
|
||||
if (self.uploading) [self.audioEncoder encodeAudioData:audioData timeStamp:NOW];
|
||||
}
|
||||
|
||||
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVPixelBufferRef)pixelBuffer {
|
||||
if (self.uploading) [self.videoEncoder encodeVideoData:pixelBuffer timeStamp:NOW];
|
||||
}
|
||||
|
||||
#pragma mark -- EncoderDelegate
|
||||
- (void)audioEncoder:(nullable id<LFAudioEncoding>)encoder audioFrame:(nullable LFAudioFrame *)frame {
|
||||
if (self.uploading) [self.socket sendFrame:frame]; //<上传
|
||||
//<上传 时间戳对齐
|
||||
if (self.uploading){
|
||||
self.hasCaptureAudio = YES;
|
||||
if(self.AVAlignment) [self pushSendBuffer:frame];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)videoEncoder:(nullable id<LFVideoEncoding>)encoder videoFrame:(nullable LFVideoFrame *)frame {
|
||||
if (self.uploading) [self.socket sendFrame:frame]; //<上传
|
||||
//<上传 时间戳对齐
|
||||
if (self.uploading){
|
||||
if(frame.isKeyFrame && self.hasCaptureAudio) self.hasKeyFrameVideo = YES;
|
||||
if(self.AVAlignment) [self pushSendBuffer:frame];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -- LFStreamTcpSocketDelegate
|
||||
- (void)socketStatus:(nullable id<LFStreamSocket>)socket status:(LFLiveState)status {
|
||||
if (status == LFLiveStart) {
|
||||
if (!self.uploading) {
|
||||
self.timestamp = 0;
|
||||
self.isFirstFrame = YES;
|
||||
self.AVAlignment = NO;
|
||||
self.hasCaptureAudio = NO;
|
||||
self.hasKeyFrameVideo = NO;
|
||||
self.relativeTimestamps = 0;
|
||||
self.uploading = YES;
|
||||
}
|
||||
}else if(status == LFLiveStop || status == LFLiveError){
|
||||
} else if(status == LFLiveStop || status == LFLiveError){
|
||||
self.uploading = NO;
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
@@ -150,16 +198,20 @@
|
||||
}
|
||||
|
||||
- (void)socketBufferStatus:(nullable id<LFStreamSocket>)socket status:(LFLiveBuffferState)status {
|
||||
NSUInteger videoBitRate = [_videoEncoder videoBitRate];
|
||||
if (status == LFLiveBuffferDecline) {
|
||||
if (videoBitRate < _videoConfiguration.videoMaxBitRate) {
|
||||
videoBitRate = videoBitRate + 50 * 1000;
|
||||
[_videoEncoder setVideoBitRate:videoBitRate];
|
||||
}
|
||||
} else {
|
||||
if (videoBitRate > _videoConfiguration.videoMinBitRate) {
|
||||
videoBitRate = videoBitRate - 100 * 1000;
|
||||
[_videoEncoder setVideoBitRate:videoBitRate];
|
||||
if((self.captureType & LFLiveCaptureMaskVideo || self.captureType & LFLiveInputMaskVideo) && self.adaptiveBitrate){
|
||||
NSUInteger videoBitRate = [self.videoEncoder videoBitRate];
|
||||
if (status == LFLiveBuffferDecline) {
|
||||
if (videoBitRate < _videoConfiguration.videoMaxBitRate) {
|
||||
videoBitRate = videoBitRate + 50 * 1000;
|
||||
[self.videoEncoder setVideoBitRate:videoBitRate];
|
||||
NSLog(@"Increase bitrate %@", @(videoBitRate));
|
||||
}
|
||||
} else {
|
||||
if (videoBitRate > self.videoConfiguration.videoMinBitRate) {
|
||||
videoBitRate = videoBitRate - 100 * 1000;
|
||||
[self.videoEncoder setVideoBitRate:videoBitRate];
|
||||
NSLog(@"Decline bitrate %@", @(videoBitRate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,18 +316,34 @@
|
||||
return self.audioCaptureSource.muted;
|
||||
}
|
||||
|
||||
- (void)setWarterMarkView:(UIView *)warterMarkView{
|
||||
[self.videoCaptureSource setWarterMarkView:warterMarkView];
|
||||
}
|
||||
|
||||
- (nullable UIView*)warterMarkView{
|
||||
return self.videoCaptureSource.warterMarkView;
|
||||
}
|
||||
|
||||
- (nullable UIImage *)currentImage{
|
||||
return self.videoCaptureSource.currentImage;
|
||||
}
|
||||
|
||||
- (LFAudioCapture *)audioCaptureSource {
|
||||
if (!_audioCaptureSource) {
|
||||
_audioCaptureSource = [[LFAudioCapture alloc] initWithAudioConfiguration:_audioConfiguration];
|
||||
_audioCaptureSource.delegate = self;
|
||||
if(self.captureType & LFLiveCaptureMaskAudio){
|
||||
_audioCaptureSource = [[LFAudioCapture alloc] initWithAudioConfiguration:_audioConfiguration];
|
||||
_audioCaptureSource.delegate = self;
|
||||
}
|
||||
}
|
||||
return _audioCaptureSource;
|
||||
}
|
||||
|
||||
- (LFVideoCapture *)videoCaptureSource {
|
||||
if (!_videoCaptureSource) {
|
||||
_videoCaptureSource = [[LFVideoCapture alloc] initWithVideoConfiguration:_videoConfiguration];
|
||||
_videoCaptureSource.delegate = self;
|
||||
if(self.captureType & LFLiveCaptureMaskVideo){
|
||||
_videoCaptureSource = [[LFVideoCapture alloc] initWithVideoConfiguration:_videoConfiguration];
|
||||
_videoCaptureSource.delegate = self;
|
||||
}
|
||||
}
|
||||
return _videoCaptureSource;
|
||||
}
|
||||
@@ -290,7 +358,11 @@
|
||||
|
||||
- (id<LFVideoEncoding>)videoEncoder {
|
||||
if (!_videoEncoder) {
|
||||
_videoEncoder = [[LFHardwareVideoEncoder alloc] initWithVideoStreamConfiguration:_videoConfiguration];
|
||||
if([[UIDevice currentDevice].systemVersion floatValue] < 8.0){
|
||||
_videoEncoder = [[LFH264VideoEncoder alloc] initWithVideoStreamConfiguration:_videoConfiguration];
|
||||
}else{
|
||||
_videoEncoder = [[LFHardwareVideoEncoder alloc] initWithVideoStreamConfiguration:_videoConfiguration];
|
||||
}
|
||||
[_videoEncoder setDelegate:self];
|
||||
}
|
||||
return _videoEncoder;
|
||||
@@ -298,7 +370,7 @@
|
||||
|
||||
- (id<LFStreamSocket>)socket {
|
||||
if (!_socket) {
|
||||
_socket = [[LFStreamRTMPSocket alloc] initWithStream:self.streamInfo videoSize:self.videoConfiguration.videoSize reconnectInterval:self.reconnectInterval reconnectCount:self.reconnectCount];
|
||||
_socket = [[LFStreamRTMPSocket alloc] initWithStream:self.streamInfo reconnectInterval:self.reconnectInterval reconnectCount:self.reconnectCount];
|
||||
[_socket setDelegate:self];
|
||||
}
|
||||
return _socket;
|
||||
@@ -311,18 +383,30 @@
|
||||
return _streamInfo;
|
||||
}
|
||||
|
||||
- (uint64_t)currentTimestamp {
|
||||
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
|
||||
uint64_t currentts = 0;
|
||||
if (_isFirstFrame == true) {
|
||||
_timestamp = NOW;
|
||||
_isFirstFrame = false;
|
||||
currentts = 0;
|
||||
} else {
|
||||
currentts = NOW - _timestamp;
|
||||
- (dispatch_semaphore_t)lock{
|
||||
if(!_lock){
|
||||
_lock = dispatch_semaphore_create(1);
|
||||
}
|
||||
dispatch_semaphore_signal(_lock);
|
||||
return _lock;
|
||||
}
|
||||
|
||||
- (uint64_t)uploadTimestamp:(uint64_t)captureTimestamp{
|
||||
dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
|
||||
uint64_t currentts = 0;
|
||||
currentts = captureTimestamp - self.relativeTimestamps;
|
||||
dispatch_semaphore_signal(self.lock);
|
||||
return currentts;
|
||||
}
|
||||
|
||||
- (BOOL)AVAlignment{
|
||||
if((self.captureType & LFLiveCaptureMaskAudio || self.captureType & LFLiveInputMaskAudio) &&
|
||||
(self.captureType & LFLiveCaptureMaskVideo || self.captureType & LFLiveInputMaskVideo)
|
||||
){
|
||||
if(self.hasCaptureAudio && self.hasKeyFrameVideo) return YES;
|
||||
else return NO;
|
||||
}else{
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -17,7 +17,7 @@ extern NSString *_Nullable const LFAudioComponentFailedToCreateNotification;
|
||||
@class LFAudioCapture;
|
||||
/** LFAudioCapture callback audioData */
|
||||
@protocol LFAudioCaptureDelegate <NSObject>
|
||||
- (void)captureOutput:(nullable LFAudioCapture *)capture audioBuffer:(AudioBufferList)inBufferList;
|
||||
- (void)captureOutput:(nullable LFAudioCapture *)capture audioData:(nullable NSData*)audioData;
|
||||
@end
|
||||
|
||||
|
||||
@@ -18,61 +18,52 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
|
||||
@property (nonatomic, assign) AudioComponent component;
|
||||
@property (nonatomic, strong) dispatch_queue_t taskQueue;
|
||||
@property (nonatomic, assign) BOOL isRunning;
|
||||
@property (nonatomic, strong) LFLiveAudioConfiguration *configuration;
|
||||
@property (nonatomic, strong,nullable) LFLiveAudioConfiguration *configuration;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LFAudioCapture
|
||||
|
||||
#pragma mark -- LiftCycle
|
||||
- (instancetype)initWithAudioConfiguration:(LFLiveAudioConfiguration *)configuration {
|
||||
if (self = [super init]) {
|
||||
- (instancetype)initWithAudioConfiguration:(LFLiveAudioConfiguration *)configuration{
|
||||
if(self = [super init]){
|
||||
_configuration = configuration;
|
||||
self.isRunning = NO;
|
||||
self.taskQueue = dispatch_queue_create("com.youku.Laifeng.audioCapture.Queue", NULL);
|
||||
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
[session setActive:YES error:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleRouteChange:)
|
||||
name:AVAudioSessionRouteChangeNotification
|
||||
object:session];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(handleInterruption:)
|
||||
name:AVAudioSessionInterruptionNotification
|
||||
object:session];
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
|
||||
|
||||
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
|
||||
|
||||
if (![session setActive:YES error:&error]) {
|
||||
[self handleAudioComponentCreationFailure];
|
||||
}
|
||||
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(handleRouteChange:)
|
||||
name: AVAudioSessionRouteChangeNotification
|
||||
object: session];
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(handleInterruption:)
|
||||
name: AVAudioSessionInterruptionNotification
|
||||
object: session];
|
||||
|
||||
AudioComponentDescription acd;
|
||||
acd.componentType = kAudioUnitType_Output;
|
||||
acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
|
||||
//acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
|
||||
acd.componentSubType = kAudioUnitSubType_RemoteIO;
|
||||
acd.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
acd.componentFlags = 0;
|
||||
acd.componentFlagsMask = 0;
|
||||
|
||||
|
||||
self.component = AudioComponentFindNext(NULL, &acd);
|
||||
|
||||
|
||||
OSStatus status = noErr;
|
||||
status = AudioComponentInstanceNew(self.component, &_componetInstance);
|
||||
|
||||
|
||||
if (noErr != status) {
|
||||
[self handleAudioComponentCreationFailure];
|
||||
}
|
||||
|
||||
|
||||
UInt32 flagOne = 1;
|
||||
|
||||
|
||||
AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flagOne, sizeof(flagOne));
|
||||
|
||||
|
||||
AudioStreamBasicDescription desc = {0};
|
||||
desc.mSampleRate = _configuration.audioSampleRate;
|
||||
desc.mFormatID = kAudioFormatLinearPCM;
|
||||
@@ -82,22 +73,23 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
|
||||
desc.mBitsPerChannel = 16;
|
||||
desc.mBytesPerFrame = desc.mBitsPerChannel / 8 * desc.mChannelsPerFrame;
|
||||
desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;
|
||||
|
||||
|
||||
AURenderCallbackStruct cb;
|
||||
cb.inputProcRefCon = (__bridge void *)(self);
|
||||
cb.inputProc = handleInputBuffer;
|
||||
AudioUnitSetProperty(self.componetInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &desc, sizeof(desc));
|
||||
AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, sizeof(cb));
|
||||
|
||||
|
||||
status = AudioUnitInitialize(self.componetInstance);
|
||||
|
||||
|
||||
if (noErr != status) {
|
||||
[self handleAudioComponentCreationFailure];
|
||||
}
|
||||
|
||||
|
||||
[session setPreferredSampleRate:_configuration.audioSampleRate error:nil];
|
||||
|
||||
|
||||
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers error:nil];
|
||||
[session setActive:YES withOptions:kAudioSessionSetActiveFlag_NotifyOthersOnDeactivation error:nil];
|
||||
|
||||
[session setActive:YES error:nil];
|
||||
}
|
||||
return self;
|
||||
@@ -124,6 +116,7 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
|
||||
dispatch_async(self.taskQueue, ^{
|
||||
self.isRunning = YES;
|
||||
NSLog(@"MicrophoneSource: startRunning");
|
||||
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers error:nil];
|
||||
AudioOutputUnitStart(self.componetInstance);
|
||||
});
|
||||
} else {
|
||||
@@ -258,8 +251,8 @@ static OSStatus handleInputBuffer(void *inRefCon,
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
if (source.delegate && [source.delegate respondsToSelector:@selector(captureOutput:audioBuffer:)]) {
|
||||
[source.delegate captureOutput:source audioBuffer:buffers];
|
||||
if (source.delegate && [source.delegate respondsToSelector:@selector(captureOutput:audioData:)]) {
|
||||
[source.delegate captureOutput:source audioData:[NSData dataWithBytes:buffers.mBuffers[0].mData length:buffers.mBuffers[0].mDataByteSize]];
|
||||
}
|
||||
}
|
||||
return status;
|
||||
@@ -13,7 +13,7 @@
|
||||
@class LFVideoCapture;
|
||||
/** LFVideoCapture callback videoData */
|
||||
@protocol LFVideoCaptureDelegate <NSObject>
|
||||
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVImageBufferRef)pixelBuffer;
|
||||
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVPixelBufferRef)pixelBuffer;
|
||||
@end
|
||||
|
||||
@interface LFVideoCapture : NSObject
|
||||
@@ -56,6 +56,10 @@
|
||||
/** The videoFrameRate control videoCapture output data count */
|
||||
@property (nonatomic, assign) NSInteger videoFrameRate;
|
||||
|
||||
/*** The warterMarkView control whether the watermark is displayed or not ,if set ni,will remove watermark,otherwise add *.*/
|
||||
@property (nonatomic, strong, nullable) UIView *warterMarkView;
|
||||
|
||||
@property (nonatomic, strong, nullable) UIImage *currentImage;
|
||||
#pragma mark - Initializer
|
||||
///=============================================================================
|
||||
/// @name Initializer
|
||||
+186
-152
@@ -7,19 +7,30 @@
|
||||
//
|
||||
|
||||
#import "LFVideoCapture.h"
|
||||
#import "GPUImage.h"
|
||||
#import "LFGPUImageBeautyFilter.h"
|
||||
#import "LFGPUImageEmptyFilter.h"
|
||||
|
||||
#if __has_include(<GPUImage/GPUImage.h>)
|
||||
#import <GPUImage/GPUImage.h>
|
||||
#elif __has_include("GPUImage/GPUImage.h")
|
||||
#import "GPUImage/GPUImage.h"
|
||||
#else
|
||||
#import "GPUImage.h"
|
||||
#endif
|
||||
|
||||
@interface LFVideoCapture ()
|
||||
|
||||
@property(nonatomic, strong) GPUImageVideoCamera *videoCamera;
|
||||
@property(nonatomic, weak) LFGPUImageBeautyFilter *beautyFilter;
|
||||
@property(nonatomic, strong) GPUImageOutput<GPUImageInput> *filter;
|
||||
@property(nonatomic, strong) GPUImageOutput<GPUImageInput> *output;
|
||||
@property(nonatomic, strong) GPUImageCropFilter *cropfilter;
|
||||
@property(nonatomic, strong) GPUImageView *gpuImageView;
|
||||
@property(nonatomic, strong) LFLiveVideoConfiguration *configuration;
|
||||
@property (nonatomic, strong) GPUImageVideoCamera *videoCamera;
|
||||
@property (nonatomic, strong) LFGPUImageBeautyFilter *beautyFilter;
|
||||
@property (nonatomic, strong) GPUImageOutput<GPUImageInput> *filter;
|
||||
@property (nonatomic, strong) GPUImageCropFilter *cropfilter;
|
||||
@property (nonatomic, strong) GPUImageOutput<GPUImageInput> *output;
|
||||
@property (nonatomic, strong) GPUImageView *gpuImageView;
|
||||
@property (nonatomic, strong) LFLiveVideoConfiguration *configuration;
|
||||
|
||||
@property (nonatomic, strong) GPUImageAlphaBlendFilter *blendFilter;
|
||||
@property (nonatomic, strong) GPUImageUIElement *uiElementInput;
|
||||
@property (nonatomic, strong) UIView *waterMarkContentView;
|
||||
|
||||
@end
|
||||
|
||||
@@ -33,37 +44,6 @@
|
||||
- (instancetype)initWithVideoConfiguration:(LFLiveVideoConfiguration *)configuration {
|
||||
if (self = [super init]) {
|
||||
_configuration = configuration;
|
||||
if([self pixelBufferImageSize].width < configuration.videoSize.width || [self pixelBufferImageSize].height < configuration.videoSize.height){
|
||||
@throw [NSException exceptionWithName:@"当前videoSize大小出错" reason:@"LFLiveVideoConfiguration videoSize error" userInfo:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:_configuration.avSessionPreset cameraPosition:AVCaptureDevicePositionFront];
|
||||
UIInterfaceOrientation statusBar = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (configuration.landscape) {
|
||||
if (statusBar != UIInterfaceOrientationLandscapeLeft && statusBar != UIInterfaceOrientationLandscapeRight) {
|
||||
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
|
||||
_videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeLeft;
|
||||
} else {
|
||||
_videoCamera.outputImageOrientation = statusBar;
|
||||
}
|
||||
} else {
|
||||
if (statusBar != UIInterfaceOrientationPortrait && statusBar != UIInterfaceOrientationPortraitUpsideDown) {
|
||||
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
|
||||
_videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
|
||||
} else {
|
||||
_videoCamera.outputImageOrientation = statusBar;
|
||||
}
|
||||
}
|
||||
|
||||
_videoCamera.horizontallyMirrorFrontFacingCamera = NO;
|
||||
_videoCamera.horizontallyMirrorRearFacingCamera = NO;
|
||||
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
|
||||
|
||||
_gpuImageView = [[GPUImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
[_gpuImageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill];
|
||||
[_gpuImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
|
||||
[_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterBackground:) name:UIApplicationWillResignActiveNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
@@ -72,6 +52,7 @@
|
||||
self.beautyLevel = 0.5;
|
||||
self.brightLevel = 0.5;
|
||||
self.zoomScale = 1.0;
|
||||
self.mirror = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -79,68 +60,95 @@
|
||||
- (void)dealloc {
|
||||
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[_videoCamera stopCameraCapture];
|
||||
[self.videoCamera stopCameraCapture];
|
||||
if(self.gpuImageView){
|
||||
[self.gpuImageView removeFromSuperview];
|
||||
self.gpuImageView = nil;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -- Setter Getter
|
||||
|
||||
- (GPUImageVideoCamera *)videoCamera{
|
||||
if(!_videoCamera){
|
||||
_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:_configuration.avSessionPreset cameraPosition:AVCaptureDevicePositionFront];
|
||||
UIInterfaceOrientation statusBar = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (self.configuration.landscape) {
|
||||
if (statusBar != UIInterfaceOrientationLandscapeLeft && statusBar != UIInterfaceOrientationLandscapeRight) {
|
||||
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
|
||||
} else {
|
||||
_videoCamera.outputImageOrientation = statusBar;
|
||||
}
|
||||
} else {
|
||||
if (statusBar != UIInterfaceOrientationPortrait && statusBar != UIInterfaceOrientationPortraitUpsideDown) {
|
||||
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
|
||||
} else {
|
||||
_videoCamera.outputImageOrientation = statusBar;
|
||||
}
|
||||
}
|
||||
|
||||
_videoCamera.horizontallyMirrorFrontFacingCamera = YES;
|
||||
_videoCamera.horizontallyMirrorRearFacingCamera = NO;
|
||||
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
|
||||
}
|
||||
return _videoCamera;
|
||||
}
|
||||
|
||||
- (void)setRunning:(BOOL)running {
|
||||
if (_running == running) return;
|
||||
_running = running;
|
||||
|
||||
|
||||
if (!_running) {
|
||||
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
||||
[_videoCamera stopCameraCapture];
|
||||
[self.videoCamera stopCameraCapture];
|
||||
} else {
|
||||
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
||||
[_videoCamera startCameraCapture];
|
||||
[self reloadFilter];
|
||||
[self.videoCamera startCameraCapture];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setPreView:(UIView *)preView {
|
||||
if (_gpuImageView.superview) [_gpuImageView removeFromSuperview];
|
||||
[preView insertSubview:_gpuImageView atIndex:0];
|
||||
if (self.gpuImageView.superview) [self.gpuImageView removeFromSuperview];
|
||||
[preView insertSubview:self.gpuImageView atIndex:0];
|
||||
self.gpuImageView.frame = CGRectMake(0, 0, preView.frame.size.width, preView.frame.size.height);
|
||||
}
|
||||
|
||||
- (UIView *)preView {
|
||||
return _gpuImageView.superview;
|
||||
return self.gpuImageView.superview;
|
||||
}
|
||||
|
||||
- (void)setCaptureDevicePosition:(AVCaptureDevicePosition)captureDevicePosition {
|
||||
[_videoCamera rotateCamera];
|
||||
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
|
||||
if (captureDevicePosition == AVCaptureDevicePositionFront) {
|
||||
[_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];
|
||||
} else {
|
||||
[_gpuImageView setInputRotation:kGPUImageNoRotation atIndex:0];
|
||||
}
|
||||
[self.videoCamera rotateCamera];
|
||||
self.videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
|
||||
}
|
||||
|
||||
- (AVCaptureDevicePosition)captureDevicePosition {
|
||||
return [_videoCamera cameraPosition];
|
||||
return [self.videoCamera cameraPosition];
|
||||
}
|
||||
|
||||
- (void)setVideoFrameRate:(NSInteger)videoFrameRate {
|
||||
if (videoFrameRate <= 0) return;
|
||||
if (videoFrameRate == _videoCamera.frameRate) return;
|
||||
_videoCamera.frameRate = (uint32_t)videoFrameRate;
|
||||
if (videoFrameRate == self.videoCamera.frameRate) return;
|
||||
self.videoCamera.frameRate = (uint32_t)videoFrameRate;
|
||||
}
|
||||
|
||||
- (NSInteger)videoFrameRate {
|
||||
return _videoCamera.frameRate;
|
||||
return self.videoCamera.frameRate;
|
||||
}
|
||||
|
||||
- (void)setTorch:(BOOL)torch {
|
||||
BOOL ret;
|
||||
if (!_videoCamera.captureSession) return;
|
||||
AVCaptureSession *session = (AVCaptureSession *)_videoCamera.captureSession;
|
||||
if (!self.videoCamera.captureSession) return;
|
||||
AVCaptureSession *session = (AVCaptureSession *)self.videoCamera.captureSession;
|
||||
[session beginConfiguration];
|
||||
if (_videoCamera.inputCamera) {
|
||||
if (_videoCamera.inputCamera.torchAvailable) {
|
||||
if (self.videoCamera.inputCamera) {
|
||||
if (self.videoCamera.inputCamera.torchAvailable) {
|
||||
NSError *err = nil;
|
||||
if ([_videoCamera.inputCamera lockForConfiguration:&err]) {
|
||||
[_videoCamera.inputCamera setTorchMode:(torch ? AVCaptureTorchModeOn : AVCaptureTorchModeOff) ];
|
||||
[_videoCamera.inputCamera unlockForConfiguration];
|
||||
ret = (_videoCamera.inputCamera.torchMode == AVCaptureTorchModeOn);
|
||||
if ([self.videoCamera.inputCamera lockForConfiguration:&err]) {
|
||||
[self.videoCamera.inputCamera setTorchMode:(torch ? AVCaptureTorchModeOn : AVCaptureTorchModeOff) ];
|
||||
[self.videoCamera.inputCamera unlockForConfiguration];
|
||||
ret = (self.videoCamera.inputCamera.torchMode == AVCaptureTorchModeOn);
|
||||
} else {
|
||||
NSLog(@"Error while locking device for torch: %@", err);
|
||||
ret = false;
|
||||
@@ -154,22 +162,23 @@
|
||||
}
|
||||
|
||||
- (BOOL)torch {
|
||||
return _videoCamera.inputCamera.torchMode;
|
||||
return self.videoCamera.inputCamera.torchMode;
|
||||
}
|
||||
|
||||
- (void)setMirror:(BOOL)mirror {
|
||||
_videoCamera.horizontallyMirrorFrontFacingCamera = mirror;
|
||||
_videoCamera.horizontallyMirrorRearFacingCamera = mirror;
|
||||
_mirror = mirror;
|
||||
self.videoCamera.horizontallyMirrorFrontFacingCamera = mirror;
|
||||
}
|
||||
|
||||
- (BOOL)mirror {
|
||||
return _videoCamera.horizontallyMirrorFrontFacingCamera;
|
||||
- (void)setBeautyFace:(BOOL)beautyFace{
|
||||
_beautyFace = beautyFace;
|
||||
[self reloadFilter];
|
||||
}
|
||||
|
||||
- (void)setBeautyLevel:(CGFloat)beautyLevel {
|
||||
_beautyLevel = beautyLevel;
|
||||
if (_beautyFilter) {
|
||||
[_beautyFilter setBeautyLevel:_beautyLevel];
|
||||
if (self.beautyFilter) {
|
||||
[self.beautyFilter setBeautyLevel:_beautyLevel];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +188,8 @@
|
||||
|
||||
- (void)setBrightLevel:(CGFloat)brightLevel {
|
||||
_brightLevel = brightLevel;
|
||||
if (_beautyFilter) {
|
||||
[_beautyFilter setBrightLevel:brightLevel];
|
||||
if (self.beautyFilter) {
|
||||
[self.beautyFilter setBrightLevel:brightLevel];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,54 +212,57 @@
|
||||
return _zoomScale;
|
||||
}
|
||||
|
||||
- (void)setBeautyFace:(BOOL)beautyFace {
|
||||
|
||||
_beautyFace = beautyFace;
|
||||
[_filter removeAllTargets];
|
||||
[_cropfilter removeAllTargets];
|
||||
[_videoCamera removeAllTargets];
|
||||
|
||||
if (_beautyFace) {
|
||||
_output = [[LFGPUImageEmptyFilter alloc] init];
|
||||
_filter = [[LFGPUImageBeautyFilter alloc] init];
|
||||
_beautyFilter = _filter;
|
||||
__weak typeof(self) _self = self;
|
||||
[_output setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
|
||||
[_self processVideo:output];
|
||||
}];
|
||||
} else {
|
||||
_filter = [[LFGPUImageEmptyFilter alloc] init];
|
||||
_beautyFilter = nil;
|
||||
__weak typeof(self) _self = self;
|
||||
[_filter setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
|
||||
[_self processVideo:output];
|
||||
}];
|
||||
- (void)setWarterMarkView:(UIView *)warterMarkView{
|
||||
if(_warterMarkView && _warterMarkView.superview){
|
||||
[_warterMarkView removeFromSuperview];
|
||||
_warterMarkView = nil;
|
||||
}
|
||||
_warterMarkView = warterMarkView;
|
||||
self.blendFilter.mix = warterMarkView.alpha;
|
||||
[self.waterMarkContentView addSubview:_warterMarkView];
|
||||
[self reloadFilter];
|
||||
}
|
||||
|
||||
CGSize imageSize = [self pixelBufferImageSize];
|
||||
CGFloat cropLeft = (imageSize.width - self.configuration.videoSize.width)/2.0/imageSize.width;
|
||||
CGFloat cropTop = (imageSize.height - self.configuration.videoSize.height)/2.0/imageSize.height;
|
||||
|
||||
if(cropLeft == 0 && cropTop == 0){
|
||||
[_videoCamera addTarget:_filter];
|
||||
}else{
|
||||
_cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(cropLeft, cropTop, 1 - cropLeft*2, 1 - cropTop*2)];
|
||||
[_videoCamera addTarget:_cropfilter];
|
||||
[_cropfilter addTarget:_filter];
|
||||
}
|
||||
|
||||
if (_beautyFace) {
|
||||
[_filter addTarget:_output];
|
||||
[_output addTarget:_gpuImageView];
|
||||
} else {
|
||||
[_filter addTarget:_gpuImageView];
|
||||
- (GPUImageUIElement *)uiElementInput{
|
||||
if(!_uiElementInput){
|
||||
_uiElementInput = [[GPUImageUIElement alloc] initWithView:self.waterMarkContentView];
|
||||
}
|
||||
return _uiElementInput;
|
||||
}
|
||||
|
||||
if (_videoCamera.cameraPosition == AVCaptureDevicePositionFront) {
|
||||
[_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];
|
||||
} else {
|
||||
[_gpuImageView setInputRotation:kGPUImageNoRotation atIndex:0];
|
||||
- (GPUImageAlphaBlendFilter *)blendFilter{
|
||||
if(!_blendFilter){
|
||||
_blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
|
||||
_blendFilter.mix = 1.0;
|
||||
[_blendFilter disableSecondFrameCheck];
|
||||
}
|
||||
return _blendFilter;
|
||||
}
|
||||
|
||||
- (UIView *)waterMarkContentView{
|
||||
if(!_waterMarkContentView){
|
||||
_waterMarkContentView = [UIView new];
|
||||
_waterMarkContentView.frame = CGRectMake(0, 0, self.configuration.videoSize.width, self.configuration.videoSize.height);
|
||||
_waterMarkContentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
}
|
||||
return _waterMarkContentView;
|
||||
}
|
||||
|
||||
- (GPUImageView *)gpuImageView{
|
||||
if(!_gpuImageView){
|
||||
_gpuImageView = [[GPUImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
[_gpuImageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill];
|
||||
[_gpuImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
|
||||
}
|
||||
return _gpuImageView;
|
||||
}
|
||||
|
||||
-(UIImage *)currentImage{
|
||||
if(_filter){
|
||||
[_filter useNextFrameForImageCapture];
|
||||
return _filter.imageFromCurrentFramebuffer;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark -- Custom Method
|
||||
@@ -259,33 +271,85 @@
|
||||
@autoreleasepool {
|
||||
GPUImageFramebuffer *imageFramebuffer = output.framebufferForOutput;
|
||||
CVPixelBufferRef pixelBuffer = [imageFramebuffer pixelBuffer];
|
||||
|
||||
if (pixelBuffer && _self.delegate && [_self.delegate respondsToSelector:@selector(captureOutput:pixelBuffer:)]) {
|
||||
[_self.delegate captureOutput:_self pixelBuffer:pixelBuffer];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)reloadFilter{
|
||||
[self.filter removeAllTargets];
|
||||
[self.blendFilter removeAllTargets];
|
||||
[self.uiElementInput removeAllTargets];
|
||||
[self.videoCamera removeAllTargets];
|
||||
[self.output removeAllTargets];
|
||||
[self.cropfilter removeAllTargets];
|
||||
|
||||
if (self.beautyFace) {
|
||||
self.output = [[LFGPUImageEmptyFilter alloc] init];
|
||||
self.filter = [[LFGPUImageBeautyFilter alloc] init];
|
||||
self.beautyFilter = (LFGPUImageBeautyFilter*)self.filter;
|
||||
} else {
|
||||
self.output = [[LFGPUImageEmptyFilter alloc] init];
|
||||
self.filter = [[LFGPUImageEmptyFilter alloc] init];
|
||||
self.beautyFilter = nil;
|
||||
}
|
||||
|
||||
//< 480*640 比例为4:3 强制转换为16:9
|
||||
if([self.configuration.avSessionPreset isEqualToString:AVCaptureSessionPreset640x480]){
|
||||
CGRect cropRect = self.configuration.landscape ? CGRectMake(0, 0.125, 1, 0.75) : CGRectMake(0.125, 0, 0.75, 1);
|
||||
self.cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:cropRect];
|
||||
[self.videoCamera addTarget:self.cropfilter];
|
||||
[self.cropfilter addTarget:self.filter];
|
||||
}else{
|
||||
[self.videoCamera addTarget:self.filter];
|
||||
}
|
||||
|
||||
//< 添加水印
|
||||
if(self.warterMarkView){
|
||||
[self.filter addTarget:self.blendFilter];
|
||||
[self.uiElementInput addTarget:self.blendFilter];
|
||||
[self.blendFilter addTarget:self.gpuImageView];
|
||||
[self.filter addTarget:self.output];
|
||||
[self.uiElementInput update];
|
||||
}else{
|
||||
[self.filter addTarget:self.output];
|
||||
[self.output addTarget:self.gpuImageView];
|
||||
}
|
||||
|
||||
[self.filter forceProcessingAtSize:self.configuration.videoSize];
|
||||
[self.output forceProcessingAtSize:self.configuration.videoSize];
|
||||
[self.blendFilter forceProcessingAtSize:self.configuration.videoSize];
|
||||
[self.uiElementInput forceProcessingAtSize:self.configuration.videoSize];
|
||||
|
||||
//< 输出数据
|
||||
__weak typeof(self) _self = self;
|
||||
[self.output setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
|
||||
[_self processVideo:output];
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark Notification
|
||||
|
||||
- (void)willEnterBackground:(NSNotification *)notification {
|
||||
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
||||
[_videoCamera pauseCameraCapture];
|
||||
[self.videoCamera pauseCameraCapture];
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
glFinish();
|
||||
});
|
||||
}
|
||||
|
||||
- (void)willEnterForeground:(NSNotification *)notification {
|
||||
[_videoCamera resumeCameraCapture];
|
||||
[self.videoCamera resumeCameraCapture];
|
||||
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
||||
}
|
||||
|
||||
- (void)statusBarChanged:(NSNotification *)notification {
|
||||
NSLog(@"UIApplicationWillChangeStatusBarOrientationNotification. UserInfo: %@", notification.userInfo);
|
||||
UIInterfaceOrientation statusBar = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (_configuration.landscape) {
|
||||
if (self.configuration.landscape) {
|
||||
if (statusBar == UIInterfaceOrientationLandscapeLeft) {
|
||||
self.videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeRight;
|
||||
} else if (statusBar == UIInterfaceOrientationLandscapeRight) {
|
||||
@@ -300,34 +364,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark --
|
||||
- (CGSize)pixelBufferImageSize{
|
||||
CGSize videoSize = CGSizeZero;
|
||||
switch (self.configuration.sessionPreset) {
|
||||
case LFCaptureSessionPreset360x640:
|
||||
{
|
||||
videoSize = CGSizeMake(480, 640);
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset540x960:
|
||||
{
|
||||
videoSize = CGSizeMake(540, 960);
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset720x1280:
|
||||
{
|
||||
videoSize = CGSizeMake(720, 1280);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(self.configuration.landscape){
|
||||
return CGSizeMake(videoSize.height, videoSize.width);
|
||||
}
|
||||
return videoSize;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -12,21 +12,20 @@
|
||||
#import <AVFoundation/AVMediaFormat.h>
|
||||
#import <AVFoundation/AVVideoSettings.h>
|
||||
#import "sys/stat.h"
|
||||
#import "VideoEncoder.h"
|
||||
#import "MP4Atom.h"
|
||||
#import "LFVideoEncoder.h"
|
||||
#import "LFMP4Atom.h"
|
||||
|
||||
typedef int (^encoder_handler_t)(NSArray *data, CMTimeValue ptsValue);
|
||||
typedef int (^param_handler_t)(NSData *params);
|
||||
|
||||
@interface AVEncoder : NSObject
|
||||
@interface LFAVEncoder : NSObject
|
||||
|
||||
@property (atomic) NSUInteger bitrate;
|
||||
|
||||
+ (AVEncoder *)encoderForHeight:(int)height andWidth:(int)width bitrate:(int)bitrate;
|
||||
+ (LFAVEncoder *)encoderForHeight:(int)height andWidth:(int)width bitrate:(int)bitrate;
|
||||
|
||||
- (void)encodeWithBlock:(encoder_handler_t)block onParams:(param_handler_t)paramsHandler;
|
||||
- (void)encodeFrame:(CMSampleBufferRef)sampleBuffer;
|
||||
- (void)encodePixelBuffer:(CVPixelBufferRef)pixelBuffer pts:(CMTime)pts;
|
||||
- (NSData *)getConfigData;
|
||||
- (void)shutdown;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// Copyright (c) 2013 GDCL http://www.gdcl.co.uk/license.htm
|
||||
//
|
||||
|
||||
#import "AVEncoder.h"
|
||||
#import "NALUnit.h"
|
||||
#import "LFAVEncoder.h"
|
||||
#import "LFNALUnit.h"
|
||||
|
||||
static void *AVEncoderContext = &AVEncoderContext;
|
||||
|
||||
@@ -19,14 +19,14 @@ static unsigned int to_host(unsigned char *p){
|
||||
#define MAX_FILENAME_INDEX 5 // filenames "capture1.mp4" wraps at capture5.mp4
|
||||
|
||||
|
||||
@interface AVEncoder ()
|
||||
@interface LFAVEncoder ()
|
||||
|
||||
{
|
||||
// initial writer, used to obtain SPS/PPS from header
|
||||
VideoEncoder *_headerWriter;
|
||||
LFVideoEncoder *_headerWriter;
|
||||
|
||||
// main encoder/writer
|
||||
VideoEncoder *_writer;
|
||||
LFVideoEncoder *_writer;
|
||||
|
||||
// writer output file (input to our extractor) and monitoring
|
||||
NSFileHandle *_inputFile;
|
||||
@@ -70,12 +70,12 @@ static unsigned int to_host(unsigned char *p){
|
||||
|
||||
@end
|
||||
|
||||
@implementation AVEncoder
|
||||
@implementation LFAVEncoder
|
||||
|
||||
@synthesize bitspersecond = _bitspersecond;
|
||||
|
||||
+ (AVEncoder *)encoderForHeight:(int)height andWidth:(int)width bitrate:(int)bitrate {
|
||||
AVEncoder *enc = [AVEncoder alloc];
|
||||
+ (LFAVEncoder *)encoderForHeight:(int)height andWidth:(int)width bitrate:(int)bitrate {
|
||||
LFAVEncoder *enc = [LFAVEncoder alloc];
|
||||
[enc initForHeight:height andWidth:width bitrate:bitrate];
|
||||
return enc;
|
||||
}
|
||||
@@ -91,12 +91,12 @@ static unsigned int to_host(unsigned char *p){
|
||||
_width = width;
|
||||
_bitrate = bitrate;
|
||||
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"params.mp4"];
|
||||
_headerWriter = [VideoEncoder encoderForPath:path Height:height andWidth:width bitrate:self.bitrate];
|
||||
_headerWriter = [LFVideoEncoder encoderForPath:path Height:height andWidth:width bitrate:(int)self.bitrate];
|
||||
_times = [NSMutableArray arrayWithCapacity:10];
|
||||
|
||||
// swap between 3 filenames
|
||||
_currentFile = 1;
|
||||
_writer = [VideoEncoder encoderForPath:[self makeFilename] Height:height andWidth:width bitrate:self.bitrate];
|
||||
_writer = [LFVideoEncoder encoderForPath:[self makeFilename] Height:height andWidth:width bitrate:(int)self.bitrate];
|
||||
|
||||
[self addObserver:self forKeyPath:NSStringFromSelector(@selector(bitrate)) options:0 context:AVEncoderContext];
|
||||
}
|
||||
@@ -123,9 +123,9 @@ static unsigned int to_host(unsigned char *p){
|
||||
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
|
||||
struct stat s;
|
||||
fstat([file fileDescriptor], &s);
|
||||
MP4Atom *movie = [MP4Atom atomAt:0 size:s.st_size type:(OSType)('file') inFile:file];
|
||||
MP4Atom *moov = [movie childOfType:(OSType)('moov') startAt:0];
|
||||
MP4Atom *trak = nil;
|
||||
LFMP4Atom *movie = [LFMP4Atom atomAt:0 size:(int)s.st_size type:(OSType)('file') inFile:file];
|
||||
LFMP4Atom *moov = [movie childOfType:(OSType)('moov') startAt:0];
|
||||
LFMP4Atom *trak = nil;
|
||||
if (moov != nil) {
|
||||
for (;; ) {
|
||||
trak = [moov nextChild];
|
||||
@@ -134,7 +134,7 @@ static unsigned int to_host(unsigned char *p){
|
||||
}
|
||||
|
||||
if (trak.type == (OSType)('trak')) {
|
||||
MP4Atom *tkhd = [trak childOfType:(OSType)('tkhd') startAt:0];
|
||||
LFMP4Atom *tkhd = [trak childOfType:(OSType)('tkhd') startAt:0];
|
||||
NSData *verflags = [tkhd readAt:0 size:4];
|
||||
unsigned char *p = (unsigned char *)[verflags bytes];
|
||||
if (p[3] & 1) {
|
||||
@@ -145,13 +145,13 @@ static unsigned int to_host(unsigned char *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
MP4Atom *stsd = nil;
|
||||
LFMP4Atom *stsd = nil;
|
||||
if (trak != nil) {
|
||||
MP4Atom *media = [trak childOfType:(OSType)('mdia') startAt:0];
|
||||
LFMP4Atom *media = [trak childOfType:(OSType)('mdia') startAt:0];
|
||||
if (media != nil) {
|
||||
MP4Atom *minf = [media childOfType:(OSType)('minf') startAt:0];
|
||||
LFMP4Atom *minf = [media childOfType:(OSType)('minf') startAt:0];
|
||||
if (minf != nil) {
|
||||
MP4Atom *stbl = [minf childOfType:(OSType)('stbl') startAt:0];
|
||||
LFMP4Atom *stbl = [minf childOfType:(OSType)('stbl') startAt:0];
|
||||
if (stbl != nil) {
|
||||
stsd = [stbl childOfType:(OSType)('stsd') startAt:0];
|
||||
}
|
||||
@@ -159,12 +159,12 @@ static unsigned int to_host(unsigned char *p){
|
||||
}
|
||||
}
|
||||
if (stsd != nil) {
|
||||
MP4Atom *avc1 = [stsd childOfType:(OSType)('avc1') startAt:8];
|
||||
LFMP4Atom *avc1 = [stsd childOfType:(OSType)('avc1') startAt:8];
|
||||
if (avc1 != nil) {
|
||||
MP4Atom *esd = [avc1 childOfType:(OSType)('avcC') startAt:78];
|
||||
LFMP4Atom *esd = [avc1 childOfType:(OSType)('avcC') startAt:78];
|
||||
if (esd != nil) {
|
||||
// this is the avcC record that we are looking for
|
||||
_avcC = [esd readAt:0 size:esd.length];
|
||||
_avcC = [esd readAt:0 size:(int)esd.length];
|
||||
if (_avcC != nil) {
|
||||
// extract size of length field
|
||||
unsigned char *p = (unsigned char *)[_avcC bytes];
|
||||
@@ -229,14 +229,14 @@ static unsigned int to_host(unsigned char *p){
|
||||
if (st.st_size > OUTPUT_FILE_SWITCH_POINT || self.bitrateChanged) {
|
||||
self.bitrateChanged = NO;
|
||||
_swapping = YES;
|
||||
VideoEncoder *oldVideo = _writer;
|
||||
LFVideoEncoder *oldVideo = _writer;
|
||||
|
||||
// construct a new writer to the next filename
|
||||
if (++_currentFile > MAX_FILENAME_INDEX) {
|
||||
_currentFile = 1;
|
||||
}
|
||||
//NSLog(@"Swap to file %d", _currentFile);
|
||||
_writer = [VideoEncoder encoderForPath:[self makeFilename] Height:_height andWidth:_width bitrate:self.bitrate];
|
||||
_writer = [LFVideoEncoder encoderForPath:[self makeFilename] Height:_height andWidth:_width bitrate:(int)self.bitrate];
|
||||
|
||||
// to do this seamlessly requires a few steps in the right order
|
||||
// first, suspend the read source
|
||||
@@ -319,7 +319,7 @@ static unsigned int to_host(unsigned char *p){
|
||||
// called whenever there is more data to read in the main encoder output file.
|
||||
struct stat s;
|
||||
fstat([_inputFile fileDescriptor], &s);
|
||||
int cReady = s.st_size - [_inputFile offsetInFile];
|
||||
int cReady = (int)(s.st_size - [_inputFile offsetInFile]);
|
||||
|
||||
// locate the mdat atom if needed
|
||||
while (!_foundMDAT && (cReady > 8)) {
|
||||
@@ -385,7 +385,7 @@ static unsigned int to_host(unsigned char *p){
|
||||
int naltype = pNal[0] & 0x1f;
|
||||
|
||||
if (_pendingNALU) {
|
||||
NALUnit nal(pNal, [nalu length]);
|
||||
LFNALUnit nal(pNal, (int)[nalu length]);
|
||||
|
||||
// we have existing data —is this the same frame?
|
||||
// typically there are a couple of NALUs per frame in iOS encoding.
|
||||
@@ -397,7 +397,7 @@ static unsigned int to_host(unsigned char *p){
|
||||
bNew = YES;
|
||||
} else if ((naltype >= 1) && (naltype <= 5)) {
|
||||
nal.Skip(8);
|
||||
int first_mb = nal.GetUE();
|
||||
int first_mb = (int)nal.GetUE();
|
||||
if (first_mb == 0) {
|
||||
bNew = YES;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// MP4Atom.h
|
||||
// LFMP4Atom.h
|
||||
// Encoder Demo
|
||||
//
|
||||
// Created by Geraint Davies on 15/01/2013.
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MP4Atom : NSObject
|
||||
@interface LFMP4Atom : NSObject
|
||||
|
||||
{
|
||||
NSFileHandle *_file;
|
||||
@@ -20,11 +20,11 @@
|
||||
@property OSType type;
|
||||
@property int64_t length;
|
||||
|
||||
+ (MP4Atom *)atomAt:(int64_t)offset size:(int)length type:(OSType)fourcc inFile:(NSFileHandle *)handle;
|
||||
+ (LFMP4Atom *)atomAt:(int64_t)offset size:(int)length type:(OSType)fourcc inFile:(NSFileHandle *)handle;
|
||||
- (BOOL)init:(int64_t)offset size:(int)length type:(OSType)fourcc inFile:(NSFileHandle *)handle;
|
||||
- (NSData *)readAt:(int64_t)offset size:(int)length;
|
||||
- (BOOL)setChildOffset:(int64_t)offset;
|
||||
- (MP4Atom *)nextChild;
|
||||
- (MP4Atom *)childOfType:(OSType)fourcc startAt:(int64_t)offset;
|
||||
- (LFMP4Atom *)nextChild;
|
||||
- (LFMP4Atom *)childOfType:(OSType)fourcc startAt:(int64_t)offset;
|
||||
|
||||
@end
|
||||
@@ -1,24 +1,24 @@
|
||||
//
|
||||
// MP4Atom.m
|
||||
// LFMP4Atom.m
|
||||
// Encoder Demo
|
||||
//
|
||||
// Created by Geraint Davies on 15/01/2013.
|
||||
// Copyright (c) 2013 GDCL http://www.gdcl.co.uk/license.htm
|
||||
//
|
||||
|
||||
#import "MP4Atom.h"
|
||||
#import "LFMP4Atom.h"
|
||||
|
||||
static unsigned int to_host(unsigned char *p){
|
||||
return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
|
||||
}
|
||||
|
||||
@implementation MP4Atom
|
||||
@implementation LFMP4Atom
|
||||
|
||||
@synthesize type = _type;
|
||||
@synthesize length = _length;
|
||||
|
||||
+ (MP4Atom *)atomAt:(int64_t)offset size:(int)length type:(OSType)fourcc inFile:(NSFileHandle *)handle {
|
||||
MP4Atom *atom = [MP4Atom alloc];
|
||||
+ (LFMP4Atom *)atomAt:(int64_t)offset size:(int)length type:(OSType)fourcc inFile:(NSFileHandle *)handle {
|
||||
LFMP4Atom *atom = [LFMP4Atom alloc];
|
||||
if (![atom init:offset size:length type:fourcc inFile:handle]) {
|
||||
return nil;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ static unsigned int to_host(unsigned char *p){
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (MP4Atom *)nextChild {
|
||||
- (LFMP4Atom *)nextChild {
|
||||
if (_nextChild <= (_length - 8)) {
|
||||
[_file seekToFileOffset:_offset + _nextChild];
|
||||
NSData *data = [_file readDataOfLength:8];
|
||||
@@ -73,14 +73,14 @@ static unsigned int to_host(unsigned char *p){
|
||||
int64_t offset = _nextChild + cHeader;
|
||||
_nextChild += len;
|
||||
len -= cHeader;
|
||||
return [MP4Atom atomAt:offset+_offset size:len type:fourcc inFile:_file];
|
||||
return [LFMP4Atom atomAt:offset+_offset size:(int)len type:fourcc inFile:_file];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (MP4Atom *)childOfType:(OSType)fourcc startAt:(int64_t)offset {
|
||||
- (LFMP4Atom *)childOfType:(OSType)fourcc startAt:(int64_t)offset {
|
||||
[self setChildOffset:offset];
|
||||
MP4Atom *child = nil;
|
||||
LFMP4Atom *child = nil;
|
||||
do {
|
||||
child = [self nextChild];
|
||||
} while ((child != nil) && (child.type != fourcc));
|
||||
@@ -10,18 +10,18 @@
|
||||
|
||||
|
||||
|
||||
#include "NALUnit.h"
|
||||
#include "LFNALUnit.h"
|
||||
|
||||
|
||||
// --- core NAL Unit implementation ------------------------------
|
||||
|
||||
NALUnit::NALUnit()
|
||||
LFNALUnit::LFNALUnit()
|
||||
: m_pStart(NULL),
|
||||
m_cBytes(0){
|
||||
}
|
||||
|
||||
bool
|
||||
NALUnit::GetStartCode(const BYTE *& pBegin, const BYTE *& pStart, int& cRemain){
|
||||
LFNALUnit::GetStartCode(const BYTE *& pBegin, const BYTE *& pStart, int& cRemain){
|
||||
// start code is any number of 00 followed by 00 00 01
|
||||
// We need to record the first 00 in pBegin and the first byte
|
||||
// following the startcode in pStart.
|
||||
@@ -54,7 +54,7 @@ NALUnit::GetStartCode(const BYTE *& pBegin, const BYTE *& pStart, int& cRemain){
|
||||
}
|
||||
|
||||
bool
|
||||
NALUnit::Parse(const BYTE *pBuffer, int cSpace, int LengthSize, bool bEnd){
|
||||
LFNALUnit::Parse(const BYTE *pBuffer, int cSpace, int LengthSize, bool bEnd){
|
||||
// if we get the start code but not the whole
|
||||
// NALU, we can return false but still have the length property valid
|
||||
m_cBytes = 0;
|
||||
@@ -102,14 +102,14 @@ NALUnit::Parse(const BYTE *pBuffer, int cSpace, int LengthSize, bool bEnd){
|
||||
|
||||
// bitwise access to data
|
||||
void
|
||||
NALUnit::ResetBitstream(){
|
||||
LFNALUnit::ResetBitstream(){
|
||||
m_idx = 0;
|
||||
m_nBits = 0;
|
||||
m_cZeros = 0;
|
||||
}
|
||||
|
||||
void
|
||||
NALUnit::Skip(int nBits){
|
||||
LFNALUnit::Skip(int nBits){
|
||||
if (nBits < m_nBits) {
|
||||
m_nBits -= nBits;
|
||||
} else {
|
||||
@@ -129,7 +129,7 @@ NALUnit::Skip(int nBits){
|
||||
|
||||
// get the next byte, removing emulation prevention bytes
|
||||
BYTE
|
||||
NALUnit::GetBYTE(){
|
||||
LFNALUnit::GetBYTE(){
|
||||
if (m_idx >= m_cBytes) {
|
||||
return 0;
|
||||
}
|
||||
@@ -151,7 +151,7 @@ NALUnit::GetBYTE(){
|
||||
}
|
||||
|
||||
unsigned long
|
||||
NALUnit::GetBit(){
|
||||
LFNALUnit::GetBit(){
|
||||
if (m_nBits == 0) {
|
||||
m_byte = GetBYTE();
|
||||
m_nBits = 8;
|
||||
@@ -161,7 +161,7 @@ NALUnit::GetBit(){
|
||||
}
|
||||
|
||||
unsigned long
|
||||
NALUnit::GetWord(int nBits){
|
||||
LFNALUnit::GetWord(int nBits){
|
||||
unsigned long u = 0;
|
||||
while (nBits > 0) {
|
||||
u <<= 1;
|
||||
@@ -172,7 +172,7 @@ NALUnit::GetWord(int nBits){
|
||||
}
|
||||
|
||||
unsigned long
|
||||
NALUnit::GetUE(){
|
||||
LFNALUnit::GetUE(){
|
||||
// Exp-Golomb entropy coding: leading zeros, then a one, then
|
||||
// the data bits. The number of leading zeros is the number of
|
||||
// data bits, counting up from that number of 1s as the base.
|
||||
@@ -188,7 +188,7 @@ NALUnit::GetUE(){
|
||||
}
|
||||
|
||||
long
|
||||
NALUnit::GetSE(){
|
||||
LFNALUnit::GetSE(){
|
||||
// same as UE but signed.
|
||||
// basically the unsigned numbers are used as codes to indicate signed numbers in pairs
|
||||
// in increasing value. Thus the encoded values
|
||||
@@ -206,7 +206,7 @@ NALUnit::GetSE(){
|
||||
}
|
||||
|
||||
// --- sequence params parsing ---------------
|
||||
SeqParamSet::SeqParamSet()
|
||||
LFSeqParamSet::LFSeqParamSet()
|
||||
: m_cx(0),
|
||||
m_cy(0),
|
||||
m_FrameBits(0){
|
||||
@@ -214,7 +214,7 @@ SeqParamSet::SeqParamSet()
|
||||
}
|
||||
|
||||
void
|
||||
ScalingList(int size, NALUnit *pnalu){
|
||||
ScalingList(int size, LFNALUnit *pnalu){
|
||||
long lastScale = 8;
|
||||
long nextScale = 8;
|
||||
for (int j = 0; j < size; j++) {
|
||||
@@ -222,14 +222,14 @@ ScalingList(int size, NALUnit *pnalu){
|
||||
long delta = pnalu->GetSE();
|
||||
nextScale = (lastScale + delta + 256) %256;
|
||||
}
|
||||
int scaling_list_j = (nextScale == 0) ? lastScale : nextScale;
|
||||
int scaling_list_j = (nextScale == 0) ? (int)lastScale : (int)nextScale;
|
||||
lastScale = scaling_list_j;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SeqParamSet::Parse(NALUnit *pnalu){
|
||||
if (pnalu->Type() != NALUnit::NAL_Sequence_Params) {
|
||||
LFSeqParamSet::Parse(LFNALUnit *pnalu){
|
||||
if (pnalu->Type() != LFNALUnit::NAL_Sequence_Params) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -237,21 +237,21 @@ SeqParamSet::Parse(NALUnit *pnalu){
|
||||
// to get through to the ones we want
|
||||
pnalu->ResetBitstream();
|
||||
pnalu->Skip(8); // type
|
||||
m_Profile = pnalu->GetWord(8);
|
||||
m_Profile =(int) pnalu->GetWord(8);
|
||||
m_Compatibility = (BYTE)pnalu->GetWord(8);
|
||||
m_Level = pnalu->GetWord(8);
|
||||
m_Level = (int)pnalu->GetWord(8);
|
||||
|
||||
/*int seq_param_id =*/ pnalu->GetUE();
|
||||
|
||||
if ((m_Profile == 100) || (m_Profile == 110) || (m_Profile == 122) || (m_Profile == 144)) {
|
||||
int chroma_fmt = pnalu->GetUE();
|
||||
int chroma_fmt = (int)pnalu->GetUE();
|
||||
if (chroma_fmt == 3) {
|
||||
pnalu->Skip(1);
|
||||
}
|
||||
/* int bit_depth_luma_minus8 = */ pnalu->GetUE();
|
||||
/* int bit_depth_chroma_minus8 = */ pnalu->GetUE();
|
||||
pnalu->Skip(1);
|
||||
int seq_scaling_matrix_present = pnalu->GetBit();
|
||||
int seq_scaling_matrix_present = (int)pnalu->GetBit();
|
||||
if (seq_scaling_matrix_present) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (pnalu->GetBit()) {
|
||||
@@ -265,16 +265,16 @@ SeqParamSet::Parse(NALUnit *pnalu){
|
||||
}
|
||||
}
|
||||
|
||||
int log2_frame_minus4 = pnalu->GetUE();
|
||||
int log2_frame_minus4 = (int)pnalu->GetUE();
|
||||
m_FrameBits = log2_frame_minus4 + 4;
|
||||
int POCtype = pnalu->GetUE();
|
||||
int POCtype = (int)pnalu->GetUE();
|
||||
if (POCtype == 0) {
|
||||
/*int log2_poc_minus4 =*/ pnalu->GetUE();
|
||||
} else if (POCtype == 1) {
|
||||
pnalu->Skip(1); // delta always zero
|
||||
/*int nsp_offset =*/ pnalu->GetSE();
|
||||
/*int nsp_top_to_bottom = */ pnalu->GetSE();
|
||||
int num_ref_in_cycle = pnalu->GetUE();
|
||||
int num_ref_in_cycle = (int)pnalu->GetUE();
|
||||
for (int i = 0; i < num_ref_in_cycle; i++) {
|
||||
/*int sf_offset =*/ pnalu->GetSE();
|
||||
}
|
||||
@@ -286,8 +286,8 @@ SeqParamSet::Parse(NALUnit *pnalu){
|
||||
/*int num_ref_frames =*/ pnalu->GetUE();
|
||||
/*int gaps_allowed =*/ pnalu->GetBit();
|
||||
|
||||
int mbs_width = pnalu->GetUE();
|
||||
int mbs_height = pnalu->GetUE();
|
||||
int mbs_width = (int)pnalu->GetUE();
|
||||
int mbs_height = (int)pnalu->GetUE();
|
||||
m_cx = (mbs_width+1) * 16;
|
||||
m_cy = (mbs_height+1) * 16;
|
||||
|
||||
@@ -339,11 +339,11 @@ SeqParamSet::Parse(NALUnit *pnalu){
|
||||
|
||||
// --- slice header --------------------
|
||||
bool
|
||||
SliceHeader::Parse(NALUnit *pnalu){
|
||||
LFSliceHeader::Parse(LFNALUnit *pnalu){
|
||||
switch (pnalu->Type()) {
|
||||
case NALUnit::NAL_IDR_Slice:
|
||||
case NALUnit::NAL_Slice:
|
||||
case NALUnit::NAL_PartitionA:
|
||||
case LFNALUnit::NAL_IDR_Slice:
|
||||
case LFNALUnit::NAL_Slice:
|
||||
case LFNALUnit::NAL_PartitionA:
|
||||
// all these begin with a slice header
|
||||
break;
|
||||
|
||||
@@ -359,14 +359,14 @@ SliceHeader::Parse(NALUnit *pnalu){
|
||||
pnalu->GetUE(); // slice type
|
||||
pnalu->GetUE(); // pic param set id
|
||||
|
||||
m_framenum = pnalu->GetWord(m_nBitsFrame);
|
||||
m_framenum = (int)pnalu->GetWord(m_nBitsFrame);
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- SEI ----------------------
|
||||
|
||||
|
||||
SEIMessage::SEIMessage(NALUnit *pnalu){
|
||||
LFSEIMessage::LFSEIMessage(LFNALUnit *pnalu){
|
||||
m_pnalu = pnalu;
|
||||
const BYTE *p = pnalu->Start();
|
||||
p++; // nalu type byte
|
||||
@@ -387,7 +387,7 @@ SEIMessage::SEIMessage(NALUnit *pnalu){
|
||||
m_idxPayload = int(p - m_pnalu->Start());
|
||||
}
|
||||
|
||||
avcCHeader::avcCHeader(const BYTE *header, int cBytes){
|
||||
LFavcCHeader::LFavcCHeader(const BYTE *header, int cBytes){
|
||||
if (cBytes < 8) {
|
||||
return;
|
||||
}
|
||||
@@ -405,7 +405,7 @@ avcCHeader::avcCHeader(const BYTE *header, int cBytes){
|
||||
return;
|
||||
}
|
||||
if (i == 0) {
|
||||
NALUnit n(header, cThis);
|
||||
LFNALUnit n(header, cThis);
|
||||
m_sps = n;
|
||||
}
|
||||
header += cThis;
|
||||
@@ -417,7 +417,7 @@ avcCHeader::avcCHeader(const BYTE *header, int cBytes){
|
||||
if (cPPS > 0) {
|
||||
int cThis = (header[1] << 8) + header[2];
|
||||
header += 3;
|
||||
NALUnit n(header, cThis);
|
||||
LFNALUnit n(header, cThis);
|
||||
m_pps = n;
|
||||
}
|
||||
}
|
||||
@@ -18,25 +18,25 @@ typedef unsigned long ULONG;
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
class NALUnit
|
||||
class LFNALUnit
|
||||
{
|
||||
public:
|
||||
NALUnit();
|
||||
NALUnit(const BYTE* pStart, int len){
|
||||
LFNALUnit();
|
||||
LFNALUnit(const BYTE* pStart, int len){
|
||||
m_pStart = m_pStartCodeStart = pStart;
|
||||
m_cBytes = len;
|
||||
ResetBitstream();
|
||||
}
|
||||
virtual ~NALUnit() {
|
||||
virtual ~LFNALUnit() {
|
||||
}
|
||||
|
||||
// assignment copies a pointer into a fixed buffer managed elsewhere. We do not copy the data
|
||||
NALUnit(const NALUnit &r){
|
||||
LFNALUnit(const LFNALUnit &r){
|
||||
m_pStart = r.m_pStart;
|
||||
m_cBytes = r.m_cBytes;
|
||||
ResetBitstream();
|
||||
}
|
||||
const NALUnit& operator = (const NALUnit &r)
|
||||
const LFNALUnit& operator = (const LFNALUnit &r)
|
||||
{
|
||||
m_pStart = r.m_pStart;
|
||||
m_cBytes = r.m_cBytes;
|
||||
@@ -109,11 +109,11 @@ private:
|
||||
|
||||
|
||||
// simple parser for the Sequence parameter set things that we need
|
||||
class SeqParamSet
|
||||
class LFSeqParamSet
|
||||
{
|
||||
public:
|
||||
SeqParamSet();
|
||||
bool Parse(NALUnit *pnalu);
|
||||
LFSeqParamSet();
|
||||
bool Parse(LFNALUnit *pnalu);
|
||||
int FrameBits(){
|
||||
return m_FrameBits;
|
||||
}
|
||||
@@ -162,12 +162,12 @@ public:
|
||||
return m_Compatibility;
|
||||
}
|
||||
|
||||
NALUnit *NALU() {
|
||||
LFNALUnit *NALU() {
|
||||
return &m_nalu;
|
||||
}
|
||||
|
||||
private:
|
||||
NALUnit m_nalu;
|
||||
LFNALUnit m_nalu;
|
||||
int m_FrameBits;
|
||||
long m_cx;
|
||||
long m_cy;
|
||||
@@ -180,15 +180,15 @@ private:
|
||||
};
|
||||
|
||||
// extract frame num from slice headers
|
||||
class SliceHeader
|
||||
class LFSliceHeader
|
||||
{
|
||||
public:
|
||||
SliceHeader(int nBitsFrame)
|
||||
LFSliceHeader(int nBitsFrame)
|
||||
: m_framenum(0),
|
||||
m_nBitsFrame(nBitsFrame){
|
||||
}
|
||||
|
||||
bool Parse(NALUnit *pnalu);
|
||||
bool Parse(LFNALUnit *pnalu);
|
||||
int FrameNum(){
|
||||
return m_framenum;
|
||||
}
|
||||
@@ -199,10 +199,10 @@ private:
|
||||
};
|
||||
|
||||
// SEI message structure
|
||||
class SEIMessage
|
||||
class LFSEIMessage
|
||||
{
|
||||
public:
|
||||
SEIMessage(NALUnit* pnalu);
|
||||
LFSEIMessage(LFNALUnit* pnalu);
|
||||
int Type() {
|
||||
return m_type;
|
||||
}
|
||||
@@ -216,27 +216,27 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
NALUnit *m_pnalu;
|
||||
LFNALUnit *m_pnalu;
|
||||
int m_type;
|
||||
int m_length;
|
||||
int m_idxPayload;
|
||||
};
|
||||
|
||||
// avcC structure from MP4
|
||||
class avcCHeader
|
||||
class LFavcCHeader
|
||||
{
|
||||
public:
|
||||
avcCHeader(const BYTE* header, int cBytes);
|
||||
NALUnit *sps() {
|
||||
LFavcCHeader(const BYTE* header, int cBytes);
|
||||
LFNALUnit *sps() {
|
||||
return &m_sps;
|
||||
}
|
||||
|
||||
NALUnit *pps() {
|
||||
LFNALUnit *pps() {
|
||||
return &m_pps;
|
||||
}
|
||||
|
||||
private:
|
||||
NALUnit m_sps;
|
||||
NALUnit m_pps;
|
||||
LFNALUnit m_sps;
|
||||
LFNALUnit m_pps;
|
||||
};
|
||||
|
||||
+2
-2
@@ -12,13 +12,13 @@
|
||||
#import "AVFoundation/AVMediaFormat.h"
|
||||
#import "AVFoundation/AVVideoSettings.h"
|
||||
|
||||
@interface VideoEncoder : NSObject
|
||||
@interface LFVideoEncoder : NSObject
|
||||
|
||||
|
||||
@property NSString *path;
|
||||
@property (nonatomic, readonly) NSUInteger bitrate;
|
||||
|
||||
+ (VideoEncoder *)encoderForPath:(NSString *)path Height:(int)height andWidth:(int)width bitrate:(int)bitrate;
|
||||
+ (LFVideoEncoder *)encoderForPath:(NSString *)path Height:(int)height andWidth:(int)width bitrate:(int)bitrate;
|
||||
|
||||
- (void)initPath:(NSString *)path Height:(int)height andWidth:(int)width bitrate:(int)bitrate;
|
||||
- (void)finishWithCompletionHandler:(void (^)(void))handler;
|
||||
+5
-5
@@ -1,14 +1,14 @@
|
||||
//
|
||||
// VideoEncoder.m
|
||||
// LFVideoEncoder.m
|
||||
// Encoder Demo
|
||||
//
|
||||
// Created by Geraint Davies on 14/01/2013.
|
||||
// Copyright (c) 2013 GDCL http://www.gdcl.co.uk/license.htm
|
||||
//
|
||||
|
||||
#import "VideoEncoder.h"
|
||||
#import "LFVideoEncoder.h"
|
||||
|
||||
@implementation VideoEncoder
|
||||
@implementation LFVideoEncoder
|
||||
{
|
||||
AVAssetWriter *_writer;
|
||||
AVAssetWriterInput *_writerInput;
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
@synthesize path = _path;
|
||||
|
||||
+ (VideoEncoder *)encoderForPath:(NSString *)path Height:(int)height andWidth:(int)width bitrate:(int)bitrate {
|
||||
VideoEncoder *enc = [VideoEncoder alloc];
|
||||
+ (LFVideoEncoder *)encoderForPath:(NSString *)path Height:(int)height andWidth:(int)width bitrate:(int)bitrate {
|
||||
LFVideoEncoder *enc = [LFVideoEncoder alloc];
|
||||
[enc initPath:path Height:height andWidth:width bitrate:bitrate];
|
||||
return enc;
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
/// 编码器抽象的接口
|
||||
@protocol LFAudioEncoding <NSObject>
|
||||
@required
|
||||
- (void)encodeAudioData:(AudioBufferList)inBufferList timeStamp:(uint64_t)timeStamp;
|
||||
- (void)encodeAudioData:(nullable NSData*)audioData timeStamp:(uint64_t)timeStamp;
|
||||
- (void)stopEncoder;
|
||||
@optional
|
||||
- (nullable instancetype)initWithAudioStreamConfiguration:(nullable LFLiveAudioConfiguration *)configuration;
|
||||
+16
-23
@@ -8,8 +8,8 @@
|
||||
|
||||
#import <CoreMedia/CoreMedia.h>
|
||||
#import <mach/mach_time.h>
|
||||
#import "NALUnit.h"
|
||||
#import "AVEncoder.h"
|
||||
#import "LFNALUnit.h"
|
||||
#import "LFAVEncoder.h"
|
||||
#import "LFH264VideoEncoder.h"
|
||||
#import "LFVideoFrame.h"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
@property (nonatomic) NSInteger currentVideoBitRate;
|
||||
@property (nonatomic, strong) dispatch_queue_t sendQueue;
|
||||
|
||||
@property (nonatomic, strong) AVEncoder *encoder;
|
||||
@property (nonatomic, strong) LFAVEncoder *encoder;
|
||||
|
||||
@property (nonatomic, strong) NSData *naluStartCode;
|
||||
@property (nonatomic, strong) NSMutableData *videoSPSandPPS;
|
||||
@@ -60,7 +60,7 @@
|
||||
[self initForFilePath];
|
||||
#endif
|
||||
|
||||
_encoder = [AVEncoder encoderForHeight:_configuration.videoSize.height andWidth:_configuration.videoSize.width bitrate:_configuration.videoBitRate];
|
||||
_encoder = [LFAVEncoder encoderForHeight:(int)_configuration.videoSize.height andWidth:(int)_configuration.videoSize.width bitrate:(int)_configuration.videoBitRate];
|
||||
[_encoder encodeWithBlock:^int(NSArray* dataArray, CMTimeValue ptsValue) {
|
||||
[self incomingVideoFrames:dataArray ptsValue:ptsValue];
|
||||
return 0;
|
||||
@@ -85,8 +85,8 @@
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
avcCHeader avcC((const BYTE*)[config bytes], [config length]);
|
||||
SeqParamSet seqParams;
|
||||
LFavcCHeader avcC((const BYTE*)[config bytes], (int)[config length]);
|
||||
LFSeqParamSet seqParams;
|
||||
seqParams.Parse(avcC.sps());
|
||||
|
||||
NSData* spsData = [NSData dataWithBytes:avcC.sps()->Start() length:avcC.sps()->Length()];
|
||||
@@ -107,6 +107,8 @@
|
||||
[_videoSPSandPPS appendData:ppsData];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)setVideoBitRate:(NSInteger)videoBitRate{
|
||||
_currentVideoBitRate = videoBitRate;
|
||||
_encoder.bitrate = _currentVideoBitRate;
|
||||
@@ -162,7 +164,7 @@
|
||||
[totalFrames addObjectsFromArray:frames];
|
||||
|
||||
NSMutableData *aggregateFrameData = [NSMutableData data];
|
||||
BOOL hasKeyframe = NO;
|
||||
//BOOL hasKeyframe = NO;
|
||||
|
||||
for (NSData *data in totalFrames) {
|
||||
unsigned char* pNal = (unsigned char*)[data bytes];
|
||||
@@ -174,7 +176,7 @@
|
||||
_sei = [NSMutableData dataWithData:data];
|
||||
continue;
|
||||
} else if (naltype == 5) { // IDR
|
||||
hasKeyframe = YES;
|
||||
//hasKeyframe = YES;
|
||||
NSMutableData *IDRData = [NSMutableData dataWithData:_videoSPSandPPS];
|
||||
if (_sei) {
|
||||
[IDRData appendData:_naluStartCode];
|
||||
@@ -246,25 +248,16 @@
|
||||
}
|
||||
|
||||
- (void)initForFilePath {
|
||||
char *path = [self GetFilePathByfileName:"IOSCamDemo.h264"];
|
||||
NSLog(@"%s", path);
|
||||
self->fp = fopen(path, "wb");
|
||||
NSString *path = [self GetFilePathByfileName:@"IOSCamDemo.h264"];
|
||||
NSLog(@"%@", path);
|
||||
self->fp = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "wb");
|
||||
}
|
||||
|
||||
- (char *)GetFilePathByfileName:(char *)filename {
|
||||
- (NSString *)GetFilePathByfileName:(NSString*)filename {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
NSString *strName = [NSString stringWithFormat:@"%s", filename];
|
||||
|
||||
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:strName];
|
||||
|
||||
NSUInteger len = [writablePath length];
|
||||
|
||||
char *filepath = (char *)malloc(sizeof(char) * (len + 1));
|
||||
|
||||
[writablePath getCString:filepath maxLength:len + 1 encoding:[NSString defaultCStringEncoding]];
|
||||
|
||||
return filepath;
|
||||
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:filename];
|
||||
return writablePath;
|
||||
}
|
||||
|
||||
@end
|
||||
+149
-34
@@ -10,7 +10,11 @@
|
||||
|
||||
@interface LFHardwareAudioEncoder (){
|
||||
AudioConverterRef m_converter;
|
||||
char *leftBuf;
|
||||
char *aacBuf;
|
||||
NSInteger leftLength;
|
||||
FILE *fp;
|
||||
BOOL enabledWriteVideoFile;
|
||||
}
|
||||
@property (nonatomic, strong) LFLiveAudioConfiguration *configuration;
|
||||
@property (nonatomic, weak) id<LFAudioEncodingDelegate> aacDeleage;
|
||||
@@ -19,16 +23,31 @@
|
||||
|
||||
@implementation LFHardwareAudioEncoder
|
||||
|
||||
- (instancetype)initWithAudioStreamConfiguration:(LFLiveAudioConfiguration *)configuration {
|
||||
- (instancetype)initWithAudioStreamConfiguration:(nullable LFLiveAudioConfiguration *)configuration {
|
||||
if (self = [super init]) {
|
||||
NSLog(@"USE LFHardwareAudioEncoder");
|
||||
_configuration = configuration;
|
||||
|
||||
if (!leftBuf) {
|
||||
leftBuf = malloc(_configuration.bufferLength);
|
||||
}
|
||||
|
||||
if (!aacBuf) {
|
||||
aacBuf = malloc(_configuration.bufferLength);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
enabledWriteVideoFile = NO;
|
||||
[self initForFilePath];
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (aacBuf) free(aacBuf);
|
||||
if (leftBuf) free(leftBuf);
|
||||
}
|
||||
|
||||
#pragma mark -- LFAudioEncoder
|
||||
@@ -36,29 +55,66 @@
|
||||
_aacDeleage = delegate;
|
||||
}
|
||||
|
||||
- (void)encodeAudioData:(AudioBufferList)inBufferList timeStamp:(uint64_t)timeStamp {
|
||||
- (void)encodeAudioData:(nullable NSData*)audioData timeStamp:(uint64_t)timeStamp {
|
||||
if (![self createAudioConvert]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aacBuf) {
|
||||
aacBuf = malloc(inBufferList.mBuffers[0].mDataByteSize);
|
||||
if(leftLength + audioData.length >= self.configuration.bufferLength){
|
||||
///< 发送
|
||||
NSInteger totalSize = leftLength + audioData.length;
|
||||
NSInteger encodeCount = totalSize/self.configuration.bufferLength;
|
||||
char *totalBuf = malloc(totalSize);
|
||||
char *p = totalBuf;
|
||||
|
||||
memset(totalBuf, (int)totalSize, 0);
|
||||
memcpy(totalBuf, leftBuf, leftLength);
|
||||
memcpy(totalBuf + leftLength, audioData.bytes, audioData.length);
|
||||
|
||||
for(NSInteger index = 0;index < encodeCount;index++){
|
||||
[self encodeBuffer:p timeStamp:timeStamp];
|
||||
p += self.configuration.bufferLength;
|
||||
}
|
||||
free(totalBuf);
|
||||
|
||||
leftLength = totalSize%self.configuration.bufferLength;
|
||||
memset(leftBuf, 0, self.configuration.bufferLength);
|
||||
memcpy(leftBuf, totalBuf + (totalSize -leftLength), leftLength);
|
||||
|
||||
}else{
|
||||
///< 积累
|
||||
memcpy(leftBuf+leftLength, audioData.bytes, audioData.length);
|
||||
leftLength = leftLength + audioData.length;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)encodeBuffer:(char*)buf timeStamp:(uint64_t)timeStamp{
|
||||
|
||||
AudioBuffer inBuffer;
|
||||
inBuffer.mNumberChannels = 1;
|
||||
inBuffer.mData = buf;
|
||||
inBuffer.mDataByteSize = (UInt32)self.configuration.bufferLength;
|
||||
|
||||
AudioBufferList buffers;
|
||||
buffers.mNumberBuffers = 1;
|
||||
buffers.mBuffers[0] = inBuffer;
|
||||
|
||||
|
||||
// 初始化一个输出缓冲列表
|
||||
AudioBufferList outBufferList;
|
||||
outBufferList.mNumberBuffers = 1;
|
||||
outBufferList.mBuffers[0].mNumberChannels = inBufferList.mBuffers[0].mNumberChannels;
|
||||
outBufferList.mBuffers[0].mDataByteSize = inBufferList.mBuffers[0].mDataByteSize; // 设置缓冲区大小
|
||||
outBufferList.mBuffers[0].mNumberChannels = inBuffer.mNumberChannels;
|
||||
outBufferList.mBuffers[0].mDataByteSize = inBuffer.mDataByteSize; // 设置缓冲区大小
|
||||
outBufferList.mBuffers[0].mData = aacBuf; // 设置AAC缓冲区
|
||||
UInt32 outputDataPacketSize = 1;
|
||||
if (AudioConverterFillComplexBuffer(m_converter, inputDataProc, &inBufferList, &outputDataPacketSize, &outBufferList, NULL) != noErr) {
|
||||
if (AudioConverterFillComplexBuffer(m_converter, inputDataProc, &buffers, &outputDataPacketSize, &outBufferList, NULL) != noErr) {
|
||||
return;
|
||||
}
|
||||
|
||||
LFAudioFrame *audioFrame = [LFAudioFrame new];
|
||||
audioFrame.timestamp = timeStamp;
|
||||
audioFrame.data = [NSData dataWithBytes:aacBuf length:outBufferList.mBuffers[0].mDataByteSize];
|
||||
|
||||
|
||||
char exeData[2];
|
||||
exeData[0] = _configuration.asc[0];
|
||||
exeData[1] = _configuration.asc[1];
|
||||
@@ -66,6 +122,13 @@
|
||||
if (self.aacDeleage && [self.aacDeleage respondsToSelector:@selector(audioEncoder:audioFrame:)]) {
|
||||
[self.aacDeleage audioEncoder:self audioFrame:audioFrame];
|
||||
}
|
||||
|
||||
if (self->enabledWriteVideoFile) {
|
||||
NSData *adts = [self adtsData:_configuration.numberOfChannels rawDataLength:audioFrame.data.length];
|
||||
fwrite(adts.bytes, 1, adts.length, self->fp);
|
||||
fwrite(audioFrame.data.bytes, 1, audioFrame.data.length, self->fp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)stopEncoder {
|
||||
@@ -108,35 +171,24 @@
|
||||
kAppleHardwareAudioCodecManufacturer
|
||||
}
|
||||
};
|
||||
OSStatus result = AudioConverterNewSpecific(&inputFormat, &outputFormat, 2, requestedCodecs, &m_converter);
|
||||
if (result != noErr) return NO;
|
||||
|
||||
OSStatus result = AudioConverterNewSpecific(&inputFormat, &outputFormat, 2, requestedCodecs, &m_converter);;
|
||||
UInt32 outputBitrate = _configuration.audioBitrate;
|
||||
UInt32 propSize = sizeof(outputBitrate);
|
||||
// UInt32 outputPacketSize = 0;
|
||||
|
||||
|
||||
if(result == noErr) {
|
||||
result = AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, propSize, &outputBitrate);
|
||||
}
|
||||
|
||||
// if(result == noErr) {
|
||||
// AudioConverterGetProperty(m_converter, kAudioConverterPropertyMaximumOutputPacketSize, &propSize, &outputPacketSize);
|
||||
// }
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (AudioClassDescription *)getAudioClassDescriptionWithType:(UInt32)type fromManufacturer:(UInt32)manufacturer { // 获得相应的编码器
|
||||
static AudioClassDescription audioDesc;
|
||||
|
||||
UInt32 encoderSpecifier = type, size = 0;
|
||||
OSStatus status;
|
||||
|
||||
memset(&audioDesc, 0, sizeof(audioDesc));
|
||||
status = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size);
|
||||
if (status) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
uint32_t count = size / sizeof(AudioClassDescription);
|
||||
AudioClassDescription descs[count];
|
||||
AudioFormatGetProperty(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size, descs);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if ((type == descs[i].mSubType) && (manufacturer == descs[i].mManufacturer)) {
|
||||
memcpy(&audioDesc, &descs[i], sizeof(audioDesc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return &audioDesc;
|
||||
}
|
||||
|
||||
#pragma mark -- AudioCallBack
|
||||
OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription * *outDataPacketDescription, void *inUserData) { //<span style="font-family: Arial, Helvetica, sans-serif;">AudioConverterFillComplexBuffer 编码过程中,会要求这个函数来填充输入数据,也就是原始PCM数据</span>
|
||||
@@ -147,6 +199,8 @@ OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPacket
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -- Custom Method
|
||||
/**
|
||||
* Add ADTS header at the beginning of each and every AAC packet.
|
||||
* This is needed as MediaCodec encoder generates a packet of raw
|
||||
@@ -162,7 +216,7 @@ OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPacket
|
||||
// Variables Recycled by addADTStoPacket
|
||||
int profile = 2; //AAC LC
|
||||
//39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
|
||||
int freqIdx = 4; //44.1KHz
|
||||
NSInteger freqIdx = [self sampleRateIndex:self.configuration.audioSampleRate]; //44.1KHz
|
||||
int chanCfg = (int)channel; //MPEG-4 Audio Channel Configuration. 1 Channel front-center
|
||||
NSUInteger fullLength = adtsLength + rawDataLength;
|
||||
// fill in ADTS data
|
||||
@@ -177,4 +231,65 @@ OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPacket
|
||||
return data;
|
||||
}
|
||||
|
||||
- (NSInteger)sampleRateIndex:(NSInteger)frequencyInHz {
|
||||
NSInteger sampleRateIndex = 0;
|
||||
switch (frequencyInHz) {
|
||||
case 96000:
|
||||
sampleRateIndex = 0;
|
||||
break;
|
||||
case 88200:
|
||||
sampleRateIndex = 1;
|
||||
break;
|
||||
case 64000:
|
||||
sampleRateIndex = 2;
|
||||
break;
|
||||
case 48000:
|
||||
sampleRateIndex = 3;
|
||||
break;
|
||||
case 44100:
|
||||
sampleRateIndex = 4;
|
||||
break;
|
||||
case 32000:
|
||||
sampleRateIndex = 5;
|
||||
break;
|
||||
case 24000:
|
||||
sampleRateIndex = 6;
|
||||
break;
|
||||
case 22050:
|
||||
sampleRateIndex = 7;
|
||||
break;
|
||||
case 16000:
|
||||
sampleRateIndex = 8;
|
||||
break;
|
||||
case 12000:
|
||||
sampleRateIndex = 9;
|
||||
break;
|
||||
case 11025:
|
||||
sampleRateIndex = 10;
|
||||
break;
|
||||
case 8000:
|
||||
sampleRateIndex = 11;
|
||||
break;
|
||||
case 7350:
|
||||
sampleRateIndex = 12;
|
||||
break;
|
||||
default:
|
||||
sampleRateIndex = 15;
|
||||
}
|
||||
return sampleRateIndex;
|
||||
}
|
||||
|
||||
- (void)initForFilePath {
|
||||
NSString *path = [self GetFilePathByfileName:@"IOSCamDemo_HW.aac"];
|
||||
NSLog(@"%@", path);
|
||||
self->fp = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "wb");
|
||||
}
|
||||
|
||||
- (NSString *)GetFilePathByfileName:(NSString*)filename {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:filename];
|
||||
return writablePath;
|
||||
}
|
||||
|
||||
@end
|
||||
+10
-19
@@ -66,9 +66,9 @@
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(_configuration.videoBitRate));
|
||||
NSArray *limit = @[@(_configuration.videoBitRate * 1.5/8), @(1)];
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_DataRateLimits, (__bridge CFArrayRef)limit);
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_RealTime, kCFBooleanFalse);
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Main_AutoLevel);
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanTrue);
|
||||
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_H264EntropyMode, kVTH264EntropyMode_CABAC);
|
||||
VTCompressionSessionPrepareToEncodeFrames(compressionSession);
|
||||
|
||||
@@ -98,11 +98,11 @@
|
||||
}
|
||||
|
||||
#pragma mark -- LFVideoEncoder
|
||||
- (void)encodeVideoData:(CVImageBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp {
|
||||
- (void)encodeVideoData:(CVPixelBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp {
|
||||
if (_isBackGround) return;
|
||||
|
||||
frameCount++;
|
||||
CMTime presentationTimeStamp = CMTimeMake(frameCount, 1000);
|
||||
CMTime presentationTimeStamp = CMTimeMake(frameCount, (int32_t)_configuration.videoFrameRate);
|
||||
VTEncodeInfoFlags flags;
|
||||
CMTime duration = CMTimeMake(1, (int32_t)_configuration.videoFrameRate);
|
||||
|
||||
@@ -226,25 +226,16 @@ static void VideoCompressonOutputCallback(void *VTref, void *VTFrameRef, OSStatu
|
||||
}
|
||||
|
||||
- (void)initForFilePath {
|
||||
char *path = [self GetFilePathByfileName:"IOSCamDemo_HW.h264"];
|
||||
NSLog(@"%s", path);
|
||||
self->fp = fopen(path, "wb");
|
||||
NSString *path = [self GetFilePathByfileName:@"IOSCamDemo.h264"];
|
||||
NSLog(@"%@", path);
|
||||
self->fp = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "wb");
|
||||
}
|
||||
|
||||
- (char *)GetFilePathByfileName:(char *)filename {
|
||||
- (NSString *)GetFilePathByfileName:(NSString*)filename {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
NSString *strName = [NSString stringWithFormat:@"%s", filename];
|
||||
|
||||
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:strName];
|
||||
|
||||
NSUInteger len = [writablePath length];
|
||||
|
||||
char *filepath = (char *)malloc(sizeof(char) * (len + 1));
|
||||
|
||||
[writablePath getCString:filepath maxLength:len + 1 encoding:[NSString defaultCStringEncoding]];
|
||||
|
||||
return filepath;
|
||||
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:filename];
|
||||
return writablePath;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -20,12 +20,11 @@
|
||||
/// 编码器抽象的接口
|
||||
@protocol LFVideoEncoding <NSObject>
|
||||
@required
|
||||
- (void)encodeVideoData:(nullable CVImageBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp;
|
||||
- (void)stopEncoder;
|
||||
- (void)encodeVideoData:(nullable CVPixelBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp;
|
||||
@optional
|
||||
@property (nonatomic, assign) NSInteger videoBitRate;
|
||||
- (nullable instancetype)initWithVideoStreamConfiguration:(nullable LFLiveVideoConfiguration *)configuration;
|
||||
- (void)setDelegate:(nullable id<LFVideoEncodingDelegate>)delegate;
|
||||
|
||||
- (void)stopEncoder;
|
||||
@end
|
||||
|
||||
+14
-10
@@ -19,14 +19,16 @@ typedef NS_ENUM (NSUInteger, LFLiveAudioBitRate) {
|
||||
/// 128Kbps 音频码率
|
||||
LFLiveAudioBitRate_128Kbps = 128000,
|
||||
/// 默认音频码率,默认为 64Kbps
|
||||
LFLiveAudioBitRate_Default = LFLiveAudioBitRate_64Kbps
|
||||
LFLiveAudioBitRate_Default = LFLiveAudioBitRate_96Kbps
|
||||
};
|
||||
|
||||
/// 采样率 (默认44.1Hz iphoneg6以上48Hz)
|
||||
/// 采样率 (默认44.1Hz)
|
||||
typedef NS_ENUM (NSUInteger, LFLiveAudioSampleRate){
|
||||
/// 44.1Hz 采样率
|
||||
/// 16KHz 采样率
|
||||
LFLiveAudioSampleRate_16000Hz = 16000,
|
||||
/// 44.1KHz 采样率
|
||||
LFLiveAudioSampleRate_44100Hz = 44100,
|
||||
/// 48Hz 采样率
|
||||
/// 48KHz 采样率
|
||||
LFLiveAudioSampleRate_48000Hz = 48000,
|
||||
/// 默认音频码率,默认为 64Kbps
|
||||
LFLiveAudioSampleRate_Default = LFLiveAudioSampleRate_44100Hz
|
||||
@@ -34,16 +36,16 @@ typedef NS_ENUM (NSUInteger, LFLiveAudioSampleRate){
|
||||
|
||||
/// Audio Live quality(音频质量)
|
||||
typedef NS_ENUM (NSUInteger, LFLiveAudioQuality){
|
||||
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 32Kbps
|
||||
/// 高音频质量 audio sample rate: 16KHz audio bitrate: numberOfChannels 1 : 32Kbps 2 : 64Kbps
|
||||
LFLiveAudioQuality_Low = 0,
|
||||
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 64Kbps
|
||||
/// 高音频质量 audio sample rate: 44KHz audio bitrate: 96Kbps
|
||||
LFLiveAudioQuality_Medium = 1,
|
||||
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 96Kbps
|
||||
/// 高音频质量 audio sample rate: 44MHz audio bitrate: 128Kbps
|
||||
LFLiveAudioQuality_High = 2,
|
||||
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 128Kbps
|
||||
/// 高音频质量 audio sample rate: 48MHz, audio bitrate: 128Kbps
|
||||
LFLiveAudioQuality_VeryHigh = 3,
|
||||
/// 默认音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 64Kbps
|
||||
LFLiveAudioQuality_Default = LFLiveAudioQuality_Medium
|
||||
/// 默认音频质量 audio sample rate: 44MHz, audio bitrate: 96Kbps
|
||||
LFLiveAudioQuality_Default = LFLiveAudioQuality_High
|
||||
};
|
||||
|
||||
@interface LFLiveAudioConfiguration : NSObject<NSCoding, NSCopying>
|
||||
@@ -65,5 +67,7 @@ typedef NS_ENUM (NSUInteger, LFLiveAudioQuality){
|
||||
@property (nonatomic, assign) LFLiveAudioBitRate audioBitrate;
|
||||
/// flv编码音频头 44100 为0x12 0x10
|
||||
@property (nonatomic, assign, readonly) char *asc;
|
||||
/// 缓存区长度
|
||||
@property (nonatomic, assign,readonly) NSUInteger bufferLength;
|
||||
|
||||
@end
|
||||
+23
-62
@@ -21,24 +21,32 @@
|
||||
LFLiveAudioConfiguration *audioConfig = [LFLiveAudioConfiguration new];
|
||||
audioConfig.numberOfChannels = 2;
|
||||
switch (audioQuality) {
|
||||
case LFLiveAudioQuality_Default: {
|
||||
audioConfig.audioBitrate = LFLiveAudioBitRate_64Kbps;
|
||||
}
|
||||
break;
|
||||
case LFLiveAudioQuality_Low: {
|
||||
audioConfig.audioBitrate = LFLiveAudioBitRate_32Kbps;
|
||||
audioConfig.audioBitrate = audioConfig.numberOfChannels == 1 ? LFLiveAudioBitRate_32Kbps : LFLiveAudioBitRate_64Kbps;
|
||||
audioConfig.audioSampleRate = LFLiveAudioSampleRate_16000Hz;
|
||||
}
|
||||
case LFLiveAudioQuality_High: {
|
||||
break;
|
||||
case LFLiveAudioQuality_Medium: {
|
||||
audioConfig.audioBitrate = LFLiveAudioBitRate_96Kbps;
|
||||
audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
|
||||
}
|
||||
break;
|
||||
case LFLiveAudioQuality_High: {
|
||||
audioConfig.audioBitrate = LFLiveAudioBitRate_128Kbps;
|
||||
audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
|
||||
}
|
||||
break;
|
||||
case LFLiveAudioQuality_VeryHigh: {
|
||||
audioConfig.audioBitrate = LFLiveAudioBitRate_128Kbps;
|
||||
audioConfig.audioSampleRate = LFLiveAudioSampleRate_48000Hz;
|
||||
}
|
||||
break;
|
||||
default:{
|
||||
audioConfig.audioBitrate = LFLiveAudioBitRate_96Kbps;
|
||||
audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
audioConfig.audioSampleRate = [self.class isNewThaniPhone6] ? LFLiveAudioSampleRate_48000Hz : LFLiveAudioSampleRate_44100Hz;
|
||||
|
||||
return audioConfig;
|
||||
}
|
||||
@@ -58,17 +66,21 @@
|
||||
- (void)setAudioSampleRate:(LFLiveAudioSampleRate)audioSampleRate {
|
||||
_audioSampleRate = audioSampleRate;
|
||||
NSInteger sampleRateIndex = [self sampleRateIndex:audioSampleRate];
|
||||
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x3);
|
||||
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x7);
|
||||
self.asc[1] = ((sampleRateIndex & 0x1)<<7) | ((self.numberOfChannels & 0xF) << 3);
|
||||
}
|
||||
|
||||
- (void)setNumberOfChannels:(NSUInteger)numberOfChannels {
|
||||
_numberOfChannels = numberOfChannels;
|
||||
NSInteger sampleRateIndex = [self sampleRateIndex:self.audioSampleRate];
|
||||
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x3);
|
||||
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x7);
|
||||
self.asc[1] = ((sampleRateIndex & 0x1)<<7) | ((numberOfChannels & 0xF) << 3);
|
||||
}
|
||||
|
||||
- (NSUInteger)bufferLength{
|
||||
return 1024*2*self.numberOfChannels;
|
||||
}
|
||||
|
||||
#pragma mark -- CustomMethod
|
||||
- (NSInteger)sampleRateIndex:(NSInteger)frequencyInHz {
|
||||
NSInteger sampleRateIndex = 0;
|
||||
@@ -118,57 +130,6 @@
|
||||
return sampleRateIndex;
|
||||
}
|
||||
|
||||
#pragma mark -- DeviceCategory
|
||||
+ (NSString *)deviceName {
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
|
||||
return [NSString stringWithCString:systemInfo.machine
|
||||
encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
//@"iPad4,1" on 5th Generation iPad (iPad Air) - Wifi
|
||||
//@"iPad4,2" on 5th Generation iPad (iPad Air) - Cellular
|
||||
//@"iPad4,4" on 2nd Generation iPad Mini - Wifi
|
||||
//@"iPad4,5" on 2nd Generation iPad Mini - Cellular
|
||||
//@"iPad4,7" on 3rd Generation iPad Mini - Wifi (model A1599)
|
||||
//@"iPhone7,1" on iPhone 6 Plus
|
||||
//@"iPhone7,2" on iPhone 6
|
||||
//@"iPhone8,1" on iPhone 6S
|
||||
//@"iPhone8,2" on iPhone 6S Plus
|
||||
|
||||
+ (BOOL)isNewThaniPhone6 {
|
||||
NSString *device = [self deviceName];
|
||||
NSLog(@"device %@", device);
|
||||
if (device == nil) {
|
||||
return NO;
|
||||
}
|
||||
NSArray *array = [device componentsSeparatedByString:@","];
|
||||
if (array.count < 2) {
|
||||
return NO;
|
||||
}
|
||||
NSString *model = [array objectAtIndex:0];
|
||||
NSLog(@"model %@", model);
|
||||
if ([model hasPrefix:@"iPhone"]) {
|
||||
NSString *str1 = [model substringFromIndex:[@"iPhone" length]];
|
||||
NSUInteger num = [str1 integerValue];
|
||||
NSLog(@"num %lu", (unsigned long)num);
|
||||
if (num > 7) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
if ([model hasPrefix:@"iPad"]) {
|
||||
NSString *str1 = [model substringFromIndex:[@"iPad" length]];
|
||||
NSUInteger num = [str1 integerValue];
|
||||
if (num > 4) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark -- Encoder
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeObject:@(self.numberOfChannels) forKey:@"numberOfChannels"];
|
||||
+4
-1
@@ -57,9 +57,12 @@ typedef NS_ENUM (NSUInteger, LFLiveVideoQuality){
|
||||
///=============================================================================
|
||||
/// @name Attribute
|
||||
///=============================================================================
|
||||
/// 视频的分辨率,宽高务必设定为 2 的倍数,否则解码播放时可能出现绿边
|
||||
/// 视频的分辨率,宽高务必设定为 2 的倍数,否则解码播放时可能出现绿边(这个videoSizeRespectingAspectRatio设置为YES则可能会改变)
|
||||
@property (nonatomic, assign) CGSize videoSize;
|
||||
|
||||
/// 输出图像是否等比例,默认为NO
|
||||
@property (nonatomic, assign) BOOL videoSizeRespectingAspectRatio;
|
||||
|
||||
/// 视频输出方向
|
||||
@property (nonatomic, assign) BOOL landscape;
|
||||
|
||||
+107
-43
@@ -9,9 +9,11 @@
|
||||
#import "LFLiveVideoConfiguration.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
|
||||
@implementation LFLiveVideoConfiguration
|
||||
|
||||
#pragma mark -- LifeCycle
|
||||
|
||||
+ (instancetype)defaultConfiguration {
|
||||
LFLiveVideoConfiguration *configuration = [LFLiveVideoConfiguration defaultConfigurationForQuality:LFLiveVideoQuality_Default];
|
||||
return configuration;
|
||||
@@ -25,8 +27,7 @@
|
||||
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality landscape:(BOOL)landscape {
|
||||
LFLiveVideoConfiguration *configuration = [LFLiveVideoConfiguration new];
|
||||
switch (videoQuality) {
|
||||
case LFLiveVideoQuality_Low1:
|
||||
{
|
||||
case LFLiveVideoQuality_Low1:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset360x640;
|
||||
configuration.videoFrameRate = 15;
|
||||
configuration.videoMaxFrameRate = 15;
|
||||
@@ -36,9 +37,8 @@
|
||||
configuration.videoMinBitRate = 400 * 1000;
|
||||
configuration.videoSize = CGSizeMake(360, 640);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_Low2:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_Low2:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset360x640;
|
||||
configuration.videoFrameRate = 24;
|
||||
configuration.videoMaxFrameRate = 24;
|
||||
@@ -48,9 +48,8 @@
|
||||
configuration.videoMinBitRate = 500 * 1000;
|
||||
configuration.videoSize = CGSizeMake(360, 640);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_Low3:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_Low3: {
|
||||
configuration.sessionPreset = LFCaptureSessionPreset360x640;
|
||||
configuration.videoFrameRate = 30;
|
||||
configuration.videoMaxFrameRate = 30;
|
||||
@@ -60,9 +59,8 @@
|
||||
configuration.videoMinBitRate = 600 * 1000;
|
||||
configuration.videoSize = CGSizeMake(360, 640);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_Medium1:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_Medium1:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset540x960;
|
||||
configuration.videoFrameRate = 15;
|
||||
configuration.videoMaxFrameRate = 15;
|
||||
@@ -72,9 +70,8 @@
|
||||
configuration.videoMinBitRate = 500 * 1000;
|
||||
configuration.videoSize = CGSizeMake(540, 960);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_Medium2:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_Medium2:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset540x960;
|
||||
configuration.videoFrameRate = 24;
|
||||
configuration.videoMaxFrameRate = 24;
|
||||
@@ -84,9 +81,8 @@
|
||||
configuration.videoMinBitRate = 500 * 1000;
|
||||
configuration.videoSize = CGSizeMake(540, 960);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_Medium3:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_Medium3:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset540x960;
|
||||
configuration.videoFrameRate = 30;
|
||||
configuration.videoMaxFrameRate = 30;
|
||||
@@ -96,9 +92,8 @@
|
||||
configuration.videoMinBitRate = 500 * 1000;
|
||||
configuration.videoSize = CGSizeMake(540, 960);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_High1:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_High1:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset720x1280;
|
||||
configuration.videoFrameRate = 15;
|
||||
configuration.videoMaxFrameRate = 15;
|
||||
@@ -108,9 +103,8 @@
|
||||
configuration.videoMinBitRate = 500 * 1000;
|
||||
configuration.videoSize = CGSizeMake(720, 1280);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_High2:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_High2:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset720x1280;
|
||||
configuration.videoFrameRate = 24;
|
||||
configuration.videoMaxFrameRate = 24;
|
||||
@@ -120,9 +114,8 @@
|
||||
configuration.videoMinBitRate = 800 * 1000;
|
||||
configuration.videoSize = CGSizeMake(720, 1280);
|
||||
}
|
||||
break;
|
||||
case LFLiveVideoQuality_High3:
|
||||
{
|
||||
break;
|
||||
case LFLiveVideoQuality_High3:{
|
||||
configuration.sessionPreset = LFCaptureSessionPreset720x1280;
|
||||
configuration.videoFrameRate = 30;
|
||||
configuration.videoMaxFrameRate = 30;
|
||||
@@ -132,7 +125,7 @@
|
||||
configuration.videoMinBitRate = 500 * 1000;
|
||||
configuration.videoSize = CGSizeMake(720, 1280);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -146,35 +139,40 @@
|
||||
configuration.videoSize = CGSizeMake(size.width, size.height);
|
||||
}
|
||||
return configuration;
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -- Setter Getter
|
||||
- (NSString *)avSessionPreset {
|
||||
NSString *avSessionPreset = nil;
|
||||
switch (self.sessionPreset) {
|
||||
case LFCaptureSessionPreset360x640:
|
||||
{
|
||||
case LFCaptureSessionPreset360x640:{
|
||||
avSessionPreset = AVCaptureSessionPreset640x480;
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset540x960:
|
||||
{
|
||||
break;
|
||||
case LFCaptureSessionPreset540x960:{
|
||||
avSessionPreset = AVCaptureSessionPresetiFrame960x540;
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset720x1280:
|
||||
{
|
||||
break;
|
||||
case LFCaptureSessionPreset720x1280:{
|
||||
avSessionPreset = AVCaptureSessionPreset1280x720;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default: {
|
||||
avSessionPreset = AVCaptureSessionPreset640x480;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return avSessionPreset;
|
||||
}
|
||||
|
||||
- (CGSize)videoSize{
|
||||
if(_videoSizeRespectingAspectRatio){
|
||||
return self.aspectRatioVideoSize;
|
||||
}
|
||||
return _videoSize;
|
||||
}
|
||||
|
||||
- (void)setVideoMaxBitRate:(NSUInteger)videoMaxBitRate {
|
||||
if (videoMaxBitRate <= _videoBitRate) return;
|
||||
_videoMaxBitRate = videoMaxBitRate;
|
||||
@@ -195,15 +193,31 @@
|
||||
_videoMinFrameRate = videoMinFrameRate;
|
||||
}
|
||||
|
||||
- (void)setSessionPreset:(LFLiveVideoSessionPreset)sessionPreset{
|
||||
_sessionPreset = sessionPreset;
|
||||
_sessionPreset = [self supportSessionPreset:sessionPreset];
|
||||
}
|
||||
|
||||
#pragma mark -- Custom Method
|
||||
- (LFLiveVideoSessionPreset)supportSessionPreset:(LFLiveVideoSessionPreset)sessionPreset {
|
||||
NSString *avSessionPreset = [self avSessionPreset];
|
||||
AVCaptureSession *session = [[AVCaptureSession alloc] init];
|
||||
|
||||
if (![session canSetSessionPreset:avSessionPreset]) {
|
||||
AVCaptureDevice *inputCamera;
|
||||
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||
for (AVCaptureDevice *device in devices){
|
||||
if ([device position] == AVCaptureDevicePositionFront){
|
||||
inputCamera = device;
|
||||
}
|
||||
}
|
||||
AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:inputCamera error:nil];
|
||||
|
||||
if ([session canAddInput:videoInput]){
|
||||
[session addInput:videoInput];
|
||||
}
|
||||
|
||||
if (![session canSetSessionPreset:self.avSessionPreset]) {
|
||||
if (sessionPreset == LFCaptureSessionPreset720x1280) {
|
||||
sessionPreset = LFCaptureSessionPreset540x960;
|
||||
if (![session canSetSessionPreset:avSessionPreset]) {
|
||||
if (![session canSetSessionPreset:self.avSessionPreset]) {
|
||||
sessionPreset = LFCaptureSessionPreset360x640;
|
||||
}
|
||||
} else if (sessionPreset == LFCaptureSessionPreset540x960) {
|
||||
@@ -213,24 +227,71 @@
|
||||
return sessionPreset;
|
||||
}
|
||||
|
||||
- (CGSize)captureOutVideoSize{
|
||||
CGSize videoSize = CGSizeZero;
|
||||
switch (_sessionPreset) {
|
||||
case LFCaptureSessionPreset360x640:{
|
||||
videoSize = CGSizeMake(360, 640);
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset540x960:{
|
||||
videoSize = CGSizeMake(540, 960);
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset720x1280:{
|
||||
videoSize = CGSizeMake(720, 1280);
|
||||
}
|
||||
break;
|
||||
|
||||
default:{
|
||||
videoSize = CGSizeMake(360, 640);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(self.landscape){
|
||||
return CGSizeMake(videoSize.height, videoSize.width);
|
||||
}
|
||||
return videoSize;
|
||||
}
|
||||
|
||||
- (CGSize)aspectRatioVideoSize{
|
||||
CGSize size = AVMakeRectWithAspectRatioInsideRect(self.captureOutVideoSize, CGRectMake(0, 0, _videoSize.width, _videoSize.height)).size;
|
||||
NSInteger width = ceil(size.width);
|
||||
NSInteger height = ceil(size.height);
|
||||
if(width %2 != 0) width = width - 1;
|
||||
if(height %2 != 0) height = height - 1;
|
||||
return CGSizeMake(width, height);
|
||||
}
|
||||
|
||||
#pragma mark -- encoder
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeObject:[NSValue valueWithCGSize:self.videoSize] forKey:@"videoSize"];
|
||||
[aCoder encodeObject:@(self.videoFrameRate) forKey:@"videoFrameRate"];
|
||||
[aCoder encodeObject:@(self.videoMaxFrameRate) forKey:@"videoMaxFrameRate"];
|
||||
[aCoder encodeObject:@(self.videoMinFrameRate) forKey:@"videoMinFrameRate"];
|
||||
[aCoder encodeObject:@(self.videoMaxKeyframeInterval) forKey:@"videoMaxKeyframeInterval"];
|
||||
[aCoder encodeObject:@(self.videoBitRate) forKey:@"videoBitRate"];
|
||||
[aCoder encodeObject:@(self.videoMaxBitRate) forKey:@"videoMaxBitRate"];
|
||||
[aCoder encodeObject:@(self.videoMinBitRate) forKey:@"videoMinBitRate"];
|
||||
[aCoder encodeObject:@(self.sessionPreset) forKey:@"sessionPreset"];
|
||||
[aCoder encodeObject:@(self.landscape) forKey:@"landscape"];
|
||||
[aCoder encodeObject:@(self.videoSizeRespectingAspectRatio) forKey:@"videoSizeRespectingAspectRatio"];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [super init];
|
||||
_videoSize = [[aDecoder decodeObjectForKey:@"videoSize"] CGSizeValue];
|
||||
_videoFrameRate = [[aDecoder decodeObjectForKey:@"videoFrameRate"] unsignedIntegerValue];
|
||||
_videoMaxFrameRate = [[aDecoder decodeObjectForKey:@"videoMaxFrameRate"] unsignedIntegerValue];
|
||||
_videoMinFrameRate = [[aDecoder decodeObjectForKey:@"videoMinFrameRate"] unsignedIntegerValue];
|
||||
_videoMaxKeyframeInterval = [[aDecoder decodeObjectForKey:@"videoMaxKeyframeInterval"] unsignedIntegerValue];
|
||||
_videoBitRate = [[aDecoder decodeObjectForKey:@"videoBitRate"] unsignedIntegerValue];
|
||||
_videoMaxBitRate = [[aDecoder decodeObjectForKey:@"videoMaxBitRate"] unsignedIntegerValue];
|
||||
_videoMinBitRate = [[aDecoder decodeObjectForKey:@"videoMinBitRate"] unsignedIntegerValue];
|
||||
_sessionPreset = [[aDecoder decodeObjectForKey:@"sessionPreset"] unsignedIntegerValue];
|
||||
_landscape = [[aDecoder decodeObjectForKey:@"landscape"] unsignedIntegerValue];
|
||||
_videoSizeRespectingAspectRatio = [[aDecoder decodeObjectForKey:@"videoSizeRespectingAspectRatio"] unsignedIntegerValue];
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -246,7 +307,8 @@
|
||||
@(self.videoMinBitRate),
|
||||
self.avSessionPreset,
|
||||
@(self.sessionPreset),
|
||||
@(self.landscape), ];
|
||||
@(self.landscape),
|
||||
@(self.videoSizeRespectingAspectRatio)];
|
||||
|
||||
for (NSObject *value in values) {
|
||||
hash ^= value.hash;
|
||||
@@ -271,7 +333,8 @@
|
||||
object.videoMinBitRate == self.videoMinBitRate &&
|
||||
[object.avSessionPreset isEqualToString:self.avSessionPreset] &&
|
||||
object.sessionPreset == self.sessionPreset &&
|
||||
object.landscape == self.landscape;
|
||||
object.landscape == self.landscape &&
|
||||
object.videoSizeRespectingAspectRatio == self.videoSizeRespectingAspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,6 +347,7 @@
|
||||
NSMutableString *desc = @"".mutableCopy;
|
||||
[desc appendFormat:@"<LFLiveVideoConfiguration: %p>", self];
|
||||
[desc appendFormat:@" videoSize:%@", NSStringFromCGSize(self.videoSize)];
|
||||
[desc appendFormat:@" videoSizeRespectingAspectRatio:%zi",self.videoSizeRespectingAspectRatio];
|
||||
[desc appendFormat:@" videoFrameRate:%zi", self.videoFrameRate];
|
||||
[desc appendFormat:@" videoMaxFrameRate:%zi", self.videoMaxFrameRate];
|
||||
[desc appendFormat:@" videoMinFrameRate:%zi", self.videoMinFrameRate];
|
||||
+7
-2
@@ -1,5 +1,10 @@
|
||||
#import "GPUImageFilter.h"
|
||||
|
||||
#if __has_include(<GPUImage/GPUImage.h>)
|
||||
#import <GPUImage/GPUImage.h>
|
||||
#elif __has_include("GPUImage/GPUImage.h")
|
||||
#import "GPUImage/GPUImage.h"
|
||||
#else
|
||||
#import "GPUImage.h"
|
||||
#endif
|
||||
@interface LFGPUImageBeautyFilter : GPUImageFilter {
|
||||
}
|
||||
|
||||
-1
@@ -238,7 +238,6 @@ NSString *const kLFGPUImageBeautyFragmentShaderString = SHADER_STRING
|
||||
}
|
||||
|
||||
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex {
|
||||
CGSize oldInputSize = inputTextureSize;
|
||||
[super setInputSize:newSize atIndex:textureIndex];
|
||||
inputTextureSize = newSize;
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#if __has_include(<GPUImage/GPUImage.h>)
|
||||
#import <GPUImage/GPUImage.h>
|
||||
#elif __has_include("GPUImage/GPUImage.h")
|
||||
#import "GPUImage/GPUImage.h"
|
||||
#else
|
||||
#import "GPUImage.h"
|
||||
#endif
|
||||
|
||||
@interface LFGPUImageEmptyFilter : GPUImageFilter
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
@interface LFFrame : NSObject
|
||||
|
||||
@property (nonatomic, assign) uint64_t timestamp;
|
||||
@property (nonatomic, assign,) uint64_t timestamp;
|
||||
@property (nonatomic, strong) NSData *data;
|
||||
///< flv或者rtmp包头
|
||||
@property (nonatomic, strong) NSData *header;
|
||||
+2
-1
@@ -45,6 +45,7 @@ typedef NS_ENUM (NSUInteger, LFLiveSocketErrorCode) {
|
||||
@property (nonatomic, strong) LFLiveAudioConfiguration *audioConfiguration;
|
||||
///视频配置
|
||||
@property (nonatomic, strong) LFLiveVideoConfiguration *videoConfiguration;
|
||||
|
||||
///是否丢帧
|
||||
@property (nonatomic, assign) BOOL needDropFrame;
|
||||
|
||||
@end
|
||||
+11
-5
@@ -33,10 +33,10 @@ SAVC(audiocodecid);
|
||||
SAVC(audiodatarate);
|
||||
SAVC(audiosamplerate);
|
||||
SAVC(audiosamplesize);
|
||||
SAVC(audiochannels);
|
||||
//SAVC(audiochannels);
|
||||
SAVC(stereo);
|
||||
SAVC(encoder);
|
||||
SAVC(av_stereo);
|
||||
//SAVC(av_stereo);
|
||||
SAVC(fileSize);
|
||||
SAVC(avc1);
|
||||
SAVC(mp4a);
|
||||
@@ -69,13 +69,17 @@ SAVC(mp4a);
|
||||
@implementation LFStreamRTMPSocket
|
||||
|
||||
#pragma mark -- LFStreamSocket
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream videoSize:(CGSize)videoSize reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount {
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream{
|
||||
return [self initWithStream:stream reconnectInterval:0 reconnectCount:0];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount{
|
||||
if (!stream) @throw [NSException exceptionWithName:@"LFStreamRtmpSocket init error" reason:@"stream is nil" userInfo:nil];
|
||||
if (self = [super init]) {
|
||||
_stream = stream;
|
||||
if (reconnectInterval > 0) _reconnectInterval = reconnectInterval;
|
||||
else _reconnectInterval = RetryTimesMargin;
|
||||
|
||||
|
||||
if (reconnectCount > 0) _reconnectCount = reconnectCount;
|
||||
else _reconnectCount = RetryTimesBreaken;
|
||||
|
||||
@@ -252,6 +256,7 @@ SAVC(mp4a);
|
||||
_rtmp->m_userData = (__bridge void *)self;
|
||||
_rtmp->m_msgCounter = 1;
|
||||
_rtmp->Link.timeout = RTMP_RECEIVE_TIMEOUT;
|
||||
|
||||
//设置可写,即发布流,这个函数必须在连接前使用,否则无效
|
||||
PILI_RTMP_EnableWrite(_rtmp);
|
||||
|
||||
@@ -340,7 +345,7 @@ Failed:
|
||||
*enc++ = 0;
|
||||
*enc++ = AMF_OBJECT_END;
|
||||
|
||||
packet.m_nBodySize = enc - packet.m_body;
|
||||
packet.m_nBodySize = (uint32_t)(enc - packet.m_body);
|
||||
if (!PILI_RTMP_SendPacket(_rtmp, &packet, FALSE, &_error)) {
|
||||
return;
|
||||
}
|
||||
@@ -533,6 +538,7 @@ void ConnectionTimeCallback(PILI_CONNECTION_TIME *conn_time, void *userData) {
|
||||
if (!_buffer) {
|
||||
_buffer = [[LFStreamingBuffer alloc] init];
|
||||
_buffer.delegate = self;
|
||||
_buffer.needDropFrame = self.stream.needDropFrame;
|
||||
}
|
||||
return _buffer;
|
||||
}
|
||||
@@ -32,6 +32,5 @@
|
||||
- (void)setDelegate:(nullable id <LFStreamSocketDelegate>)delegate;
|
||||
@optional
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream;
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream videoSize:(CGSize)videoSize;
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream videoSize:(CGSize)videoSize reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount;
|
||||
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount;
|
||||
@end
|
||||
+3
@@ -27,6 +27,9 @@ typedef NS_ENUM (NSUInteger, LFLiveBuffferState) {
|
||||
|
||||
@interface LFStreamingBuffer : NSObject
|
||||
|
||||
/** The needDropFrame control Dynamic frame loss ,default is YES */
|
||||
@property (nonatomic, assign) BOOL needDropFrame;
|
||||
|
||||
/** The delegate of the buffer. buffer callback */
|
||||
@property (nullable, nonatomic, weak) id <LFStreamingBufferDelegate> delegate;
|
||||
|
||||
+21
-15
@@ -41,6 +41,7 @@ static const NSUInteger defaultSendBufferMaxCount = 600;///< 最大缓冲区为6
|
||||
self.maxCount = defaultSendBufferMaxCount;
|
||||
self.lastDropFrames = 0;
|
||||
self.startTimer = NO;
|
||||
self.needDropFrame = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -91,21 +92,26 @@ static const NSUInteger defaultSendBufferMaxCount = 600;///< 最大缓冲区为6
|
||||
- (void)removeExpireFrame {
|
||||
if (self.list.count < self.maxCount) return;
|
||||
|
||||
NSArray *pFrames = [self expirePFrames];///< 第一个P到第一个I之间的p帧
|
||||
self.lastDropFrames += [pFrames count];
|
||||
if (pFrames && pFrames.count > 0) {
|
||||
[self.list removeObjectsInArray:pFrames];
|
||||
return;
|
||||
if(self.needDropFrame){
|
||||
NSArray *pFrames = [self expirePFrames];///< 第一个P到第一个I之间的p帧
|
||||
self.lastDropFrames += [pFrames count];
|
||||
if (pFrames && pFrames.count > 0) {
|
||||
[self.list removeObjectsInArray:pFrames];
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *iFrames = [self expireIFrames];///< 删除一个I帧(但一个I帧可能对应多个nal)
|
||||
self.lastDropFrames += [iFrames count];
|
||||
if (iFrames) {
|
||||
[self.list removeObjectsInArray:iFrames];
|
||||
return;
|
||||
}
|
||||
|
||||
[self.list removeAllObjects];
|
||||
}else{
|
||||
[self.list lfPopFirstObject];
|
||||
}
|
||||
|
||||
NSArray *iFrames = [self expireIFrames];///< 删除一个I帧(但一个I帧可能对应多个nal)
|
||||
self.lastDropFrames += [iFrames count];
|
||||
if (iFrames) {
|
||||
[self.list removeObjectsInArray:iFrames];
|
||||
return;
|
||||
}
|
||||
|
||||
[self.list removeAllObjects];
|
||||
|
||||
}
|
||||
|
||||
- (NSArray *)expirePFrames {
|
||||
@@ -222,7 +228,7 @@ NSInteger frameDataCompare(id obj1, id obj2, void *context){
|
||||
}
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.updateInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
__weak typeof(_self) self = _self;
|
||||
__strong typeof(_self) self = _self;
|
||||
[self tick];
|
||||
});
|
||||
}
|
||||
-236
@@ -1,236 +0,0 @@
|
||||
// This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book.
|
||||
// A description of this can be found at his page on the topic:
|
||||
// http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html
|
||||
|
||||
|
||||
#import "GLProgram.h"
|
||||
// START:typedefs
|
||||
#pragma mark Function Pointer Definitions
|
||||
typedef void (*GLInfoFunction)(GLuint program, GLenum pname, GLint* params);
|
||||
typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
// END:typedefs
|
||||
#pragma mark -
|
||||
#pragma mark Private Extension Method Declaration
|
||||
// START:extension
|
||||
@interface GLProgram()
|
||||
|
||||
- (BOOL)compileShader:(GLuint *)shader
|
||||
type:(GLenum)type
|
||||
string:(NSString *)shaderString;
|
||||
@end
|
||||
// END:extension
|
||||
#pragma mark -
|
||||
|
||||
@implementation GLProgram
|
||||
// START:init
|
||||
|
||||
@synthesize initialized = _initialized;
|
||||
|
||||
- (id)initWithVertexShaderString:(NSString *)vShaderString
|
||||
fragmentShaderString:(NSString *)fShaderString;
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_initialized = NO;
|
||||
|
||||
attributes = [[NSMutableArray alloc] init];
|
||||
uniforms = [[NSMutableArray alloc] init];
|
||||
program = glCreateProgram();
|
||||
|
||||
if (![self compileShader:&vertShader
|
||||
type:GL_VERTEX_SHADER
|
||||
string:vShaderString])
|
||||
{
|
||||
NSLog(@"Failed to compile vertex shader");
|
||||
}
|
||||
|
||||
// Create and compile fragment shader
|
||||
if (![self compileShader:&fragShader
|
||||
type:GL_FRAGMENT_SHADER
|
||||
string:fShaderString])
|
||||
{
|
||||
NSLog(@"Failed to compile fragment shader");
|
||||
}
|
||||
|
||||
glAttachShader(program, vertShader);
|
||||
glAttachShader(program, fragShader);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithVertexShaderString:(NSString *)vShaderString
|
||||
fragmentShaderFilename:(NSString *)fShaderFilename;
|
||||
{
|
||||
NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
|
||||
NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
|
||||
|
||||
if ((self = [self initWithVertexShaderString:vShaderString fragmentShaderString:fragmentShaderString]))
|
||||
{
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
|
||||
fragmentShaderFilename:(NSString *)fShaderFilename;
|
||||
{
|
||||
NSString *vertShaderPathname = [[NSBundle mainBundle] pathForResource:vShaderFilename ofType:@"vsh"];
|
||||
NSString *vertexShaderString = [NSString stringWithContentsOfFile:vertShaderPathname encoding:NSUTF8StringEncoding error:nil];
|
||||
|
||||
NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
|
||||
NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
|
||||
|
||||
if ((self = [self initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString]))
|
||||
{
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
// END:init
|
||||
// START:compile
|
||||
- (BOOL)compileShader:(GLuint *)shader
|
||||
type:(GLenum)type
|
||||
string:(NSString *)shaderString
|
||||
{
|
||||
// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
|
||||
|
||||
GLint status;
|
||||
const GLchar *source;
|
||||
|
||||
source =
|
||||
(GLchar *)[shaderString UTF8String];
|
||||
if (!source)
|
||||
{
|
||||
NSLog(@"Failed to load vertex shader");
|
||||
return NO;
|
||||
}
|
||||
|
||||
*shader = glCreateShader(type);
|
||||
glShaderSource(*shader, 1, &source, NULL);
|
||||
glCompileShader(*shader);
|
||||
|
||||
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (status != GL_TRUE)
|
||||
{
|
||||
GLint logLength;
|
||||
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0)
|
||||
{
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(*shader, logLength, &logLength, log);
|
||||
if (shader == &vertShader)
|
||||
{
|
||||
self.vertexShaderLog = [NSString stringWithFormat:@"%s", log];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log];
|
||||
}
|
||||
|
||||
free(log);
|
||||
}
|
||||
}
|
||||
|
||||
// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
|
||||
// NSLog(@"Compiled in %f ms", linkTime * 1000.0);
|
||||
|
||||
return status == GL_TRUE;
|
||||
}
|
||||
// END:compile
|
||||
#pragma mark -
|
||||
// START:addattribute
|
||||
- (void)addAttribute:(NSString *)attributeName
|
||||
{
|
||||
if (![attributes containsObject:attributeName])
|
||||
{
|
||||
[attributes addObject:attributeName];
|
||||
glBindAttribLocation(program,
|
||||
(GLuint)[attributes indexOfObject:attributeName],
|
||||
[attributeName UTF8String]);
|
||||
}
|
||||
}
|
||||
// END:addattribute
|
||||
// START:indexmethods
|
||||
- (GLuint)attributeIndex:(NSString *)attributeName
|
||||
{
|
||||
return (GLuint)[attributes indexOfObject:attributeName];
|
||||
}
|
||||
- (GLuint)uniformIndex:(NSString *)uniformName
|
||||
{
|
||||
return glGetUniformLocation(program, [uniformName UTF8String]);
|
||||
}
|
||||
// END:indexmethods
|
||||
#pragma mark -
|
||||
// START:link
|
||||
- (BOOL)link
|
||||
{
|
||||
// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
|
||||
|
||||
GLint status;
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
return NO;
|
||||
|
||||
if (vertShader)
|
||||
{
|
||||
glDeleteShader(vertShader);
|
||||
vertShader = 0;
|
||||
}
|
||||
if (fragShader)
|
||||
{
|
||||
glDeleteShader(fragShader);
|
||||
fragShader = 0;
|
||||
}
|
||||
|
||||
self.initialized = YES;
|
||||
|
||||
// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
|
||||
// NSLog(@"Linked in %f ms", linkTime * 1000.0);
|
||||
|
||||
return YES;
|
||||
}
|
||||
// END:link
|
||||
// START:use
|
||||
- (void)use
|
||||
{
|
||||
glUseProgram(program);
|
||||
}
|
||||
// END:use
|
||||
#pragma mark -
|
||||
|
||||
- (void)validate;
|
||||
{
|
||||
GLint logLength;
|
||||
|
||||
glValidateProgram(program);
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0)
|
||||
{
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
self.programLog = [NSString stringWithFormat:@"%s", log];
|
||||
free(log);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
// START:dealloc
|
||||
- (void)dealloc
|
||||
{
|
||||
if (vertShader)
|
||||
glDeleteShader(vertShader);
|
||||
|
||||
if (fragShader)
|
||||
glDeleteShader(fragShader);
|
||||
|
||||
if (program)
|
||||
glDeleteProgram(program);
|
||||
|
||||
}
|
||||
// END:dealloc
|
||||
@end
|
||||
@@ -1,128 +0,0 @@
|
||||
#import "GPUImage3x3ConvolutionFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform mediump mat3 convolutionMatrix;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
mediump vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
|
||||
mediump vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
|
||||
mediump vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
|
||||
mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
mediump vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
|
||||
mediump vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
|
||||
mediump vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
|
||||
mediump vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
|
||||
mediump vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
|
||||
|
||||
mediump vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
|
||||
resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
|
||||
resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];
|
||||
|
||||
gl_FragColor = vec4(resultColor, centerColor.a);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform mat3 convolutionMatrix;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
|
||||
vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
|
||||
vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
|
||||
vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
|
||||
vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
|
||||
vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
|
||||
vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
|
||||
vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
|
||||
|
||||
vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
|
||||
resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
|
||||
resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];
|
||||
|
||||
gl_FragColor = vec4(resultColor, centerColor.a);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImage3x3ConvolutionFilter
|
||||
|
||||
@synthesize convolutionKernel = _convolutionKernel;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [self initWithFragmentShaderFromString:kGPUImage3x3ConvolutionFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
self.convolutionKernel = (GPUMatrix3x3){
|
||||
{0.f, 0.f, 0.f},
|
||||
{0.f, 1.f, 0.f},
|
||||
{0.f, 0.f, 0.f}
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
convolutionMatrixUniform = [filterProgram uniformIndex:@"convolutionMatrix"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setConvolutionKernel:(GPUMatrix3x3)newValue;
|
||||
{
|
||||
_convolutionKernel = newValue;
|
||||
|
||||
[self setMatrix3f:_convolutionKernel forUniform:convolutionMatrixUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,121 +0,0 @@
|
||||
#import "GPUImage3x3TextureSamplingFilter.h"
|
||||
|
||||
// Override vertex shader to remove dependent texture reads
|
||||
NSString *const kGPUImageNearbyTexelSamplingVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec4 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidth;
|
||||
uniform float texelHeight;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
vec2 widthStep = vec2(texelWidth, 0.0);
|
||||
vec2 heightStep = vec2(0.0, texelHeight);
|
||||
vec2 widthHeightStep = vec2(texelWidth, texelHeight);
|
||||
vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);
|
||||
|
||||
textureCoordinate = inputTextureCoordinate.xy;
|
||||
leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;
|
||||
rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;
|
||||
|
||||
topTextureCoordinate = inputTextureCoordinate.xy - heightStep;
|
||||
topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;
|
||||
topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;
|
||||
|
||||
bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;
|
||||
bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;
|
||||
bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@implementation GPUImage3x3TextureSamplingFilter
|
||||
|
||||
@synthesize texelWidth = _texelWidth;
|
||||
@synthesize texelHeight = _texelHeight;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString;
|
||||
{
|
||||
if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
|
||||
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
|
||||
{
|
||||
if (!(self = [self initWithVertexShaderFromString:kGPUImageNearbyTexelSamplingVertexShaderString fragmentShaderFromString:fragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupFilterForSize:(CGSize)filterFrameSize;
|
||||
{
|
||||
if (!hasOverriddenImageSizeFactor)
|
||||
{
|
||||
_texelWidth = 1.0 / filterFrameSize.width;
|
||||
_texelHeight = 1.0 / filterFrameSize.height;
|
||||
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
[GPUImageContext setActiveShaderProgram:filterProgram];
|
||||
if (GPUImageRotationSwapsWidthAndHeight(inputRotation))
|
||||
{
|
||||
glUniform1f(texelWidthUniform, _texelHeight);
|
||||
glUniform1f(texelHeightUniform, _texelWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUniform1f(texelWidthUniform, _texelWidth);
|
||||
glUniform1f(texelHeightUniform, _texelHeight);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setTexelWidth:(CGFloat)newValue;
|
||||
{
|
||||
hasOverriddenImageSizeFactor = YES;
|
||||
_texelWidth = newValue;
|
||||
|
||||
[self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setTexelHeight:(CGFloat)newValue;
|
||||
{
|
||||
hasOverriddenImageSizeFactor = YES;
|
||||
_texelHeight = newValue;
|
||||
|
||||
[self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,100 +0,0 @@
|
||||
#import "GPUImageAdaptiveThresholdFilter.h"
|
||||
#import "GPUImageFilter.h"
|
||||
#import "GPUImageTwoInputFilter.h"
|
||||
#import "GPUImageGrayscaleFilter.h"
|
||||
#import "GPUImageBoxBlurFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageAdaptiveThresholdFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
highp float blurredInput = texture2D(inputImageTexture, textureCoordinate).r;
|
||||
highp float localLuminance = texture2D(inputImageTexture2, textureCoordinate2).r;
|
||||
highp float thresholdResult = step(blurredInput - 0.05, localLuminance);
|
||||
|
||||
gl_FragColor = vec4(vec3(thresholdResult), 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageAdaptiveThresholdFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
float blurredInput = texture2D(inputImageTexture, textureCoordinate).r;
|
||||
float localLuminance = texture2D(inputImageTexture2, textureCoordinate2).r;
|
||||
float thresholdResult = step(blurredInput - 0.05, localLuminance);
|
||||
|
||||
gl_FragColor = vec4(vec3(thresholdResult), 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@interface GPUImageAdaptiveThresholdFilter()
|
||||
{
|
||||
GPUImageBoxBlurFilter *boxBlurFilter;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GPUImageAdaptiveThresholdFilter
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
// First pass: reduce to luminance
|
||||
GPUImageGrayscaleFilter *luminanceFilter = [[GPUImageGrayscaleFilter alloc] init];
|
||||
[self addFilter:luminanceFilter];
|
||||
|
||||
// Second pass: perform a box blur
|
||||
boxBlurFilter = [[GPUImageBoxBlurFilter alloc] init];
|
||||
[self addFilter:boxBlurFilter];
|
||||
|
||||
// Third pass: compare the blurred background luminance to the local value
|
||||
GPUImageFilter *adaptiveThresholdFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageAdaptiveThresholdFragmentShaderString];
|
||||
[self addFilter:adaptiveThresholdFilter];
|
||||
|
||||
[luminanceFilter addTarget:boxBlurFilter];
|
||||
|
||||
[boxBlurFilter addTarget:adaptiveThresholdFilter];
|
||||
// To prevent double updating of this filter, disable updates from the sharp luminance image side
|
||||
[luminanceFilter addTarget:adaptiveThresholdFilter];
|
||||
|
||||
self.initialFilters = [NSArray arrayWithObject:luminanceFilter];
|
||||
self.terminalFilter = adaptiveThresholdFilter;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
|
||||
{
|
||||
boxBlurFilter.blurRadiusInPixels = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)blurRadiusInPixels;
|
||||
{
|
||||
return boxBlurFilter.blurRadiusInPixels;
|
||||
}
|
||||
|
||||
@end
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
#import "GPUImageAddBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageAddBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 base = texture2D(inputImageTexture, textureCoordinate);
|
||||
lowp vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
mediump float r;
|
||||
if (overlay.r * base.a + base.r * overlay.a >= overlay.a * base.a) {
|
||||
r = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
|
||||
} else {
|
||||
r = overlay.r + base.r;
|
||||
}
|
||||
|
||||
mediump float g;
|
||||
if (overlay.g * base.a + base.g * overlay.a >= overlay.a * base.a) {
|
||||
g = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
|
||||
} else {
|
||||
g = overlay.g + base.g;
|
||||
}
|
||||
|
||||
mediump float b;
|
||||
if (overlay.b * base.a + base.b * overlay.a >= overlay.a * base.a) {
|
||||
b = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
|
||||
} else {
|
||||
b = overlay.b + base.b;
|
||||
}
|
||||
|
||||
mediump float a = overlay.a + base.a - overlay.a * base.a;
|
||||
|
||||
gl_FragColor = vec4(r, g, b, a);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageAddBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
float r;
|
||||
if (overlay.r * base.a + base.r * overlay.a >= overlay.a * base.a) {
|
||||
r = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
|
||||
} else {
|
||||
r = overlay.r + base.r;
|
||||
}
|
||||
|
||||
float g;
|
||||
if (overlay.g * base.a + base.g * overlay.a >= overlay.a * base.a) {
|
||||
g = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
|
||||
} else {
|
||||
g = overlay.g + base.g;
|
||||
}
|
||||
|
||||
float b;
|
||||
if (overlay.b * base.a + base.b * overlay.a >= overlay.a * base.a) {
|
||||
b = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
|
||||
} else {
|
||||
b = overlay.b + base.b;
|
||||
}
|
||||
|
||||
float a = overlay.a + base.a - overlay.a * base.a;
|
||||
|
||||
gl_FragColor = vec4(r, g, b, a);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@implementation GPUImageAddBlendFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageAddBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#import "GPUImageAlphaBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageAlphaBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
uniform lowp float mixturePercent;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageAlphaBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
uniform float mixturePercent;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageAlphaBlendFilter
|
||||
|
||||
@synthesize mix = _mix;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageAlphaBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
mixUniform = [filterProgram uniformIndex:@"mixturePercent"];
|
||||
self.mix = 0.5;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setMix:(CGFloat)newValue;
|
||||
{
|
||||
_mix = newValue;
|
||||
|
||||
[self setFloat:_mix forUniform:mixUniform program:filterProgram];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,38 +0,0 @@
|
||||
#import "GPUImageAmatorkaFilter.h"
|
||||
#import "GPUImagePicture.h"
|
||||
#import "GPUImageLookupFilter.h"
|
||||
|
||||
@implementation GPUImageAmatorkaFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
UIImage *image = [UIImage imageNamed:@"lookup_amatorka.png"];
|
||||
#else
|
||||
NSImage *image = [NSImage imageNamed:@"lookup_amatorka.png"];
|
||||
#endif
|
||||
|
||||
NSAssert(image, @"To use GPUImageAmatorkaFilter you need to add lookup_amatorka.png from GPUImage/framework/Resources to your application bundle.");
|
||||
|
||||
lookupImageSource = [[GPUImagePicture alloc] initWithImage:image];
|
||||
GPUImageLookupFilter *lookupFilter = [[GPUImageLookupFilter alloc] init];
|
||||
[self addFilter:lookupFilter];
|
||||
|
||||
[lookupImageSource addTarget:lookupFilter atTextureLocation:1];
|
||||
[lookupImageSource processImage];
|
||||
|
||||
self.initialFilters = [NSArray arrayWithObjects:lookupFilter, nil];
|
||||
self.terminalFilter = lookupFilter;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
@end
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
#import "GPUImageAverageColor.h"
|
||||
|
||||
NSString *const kGPUImageColorAveragingVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec4 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidth;
|
||||
uniform float texelHeight;
|
||||
|
||||
varying vec2 upperLeftInputTextureCoordinate;
|
||||
varying vec2 upperRightInputTextureCoordinate;
|
||||
varying vec2 lowerLeftInputTextureCoordinate;
|
||||
varying vec2 lowerRightInputTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
upperLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, -texelHeight);
|
||||
upperRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, -texelHeight);
|
||||
lowerLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, texelHeight);
|
||||
lowerRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, texelHeight);
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorAveragingFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
varying highp vec2 outputTextureCoordinate;
|
||||
|
||||
varying highp vec2 upperLeftInputTextureCoordinate;
|
||||
varying highp vec2 upperRightInputTextureCoordinate;
|
||||
varying highp vec2 lowerLeftInputTextureCoordinate;
|
||||
varying highp vec2 lowerRightInputTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
highp vec4 upperLeftColor = texture2D(inputImageTexture, upperLeftInputTextureCoordinate);
|
||||
highp vec4 upperRightColor = texture2D(inputImageTexture, upperRightInputTextureCoordinate);
|
||||
highp vec4 lowerLeftColor = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate);
|
||||
highp vec4 lowerRightColor = texture2D(inputImageTexture, lowerRightInputTextureCoordinate);
|
||||
|
||||
gl_FragColor = 0.25 * (upperLeftColor + upperRightColor + lowerLeftColor + lowerRightColor);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorAveragingFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
varying vec2 outputTextureCoordinate;
|
||||
|
||||
varying vec2 upperLeftInputTextureCoordinate;
|
||||
varying vec2 upperRightInputTextureCoordinate;
|
||||
varying vec2 lowerLeftInputTextureCoordinate;
|
||||
varying vec2 lowerRightInputTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 upperLeftColor = texture2D(inputImageTexture, upperLeftInputTextureCoordinate);
|
||||
vec4 upperRightColor = texture2D(inputImageTexture, upperRightInputTextureCoordinate);
|
||||
vec4 lowerLeftColor = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate);
|
||||
vec4 lowerRightColor = texture2D(inputImageTexture, lowerRightInputTextureCoordinate);
|
||||
|
||||
gl_FragColor = 0.25 * (upperLeftColor + upperRightColor + lowerLeftColor + lowerRightColor);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageAverageColor
|
||||
|
||||
@synthesize colorAverageProcessingFinishedBlock = _colorAverageProcessingFinishedBlock;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithVertexShaderFromString:kGPUImageColorAveragingVertexShaderString fragmentShaderFromString:kGPUImageColorAveragingFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
|
||||
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
|
||||
finalStageSize = CGSizeMake(1.0, 1.0);
|
||||
|
||||
__unsafe_unretained GPUImageAverageColor *weakSelf = self;
|
||||
[self setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) {
|
||||
[weakSelf extractAverageColorAtFrameTime:frameTime];
|
||||
}];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc;
|
||||
{
|
||||
if (rawImagePixels != NULL)
|
||||
{
|
||||
free(rawImagePixels);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Managing the display FBOs
|
||||
|
||||
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
|
||||
{
|
||||
if (self.preventRendering)
|
||||
{
|
||||
[firstInputFramebuffer unlock];
|
||||
return;
|
||||
}
|
||||
|
||||
outputFramebuffer = nil;
|
||||
[GPUImageContext setActiveShaderProgram:filterProgram];
|
||||
|
||||
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
|
||||
glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
|
||||
|
||||
GLuint currentTexture = [firstInputFramebuffer texture];
|
||||
|
||||
NSUInteger numberOfReductionsInX = floor(log(inputTextureSize.width) / log(4.0));
|
||||
NSUInteger numberOfReductionsInY = floor(log(inputTextureSize.height) / log(4.0));
|
||||
NSUInteger reductionsToHitSideLimit = MIN(numberOfReductionsInX, numberOfReductionsInY);
|
||||
for (NSUInteger currentReduction = 0; currentReduction < reductionsToHitSideLimit; currentReduction++)
|
||||
{
|
||||
CGSize currentStageSize = CGSizeMake(floor(inputTextureSize.width / pow(4.0, currentReduction + 1.0)), floor(inputTextureSize.height / pow(4.0, currentReduction + 1.0)));
|
||||
|
||||
[outputFramebuffer unlock];
|
||||
outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:currentStageSize textureOptions:self.outputTextureOptions onlyTexture:NO];
|
||||
[outputFramebuffer activateFramebuffer];
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, currentTexture);
|
||||
|
||||
glUniform1i(filterInputTextureUniform, 2);
|
||||
|
||||
glUniform1f(texelWidthUniform, 0.25 / currentStageSize.width);
|
||||
glUniform1f(texelHeightUniform, 0.25 / currentStageSize.height);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
currentTexture = [outputFramebuffer texture];
|
||||
finalStageSize = currentStageSize;
|
||||
}
|
||||
|
||||
[firstInputFramebuffer unlock];
|
||||
}
|
||||
|
||||
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
inputRotation = kGPUImageNoRotation;
|
||||
}
|
||||
|
||||
- (void)extractAverageColorAtFrameTime:(CMTime)frameTime;
|
||||
{
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
// we need a normal color texture for averaging the color values
|
||||
NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture internal format for this filter must be GL_RGBA.");
|
||||
NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE.");
|
||||
|
||||
NSUInteger totalNumberOfPixels = round(finalStageSize.width * finalStageSize.height);
|
||||
|
||||
if (rawImagePixels == NULL)
|
||||
{
|
||||
rawImagePixels = (GLubyte *)malloc(totalNumberOfPixels * 4);
|
||||
}
|
||||
|
||||
[GPUImageContext useImageProcessingContext];
|
||||
[outputFramebuffer activateFramebuffer];
|
||||
glReadPixels(0, 0, (int)finalStageSize.width, (int)finalStageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels);
|
||||
|
||||
NSUInteger redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
|
||||
NSUInteger byteIndex = 0;
|
||||
for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++)
|
||||
{
|
||||
redTotal += rawImagePixels[byteIndex++];
|
||||
greenTotal += rawImagePixels[byteIndex++];
|
||||
blueTotal += rawImagePixels[byteIndex++];
|
||||
alphaTotal += rawImagePixels[byteIndex++];
|
||||
}
|
||||
|
||||
CGFloat normalizedRedTotal = (CGFloat)redTotal / (CGFloat)totalNumberOfPixels / 255.0;
|
||||
CGFloat normalizedGreenTotal = (CGFloat)greenTotal / (CGFloat)totalNumberOfPixels / 255.0;
|
||||
CGFloat normalizedBlueTotal = (CGFloat)blueTotal / (CGFloat)totalNumberOfPixels / 255.0;
|
||||
CGFloat normalizedAlphaTotal = (CGFloat)alphaTotal / (CGFloat)totalNumberOfPixels / 255.0;
|
||||
|
||||
if (_colorAverageProcessingFinishedBlock != NULL)
|
||||
{
|
||||
_colorAverageProcessingFinishedBlock(normalizedRedTotal, normalizedGreenTotal, normalizedBlueTotal, normalizedAlphaTotal, frameTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,47 +0,0 @@
|
||||
#import "GPUImageAverageLuminanceThresholdFilter.h"
|
||||
#import "GPUImageLuminosity.h"
|
||||
#import "GPUImageLuminanceThresholdFilter.h"
|
||||
|
||||
@interface GPUImageAverageLuminanceThresholdFilter()
|
||||
{
|
||||
GPUImageLuminosity *luminosityFilter;
|
||||
GPUImageLuminanceThresholdFilter *luminanceThresholdFilter;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GPUImageAverageLuminanceThresholdFilter
|
||||
|
||||
@synthesize thresholdMultiplier = _thresholdMultiplier;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
self.thresholdMultiplier = 1.0;
|
||||
|
||||
luminosityFilter = [[GPUImageLuminosity alloc] init];
|
||||
[self addFilter:luminosityFilter];
|
||||
|
||||
luminanceThresholdFilter = [[GPUImageLuminanceThresholdFilter alloc] init];
|
||||
[self addFilter:luminanceThresholdFilter];
|
||||
|
||||
__unsafe_unretained GPUImageAverageLuminanceThresholdFilter *weakSelf = self;
|
||||
__unsafe_unretained GPUImageLuminanceThresholdFilter *weakThreshold = luminanceThresholdFilter;
|
||||
|
||||
[luminosityFilter setLuminosityProcessingFinishedBlock:^(CGFloat luminosity, CMTime frameTime) {
|
||||
weakThreshold.threshold = luminosity * weakSelf.thresholdMultiplier;
|
||||
}];
|
||||
|
||||
self.initialFilters = [NSArray arrayWithObjects:luminosityFilter, luminanceThresholdFilter, nil];
|
||||
self.terminalFilter = luminanceThresholdFilter;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
-231
@@ -1,231 +0,0 @@
|
||||
#import "GPUImageBilateralFilter.h"
|
||||
|
||||
NSString *const kGPUImageBilateralBlurVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec4 inputTextureCoordinate;
|
||||
|
||||
const int GAUSSIAN_SAMPLES = 9;
|
||||
|
||||
uniform float texelWidthOffset;
|
||||
uniform float texelHeightOffset;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
textureCoordinate = inputTextureCoordinate.xy;
|
||||
|
||||
// Calculate the positions for the blur
|
||||
int multiplier = 0;
|
||||
vec2 blurStep;
|
||||
vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);
|
||||
|
||||
for (int i = 0; i < GAUSSIAN_SAMPLES; i++)
|
||||
{
|
||||
multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));
|
||||
// Blur in x (horizontal)
|
||||
blurStep = float(multiplier) * singleStepOffset;
|
||||
blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageBilateralFilterFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
const lowp int GAUSSIAN_SAMPLES = 9;
|
||||
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];
|
||||
|
||||
uniform mediump float distanceNormalizationFactor;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 centralColor;
|
||||
lowp float gaussianWeightTotal;
|
||||
lowp vec4 sum;
|
||||
lowp vec4 sampleColor;
|
||||
lowp float distanceFromCentralColor;
|
||||
lowp float gaussianWeight;
|
||||
|
||||
centralColor = texture2D(inputImageTexture, blurCoordinates[4]);
|
||||
gaussianWeightTotal = 0.18;
|
||||
sum = centralColor * 0.18;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
gl_FragColor = sum / gaussianWeightTotal;
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageBilateralFilterFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
const int GAUSSIAN_SAMPLES = 9;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];
|
||||
|
||||
uniform float distanceNormalizationFactor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 centralColor;
|
||||
float gaussianWeightTotal;
|
||||
vec4 sum;
|
||||
vec4 sampleColor;
|
||||
float distanceFromCentralColor;
|
||||
float gaussianWeight;
|
||||
|
||||
centralColor = texture2D(inputImageTexture, blurCoordinates[4]);
|
||||
gaussianWeightTotal = 0.18;
|
||||
sum = centralColor * 0.18;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);
|
||||
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
|
||||
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
|
||||
gaussianWeightTotal += gaussianWeight;
|
||||
sum += sampleColor * gaussianWeight;
|
||||
|
||||
gl_FragColor = sum / gaussianWeightTotal;
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageBilateralFilter
|
||||
|
||||
@synthesize distanceNormalizationFactor = _distanceNormalizationFactor;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
|
||||
if (!(self = [super initWithFirstStageVertexShaderFromString:kGPUImageBilateralBlurVertexShaderString
|
||||
firstStageFragmentShaderFromString:kGPUImageBilateralFilterFragmentShaderString
|
||||
secondStageVertexShaderFromString:kGPUImageBilateralBlurVertexShaderString
|
||||
secondStageFragmentShaderFromString:kGPUImageBilateralFilterFragmentShaderString])) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
firstDistanceNormalizationFactorUniform = [filterProgram uniformIndex:@"distanceNormalizationFactor"];
|
||||
secondDistanceNormalizationFactorUniform = [filterProgram uniformIndex:@"distanceNormalizationFactor"];
|
||||
|
||||
self.texelSpacingMultiplier = 4.0;
|
||||
self.distanceNormalizationFactor = 8.0;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setDistanceNormalizationFactor:(CGFloat)newValue
|
||||
{
|
||||
_distanceNormalizationFactor = newValue;
|
||||
|
||||
[self setFloat:newValue
|
||||
forUniform:firstDistanceNormalizationFactorUniform
|
||||
program:filterProgram];
|
||||
|
||||
[self setFloat:newValue
|
||||
forUniform:secondDistanceNormalizationFactorUniform
|
||||
program:secondFilterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
-178
@@ -1,178 +0,0 @@
|
||||
#import "GPUImageBoxBlurFilter.h"
|
||||
|
||||
|
||||
@implementation GPUImageBoxBlurFilter
|
||||
|
||||
+ (NSString *)vertexShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma;
|
||||
{
|
||||
if (blurRadius < 1)
|
||||
{
|
||||
return kGPUImageVertexShaderString;
|
||||
}
|
||||
|
||||
// From these weights we calculate the offsets to read interpolated values from
|
||||
NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7);
|
||||
|
||||
NSMutableString *shaderString = [[NSMutableString alloc] init];
|
||||
// Header
|
||||
[shaderString appendFormat:@"\
|
||||
attribute vec4 position;\n\
|
||||
attribute vec4 inputTextureCoordinate;\n\
|
||||
\n\
|
||||
uniform float texelWidthOffset;\n\
|
||||
uniform float texelHeightOffset;\n\
|
||||
\n\
|
||||
varying vec2 blurCoordinates[%lu];\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
gl_Position = position;\n\
|
||||
\n\
|
||||
vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2))];
|
||||
|
||||
// Inner offset loop
|
||||
[shaderString appendString:@"blurCoordinates[0] = inputTextureCoordinate.xy;\n"];
|
||||
for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++)
|
||||
{
|
||||
GLfloat optimizedOffset = (GLfloat)(currentOptimizedOffset * 2) + 1.5;
|
||||
|
||||
[shaderString appendFormat:@"\
|
||||
blurCoordinates[%lu] = inputTextureCoordinate.xy + singleStepOffset * %f;\n\
|
||||
blurCoordinates[%lu] = inputTextureCoordinate.xy - singleStepOffset * %f;\n", (unsigned long)((currentOptimizedOffset * 2) + 1), optimizedOffset, (unsigned long)((currentOptimizedOffset * 2) + 2), optimizedOffset];
|
||||
}
|
||||
|
||||
// Footer
|
||||
[shaderString appendString:@"}\n"];
|
||||
|
||||
return shaderString;
|
||||
}
|
||||
|
||||
+ (NSString *)fragmentShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma;
|
||||
{
|
||||
if (blurRadius < 1)
|
||||
{
|
||||
return kGPUImagePassthroughFragmentShaderString;
|
||||
}
|
||||
|
||||
NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7);
|
||||
NSUInteger trueNumberOfOptimizedOffsets = blurRadius / 2 + (blurRadius % 2);
|
||||
|
||||
NSMutableString *shaderString = [[NSMutableString alloc] init];
|
||||
|
||||
// Header
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
[shaderString appendFormat:@"\
|
||||
uniform sampler2D inputImageTexture;\n\
|
||||
uniform highp float texelWidthOffset;\n\
|
||||
uniform highp float texelHeightOffset;\n\
|
||||
\n\
|
||||
varying highp vec2 blurCoordinates[%lu];\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
lowp vec4 sum = vec4(0.0);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2)) ];
|
||||
#else
|
||||
[shaderString appendFormat:@"\
|
||||
uniform sampler2D inputImageTexture;\n\
|
||||
uniform float texelWidthOffset;\n\
|
||||
uniform float texelHeightOffset;\n\
|
||||
\n\
|
||||
varying vec2 blurCoordinates[%lu];\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
vec4 sum = vec4(0.0);\n", 1 + (numberOfOptimizedOffsets * 2) ];
|
||||
#endif
|
||||
|
||||
GLfloat boxWeight = 1.0 / (GLfloat)((blurRadius * 2) + 1);
|
||||
|
||||
// Inner texture loop
|
||||
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0]) * %f;\n", boxWeight];
|
||||
|
||||
for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < numberOfOptimizedOffsets; currentBlurCoordinateIndex++)
|
||||
{
|
||||
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 1), boxWeight * 2.0];
|
||||
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 2), boxWeight * 2.0];
|
||||
}
|
||||
|
||||
// If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader
|
||||
if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets)
|
||||
{
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
[shaderString appendString:@"highp vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"];
|
||||
#else
|
||||
[shaderString appendString:@"vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"];
|
||||
#endif
|
||||
|
||||
for (NSUInteger currentOverlowTextureRead = numberOfOptimizedOffsets; currentOverlowTextureRead < trueNumberOfOptimizedOffsets; currentOverlowTextureRead++)
|
||||
{
|
||||
GLfloat optimizedOffset = (GLfloat)(currentOverlowTextureRead * 2) + 1.5;
|
||||
|
||||
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] + singleStepOffset * %f) * %f;\n", optimizedOffset, boxWeight * 2.0];
|
||||
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] - singleStepOffset * %f) * %f;\n", optimizedOffset, boxWeight * 2.0];
|
||||
}
|
||||
}
|
||||
|
||||
// Footer
|
||||
[shaderString appendString:@"\
|
||||
gl_FragColor = sum;\n\
|
||||
}\n"];
|
||||
|
||||
return shaderString;
|
||||
}
|
||||
|
||||
- (void)setupFilterForSize:(CGSize)filterFrameSize;
|
||||
{
|
||||
[super setupFilterForSize:filterFrameSize];
|
||||
|
||||
if (shouldResizeBlurRadiusWithImageSize == YES)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
// NSString *currentGaussianBlurVertexShader = [GPUImageGaussianBlurFilter vertexShaderForStandardGaussianOfRadius:4 sigma:2.0];
|
||||
// NSString *currentGaussianBlurFragmentShader = [GPUImageGaussianBlurFilter fragmentShaderForStandardGaussianOfRadius:4 sigma:2.0];
|
||||
|
||||
NSString *currentBoxBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:4 sigma:0.0];
|
||||
NSString *currentBoxBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:4 sigma:0.0];
|
||||
|
||||
if (!(self = [super initWithFirstStageVertexShaderFromString:currentBoxBlurVertexShader firstStageFragmentShaderFromString:currentBoxBlurFragmentShader secondStageVertexShaderFromString:currentBoxBlurVertexShader secondStageFragmentShaderFromString:currentBoxBlurFragmentShader]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
_blurRadiusInPixels = 4.0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
|
||||
{
|
||||
CGFloat newBlurRadius = round(round(newValue / 2.0) * 2.0); // For now, only do even radii
|
||||
|
||||
if (newBlurRadius != _blurRadiusInPixels)
|
||||
{
|
||||
_blurRadiusInPixels = newBlurRadius;
|
||||
|
||||
NSString *newGaussianBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:_blurRadiusInPixels sigma:0.0];
|
||||
NSString *newGaussianBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:_blurRadiusInPixels sigma:0.0];
|
||||
|
||||
// NSLog(@"Optimized vertex shader: \n%@", newGaussianBlurVertexShader);
|
||||
// NSLog(@"Optimized fragment shader: \n%@", newGaussianBlurFragmentShader);
|
||||
//
|
||||
[self switchToVertexShader:newGaussianBlurVertexShader fragmentShader:newGaussianBlurFragmentShader];
|
||||
}
|
||||
shouldResizeBlurRadiusWithImageSize = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
#import "GPUImageBrightnessFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform lowp float brightness;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform float brightness;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageBrightnessFilter
|
||||
|
||||
@synthesize brightness = _brightness;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageBrightnessFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
brightnessUniform = [filterProgram uniformIndex:@"brightness"];
|
||||
self.brightness = 0.0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setBrightness:(CGFloat)newValue;
|
||||
{
|
||||
_brightness = newValue;
|
||||
|
||||
[self setFloat:_brightness forUniform:brightnessUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
#import "GPUImageBuffer.h"
|
||||
|
||||
@interface GPUImageBuffer()
|
||||
|
||||
@end
|
||||
|
||||
@implementation GPUImageBuffer
|
||||
|
||||
@synthesize bufferSize = _bufferSize;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [self initWithFragmentShaderFromString:kGPUImagePassthroughFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
bufferedFramebuffers = [[NSMutableArray alloc] init];
|
||||
// [bufferedTextures addObject:[NSNumber numberWithInt:outputTexture]];
|
||||
_bufferSize = 1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
for (GPUImageFramebuffer *currentFramebuffer in bufferedFramebuffers)
|
||||
{
|
||||
[currentFramebuffer unlock];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark GPUImageInput
|
||||
|
||||
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
if ([bufferedFramebuffers count] >= _bufferSize)
|
||||
{
|
||||
outputFramebuffer = [bufferedFramebuffers objectAtIndex:0];
|
||||
[bufferedFramebuffers removeObjectAtIndex:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing yet in the buffer, so don't process further until the buffer is full
|
||||
outputFramebuffer = firstInputFramebuffer;
|
||||
[firstInputFramebuffer lock];
|
||||
}
|
||||
|
||||
[bufferedFramebuffers addObject:firstInputFramebuffer];
|
||||
|
||||
// Need to pass along rotation information, as we're just holding on to buffered framebuffers and not rotating them ourselves
|
||||
for (id<GPUImageInput> currentTarget in targets)
|
||||
{
|
||||
if (currentTarget != self.targetToIgnoreForUpdates)
|
||||
{
|
||||
NSInteger indexOfObject = [targets indexOfObject:currentTarget];
|
||||
NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
|
||||
|
||||
[currentTarget setInputRotation:inputRotation atIndex:textureIndex];
|
||||
}
|
||||
}
|
||||
|
||||
// Let the downstream video elements see the previous frame from the buffer before rendering a new one into place
|
||||
[self informTargetsAboutNewFrameAtTime:frameTime];
|
||||
|
||||
// [self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]];
|
||||
}
|
||||
|
||||
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
|
||||
{
|
||||
// No need to render to another texture anymore, since we'll be hanging on to the textures in our buffer
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setBufferSize:(NSUInteger)newValue;
|
||||
{
|
||||
if ( (newValue == _bufferSize) || (newValue < 1) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (newValue > _bufferSize)
|
||||
{
|
||||
NSUInteger texturesToAdd = newValue - _bufferSize;
|
||||
for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToAdd; currentTextureIndex++)
|
||||
{
|
||||
// TODO: Deal with the growth of the size of the buffer by rotating framebuffers, no textures
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSUInteger texturesToRemove = _bufferSize - newValue;
|
||||
for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToRemove; currentTextureIndex++)
|
||||
{
|
||||
GPUImageFramebuffer *lastFramebuffer = [bufferedFramebuffers lastObject];
|
||||
[bufferedFramebuffers removeObjectAtIndex:([bufferedFramebuffers count] - 1)];
|
||||
|
||||
[lastFramebuffer unlock];
|
||||
lastFramebuffer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
_bufferSize = newValue;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,174 +0,0 @@
|
||||
#import "GPUImageBulgeDistortionFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageBulgeDistortionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform highp float aspectRatio;
|
||||
uniform highp vec2 center;
|
||||
uniform highp float radius;
|
||||
uniform highp float scale;
|
||||
|
||||
void main()
|
||||
{
|
||||
highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, ((textureCoordinate.y - center.y) * aspectRatio) + center.y);
|
||||
highp float dist = distance(center, textureCoordinateToUse);
|
||||
textureCoordinateToUse = textureCoordinate;
|
||||
|
||||
if (dist < radius)
|
||||
{
|
||||
textureCoordinateToUse -= center;
|
||||
highp float percent = 1.0 - ((radius - dist) / radius) * scale;
|
||||
percent = percent * percent;
|
||||
|
||||
textureCoordinateToUse = textureCoordinateToUse * percent;
|
||||
textureCoordinateToUse += center;
|
||||
}
|
||||
|
||||
gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse );
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageBulgeDistortionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform float aspectRatio;
|
||||
uniform vec2 center;
|
||||
uniform float radius;
|
||||
uniform float scale;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 textureCoordinateToUse = vec2(textureCoordinate.x, ((textureCoordinate.y - center.y) * aspectRatio) + center.y);
|
||||
float dist = distance(center, textureCoordinateToUse);
|
||||
textureCoordinateToUse = textureCoordinate;
|
||||
|
||||
if (dist < radius)
|
||||
{
|
||||
textureCoordinateToUse -= center;
|
||||
float percent = 1.0 - ((radius - dist) / radius) * scale;
|
||||
percent = percent * percent;
|
||||
|
||||
textureCoordinateToUse = textureCoordinateToUse * percent;
|
||||
textureCoordinateToUse += center;
|
||||
}
|
||||
|
||||
gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse );
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
@interface GPUImageBulgeDistortionFilter ()
|
||||
|
||||
- (void)adjustAspectRatio;
|
||||
|
||||
@property (readwrite, nonatomic) CGFloat aspectRatio;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GPUImageBulgeDistortionFilter
|
||||
|
||||
@synthesize aspectRatio = _aspectRatio;
|
||||
@synthesize center = _center;
|
||||
@synthesize radius = _radius;
|
||||
@synthesize scale = _scale;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageBulgeDistortionFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"];
|
||||
radiusUniform = [filterProgram uniformIndex:@"radius"];
|
||||
scaleUniform = [filterProgram uniformIndex:@"scale"];
|
||||
centerUniform = [filterProgram uniformIndex:@"center"];
|
||||
|
||||
self.radius = 0.25;
|
||||
self.scale = 0.5;
|
||||
self.center = CGPointMake(0.5, 0.5);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)adjustAspectRatio;
|
||||
{
|
||||
if (GPUImageRotationSwapsWidthAndHeight(inputRotation))
|
||||
{
|
||||
[self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)forceProcessingAtSize:(CGSize)frameSize;
|
||||
{
|
||||
[super forceProcessingAtSize:frameSize];
|
||||
[self adjustAspectRatio];
|
||||
}
|
||||
|
||||
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
CGSize oldInputSize = inputTextureSize;
|
||||
[super setInputSize:newSize atIndex:textureIndex];
|
||||
|
||||
if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) )
|
||||
{
|
||||
[self adjustAspectRatio];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setAspectRatio:(CGFloat)newValue;
|
||||
{
|
||||
_aspectRatio = newValue;
|
||||
|
||||
[self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
[super setInputRotation:newInputRotation atIndex:textureIndex];
|
||||
[self setCenter:self.center];
|
||||
[self adjustAspectRatio];
|
||||
}
|
||||
|
||||
- (void)setRadius:(CGFloat)newValue;
|
||||
{
|
||||
_radius = newValue;
|
||||
|
||||
[self setFloat:_radius forUniform:radiusUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setScale:(CGFloat)newValue;
|
||||
{
|
||||
_scale = newValue;
|
||||
|
||||
[self setFloat:_scale forUniform:scaleUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setCenter:(CGPoint)newValue;
|
||||
{
|
||||
_center = newValue;
|
||||
|
||||
CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation];
|
||||
|
||||
[self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,113 +0,0 @@
|
||||
//
|
||||
// GPUImageCGAColorspaceFilter.m
|
||||
//
|
||||
|
||||
#import "GPUImageCGAColorspaceFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageCGAColorspaceFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
highp vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0);
|
||||
//highp vec4 colorDivisor = vec4(colorDepth);
|
||||
|
||||
highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor);
|
||||
highp vec4 color = texture2D(inputImageTexture, samplePos );
|
||||
|
||||
//gl_FragColor = texture2D(inputImageTexture, samplePos );
|
||||
mediump vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0);
|
||||
mediump vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0);
|
||||
mediump vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
mediump vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
mediump vec4 endColor;
|
||||
highp float blackDistance = distance(color, colorBlack);
|
||||
highp float whiteDistance = distance(color, colorWhite);
|
||||
highp float magentaDistance = distance(color, colorMagenta);
|
||||
highp float cyanDistance = distance(color, colorCyan);
|
||||
|
||||
mediump vec4 finalColor;
|
||||
|
||||
highp float colorDistance = min(magentaDistance, cyanDistance);
|
||||
colorDistance = min(colorDistance, whiteDistance);
|
||||
colorDistance = min(colorDistance, blackDistance);
|
||||
|
||||
if (colorDistance == blackDistance) {
|
||||
finalColor = colorBlack;
|
||||
} else if (colorDistance == whiteDistance) {
|
||||
finalColor = colorWhite;
|
||||
} else if (colorDistance == cyanDistance) {
|
||||
finalColor = colorCyan;
|
||||
} else {
|
||||
finalColor = colorMagenta;
|
||||
}
|
||||
|
||||
gl_FragColor = finalColor;
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageCGAColorspaceFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0);
|
||||
//highp vec4 colorDivisor = vec4(colorDepth);
|
||||
|
||||
vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor);
|
||||
vec4 color = texture2D(inputImageTexture, samplePos );
|
||||
|
||||
//gl_FragColor = texture2D(inputImageTexture, samplePos );
|
||||
vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0);
|
||||
vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0);
|
||||
vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
vec4 endColor;
|
||||
float blackDistance = distance(color, colorBlack);
|
||||
float whiteDistance = distance(color, colorWhite);
|
||||
float magentaDistance = distance(color, colorMagenta);
|
||||
float cyanDistance = distance(color, colorCyan);
|
||||
|
||||
vec4 finalColor;
|
||||
|
||||
float colorDistance = min(magentaDistance, cyanDistance);
|
||||
colorDistance = min(colorDistance, whiteDistance);
|
||||
colorDistance = min(colorDistance, blackDistance);
|
||||
|
||||
if (colorDistance == blackDistance) {
|
||||
finalColor = colorBlack;
|
||||
} else if (colorDistance == whiteDistance) {
|
||||
finalColor = colorWhite;
|
||||
} else if (colorDistance == cyanDistance) {
|
||||
finalColor = colorCyan;
|
||||
} else {
|
||||
finalColor = colorMagenta;
|
||||
}
|
||||
|
||||
gl_FragColor = finalColor;
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageCGAColorspaceFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageCGAColorspaceFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,125 +0,0 @@
|
||||
#import "GPUImageCannyEdgeDetectionFilter.h"
|
||||
|
||||
#import "GPUImageGrayscaleFilter.h"
|
||||
#import "GPUImageDirectionalSobelEdgeDetectionFilter.h"
|
||||
#import "GPUImageDirectionalNonMaximumSuppressionFilter.h"
|
||||
#import "GPUImageWeakPixelInclusionFilter.h"
|
||||
#import "GPUImageSingleComponentGaussianBlurFilter.h"
|
||||
|
||||
@implementation GPUImageCannyEdgeDetectionFilter
|
||||
|
||||
@synthesize upperThreshold;
|
||||
@synthesize lowerThreshold;
|
||||
@synthesize blurRadiusInPixels;
|
||||
@synthesize blurTexelSpacingMultiplier;
|
||||
@synthesize texelWidth;
|
||||
@synthesize texelHeight;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
// First pass: convert image to luminance
|
||||
luminanceFilter = [[GPUImageGrayscaleFilter alloc] init];
|
||||
[self addFilter:luminanceFilter];
|
||||
|
||||
// Second pass: apply a variable Gaussian blur
|
||||
blurFilter = [[GPUImageSingleComponentGaussianBlurFilter alloc] init];
|
||||
[self addFilter:blurFilter];
|
||||
|
||||
// Third pass: run the Sobel edge detection, with calculated gradient directions, on this blurred image
|
||||
edgeDetectionFilter = [[GPUImageDirectionalSobelEdgeDetectionFilter alloc] init];
|
||||
[self addFilter:edgeDetectionFilter];
|
||||
|
||||
// Fourth pass: apply non-maximum suppression
|
||||
nonMaximumSuppressionFilter = [[GPUImageDirectionalNonMaximumSuppressionFilter alloc] init];
|
||||
[self addFilter:nonMaximumSuppressionFilter];
|
||||
|
||||
// Fifth pass: include weak pixels to complete edges
|
||||
weakPixelInclusionFilter = [[GPUImageWeakPixelInclusionFilter alloc] init];
|
||||
[self addFilter:weakPixelInclusionFilter];
|
||||
|
||||
[luminanceFilter addTarget:blurFilter];
|
||||
[blurFilter addTarget:edgeDetectionFilter];
|
||||
[edgeDetectionFilter addTarget:nonMaximumSuppressionFilter];
|
||||
[nonMaximumSuppressionFilter addTarget:weakPixelInclusionFilter];
|
||||
|
||||
self.initialFilters = [NSArray arrayWithObject:luminanceFilter];
|
||||
// self.terminalFilter = nonMaximumSuppressionFilter;
|
||||
self.terminalFilter = weakPixelInclusionFilter;
|
||||
|
||||
self.blurRadiusInPixels = 2.0;
|
||||
self.blurTexelSpacingMultiplier = 1.0;
|
||||
self.upperThreshold = 0.4;
|
||||
self.lowerThreshold = 0.1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
|
||||
{
|
||||
blurFilter.blurRadiusInPixels = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)blurRadiusInPixels;
|
||||
{
|
||||
return blurFilter.blurRadiusInPixels;
|
||||
}
|
||||
|
||||
- (void)setBlurTexelSpacingMultiplier:(CGFloat)newValue;
|
||||
{
|
||||
blurFilter.texelSpacingMultiplier = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)blurTexelSpacingMultiplier;
|
||||
{
|
||||
return blurFilter.texelSpacingMultiplier;
|
||||
}
|
||||
|
||||
- (void)setTexelWidth:(CGFloat)newValue;
|
||||
{
|
||||
edgeDetectionFilter.texelWidth = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)texelWidth;
|
||||
{
|
||||
return edgeDetectionFilter.texelWidth;
|
||||
}
|
||||
|
||||
- (void)setTexelHeight:(CGFloat)newValue;
|
||||
{
|
||||
edgeDetectionFilter.texelHeight = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)texelHeight;
|
||||
{
|
||||
return edgeDetectionFilter.texelHeight;
|
||||
}
|
||||
|
||||
- (void)setUpperThreshold:(CGFloat)newValue;
|
||||
{
|
||||
nonMaximumSuppressionFilter.upperThreshold = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)upperThreshold;
|
||||
{
|
||||
return nonMaximumSuppressionFilter.upperThreshold;
|
||||
}
|
||||
|
||||
- (void)setLowerThreshold:(CGFloat)newValue;
|
||||
{
|
||||
nonMaximumSuppressionFilter.lowerThreshold = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)lowerThreshold;
|
||||
{
|
||||
return nonMaximumSuppressionFilter.lowerThreshold;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,117 +0,0 @@
|
||||
#import "GPUImageChromaKeyBlendFilter.h"
|
||||
|
||||
// Shader code based on Apple's CIChromaKeyFilter example: https://developer.apple.com/library/mac/#samplecode/CIChromaKeyFilter/Introduction/Intro.html
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageChromaKeyBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision highp float;
|
||||
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform float thresholdSensitivity;
|
||||
uniform float smoothing;
|
||||
uniform vec3 colorToReplace;
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
|
||||
float maskCr = 0.7132 * (colorToReplace.r - maskY);
|
||||
float maskCb = 0.5647 * (colorToReplace.b - maskY);
|
||||
|
||||
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
|
||||
float Cr = 0.7132 * (textureColor.r - Y);
|
||||
float Cb = 0.5647 * (textureColor.b - Y);
|
||||
|
||||
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
|
||||
float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
|
||||
gl_FragColor = mix(textureColor, textureColor2, blendValue);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageChromaKeyBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform float thresholdSensitivity;
|
||||
uniform float smoothing;
|
||||
uniform vec3 colorToReplace;
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
|
||||
float maskCr = 0.7132 * (colorToReplace.r - maskY);
|
||||
float maskCb = 0.5647 * (colorToReplace.b - maskY);
|
||||
|
||||
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
|
||||
float Cr = 0.7132 * (textureColor.r - Y);
|
||||
float Cb = 0.5647 * (textureColor.b - Y);
|
||||
|
||||
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
|
||||
float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
|
||||
gl_FragColor = mix(textureColor, textureColor2, blendValue);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageChromaKeyBlendFilter
|
||||
|
||||
@synthesize thresholdSensitivity = _thresholdSensitivity;
|
||||
@synthesize smoothing = _smoothing;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageChromaKeyBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
thresholdSensitivityUniform = [filterProgram uniformIndex:@"thresholdSensitivity"];
|
||||
smoothingUniform = [filterProgram uniformIndex:@"smoothing"];
|
||||
colorToReplaceUniform = [filterProgram uniformIndex:@"colorToReplace"];
|
||||
|
||||
self.thresholdSensitivity = 0.4;
|
||||
self.smoothing = 0.1;
|
||||
[self setColorToReplaceRed:0.0 green:1.0 blue:0.0];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
|
||||
{
|
||||
GPUVector3 colorToReplace = {redComponent, greenComponent, blueComponent};
|
||||
|
||||
[self setVec3:colorToReplace forUniform:colorToReplaceUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setThresholdSensitivity:(CGFloat)newValue;
|
||||
{
|
||||
_thresholdSensitivity = newValue;
|
||||
|
||||
[self setFloat:(GLfloat)_thresholdSensitivity forUniform:thresholdSensitivityUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setSmoothing:(CGFloat)newValue;
|
||||
{
|
||||
_smoothing = newValue;
|
||||
|
||||
[self setFloat:(GLfloat)_smoothing forUniform:smoothingUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
#import "GPUImageChromaKeyFilter.h"
|
||||
|
||||
// Shader code based on Apple's CIChromaKeyFilter example: https://developer.apple.com/library/mac/#samplecode/CIChromaKeyFilter/Introduction/Intro.html
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageChromaKeyFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision highp float;
|
||||
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform float thresholdSensitivity;
|
||||
uniform float smoothing;
|
||||
uniform vec3 colorToReplace;
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
|
||||
float maskCr = 0.7132 * (colorToReplace.r - maskY);
|
||||
float maskCb = 0.5647 * (colorToReplace.b - maskY);
|
||||
|
||||
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
|
||||
float Cr = 0.7132 * (textureColor.r - Y);
|
||||
float Cb = 0.5647 * (textureColor.b - Y);
|
||||
|
||||
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
|
||||
float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
|
||||
gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageChromaKeyFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform float thresholdSensitivity;
|
||||
uniform float smoothing;
|
||||
uniform vec3 colorToReplace;
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
|
||||
float maskCr = 0.7132 * (colorToReplace.r - maskY);
|
||||
float maskCb = 0.5647 * (colorToReplace.b - maskY);
|
||||
|
||||
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
|
||||
float Cr = 0.7132 * (textureColor.r - Y);
|
||||
float Cb = 0.5647 * (textureColor.b - Y);
|
||||
|
||||
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
|
||||
float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
|
||||
gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageChromaKeyFilter
|
||||
|
||||
@synthesize thresholdSensitivity = _thresholdSensitivity;
|
||||
@synthesize smoothing = _smoothing;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageChromaKeyFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
thresholdSensitivityUniform = [filterProgram uniformIndex:@"thresholdSensitivity"];
|
||||
smoothingUniform = [filterProgram uniformIndex:@"smoothing"];
|
||||
colorToReplaceUniform = [filterProgram uniformIndex:@"colorToReplace"];
|
||||
|
||||
self.thresholdSensitivity = 0.4;
|
||||
self.smoothing = 0.1;
|
||||
[self setColorToReplaceRed:0.0 green:1.0 blue:0.0];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
|
||||
{
|
||||
GPUVector3 colorToReplace = {redComponent, greenComponent, blueComponent};
|
||||
|
||||
[self setVec3:colorToReplace forUniform:colorToReplaceUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setThresholdSensitivity:(CGFloat)newValue;
|
||||
{
|
||||
_thresholdSensitivity = newValue;
|
||||
|
||||
[self setFloat:(GLfloat)_thresholdSensitivity forUniform:thresholdSensitivityUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setSmoothing:(CGFloat)newValue;
|
||||
{
|
||||
_smoothing = newValue;
|
||||
|
||||
[self setFloat:(GLfloat)_smoothing forUniform:smoothingUniform program:filterProgram];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,57 +0,0 @@
|
||||
#import "GPUImageClosingFilter.h"
|
||||
#import "GPUImageErosionFilter.h"
|
||||
#import "GPUImageDilationFilter.h"
|
||||
|
||||
@implementation GPUImageClosingFilter
|
||||
|
||||
@synthesize verticalTexelSpacing = _verticalTexelSpacing;
|
||||
@synthesize horizontalTexelSpacing = _horizontalTexelSpacing;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [self initWithRadius:1]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithRadius:(NSUInteger)radius;
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
// First pass: dilation
|
||||
dilationFilter = [[GPUImageDilationFilter alloc] initWithRadius:radius];
|
||||
[self addFilter:dilationFilter];
|
||||
|
||||
// Second pass: erosion
|
||||
erosionFilter = [[GPUImageErosionFilter alloc] initWithRadius:radius];
|
||||
[self addFilter:erosionFilter];
|
||||
|
||||
[dilationFilter addTarget:erosionFilter];
|
||||
|
||||
self.initialFilters = [NSArray arrayWithObjects:dilationFilter, nil];
|
||||
self.terminalFilter = erosionFilter;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setVerticalTexelSpacing:(CGFloat)newValue;
|
||||
{
|
||||
_verticalTexelSpacing = newValue;
|
||||
erosionFilter.verticalTexelSpacing = newValue;
|
||||
dilationFilter.verticalTexelSpacing = newValue;
|
||||
}
|
||||
|
||||
- (void)setHorizontalTexelSpacing:(CGFloat)newValue;
|
||||
{
|
||||
_horizontalTexelSpacing = newValue;
|
||||
erosionFilter.horizontalTexelSpacing = newValue;
|
||||
dilationFilter.horizontalTexelSpacing = newValue;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,113 +0,0 @@
|
||||
#import "GPUImageColorBlendFilter.h"
|
||||
|
||||
/**
|
||||
* Color blend mode based upon pseudo code from the PDF specification.
|
||||
*/
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
highp float lum(lowp vec3 c) {
|
||||
return dot(c, vec3(0.3, 0.59, 0.11));
|
||||
}
|
||||
|
||||
lowp vec3 clipcolor(lowp vec3 c) {
|
||||
highp float l = lum(c);
|
||||
lowp float n = min(min(c.r, c.g), c.b);
|
||||
lowp float x = max(max(c.r, c.g), c.b);
|
||||
|
||||
if (n < 0.0) {
|
||||
c.r = l + ((c.r - l) * l) / (l - n);
|
||||
c.g = l + ((c.g - l) * l) / (l - n);
|
||||
c.b = l + ((c.b - l) * l) / (l - n);
|
||||
}
|
||||
if (x > 1.0) {
|
||||
c.r = l + ((c.r - l) * (1.0 - l)) / (x - l);
|
||||
c.g = l + ((c.g - l) * (1.0 - l)) / (x - l);
|
||||
c.b = l + ((c.b - l) * (1.0 - l)) / (x - l);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
lowp vec3 setlum(lowp vec3 c, highp float l) {
|
||||
highp float d = l - lum(c);
|
||||
c = c + vec3(d);
|
||||
return clipcolor(c);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
highp vec4 baseColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
highp vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(overlayColor.rgb, lum(baseColor.rgb)) * overlayColor.a, baseColor.a);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
float lum(vec3 c) {
|
||||
return dot(c, vec3(0.3, 0.59, 0.11));
|
||||
}
|
||||
|
||||
vec3 clipcolor(vec3 c) {
|
||||
float l = lum(c);
|
||||
float n = min(min(c.r, c.g), c.b);
|
||||
float x = max(max(c.r, c.g), c.b);
|
||||
|
||||
if (n < 0.0) {
|
||||
c.r = l + ((c.r - l) * l) / (l - n);
|
||||
c.g = l + ((c.g - l) * l) / (l - n);
|
||||
c.b = l + ((c.b - l) * l) / (l - n);
|
||||
}
|
||||
if (x > 1.0) {
|
||||
c.r = l + ((c.r - l) * (1.0 - l)) / (x - l);
|
||||
c.g = l + ((c.g - l) * (1.0 - l)) / (x - l);
|
||||
c.b = l + ((c.b - l) * (1.0 - l)) / (x - l);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
vec3 setlum(vec3 c, float l) {
|
||||
float d = l - lum(c);
|
||||
c = c + vec3(d);
|
||||
return clipcolor(c);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 baseColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(overlayColor.rgb, lum(baseColor.rgb)) * overlayColor.a, baseColor.a);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
@implementation GPUImageColorBlendFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,52 +0,0 @@
|
||||
#import "GPUImageColorBurnBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorBurnBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
mediump vec4 whiteColor = vec4(1.0);
|
||||
gl_FragColor = whiteColor - (whiteColor - textureColor) / textureColor2;
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorBurnBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
vec4 whiteColor = vec4(1.0);
|
||||
gl_FragColor = whiteColor - (whiteColor - textureColor) / textureColor2;
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageColorBurnBlendFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorBurnBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
-159
@@ -1,159 +0,0 @@
|
||||
#import "GPUImageFilter.h"
|
||||
|
||||
// Color Conversion Constants (YUV to RGB) including adjustment from 16-235/16-240 (video range)
|
||||
|
||||
// BT.601, which is the standard for SDTV.
|
||||
GLfloat kColorConversion601Default[] = {
|
||||
1.164, 1.164, 1.164,
|
||||
0.0, -0.392, 2.017,
|
||||
1.596, -0.813, 0.0,
|
||||
};
|
||||
|
||||
// BT.601 full range (ref: http://www.equasys.de/colorconversion.html)
|
||||
GLfloat kColorConversion601FullRangeDefault[] = {
|
||||
1.0, 1.0, 1.0,
|
||||
0.0, -0.343, 1.765,
|
||||
1.4, -0.711, 0.0,
|
||||
};
|
||||
|
||||
// BT.709, which is the standard for HDTV.
|
||||
GLfloat kColorConversion709Default[] = {
|
||||
1.164, 1.164, 1.164,
|
||||
0.0, -0.213, 2.112,
|
||||
1.793, -0.533, 0.0,
|
||||
};
|
||||
|
||||
|
||||
GLfloat *kColorConversion601 = kColorConversion601Default;
|
||||
GLfloat *kColorConversion601FullRange = kColorConversion601FullRangeDefault;
|
||||
GLfloat *kColorConversion709 = kColorConversion709Default;
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D luminanceTexture;
|
||||
uniform sampler2D chrominanceTexture;
|
||||
uniform mediump mat3 colorConversionMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
mediump vec3 yuv;
|
||||
lowp vec3 rgb;
|
||||
|
||||
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
|
||||
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);
|
||||
rgb = colorConversionMatrix * yuv;
|
||||
|
||||
gl_FragColor = vec4(rgb, 1);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D luminanceTexture;
|
||||
uniform sampler2D chrominanceTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 yuv;
|
||||
vec3 rgb;
|
||||
|
||||
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
|
||||
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);
|
||||
|
||||
// BT.601, which is the standard for SDTV is provided as a reference
|
||||
/*
|
||||
rgb = mat3( 1, 1, 1,
|
||||
0, -.39465, 2.03211,
|
||||
1.13983, -.58060, 0) * yuv;
|
||||
*/
|
||||
|
||||
// Using BT.709 which is the standard for HDTV
|
||||
rgb = mat3( 1, 1, 1,
|
||||
0, -.21482, 2.12798,
|
||||
1.28033, -.38059, 0) * yuv;
|
||||
|
||||
gl_FragColor = vec4(rgb, 1);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
NSString *const kGPUImageYUVFullRangeConversionForLAFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D luminanceTexture;
|
||||
uniform sampler2D chrominanceTexture;
|
||||
uniform mediump mat3 colorConversionMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
mediump vec3 yuv;
|
||||
lowp vec3 rgb;
|
||||
|
||||
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
|
||||
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
|
||||
rgb = colorConversionMatrix * yuv;
|
||||
|
||||
gl_FragColor = vec4(rgb, 1);
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D luminanceTexture;
|
||||
uniform sampler2D chrominanceTexture;
|
||||
uniform mediump mat3 colorConversionMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
mediump vec3 yuv;
|
||||
lowp vec3 rgb;
|
||||
|
||||
yuv.x = texture2D(luminanceTexture, textureCoordinate).r - (16.0/255.0);
|
||||
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
|
||||
rgb = colorConversionMatrix * yuv;
|
||||
|
||||
gl_FragColor = vec4(rgb, 1);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D luminanceTexture;
|
||||
uniform sampler2D chrominanceTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 yuv;
|
||||
vec3 rgb;
|
||||
|
||||
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
|
||||
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
|
||||
|
||||
// BT.601, which is the standard for SDTV is provided as a reference
|
||||
/*
|
||||
rgb = mat3( 1, 1, 1,
|
||||
0, -.39465, 2.03211,
|
||||
1.13983, -.58060, 0) * yuv;
|
||||
*/
|
||||
|
||||
// Using BT.709 which is the standard for HDTV
|
||||
rgb = mat3( 1, 1, 1,
|
||||
0, -.21482, 2.12798,
|
||||
1.28033, -.38059, 0) * yuv;
|
||||
|
||||
gl_FragColor = vec4(rgb, 1);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#import "GPUImageColorDodgeBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorDodgeBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
vec3 baseOverlayAlphaProduct = vec3(overlay.a * base.a);
|
||||
vec3 rightHandProduct = overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a);
|
||||
|
||||
vec3 firstBlendColor = baseOverlayAlphaProduct + rightHandProduct;
|
||||
vec3 overlayRGB = clamp((overlay.rgb / clamp(overlay.a, 0.01, 1.0)) * step(0.0, overlay.a), 0.0, 0.99);
|
||||
|
||||
vec3 secondBlendColor = (base.rgb * overlay.a) / (1.0 - overlayRGB) + rightHandProduct;
|
||||
|
||||
vec3 colorChoice = step((overlay.rgb * base.a + base.rgb * overlay.a), baseOverlayAlphaProduct);
|
||||
|
||||
gl_FragColor = vec4(mix(firstBlendColor, secondBlendColor, colorChoice), 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorDodgeBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
vec3 baseOverlayAlphaProduct = vec3(overlay.a * base.a);
|
||||
vec3 rightHandProduct = overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a);
|
||||
|
||||
vec3 firstBlendColor = baseOverlayAlphaProduct + rightHandProduct;
|
||||
vec3 overlayRGB = clamp((overlay.rgb / clamp(overlay.a, 0.01, 1.0)) * step(0.0, overlay.a), 0.0, 0.99);
|
||||
|
||||
vec3 secondBlendColor = (base.rgb * overlay.a) / (1.0 - overlayRGB) + rightHandProduct;
|
||||
|
||||
vec3 colorChoice = step((overlay.rgb * base.a + base.rgb * overlay.a), baseOverlayAlphaProduct);
|
||||
|
||||
gl_FragColor = vec4(mix(firstBlendColor, secondBlendColor, colorChoice), 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageColorDodgeBlendFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorDodgeBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#import "GPUImageColorInvertFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.w);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.w);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageColorInvertFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageInvertFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
#import "GPUImageColorLocalBinaryPatternFilter.h"
|
||||
|
||||
// This is based on "Accelerating image recognition on mobile devices using GPGPU" by Miguel Bordallo Lopez, Henri Nykanen, Jari Hannuksela, Olli Silven and Markku Vehvilainen
|
||||
// http://www.ee.oulu.fi/~jhannuks/publications/SPIE2011a.pdf
|
||||
|
||||
// Right pixel is the most significant bit, traveling clockwise to get to the upper right, which is the least significant
|
||||
// If the external pixel is greater than or equal to the center, set to 1, otherwise 0
|
||||
//
|
||||
// 2 1 0
|
||||
// 3 7
|
||||
// 4 5 6
|
||||
|
||||
// 01101101
|
||||
// 76543210
|
||||
|
||||
@implementation GPUImageColorLocalBinaryPatternFilter
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorLocalBinaryPatternFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision highp float;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
|
||||
lowp vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
|
||||
lowp vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
|
||||
lowp vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
|
||||
lowp vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
|
||||
lowp vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
|
||||
lowp vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
|
||||
lowp vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
|
||||
lowp vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
|
||||
|
||||
lowp float redByteTally = 1.0 / 255.0 * step(centerColor.r, topRightColor.r);
|
||||
redByteTally += 2.0 / 255.0 * step(centerColor.r, topColor.r);
|
||||
redByteTally += 4.0 / 255.0 * step(centerColor.r, topLeftColor.r);
|
||||
redByteTally += 8.0 / 255.0 * step(centerColor.r, leftColor.r);
|
||||
redByteTally += 16.0 / 255.0 * step(centerColor.r, bottomLeftColor.r);
|
||||
redByteTally += 32.0 / 255.0 * step(centerColor.r, bottomColor.r);
|
||||
redByteTally += 64.0 / 255.0 * step(centerColor.r, bottomRightColor.r);
|
||||
redByteTally += 128.0 / 255.0 * step(centerColor.r, rightColor.r);
|
||||
|
||||
lowp float blueByteTally = 1.0 / 255.0 * step(centerColor.b, topRightColor.b);
|
||||
blueByteTally += 2.0 / 255.0 * step(centerColor.b, topColor.b);
|
||||
blueByteTally += 4.0 / 255.0 * step(centerColor.b, topLeftColor.b);
|
||||
blueByteTally += 8.0 / 255.0 * step(centerColor.b, leftColor.b);
|
||||
blueByteTally += 16.0 / 255.0 * step(centerColor.b, bottomLeftColor.b);
|
||||
blueByteTally += 32.0 / 255.0 * step(centerColor.b, bottomColor.b);
|
||||
blueByteTally += 64.0 / 255.0 * step(centerColor.b, bottomRightColor.b);
|
||||
blueByteTally += 128.0 / 255.0 * step(centerColor.b, rightColor.b);
|
||||
|
||||
lowp float greenByteTally = 1.0 / 255.0 * step(centerColor.g, topRightColor.g);
|
||||
greenByteTally += 2.0 / 255.0 * step(centerColor.g, topColor.g);
|
||||
greenByteTally += 4.0 / 255.0 * step(centerColor.g, topLeftColor.g);
|
||||
greenByteTally += 8.0 / 255.0 * step(centerColor.g, leftColor.g);
|
||||
greenByteTally += 16.0 / 255.0 * step(centerColor.g, bottomLeftColor.g);
|
||||
greenByteTally += 32.0 / 255.0 * step(centerColor.g, bottomColor.g);
|
||||
greenByteTally += 64.0 / 255.0 * step(centerColor.g, bottomRightColor.g);
|
||||
greenByteTally += 128.0 / 255.0 * step(centerColor.g, rightColor.g);
|
||||
|
||||
// TODO: Replace the above with a dot product and two vec4s
|
||||
// TODO: Apply step to a matrix, rather than individually
|
||||
|
||||
gl_FragColor = vec4(redByteTally, blueByteTally, greenByteTally, 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorLocalBinaryPatternFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
|
||||
vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
|
||||
vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
|
||||
vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
|
||||
vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
|
||||
vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
|
||||
vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
|
||||
vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
|
||||
vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
|
||||
|
||||
float redByteTally = 1.0 / 255.0 * step(centerColor.r, topRightColor.r);
|
||||
redByteTally += 2.0 / 255.0 * step(centerColor.r, topColor.r);
|
||||
redByteTally += 4.0 / 255.0 * step(centerColor.r, topLeftColor.r);
|
||||
redByteTally += 8.0 / 255.0 * step(centerColor.r, leftColor.r);
|
||||
redByteTally += 16.0 / 255.0 * step(centerColor.r, bottomLeftColor.r);
|
||||
redByteTally += 32.0 / 255.0 * step(centerColor.r, bottomColor.r);
|
||||
redByteTally += 64.0 / 255.0 * step(centerColor.r, bottomRightColor.r);
|
||||
redByteTally += 128.0 / 255.0 * step(centerColor.r, rightColor.r);
|
||||
|
||||
float blueByteTally = 1.0 / 255.0 * step(centerColor.b, topRightColor.b);
|
||||
blueByteTally += 2.0 / 255.0 * step(centerColor.b, topColor.b);
|
||||
blueByteTally += 4.0 / 255.0 * step(centerColor.b, topLeftColor.b);
|
||||
blueByteTally += 8.0 / 255.0 * step(centerColor.b, leftColor.b);
|
||||
blueByteTally += 16.0 / 255.0 * step(centerColor.b, bottomLeftColor.b);
|
||||
blueByteTally += 32.0 / 255.0 * step(centerColor.b, bottomColor.b);
|
||||
blueByteTally += 64.0 / 255.0 * step(centerColor.b, bottomRightColor.b);
|
||||
blueByteTally += 128.0 / 255.0 * step(centerColor.b, rightColor.b);
|
||||
|
||||
float greenByteTally = 1.0 / 255.0 * step(centerColor.g, topRightColor.g);
|
||||
greenByteTally += 2.0 / 255.0 * step(centerColor.g, topColor.g);
|
||||
greenByteTally += 4.0 / 255.0 * step(centerColor.g, topLeftColor.g);
|
||||
greenByteTally += 8.0 / 255.0 * step(centerColor.g, leftColor.g);
|
||||
greenByteTally += 16.0 / 255.0 * step(centerColor.g, bottomLeftColor.g);
|
||||
greenByteTally += 32.0 / 255.0 * step(centerColor.g, bottomColor.g);
|
||||
greenByteTally += 64.0 / 255.0 * step(centerColor.g, bottomRightColor.g);
|
||||
greenByteTally += 128.0 / 255.0 * step(centerColor.g, rightColor.g);
|
||||
|
||||
// TODO: Replace the above with a dot product and two vec4s
|
||||
// TODO: Apply step to a matrix, rather than individually
|
||||
|
||||
gl_FragColor = vec4(redByteTally, blueByteTally, greenByteTally, 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorLocalBinaryPatternFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,87 +0,0 @@
|
||||
#import "GPUImageColorMatrixFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform lowp mat4 colorMatrix;
|
||||
uniform lowp float intensity;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
lowp vec4 outputColor = textureColor * colorMatrix;
|
||||
|
||||
gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform mat4 colorMatrix;
|
||||
uniform float intensity;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 outputColor = textureColor * colorMatrix;
|
||||
|
||||
gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageColorMatrixFilter
|
||||
|
||||
@synthesize intensity = _intensity;
|
||||
@synthesize colorMatrix = _colorMatrix;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorMatrixFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
colorMatrixUniform = [filterProgram uniformIndex:@"colorMatrix"];
|
||||
intensityUniform = [filterProgram uniformIndex:@"intensity"];
|
||||
|
||||
self.intensity = 1.f;
|
||||
self.colorMatrix = (GPUMatrix4x4){
|
||||
{1.f, 0.f, 0.f, 0.f},
|
||||
{0.f, 1.f, 0.f, 0.f},
|
||||
{0.f, 0.f, 1.f, 0.f},
|
||||
{0.f, 0.f, 0.f, 1.f}
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setIntensity:(CGFloat)newIntensity;
|
||||
{
|
||||
_intensity = newIntensity;
|
||||
|
||||
[self setFloat:_intensity forUniform:intensityUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setColorMatrix:(GPUMatrix4x4)newColorMatrix;
|
||||
{
|
||||
_colorMatrix = newColorMatrix;
|
||||
|
||||
[self setMatrix4f:_colorMatrix forUniform:colorMatrixUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,139 +0,0 @@
|
||||
#import "GPUImageColorPackingFilter.h"
|
||||
|
||||
NSString *const kGPUImageColorPackingVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec4 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidth;
|
||||
uniform float texelHeight;
|
||||
|
||||
varying vec2 upperLeftInputTextureCoordinate;
|
||||
varying vec2 upperRightInputTextureCoordinate;
|
||||
varying vec2 lowerLeftInputTextureCoordinate;
|
||||
varying vec2 lowerRightInputTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
upperLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, -texelHeight);
|
||||
upperRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, -texelHeight);
|
||||
lowerLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, texelHeight);
|
||||
lowerRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, texelHeight);
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColorPackingFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision lowp float;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform mediump mat3 convolutionMatrix;
|
||||
|
||||
varying highp vec2 outputTextureCoordinate;
|
||||
|
||||
varying highp vec2 upperLeftInputTextureCoordinate;
|
||||
varying highp vec2 upperRightInputTextureCoordinate;
|
||||
varying highp vec2 lowerLeftInputTextureCoordinate;
|
||||
varying highp vec2 lowerRightInputTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
float upperLeftIntensity = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r;
|
||||
float upperRightIntensity = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r;
|
||||
float lowerLeftIntensity = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r;
|
||||
float lowerRightIntensity = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r;
|
||||
|
||||
gl_FragColor = vec4(upperLeftIntensity, upperRightIntensity, lowerLeftIntensity, lowerRightIntensity);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColorPackingFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform mat3 convolutionMatrix;
|
||||
|
||||
varying vec2 outputTextureCoordinate;
|
||||
|
||||
varying vec2 upperLeftInputTextureCoordinate;
|
||||
varying vec2 upperRightInputTextureCoordinate;
|
||||
varying vec2 lowerLeftInputTextureCoordinate;
|
||||
varying vec2 lowerRightInputTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
float upperLeftIntensity = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r;
|
||||
float upperRightIntensity = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r;
|
||||
float lowerLeftIntensity = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r;
|
||||
float lowerRightIntensity = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r;
|
||||
|
||||
gl_FragColor = vec4(upperLeftIntensity, upperRightIntensity, lowerLeftIntensity, lowerRightIntensity);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageColorPackingFilter
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithVertexShaderFromString:kGPUImageColorPackingVertexShaderString fragmentShaderFromString:kGPUImageColorPackingFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
|
||||
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupFilterForSize:(CGSize)filterFrameSize;
|
||||
{
|
||||
texelWidth = 0.5 / inputTextureSize.width;
|
||||
texelHeight = 0.5 / inputTextureSize.height;
|
||||
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
[GPUImageContext setActiveShaderProgram:filterProgram];
|
||||
glUniform1f(texelWidthUniform, texelWidth);
|
||||
glUniform1f(texelHeightUniform, texelHeight);
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Managing the display FBOs
|
||||
|
||||
- (CGSize)sizeOfFBO;
|
||||
{
|
||||
CGSize outputSize = [self maximumOutputSize];
|
||||
if ( (CGSizeEqualToSize(outputSize, CGSizeZero)) || (inputTextureSize.width < outputSize.width) )
|
||||
{
|
||||
CGSize quarterSize;
|
||||
quarterSize.width = inputTextureSize.width / 2.0;
|
||||
quarterSize.height = inputTextureSize.height / 2.0;
|
||||
return quarterSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return outputSize;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Rendering
|
||||
|
||||
- (CGSize)outputFrameSize;
|
||||
{
|
||||
CGSize quarterSize;
|
||||
quarterSize.width = inputTextureSize.width / 2.0;
|
||||
quarterSize.height = inputTextureSize.height / 2.0;
|
||||
return quarterSize;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,48 +0,0 @@
|
||||
#import "GPUImageColourFASTFeatureDetector.h"
|
||||
#import "GPUImageColourFASTSamplingOperation.h"
|
||||
#import "GPUImageBoxBlurFilter.h"
|
||||
|
||||
@implementation GPUImageColourFASTFeatureDetector
|
||||
|
||||
@synthesize blurRadiusInPixels;
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
// First pass: apply a variable Gaussian blur
|
||||
blurFilter = [[GPUImageBoxBlurFilter alloc] init];
|
||||
[self addFilter:blurFilter];
|
||||
|
||||
// Second pass: combine the blurred image with the original sharp one
|
||||
colourFASTSamplingOperation = [[GPUImageColourFASTSamplingOperation alloc] init];
|
||||
[self addFilter:colourFASTSamplingOperation];
|
||||
|
||||
// Texture location 0 needs to be the sharp image for both the blur and the second stage processing
|
||||
[blurFilter addTarget:colourFASTSamplingOperation atTextureLocation:1];
|
||||
|
||||
self.initialFilters = [NSArray arrayWithObjects:blurFilter, colourFASTSamplingOperation, nil];
|
||||
self.terminalFilter = colourFASTSamplingOperation;
|
||||
|
||||
self.blurRadiusInPixels = 3.0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
|
||||
{
|
||||
blurFilter.blurRadiusInPixels = newValue;
|
||||
}
|
||||
|
||||
- (CGFloat)blurRadiusInPixels;
|
||||
{
|
||||
return blurFilter.blurRadiusInPixels;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,204 +0,0 @@
|
||||
#import "GPUImageColourFASTSamplingOperation.h"
|
||||
|
||||
NSString *const kGPUImageColourFASTSamplingVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec4 inputTextureCoordinate;
|
||||
attribute vec4 inputTextureCoordinate2;
|
||||
|
||||
uniform float texelWidth;
|
||||
uniform float texelHeight;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 pointATextureCoordinate;
|
||||
varying vec2 pointBTextureCoordinate;
|
||||
varying vec2 pointCTextureCoordinate;
|
||||
varying vec2 pointDTextureCoordinate;
|
||||
varying vec2 pointETextureCoordinate;
|
||||
varying vec2 pointFTextureCoordinate;
|
||||
varying vec2 pointGTextureCoordinate;
|
||||
varying vec2 pointHTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
float tripleTexelWidth = 3.0 * texelWidth;
|
||||
float tripleTexelHeight = 3.0 * texelHeight;
|
||||
|
||||
textureCoordinate = inputTextureCoordinate.xy;
|
||||
|
||||
pointATextureCoordinate = vec2(textureCoordinate.x + tripleTexelWidth, textureCoordinate.y + texelHeight);
|
||||
pointBTextureCoordinate = vec2(textureCoordinate.x + texelWidth, textureCoordinate.y + tripleTexelHeight);
|
||||
pointCTextureCoordinate = vec2(textureCoordinate.x - texelWidth, textureCoordinate.y + tripleTexelHeight);
|
||||
pointDTextureCoordinate = vec2(textureCoordinate.x - tripleTexelWidth, textureCoordinate.y + texelHeight);
|
||||
pointETextureCoordinate = vec2(textureCoordinate.x - tripleTexelWidth, textureCoordinate.y - texelHeight);
|
||||
pointFTextureCoordinate = vec2(textureCoordinate.x - texelWidth, textureCoordinate.y - tripleTexelHeight);
|
||||
pointGTextureCoordinate = vec2(textureCoordinate.x + texelWidth, textureCoordinate.y - tripleTexelHeight);
|
||||
pointHTextureCoordinate = vec2(textureCoordinate.x + tripleTexelWidth, textureCoordinate.y - texelHeight);
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageColourFASTSamplingFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision highp float;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 pointATextureCoordinate;
|
||||
varying vec2 pointBTextureCoordinate;
|
||||
varying vec2 pointCTextureCoordinate;
|
||||
varying vec2 pointDTextureCoordinate;
|
||||
varying vec2 pointETextureCoordinate;
|
||||
varying vec2 pointFTextureCoordinate;
|
||||
varying vec2 pointGTextureCoordinate;
|
||||
varying vec2 pointHTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
const float PITwo = 6.2832;
|
||||
const float PI = 3.1416;
|
||||
void main()
|
||||
{
|
||||
vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
|
||||
|
||||
vec3 pointAColor = texture2D(inputImageTexture, pointATextureCoordinate).rgb;
|
||||
vec3 pointBColor = texture2D(inputImageTexture, pointBTextureCoordinate).rgb;
|
||||
vec3 pointCColor = texture2D(inputImageTexture, pointCTextureCoordinate).rgb;
|
||||
vec3 pointDColor = texture2D(inputImageTexture, pointDTextureCoordinate).rgb;
|
||||
vec3 pointEColor = texture2D(inputImageTexture, pointETextureCoordinate).rgb;
|
||||
vec3 pointFColor = texture2D(inputImageTexture, pointFTextureCoordinate).rgb;
|
||||
vec3 pointGColor = texture2D(inputImageTexture, pointGTextureCoordinate).rgb;
|
||||
vec3 pointHColor = texture2D(inputImageTexture, pointHTextureCoordinate).rgb;
|
||||
|
||||
vec3 colorComparison = ((pointAColor + pointBColor + pointCColor + pointDColor + pointEColor + pointFColor + pointGColor + pointHColor) * 0.125) - centerColor;
|
||||
|
||||
// Direction calculation drawn from Appendix B of Seth Hall's Ph.D. thesis
|
||||
|
||||
vec3 dirX = (pointAColor*0.94868) + (pointBColor*0.316227) - (pointCColor*0.316227) - (pointDColor*0.94868) - (pointEColor*0.94868) - (pointFColor*0.316227) + (pointGColor*0.316227) + (pointHColor*0.94868);
|
||||
vec3 dirY = (pointAColor*0.316227) + (pointBColor*0.94868) + (pointCColor*0.94868) + (pointDColor*0.316227) - (pointEColor*0.316227) - (pointFColor*0.94868) - (pointGColor*0.94868) - (pointHColor*0.316227);
|
||||
vec3 absoluteDifference = abs(colorComparison);
|
||||
float componentLength = length(colorComparison);
|
||||
float avgX = dot(absoluteDifference, dirX) / componentLength;
|
||||
float avgY = dot(absoluteDifference, dirY) / componentLength;
|
||||
float angle = atan(avgY, avgX);
|
||||
|
||||
vec3 normalizedColorComparison = (colorComparison + 1.0) * 0.5;
|
||||
|
||||
gl_FragColor = vec4(normalizedColorComparison, (angle+PI)/PITwo);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageColourFASTSamplingFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 pointATextureCoordinate;
|
||||
varying vec2 pointBTextureCoordinate;
|
||||
varying vec2 pointCTextureCoordinate;
|
||||
varying vec2 pointDTextureCoordinate;
|
||||
varying vec2 pointETextureCoordinate;
|
||||
varying vec2 pointFTextureCoordinate;
|
||||
varying vec2 pointGTextureCoordinate;
|
||||
varying vec2 pointHTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
const float PITwo = 6.2832;
|
||||
const float PI = 3.1416;
|
||||
void main()
|
||||
{
|
||||
vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
|
||||
|
||||
vec3 pointAColor = texture2D(inputImageTexture, pointATextureCoordinate).rgb;
|
||||
vec3 pointBColor = texture2D(inputImageTexture, pointBTextureCoordinate).rgb;
|
||||
vec3 pointCColor = texture2D(inputImageTexture, pointCTextureCoordinate).rgb;
|
||||
vec3 pointDColor = texture2D(inputImageTexture, pointDTextureCoordinate).rgb;
|
||||
vec3 pointEColor = texture2D(inputImageTexture, pointETextureCoordinate).rgb;
|
||||
vec3 pointFColor = texture2D(inputImageTexture, pointFTextureCoordinate).rgb;
|
||||
vec3 pointGColor = texture2D(inputImageTexture, pointGTextureCoordinate).rgb;
|
||||
vec3 pointHColor = texture2D(inputImageTexture, pointHTextureCoordinate).rgb;
|
||||
|
||||
vec3 colorComparison = ((pointAColor + pointBColor + pointCColor + pointDColor + pointEColor + pointFColor + pointGColor + pointHColor) * 0.125) - centerColor;
|
||||
|
||||
// Direction calculation drawn from Appendix B of Seth Hall's Ph.D. thesis
|
||||
|
||||
vec3 dirX = (pointAColor*0.94868) + (pointBColor*0.316227) - (pointCColor*0.316227) - (pointDColor*0.94868) - (pointEColor*0.94868) - (pointFColor*0.316227) + (pointGColor*0.316227) + (pointHColor*0.94868);
|
||||
vec3 dirY = (pointAColor*0.316227) + (pointBColor*0.94868) + (pointCColor*0.94868) + (pointDColor*0.316227) - (pointEColor*0.316227) - (pointFColor*0.94868) - (pointGColor*0.94868) - (pointHColor*0.316227);
|
||||
vec3 absoluteDifference = abs(colorComparison);
|
||||
float componentLength = length(colorComparison);
|
||||
float avgX = dot(absoluteDifference, dirX) / componentLength;
|
||||
float avgY = dot(absoluteDifference, dirY) / componentLength;
|
||||
float angle = atan(avgY, avgX);
|
||||
|
||||
vec3 normalizedColorComparison = (colorComparison + 1.0) * 0.5;
|
||||
|
||||
gl_FragColor = vec4(normalizedColorComparison, (angle+PI)/PITwo);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
@implementation GPUImageColourFASTSamplingOperation
|
||||
|
||||
@synthesize texelWidth = _texelWidth;
|
||||
@synthesize texelHeight = _texelHeight;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
|
||||
{
|
||||
if (!(self = [super initWithVertexShaderFromString:kGPUImageColourFASTSamplingVertexShaderString fragmentShaderFromString:kGPUImageColourFASTSamplingFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
|
||||
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupFilterForSize:(CGSize)filterFrameSize;
|
||||
{
|
||||
if (!hasOverriddenImageSizeFactor)
|
||||
{
|
||||
_texelWidth = 1.0 / filterFrameSize.width;
|
||||
_texelHeight = 1.0 / filterFrameSize.height;
|
||||
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
[GPUImageContext setActiveShaderProgram:filterProgram];
|
||||
if (GPUImageRotationSwapsWidthAndHeight(inputRotation))
|
||||
{
|
||||
glUniform1f(texelWidthUniform, _texelHeight);
|
||||
glUniform1f(texelHeightUniform, _texelWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUniform1f(texelWidthUniform, _texelWidth);
|
||||
glUniform1f(texelHeightUniform, _texelHeight);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setTexelWidth:(CGFloat)newValue;
|
||||
{
|
||||
hasOverriddenImageSizeFactor = YES;
|
||||
_texelWidth = newValue;
|
||||
|
||||
[self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setTexelHeight:(CGFloat)newValue;
|
||||
{
|
||||
hasOverriddenImageSizeFactor = YES;
|
||||
_texelHeight = newValue;
|
||||
|
||||
[self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,66 +0,0 @@
|
||||
#import "GPUImageContrastFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageContrastFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform lowp float contrast;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageContrastFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform float contrast;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
|
||||
gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageContrastFilter
|
||||
|
||||
@synthesize contrast = _contrast;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageContrastFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
contrastUniform = [filterProgram uniformIndex:@"contrast"];
|
||||
self.contrast = 1.0;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setContrast:(CGFloat)newValue;
|
||||
{
|
||||
_contrast = newValue;
|
||||
|
||||
[self setFloat:_contrast forUniform:contrastUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
-274
@@ -1,274 +0,0 @@
|
||||
#import "GPUImageCropFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@interface GPUImageCropFilter ()
|
||||
|
||||
- (void)calculateCropTextureCoordinates;
|
||||
|
||||
@end
|
||||
|
||||
@interface GPUImageCropFilter()
|
||||
{
|
||||
CGSize originallySuppliedInputSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GPUImageCropFilter
|
||||
|
||||
@synthesize cropRegion = _cropRegion;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)initWithCropRegion:(CGRect)newCropRegion;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageCropFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
self.cropRegion = newCropRegion;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [self initWithCropRegion:CGRectMake(0.0, 0.0, 1.0, 1.0)]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Rendering
|
||||
|
||||
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
if (self.preventRendering)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if (overrideInputSize)
|
||||
// {
|
||||
// if (CGSizeEqualToSize(forcedMaximumSize, CGSizeZero))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(newSize, CGRectMake(0.0, 0.0, forcedMaximumSize.width, forcedMaximumSize.height));
|
||||
// inputTextureSize = insetRect.size;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
CGSize rotatedSize = [self rotatedSize:newSize forIndex:textureIndex];
|
||||
originallySuppliedInputSize = rotatedSize;
|
||||
|
||||
CGSize scaledSize;
|
||||
scaledSize.width = rotatedSize.width * _cropRegion.size.width;
|
||||
scaledSize.height = rotatedSize.height * _cropRegion.size.height;
|
||||
|
||||
|
||||
if (CGSizeEqualToSize(scaledSize, CGSizeZero))
|
||||
{
|
||||
inputTextureSize = scaledSize;
|
||||
}
|
||||
else if (!CGSizeEqualToSize(inputTextureSize, scaledSize))
|
||||
{
|
||||
inputTextureSize = scaledSize;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark GPUImageInput
|
||||
|
||||
- (void)calculateCropTextureCoordinates;
|
||||
{
|
||||
CGFloat minX = _cropRegion.origin.x;
|
||||
CGFloat minY = _cropRegion.origin.y;
|
||||
CGFloat maxX = CGRectGetMaxX(_cropRegion);
|
||||
CGFloat maxY = CGRectGetMaxY(_cropRegion);
|
||||
|
||||
switch(inputRotation)
|
||||
{
|
||||
case kGPUImageNoRotation: // Works
|
||||
{
|
||||
cropTextureCoordinates[0] = minX; // 0,0
|
||||
cropTextureCoordinates[1] = minY;
|
||||
|
||||
cropTextureCoordinates[2] = maxX; // 1,0
|
||||
cropTextureCoordinates[3] = minY;
|
||||
|
||||
cropTextureCoordinates[4] = minX; // 0,1
|
||||
cropTextureCoordinates[5] = maxY;
|
||||
|
||||
cropTextureCoordinates[6] = maxX; // 1,1
|
||||
cropTextureCoordinates[7] = maxY;
|
||||
}; break;
|
||||
case kGPUImageRotateLeft: // Fixed
|
||||
{
|
||||
cropTextureCoordinates[0] = maxY; // 1,0
|
||||
cropTextureCoordinates[1] = 1.0 - maxX;
|
||||
|
||||
cropTextureCoordinates[2] = maxY; // 1,1
|
||||
cropTextureCoordinates[3] = 1.0 - minX;
|
||||
|
||||
cropTextureCoordinates[4] = minY; // 0,0
|
||||
cropTextureCoordinates[5] = 1.0 - maxX;
|
||||
|
||||
cropTextureCoordinates[6] = minY; // 0,1
|
||||
cropTextureCoordinates[7] = 1.0 - minX;
|
||||
}; break;
|
||||
case kGPUImageRotateRight: // Fixed
|
||||
{
|
||||
cropTextureCoordinates[0] = minY; // 0,1
|
||||
cropTextureCoordinates[1] = 1.0 - minX;
|
||||
|
||||
cropTextureCoordinates[2] = minY; // 0,0
|
||||
cropTextureCoordinates[3] = 1.0 - maxX;
|
||||
|
||||
cropTextureCoordinates[4] = maxY; // 1,1
|
||||
cropTextureCoordinates[5] = 1.0 - minX;
|
||||
|
||||
cropTextureCoordinates[6] = maxY; // 1,0
|
||||
cropTextureCoordinates[7] = 1.0 - maxX;
|
||||
}; break;
|
||||
case kGPUImageFlipVertical: // Works for me
|
||||
{
|
||||
cropTextureCoordinates[0] = minX; // 0,1
|
||||
cropTextureCoordinates[1] = maxY;
|
||||
|
||||
cropTextureCoordinates[2] = maxX; // 1,1
|
||||
cropTextureCoordinates[3] = maxY;
|
||||
|
||||
cropTextureCoordinates[4] = minX; // 0,0
|
||||
cropTextureCoordinates[5] = minY;
|
||||
|
||||
cropTextureCoordinates[6] = maxX; // 1,0
|
||||
cropTextureCoordinates[7] = minY;
|
||||
}; break;
|
||||
case kGPUImageFlipHorizonal: // Works for me
|
||||
{
|
||||
cropTextureCoordinates[0] = maxX; // 1,0
|
||||
cropTextureCoordinates[1] = minY;
|
||||
|
||||
cropTextureCoordinates[2] = minX; // 0,0
|
||||
cropTextureCoordinates[3] = minY;
|
||||
|
||||
cropTextureCoordinates[4] = maxX; // 1,1
|
||||
cropTextureCoordinates[5] = maxY;
|
||||
|
||||
cropTextureCoordinates[6] = minX; // 0,1
|
||||
cropTextureCoordinates[7] = maxY;
|
||||
}; break;
|
||||
case kGPUImageRotate180: // Fixed
|
||||
{
|
||||
cropTextureCoordinates[0] = maxX; // 1,1
|
||||
cropTextureCoordinates[1] = maxY;
|
||||
|
||||
cropTextureCoordinates[2] = minX; // 0,1
|
||||
cropTextureCoordinates[3] = maxY;
|
||||
|
||||
cropTextureCoordinates[4] = maxX; // 1,0
|
||||
cropTextureCoordinates[5] = minY;
|
||||
|
||||
cropTextureCoordinates[6] = minX; // 0,0
|
||||
cropTextureCoordinates[7] = minY;
|
||||
}; break;
|
||||
case kGPUImageRotateRightFlipVertical: // Fixed
|
||||
{
|
||||
cropTextureCoordinates[0] = minY; // 0,0
|
||||
cropTextureCoordinates[1] = 1.0 - maxX;
|
||||
|
||||
cropTextureCoordinates[2] = minY; // 0,1
|
||||
cropTextureCoordinates[3] = 1.0 - minX;
|
||||
|
||||
cropTextureCoordinates[4] = maxY; // 1,0
|
||||
cropTextureCoordinates[5] = 1.0 - maxX;
|
||||
|
||||
cropTextureCoordinates[6] = maxY; // 1,1
|
||||
cropTextureCoordinates[7] = 1.0 - minX;
|
||||
}; break;
|
||||
case kGPUImageRotateRightFlipHorizontal: // Fixed
|
||||
{
|
||||
cropTextureCoordinates[0] = maxY; // 1,1
|
||||
cropTextureCoordinates[1] = 1.0 - minX;
|
||||
|
||||
cropTextureCoordinates[2] = maxY; // 1,0
|
||||
cropTextureCoordinates[3] = 1.0 - maxX;
|
||||
|
||||
cropTextureCoordinates[4] = minY; // 0,1
|
||||
cropTextureCoordinates[5] = 1.0 - minX;
|
||||
|
||||
cropTextureCoordinates[6] = minY; // 0,0
|
||||
cropTextureCoordinates[7] = 1.0 - maxX;
|
||||
}; break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
static const GLfloat cropSquareVertices[] = {
|
||||
-1.0f, -1.0f,
|
||||
1.0f, -1.0f,
|
||||
-1.0f, 1.0f,
|
||||
1.0f, 1.0f,
|
||||
};
|
||||
|
||||
[self renderToTextureWithVertices:cropSquareVertices textureCoordinates:cropTextureCoordinates];
|
||||
|
||||
[self informTargetsAboutNewFrameAtTime:frameTime];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setCropRegion:(CGRect)newValue;
|
||||
{
|
||||
NSParameterAssert(newValue.origin.x >= 0 && newValue.origin.x <= 1 &&
|
||||
newValue.origin.y >= 0 && newValue.origin.y <= 1 &&
|
||||
newValue.size.width >= 0 && newValue.size.width <= 1 &&
|
||||
newValue.size.height >= 0 && newValue.size.height <= 1);
|
||||
|
||||
_cropRegion = newValue;
|
||||
[self calculateCropTextureCoordinates];
|
||||
}
|
||||
|
||||
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
|
||||
{
|
||||
[super setInputRotation:newInputRotation atIndex:textureIndex];
|
||||
[self calculateCropTextureCoordinates];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,139 +0,0 @@
|
||||
#import "GPUImageCrosshairGenerator.h"
|
||||
|
||||
NSString *const kGPUImageCrosshairVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
|
||||
uniform float crosshairWidth;
|
||||
|
||||
varying vec2 centerLocation;
|
||||
varying float pointSpacing;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(((position.xy * 2.0) - 1.0), 0.0, 1.0);
|
||||
gl_PointSize = crosshairWidth + 1.0;
|
||||
pointSpacing = 1.0 / crosshairWidth;
|
||||
centerLocation = vec2(pointSpacing * ceil(crosshairWidth / 2.0), pointSpacing * ceil(crosshairWidth / 2.0));
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageCrosshairFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
uniform lowp vec3 crosshairColor;
|
||||
|
||||
varying highp vec2 centerLocation;
|
||||
varying highp float pointSpacing;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec2 distanceFromCenter = abs(centerLocation - gl_PointCoord.xy);
|
||||
lowp float axisTest = step(pointSpacing, gl_PointCoord.y) * step(distanceFromCenter.x, 0.09) + step(pointSpacing, gl_PointCoord.x) * step(distanceFromCenter.y, 0.09);
|
||||
|
||||
gl_FragColor = vec4(crosshairColor * axisTest, axisTest);
|
||||
// gl_FragColor = vec4(distanceFromCenterInX, distanceFromCenterInY, 0.0, 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageCrosshairFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
GPUImageEscapedHashIdentifier(version 120)\n
|
||||
|
||||
uniform vec3 crosshairColor;
|
||||
|
||||
varying vec2 centerLocation;
|
||||
varying float pointSpacing;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 distanceFromCenter = abs(centerLocation - gl_PointCoord.xy);
|
||||
float axisTest = step(pointSpacing, gl_PointCoord.y) * step(distanceFromCenter.x, 0.09) + step(pointSpacing, gl_PointCoord.x) * step(distanceFromCenter.y, 0.09);
|
||||
|
||||
gl_FragColor = vec4(crosshairColor * axisTest, axisTest);
|
||||
// gl_FragColor = vec4(distanceFromCenterInX, distanceFromCenterInY, 0.0, 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageCrosshairGenerator
|
||||
|
||||
@synthesize crosshairWidth = _crosshairWidth;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithVertexShaderFromString:kGPUImageCrosshairVertexShaderString fragmentShaderFromString:kGPUImageCrosshairFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
crosshairWidthUniform = [filterProgram uniformIndex:@"crosshairWidth"];
|
||||
crosshairColorUniform = [filterProgram uniformIndex:@"crosshairColor"];
|
||||
|
||||
self.crosshairWidth = 5.0;
|
||||
[self setCrosshairColorRed:0.0 green:1.0 blue:0.0];
|
||||
});
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Rendering
|
||||
|
||||
- (void)renderCrosshairsFromArray:(GLfloat *)crosshairCoordinates count:(NSUInteger)numberOfCrosshairs frameTime:(CMTime)frameTime;
|
||||
{
|
||||
if (self.preventRendering)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
[GPUImageContext setActiveShaderProgram:filterProgram];
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
#else
|
||||
glEnable(GL_POINT_SPRITE);
|
||||
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
#endif
|
||||
|
||||
outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO];
|
||||
[outputFramebuffer activateFramebuffer];
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, crosshairCoordinates);
|
||||
|
||||
glDrawArrays(GL_POINTS, 0, (GLsizei)numberOfCrosshairs);
|
||||
|
||||
[self informTargetsAboutNewFrameAtTime:frameTime];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
|
||||
{
|
||||
// Prevent rendering of the frame by normal means
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setCrosshairWidth:(CGFloat)newValue;
|
||||
{
|
||||
_crosshairWidth = newValue;
|
||||
|
||||
[self setFloat:_crosshairWidth forUniform:crosshairWidthUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setCrosshairColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
|
||||
{
|
||||
GPUVector3 crosshairColor = {redComponent, greenComponent, blueComponent};
|
||||
|
||||
[self setVec3:crosshairColor forUniform:crosshairColorUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,163 +0,0 @@
|
||||
#import "GPUImageCrosshatchFilter.h"
|
||||
|
||||
// Shader code based on http://machinesdontcare.wordpress.com/
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageCrosshatchFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform highp float crossHatchSpacing;
|
||||
uniform highp float lineWidth;
|
||||
|
||||
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
void main()
|
||||
{
|
||||
highp float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W);
|
||||
|
||||
lowp vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
if (luminance < 1.00)
|
||||
{
|
||||
if (mod(textureCoordinate.x + textureCoordinate.y, crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (luminance < 0.75)
|
||||
{
|
||||
if (mod(textureCoordinate.x - textureCoordinate.y, crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (luminance < 0.50)
|
||||
{
|
||||
if (mod(textureCoordinate.x + textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (luminance < 0.3)
|
||||
{
|
||||
if (mod(textureCoordinate.x - textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = colorToDisplay;
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageCrosshatchFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
uniform float crossHatchSpacing;
|
||||
uniform float lineWidth;
|
||||
|
||||
const vec3 W = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
void main()
|
||||
{
|
||||
float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W);
|
||||
|
||||
vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
if (luminance < 1.00)
|
||||
{
|
||||
if (mod(textureCoordinate.x + textureCoordinate.y, crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (luminance < 0.75)
|
||||
{
|
||||
if (mod(textureCoordinate.x - textureCoordinate.y, crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (luminance < 0.50)
|
||||
{
|
||||
if (mod(textureCoordinate.x + textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
if (luminance < 0.3)
|
||||
{
|
||||
if (mod(textureCoordinate.x - textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
|
||||
{
|
||||
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = colorToDisplay;
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageCrosshatchFilter
|
||||
|
||||
@synthesize crossHatchSpacing = _crossHatchSpacing;
|
||||
@synthesize lineWidth = _lineWidth;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageCrosshatchFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
crossHatchSpacingUniform = [filterProgram uniformIndex:@"crossHatchSpacing"];
|
||||
lineWidthUniform = [filterProgram uniformIndex:@"lineWidth"];
|
||||
|
||||
self.crossHatchSpacing = 0.03;
|
||||
self.lineWidth = 0.003;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setCrossHatchSpacing:(CGFloat)newValue;
|
||||
{
|
||||
CGFloat singlePixelSpacing;
|
||||
if (inputTextureSize.width != 0.0)
|
||||
{
|
||||
singlePixelSpacing = 1.0 / inputTextureSize.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
singlePixelSpacing = 1.0 / 2048.0;
|
||||
}
|
||||
|
||||
if (newValue < singlePixelSpacing)
|
||||
{
|
||||
_crossHatchSpacing = singlePixelSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
_crossHatchSpacing = newValue;
|
||||
}
|
||||
|
||||
[self setFloat:_crossHatchSpacing forUniform:crossHatchSpacingUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setLineWidth:(CGFloat)newValue;
|
||||
{
|
||||
_lineWidth = newValue;
|
||||
|
||||
[self setFloat:_lineWidth forUniform:lineWidthUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,52 +0,0 @@
|
||||
#import "GPUImageDarkenBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 base = texture2D(inputImageTexture, textureCoordinate);
|
||||
lowp vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageDarkenBlendFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDarkenBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
#import "GPUImageDifferenceBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
gl_FragColor = vec4(abs(textureColor2.rgb - textureColor.rgb), textureColor.a);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
gl_FragColor = vec4(abs(textureColor2.rgb - textureColor.rgb), textureColor.a);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageDifferenceBlendFilter
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDifferenceBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
-431
@@ -1,431 +0,0 @@
|
||||
#import "GPUImageDilationFilter.h"
|
||||
|
||||
@implementation GPUImageDilationFilter
|
||||
|
||||
NSString *const kGPUImageDilationRadiusOneVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec2 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidthOffset;
|
||||
uniform float texelHeightOffset;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
|
||||
|
||||
centerTextureCoordinate = inputTextureCoordinate;
|
||||
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
|
||||
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusTwoVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec2 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidthOffset;
|
||||
uniform float texelHeightOffset;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
|
||||
|
||||
centerTextureCoordinate = inputTextureCoordinate;
|
||||
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
|
||||
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
|
||||
twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);
|
||||
twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusThreeVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec2 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidthOffset;
|
||||
uniform float texelHeightOffset;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
varying vec2 threeStepsPositiveTextureCoordinate;
|
||||
varying vec2 threeStepsNegativeTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
|
||||
|
||||
centerTextureCoordinate = inputTextureCoordinate;
|
||||
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
|
||||
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
|
||||
twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);
|
||||
twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);
|
||||
threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0);
|
||||
threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusFourVertexShaderString = SHADER_STRING
|
||||
(
|
||||
attribute vec4 position;
|
||||
attribute vec2 inputTextureCoordinate;
|
||||
|
||||
uniform float texelWidthOffset;
|
||||
uniform float texelHeightOffset;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
varying vec2 threeStepsPositiveTextureCoordinate;
|
||||
varying vec2 threeStepsNegativeTextureCoordinate;
|
||||
varying vec2 fourStepsPositiveTextureCoordinate;
|
||||
varying vec2 fourStepsNegativeTextureCoordinate;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
|
||||
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
|
||||
|
||||
centerTextureCoordinate = inputTextureCoordinate;
|
||||
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
|
||||
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
|
||||
twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);
|
||||
twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);
|
||||
threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0);
|
||||
threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0);
|
||||
fourStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 4.0);
|
||||
fourStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 4.0);
|
||||
}
|
||||
);
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageDilationRadiusOneFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision lowp float;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
|
||||
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusTwoFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision lowp float;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
|
||||
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
|
||||
|
||||
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
maxValue = max(maxValue, twoStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, twoStepsNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusThreeFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision lowp float;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
varying vec2 threeStepsPositiveTextureCoordinate;
|
||||
varying vec2 threeStepsNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
|
||||
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
|
||||
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
|
||||
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
|
||||
|
||||
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
maxValue = max(maxValue, twoStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, twoStepsNegativeIntensity);
|
||||
maxValue = max(maxValue, threeStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, threeStepsNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusFourFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision lowp float;
|
||||
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
varying vec2 threeStepsPositiveTextureCoordinate;
|
||||
varying vec2 threeStepsNegativeTextureCoordinate;
|
||||
varying vec2 fourStepsPositiveTextureCoordinate;
|
||||
varying vec2 fourStepsNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
|
||||
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
|
||||
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
|
||||
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
|
||||
float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;
|
||||
float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;
|
||||
|
||||
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
maxValue = max(maxValue, twoStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, twoStepsNegativeIntensity);
|
||||
maxValue = max(maxValue, threeStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, threeStepsNegativeIntensity);
|
||||
maxValue = max(maxValue, fourStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, fourStepsNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageDilationRadiusOneFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
|
||||
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusTwoFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
|
||||
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
|
||||
|
||||
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
maxValue = max(maxValue, twoStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, twoStepsNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusThreeFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
varying vec2 threeStepsPositiveTextureCoordinate;
|
||||
varying vec2 threeStepsNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
|
||||
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
|
||||
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
|
||||
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
|
||||
|
||||
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
maxValue = max(maxValue, twoStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, twoStepsNegativeIntensity);
|
||||
maxValue = max(maxValue, threeStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, threeStepsNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
|
||||
NSString *const kGPUImageDilationRadiusFourFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 centerTextureCoordinate;
|
||||
varying vec2 oneStepPositiveTextureCoordinate;
|
||||
varying vec2 oneStepNegativeTextureCoordinate;
|
||||
varying vec2 twoStepsPositiveTextureCoordinate;
|
||||
varying vec2 twoStepsNegativeTextureCoordinate;
|
||||
varying vec2 threeStepsPositiveTextureCoordinate;
|
||||
varying vec2 threeStepsNegativeTextureCoordinate;
|
||||
varying vec2 fourStepsPositiveTextureCoordinate;
|
||||
varying vec2 fourStepsNegativeTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
|
||||
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
|
||||
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
|
||||
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
|
||||
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
|
||||
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
|
||||
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
|
||||
float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;
|
||||
float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;
|
||||
|
||||
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
|
||||
maxValue = max(maxValue, oneStepNegativeIntensity);
|
||||
maxValue = max(maxValue, twoStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, twoStepsNegativeIntensity);
|
||||
maxValue = max(maxValue, threeStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, threeStepsNegativeIntensity);
|
||||
maxValue = max(maxValue, fourStepsPositiveIntensity);
|
||||
maxValue = max(maxValue, fourStepsNegativeIntensity);
|
||||
|
||||
gl_FragColor = vec4(vec3(maxValue), 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)initWithRadius:(NSUInteger)dilationRadius;
|
||||
{
|
||||
NSString *fragmentShaderForThisRadius = nil;
|
||||
NSString *vertexShaderForThisRadius = nil;
|
||||
|
||||
switch (dilationRadius)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString;
|
||||
fragmentShaderForThisRadius = kGPUImageDilationRadiusOneFragmentShaderString;
|
||||
}; break;
|
||||
case 2:
|
||||
{
|
||||
vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString;
|
||||
fragmentShaderForThisRadius = kGPUImageDilationRadiusTwoFragmentShaderString;
|
||||
}; break;
|
||||
case 3:
|
||||
{
|
||||
vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString;
|
||||
fragmentShaderForThisRadius = kGPUImageDilationRadiusThreeFragmentShaderString;
|
||||
}; break;
|
||||
case 4:
|
||||
{
|
||||
vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString;
|
||||
fragmentShaderForThisRadius = kGPUImageDilationRadiusFourFragmentShaderString;
|
||||
}; break;
|
||||
default:
|
||||
{
|
||||
vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString;
|
||||
fragmentShaderForThisRadius = kGPUImageDilationRadiusFourFragmentShaderString;
|
||||
}; break;
|
||||
}
|
||||
|
||||
if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [self initWithRadius:1]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,141 +0,0 @@
|
||||
#import "GPUImageDirectionalNonMaximumSuppressionFilter.h"
|
||||
|
||||
@implementation GPUImageDirectionalNonMaximumSuppressionFilter
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision mediump float;
|
||||
|
||||
varying highp vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform highp float texelWidth;
|
||||
uniform highp float texelHeight;
|
||||
uniform mediump float upperThreshold;
|
||||
uniform mediump float lowerThreshold;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb;
|
||||
vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight);
|
||||
|
||||
float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r;
|
||||
float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r;
|
||||
|
||||
float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r);
|
||||
multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r);
|
||||
|
||||
float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r);
|
||||
multiplier = multiplier * thresholdCompliance;
|
||||
|
||||
gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform float texelWidth;
|
||||
uniform float texelHeight;
|
||||
uniform float upperThreshold;
|
||||
uniform float lowerThreshold;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb;
|
||||
vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight);
|
||||
|
||||
float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r;
|
||||
float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r;
|
||||
|
||||
float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r);
|
||||
multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r);
|
||||
|
||||
float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r);
|
||||
multiplier = multiplier * thresholdCompliance;
|
||||
|
||||
gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@synthesize texelWidth = _texelWidth;
|
||||
@synthesize texelHeight = _texelHeight;
|
||||
@synthesize upperThreshold = _upperThreshold;
|
||||
@synthesize lowerThreshold = _lowerThreshold;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
|
||||
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
|
||||
upperThresholdUniform = [filterProgram uniformIndex:@"upperThreshold"];
|
||||
lowerThresholdUniform = [filterProgram uniformIndex:@"lowerThreshold"];
|
||||
|
||||
self.upperThreshold = 0.5;
|
||||
self.lowerThreshold = 0.1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupFilterForSize:(CGSize)filterFrameSize;
|
||||
{
|
||||
if (!hasOverriddenImageSizeFactor)
|
||||
{
|
||||
_texelWidth = 1.0 / filterFrameSize.width;
|
||||
_texelHeight = 1.0 / filterFrameSize.height;
|
||||
|
||||
runSynchronouslyOnVideoProcessingQueue(^{
|
||||
[GPUImageContext setActiveShaderProgram:filterProgram];
|
||||
glUniform1f(texelWidthUniform, _texelWidth);
|
||||
glUniform1f(texelHeightUniform, _texelHeight);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setTexelWidth:(CGFloat)newValue;
|
||||
{
|
||||
hasOverriddenImageSizeFactor = YES;
|
||||
_texelWidth = newValue;
|
||||
|
||||
[self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setTexelHeight:(CGFloat)newValue;
|
||||
{
|
||||
hasOverriddenImageSizeFactor = YES;
|
||||
_texelHeight = newValue;
|
||||
|
||||
[self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setLowerThreshold:(CGFloat)newValue;
|
||||
{
|
||||
_lowerThreshold = newValue;
|
||||
|
||||
[self setFloat:_lowerThreshold forUniform:lowerThresholdUniform program:filterProgram];
|
||||
}
|
||||
|
||||
- (void)setUpperThreshold:(CGFloat)newValue;
|
||||
{
|
||||
_upperThreshold = newValue;
|
||||
|
||||
[self setFloat:_upperThreshold forUniform:upperThresholdUniform program:filterProgram];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,103 +0,0 @@
|
||||
#import "GPUImageDirectionalSobelEdgeDetectionFilter.h"
|
||||
|
||||
@implementation GPUImageDirectionalSobelEdgeDetectionFilter
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
|
||||
float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
|
||||
float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
|
||||
float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
|
||||
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
|
||||
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
|
||||
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
|
||||
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
|
||||
|
||||
vec2 gradientDirection;
|
||||
gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
|
||||
gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
|
||||
|
||||
float gradientMagnitude = length(gradientDirection);
|
||||
vec2 normalizedDirection = normalize(gradientDirection);
|
||||
normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away
|
||||
normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0
|
||||
|
||||
gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 leftTextureCoordinate;
|
||||
varying vec2 rightTextureCoordinate;
|
||||
|
||||
varying vec2 topTextureCoordinate;
|
||||
varying vec2 topLeftTextureCoordinate;
|
||||
varying vec2 topRightTextureCoordinate;
|
||||
|
||||
varying vec2 bottomTextureCoordinate;
|
||||
varying vec2 bottomLeftTextureCoordinate;
|
||||
varying vec2 bottomRightTextureCoordinate;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
|
||||
float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
|
||||
float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
|
||||
float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
|
||||
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
|
||||
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
|
||||
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
|
||||
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
|
||||
|
||||
vec2 gradientDirection;
|
||||
gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
|
||||
gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
|
||||
|
||||
float gradientMagnitude = length(gradientDirection);
|
||||
vec2 normalizedDirection = normalize(gradientDirection);
|
||||
normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away
|
||||
normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0
|
||||
|
||||
gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,72 +0,0 @@
|
||||
#import "GPUImageDissolveBlendFilter.h"
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
|
||||
NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying highp vec2 textureCoordinate;
|
||||
varying highp vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
uniform lowp float mixturePercent;
|
||||
|
||||
void main()
|
||||
{
|
||||
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = mix(textureColor, textureColor2, mixturePercent);
|
||||
}
|
||||
);
|
||||
#else
|
||||
NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING
|
||||
(
|
||||
varying vec2 textureCoordinate;
|
||||
varying vec2 textureCoordinate2;
|
||||
|
||||
uniform sampler2D inputImageTexture;
|
||||
uniform sampler2D inputImageTexture2;
|
||||
uniform float mixturePercent;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
|
||||
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
|
||||
|
||||
gl_FragColor = mix(textureColor, textureColor2, mixturePercent);
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
@implementation GPUImageDissolveBlendFilter
|
||||
|
||||
@synthesize mix = _mix;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization and teardown
|
||||
|
||||
- (id)init;
|
||||
{
|
||||
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDissolveBlendFragmentShaderString]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
mixUniform = [filterProgram uniformIndex:@"mixturePercent"];
|
||||
self.mix = 0.5;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessors
|
||||
|
||||
- (void)setMix:(CGFloat)newValue;
|
||||
{
|
||||
_mix = newValue;
|
||||
|
||||
[self setFloat:_mix forUniform:mixUniform program:filterProgram];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user