Compare commits

..

58 Commits

Author SHA1 Message Date
chenliming 8c2596c23e fix Third party library external introduction 2016-08-30 16:46:25 +08:00
chenliming 681b1cd107 Modified time stamp logic 2016-08-30 12:17:45 +08:00
chenliming 13094108e3 fix bug https://github.com/LaiFengiOS/LFLiveKit/issues/61 2016-08-30 11:01:24 +08:00
chenliming abd55c5511 fix bug https://github.com/LaiFengiOS/LFLiveKit/issues/67 2016-08-29 20:57:53 +08:00
chenliming fc52abe7bd fix code format 2016-08-29 18:05:37 +08:00
chenliming fa10e28281 Support sampling rate 16K
Modify 44.1K iphone6s sound problem
Add a local record sound(aac)
2016-08-29 17:58:58 +08:00
chenliming c624fbe78c iphone6 after audio 48000 2016-08-24 14:25:39 +08:00
小歪~~~ 19a355e697 Merge pull request #44 from zzgo/master
Add currentImage
2016-08-24 13:44:21 +08:00
chenliming 7799f0f613 fix bug https://github.com/LaiFengiOS/LFLiveKit/issues/60 2016-08-22 21:10:23 +08:00
chenliming ecf3b557cf fix memory leak 2016-08-19 16:01:17 +08:00
chenliming 58d83ed0dc modify capture sessionPreset(1280X720) bug set videoSize 360 640 2016-08-16 18:09:42 +08:00
小歪~~~ b167bda396 Merge pull request #54 from Michael-Owen/master
修复画面抖动模糊的问题
2016-08-16 18:06:05 +08:00
Michael 336a6e2432 修复画面抖动模糊的问题,presentationTimeStamp根据帧率计算 2016-08-16 17:18:29 +08:00
Michael 8acddcda90 修复画面抖动模糊的问题 2016-08-16 13:51:04 +08:00
chenliming cf2fc51fea add build sh 2016-08-15 20:25:41 +08:00
chenliming ae5f68661e update version 2016-08-12 21:06:42 +08:00
chenliming e30467dc13 fix videoSizeRespectingAspectRatio show error 2016-08-11 14:18:15 +08:00
chenliming a217868694 support External input video or audio ,set LFLiveCaptureTypeMask 2016-08-10 14:23:26 +08:00
小歪~~~ 3053a16cd3 Merge pull request #47 from toss156/master
fix #46 never mirrored rear facing camera
2016-08-09 17:21:32 +08:00
toss156 d2d7140312 update project file 2016-08-09 17:12:09 +08:00
toss156 e93549619e never mirror the rear facing camera 2016-08-09 16:51:49 +08:00
toss156 0196b1be79 Merge branch 'master' of https://github.com/LaiFengiOS/LFLiveKit
# By chenliming
# Via chenliming
* 'master' of https://github.com/LaiFengiOS/LFLiveKit:
  update waterMark postion and set outVideoSize
  Support output arbitrary size and fix iphone4  1920*720 crash

Conflicts:
	LFLiveKit/capture/LFVideoCapture.m
	LFLiveKitDemo/LFLiveKitDemo.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
2016-08-05 15:33:27 +08:00
toss156 23ab30e668 Merge branch 'master' of https://github.com/LaiFengiOS/LFLiveKit
# By chenliming (35) and others
# Via GitHub (2) and chenliming (1)
* 'master' of https://github.com/LaiFengiOS/LFLiveKit: (37 commits)
  水印
  add watermark ..
  Update LFLiveKit.podspec
  change the AVAudioSession Category before start, or it will fail
  update..
  update
  update ..
  add a icon
  update read
  update readme
  update
  modify read
  modify read
  update travis 
  update read
  update version2.0
  add  iOS  encoder
  add carthage
  update version
  update version
  ...

Conflicts:
	LFLiveKit.xcodeproj/project.pbxproj
	LFLiveKit.xcworkspace/xcuserdata/feng.xcuserdatad/UserInterfaceState.xcuserstate
	LFLiveKit/LFLiveSession.m
	LFLiveKit/capture/LFVideoCapture.m
2016-08-05 15:27:08 +08:00
chenliming 42bd5c1f6b update waterMark postion and set outVideoSize 2016-08-05 14:06:11 +08:00
chenliming 41393ffed8 Support output arbitrary size and fix iphone4 1920*720 crash 2016-08-05 12:20:17 +08:00
zz 2b236b2a35 add currentImage
改currentImageView 为currentImage
2016-08-05 12:05:39 +08:00
zz e59699b7fd add currentImage
改currentImageView 为currentImage
2016-08-05 12:05:07 +08:00
zz e9f3c66a3b add currentImage
改currentImageView为currentImage
2016-08-05 12:04:14 +08:00
zz dc1dc18824 add currentImage
改currentImageView为currentImage
2016-08-05 12:03:15 +08:00
zz 014e73f44c add currentImage
改currentImageView为currentImage
2016-08-05 12:01:48 +08:00
zz ee7c25727b add currentImageView
获取当前视频截图
2016-08-05 11:36:45 +08:00
zz 79f0ba930b add currentImageView
获取当前视频截图
2016-08-05 11:34:37 +08:00
zz c5edbfba8e add currentImageView
获取当前视频截图
2016-08-05 11:32:47 +08:00
zz 91c689a41f add currentImageView
获取当前视频截图
2016-08-05 11:18:46 +08:00
chenliming ba48a45c0a 水印 2016-08-04 14:05:52 +08:00
chenliming af09e79e74 add watermark .. 2016-08-04 13:59:43 +08:00
小歪~~~ e4327de704 Merge pull request #38 from zhangyu528/master
Update LFLiveKit.podspec
2016-08-03 13:49:34 +08:00
Justin 9760129763 Update LFLiveKit.podspec
fix issue  #36 关于use_frameworks!的问题
2016-08-03 13:23:46 +08:00
小歪~~~ dc7f8d1d10 Merge pull request #37 from Guikunzhi/master
change the AVAudioSession Category before start, or it will fail
2016-08-03 12:18:24 +08:00
琨君 8f8bedb93d change the AVAudioSession Category before start, or it will fail 2016-08-03 10:41:55 +08:00
chenliming 9428dc2c7f update.. 2016-08-02 16:06:07 +08:00
chenliming e6c0d148ab update 2016-08-02 16:02:30 +08:00
chenliming 0ca5c18c19 update .. 2016-08-02 16:01:12 +08:00
chenliming cb98f0e70d add a icon 2016-08-02 15:55:45 +08:00
chenliming 06f1e40fba update read 2016-08-02 10:17:39 +08:00
chenliming dfbc4a51ff update readme 2016-08-01 19:46:18 +08:00
chenliming f045bb14e4 update 2016-08-01 17:26:00 +08:00
chenliming ebafc22eca modify read 2016-08-01 17:25:09 +08:00
chenliming 6e3e92a6b9 modify read 2016-08-01 17:23:14 +08:00
chenliming 26a47ffccc update travis 2016-08-01 17:12:42 +08:00
chenliming e57d3e3806 update read 2016-08-01 17:08:52 +08:00
chenliming b73bfee6ac update version2.0 2016-08-01 16:45:50 +08:00
chenliming 09398d0cb3 add iOS encoder 2016-08-01 16:42:02 +08:00
chenliming f69b586d70 add carthage 2016-08-01 16:19:36 +08:00
toss156 edcb2efaa0 never mirrored rear facing camera 2016-07-27 10:06:17 +08:00
feng 3842ff80bf Merge pull request #7 from LaiFengiOS/master
update to last version
2016-07-26 18:20:15 +08:00
toss156 d3d5f6cb24 fix mirror bug: present view is different with the stream 2016-07-26 18:15:23 +08:00
toss156 37bfd377d6 rename h264 encode lib to avoid duplicate symbol error 2016-07-26 11:16:43 +08:00
478 changed files with 5014 additions and 40990 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
language: objective-c
osx_image: xcode7
xcode_workspace: LFLiveKit.xcworkspace
xcode_project: LFLiveKit.xcodeproj
xcode_scheme: LFLiveKit
script:
- xctool -workspace LFLiveKit.xcworkspace -scheme 'LFLiveKit' -configuration Release -sdk iphonesimulator -arch i386 build
- xctool -project LFLiveKit.xcodeproj -scheme 'LFLiveKit' -configuration Release -sdk iphonesimulator -arch i386 build
+3 -2
View File
@@ -2,7 +2,7 @@
Pod::Spec.new do |s|
s.name = "LFLiveKit"
s.version = "1.9.6"
s.version = "2.2"
s.summary = "LaiFeng ios Live. LFLiveKit."
s.homepage = "https://github.com/chenliming777"
s.license = { :type => "MIT", :file => "LICENSE" }
@@ -11,7 +11,8 @@ 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"
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>
@@ -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>
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.9.6</string>
<string>2.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
-15
View File
@@ -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_librtmp.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_librtmp.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 */;
}
+25
View File
@@ -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
@@ -13,13 +13,17 @@
@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 +37,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 +45,7 @@
self.beautyLevel = 0.5;
self.brightLevel = 0.5;
self.zoomScale = 1.0;
self.mirror = YES;
}
return self;
}
@@ -79,68 +53,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 +155,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 +181,8 @@
- (void)setBrightLevel:(CGFloat)brightLevel {
_brightLevel = brightLevel;
if (_beautyFilter) {
[_beautyFilter setBrightLevel:brightLevel];
if (self.beautyFilter) {
[self.beautyFilter setBrightLevel:brightLevel];
}
}
@@ -203,54 +205,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 +264,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 +357,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;
};
@@ -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;
@@ -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;
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"];
@@ -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;
@@ -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];
@@ -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;
@@ -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;
@@ -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
@@ -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
@@ -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;
@@ -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
View File
@@ -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
-128
View File
@@ -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
View File
@@ -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
-72
View File
@@ -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
-38
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-66
View File
@@ -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
View File
@@ -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
-113
View File
@@ -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
-117
View File
@@ -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
View File
@@ -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
-57
View File
@@ -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
-113
View File
@@ -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
View File
@@ -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
-46
View File
@@ -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
-87
View File
@@ -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
-139
View File
@@ -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
-66
View File
@@ -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
View File
@@ -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
-139
View File
@@ -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
-163
View File
@@ -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
-52
View File
@@ -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
View File
@@ -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
-72
View File
@@ -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
-96
View File
@@ -1,96 +0,0 @@
#import "GPUImageDivideBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDivideBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
mediump vec4 base = texture2D(inputImageTexture, textureCoordinate);
mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
mediump float ra;
if (overlay.a == 0.0 || ((base.r / overlay.r) > (base.a / overlay.a)))
ra = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
else
ra = (base.r * overlay.a * overlay.a) / overlay.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
mediump float ga;
if (overlay.a == 0.0 || ((base.g / overlay.g) > (base.a / overlay.a)))
ga = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
else
ga = (base.g * overlay.a * overlay.a) / overlay.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
mediump float ba;
if (overlay.a == 0.0 || ((base.b / overlay.b) > (base.a / overlay.a)))
ba = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
else
ba = (base.b * overlay.a * overlay.a) / overlay.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
mediump float a = overlay.a + base.a - overlay.a * base.a;
gl_FragColor = vec4(ra, ga, ba, a);
}
);
#else
NSString *const kGPUImageDivideBlendFragmentShaderString = 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 ra;
if (overlay.a == 0.0 || ((base.r / overlay.r) > (base.a / overlay.a)))
ra = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
else
ra = (base.r * overlay.a * overlay.a) / overlay.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
float ga;
if (overlay.a == 0.0 || ((base.g / overlay.g) > (base.a / overlay.a)))
ga = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
else
ga = (base.g * overlay.a * overlay.a) / overlay.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
float ba;
if (overlay.a == 0.0 || ((base.b / overlay.b) > (base.a / overlay.a)))
ba = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
else
ba = (base.b * overlay.a * overlay.a) / overlay.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
float a = overlay.a + base.a - overlay.a * base.a;
gl_FragColor = vec4(ra, ga, ba, a);
}
);
#endif
@implementation GPUImageDivideBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDivideBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end

Some files were not shown because too many files have changed in this diff Show More