Skip to content

Commit 047354f

Browse files
committed
feat: add filter
1 parent 552db9b commit 047354f

File tree

5 files changed

+95
-1
lines changed

5 files changed

+95
-1
lines changed

SimpleWebRTC.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
28D5CAE0E83A76C0FFBC9536 /* Pods_SimpleWebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BFABE961561EF9B2240A098 /* Pods_SimpleWebRTC.framework */; };
11+
378B38D82365C2A8002C5E8B /* CameraFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 378B38D72365C2A8002C5E8B /* CameraFilter.swift */; };
1112
AF15C0B221E422D9005B4ED6 /* UIViewExtention.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF15C0B121E422D9005B4ED6 /* UIViewExtention.swift */; };
1213
AF15C0B521E4F1F7005B4ED6 /* SignalingMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF15C0B421E4F1F7005B4ED6 /* SignalingMessage.swift */; };
1314
AF15C0B721E54EB1005B4ED6 /* SignalingCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF15C0B621E54EB1005B4ED6 /* SignalingCandidate.swift */; };
@@ -69,6 +70,7 @@
6970
05D95DE48BD4CC42D39620AF /* Pods-SimpleWebRTCTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleWebRTCTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleWebRTCTests/Pods-SimpleWebRTCTests.debug.xcconfig"; sourceTree = "<group>"; };
7071
2D2A5F0229AE703BFD44F9F1 /* Pods-SimpleWebRTCUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleWebRTCUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleWebRTCUITests/Pods-SimpleWebRTCUITests.release.xcconfig"; sourceTree = "<group>"; };
7172
31148F7848EBC2EEA7F21F0F /* Pods_SimpleWebRTCTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SimpleWebRTCTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
73+
378B38D72365C2A8002C5E8B /* CameraFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraFilter.swift; sourceTree = "<group>"; };
7274
53C8300D672FBC2658413CC6 /* Pods-SimpleWebRTC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleWebRTC.release.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleWebRTC/Pods-SimpleWebRTC.release.xcconfig"; sourceTree = "<group>"; };
7375
8D9A48F6D592CC1505389F06 /* Pods-SimpleWebRTCTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SimpleWebRTCTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SimpleWebRTCTests/Pods-SimpleWebRTCTests.release.xcconfig"; sourceTree = "<group>"; };
7476
9BFABE961561EF9B2240A098 /* Pods_SimpleWebRTC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SimpleWebRTC.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -145,6 +147,14 @@
145147
name = Pods;
146148
sourceTree = "<group>";
147149
};
150+
378B38D62365C281002C5E8B /* CameraFilter */ = {
151+
isa = PBXGroup;
152+
children = (
153+
378B38D72365C2A8002C5E8B /* CameraFilter.swift */,
154+
);
155+
path = CameraFilter;
156+
sourceTree = "<group>";
157+
};
148158
AF15C0AE21E41A58005B4ED6 /* Extentions */ = {
149159
isa = PBXGroup;
150160
children = (
@@ -190,6 +200,7 @@
190200
AF711AA321DFAD6C005CA4FA /* SimpleWebRTC */ = {
191201
isa = PBXGroup;
192202
children = (
203+
378B38D62365C281002C5E8B /* CameraFilter */,
193204
AF90A8E1220D00500083687C /* CameraSession */,
194205
AFF1031921E569990011C1FC /* Assets */,
195206
AF15C0B321E4F1B9005B4ED6 /* Data */,
@@ -511,6 +522,7 @@
511522
isa = PBXSourcesBuildPhase;
512523
buildActionMask = 2147483647;
513524
files = (
525+
378B38D82365C2A8002C5E8B /* CameraFilter.swift in Sources */,
514526
AF15C0B721E54EB1005B4ED6 /* SignalingCandidate.swift in Sources */,
515527
AF711AA721DFAD6C005CA4FA /* ViewController.swift in Sources */,
516528
AF90A8E0220CF07A0083687C /* RTCCustomFrameCapture.swift in Sources */,
@@ -695,6 +707,7 @@
695707
baseConfigurationReference = F150849F443D0DC1BDD78D03 /* Pods-SimpleWebRTC.debug.xcconfig */;
696708
buildSettings = {
697709
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
710+
CODE_SIGN_IDENTITY = "iPhone Developer";
698711
CODE_SIGN_STYLE = Automatic;
699712
DEVELOPMENT_TEAM = QAHL4SN6S5;
700713
ENABLE_BITCODE = NO;
@@ -710,6 +723,7 @@
710723
);
711724
PRODUCT_BUNDLE_IDENTIFIER = test.SimpleWebRTC;
712725
PRODUCT_NAME = "$(TARGET_NAME)";
726+
PROVISIONING_PROFILE_SPECIFIER = "";
713727
SWIFT_VERSION = 5.0;
714728
TARGETED_DEVICE_FAMILY = "1,2";
715729
};
@@ -720,6 +734,7 @@
720734
baseConfigurationReference = 53C8300D672FBC2658413CC6 /* Pods-SimpleWebRTC.release.xcconfig */;
721735
buildSettings = {
722736
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
737+
CODE_SIGN_IDENTITY = "iPhone Developer";
723738
CODE_SIGN_STYLE = Automatic;
724739
DEVELOPMENT_TEAM = QAHL4SN6S5;
725740
ENABLE_BITCODE = NO;
@@ -735,6 +750,7 @@
735750
);
736751
PRODUCT_BUNDLE_IDENTIFIER = test.SimpleWebRTC;
737752
PRODUCT_NAME = "$(TARGET_NAME)";
753+
PROVISIONING_PROFILE_SPECIFIER = "";
738754
SWIFT_VERSION = 5.0;
739755
TARGETED_DEVICE_FAMILY = "1,2";
740756
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//
2+
// CameraFilter.swift
3+
// SimpleWebRTC
4+
//
5+
// Created by n0 on 2019/10/27.
6+
// Copyright © 2019 n0. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import AVFoundation
11+
import CoreImage
12+
13+
class CameraFilter {
14+
15+
private let filter: CIFilter
16+
private let context: CIContext
17+
18+
init() {
19+
self.filter = CIFilter(name: "CISepiaTone")!
20+
self.context = CIContext()
21+
}
22+
23+
func apply(_ sampleBuffer: CVPixelBuffer) -> CVPixelBuffer?{
24+
let ciimage = CIImage(cvPixelBuffer: sampleBuffer)
25+
self.filter.setValue(ciimage, forKey: kCIInputImageKey)
26+
self.filter.setValue(0.8, forKey: "inputIntensity")
27+
28+
let size: CGSize = ciimage.extent.size
29+
30+
let filtered = self.filter.outputImage
31+
var pixelBuffer: CVPixelBuffer? = nil
32+
33+
let options = [
34+
kCVPixelBufferCGImageCompatibilityKey as String: kCFBooleanTrue,
35+
kCVPixelBufferCGBitmapContextCompatibilityKey as String: kCFBooleanTrue
36+
] as [String : Any]
37+
38+
let status: CVReturn = CVPixelBufferCreate(kCFAllocatorDefault,
39+
Int(size.width),
40+
Int(size.height),
41+
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
42+
options as CFDictionary?,
43+
&pixelBuffer)
44+
45+
if (status == kCVReturnSuccess && pixelBuffer != nil) {
46+
self.context.render(filtered!, to: pixelBuffer!)
47+
}
48+
return pixelBuffer
49+
}
50+
}

SimpleWebRTC/ViewController/ViewController.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ViewController: UIViewController, WebSocketDelegate, WebRTCClientDelegate,
3535

3636
// You can create video source from CMSampleBuffer :)
3737
var useCustomCapturer: Bool = true
38+
var cameraFilter: CameraFilter?
3839

3940
// Constants
4041
let ipAddress: String = "192.168.1.139"
@@ -66,6 +67,8 @@ class ViewController: UIViewController, WebSocketDelegate, WebRTCClientDelegate,
6667
self.cameraSession = CameraSession()
6768
self.cameraSession?.delegate = self
6869
self.cameraSession?.setupSession()
70+
71+
self.cameraFilter = CameraFilter()
6972
}
7073

7174
socket = WebSocket(url: URL(string: "ws://" + ipAddress + ":8080/")!)
@@ -342,7 +345,16 @@ extension ViewController {
342345
extension ViewController {
343346
func didOutput(_ sampleBuffer: CMSampleBuffer) {
344347
if self.useCustomCapturer {
345-
self.webRTCClient.captureCurrentFrame(sampleBuffer: sampleBuffer)
348+
if let cvpixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer){
349+
if let buffer = self.cameraFilter?.apply(cvpixelBuffer){
350+
self.webRTCClient.captureCurrentFrame(sampleBuffer: buffer)
351+
}else{
352+
print("no applied image")
353+
}
354+
}else{
355+
print("no pixelbuffer")
356+
}
357+
// self.webRTCClient.captureCurrentFrame(sampleBuffer: buffer)
346358
}
347359
}
348360
}

SimpleWebRTC/WebRTC/RTCCustomFrameCapture.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import WebRTC
1212
class RTCCustomFrameCapturer: RTCVideoCapturer {
1313

1414
let kNanosecondsPerSecond: Float64 = 1000000000
15+
var nanoseconds: Float64 = 0
1516

1617
override init(delegate: RTCVideoCapturerDelegate) {
1718
super.init(delegate: delegate)
@@ -26,4 +27,13 @@ class RTCCustomFrameCapturer: RTCVideoCapturer {
2627
self.delegate?.capturer(self, didCapture: rtcVideoFrame)
2728
}
2829
}
30+
31+
public func capture(_ pixelBuffer: CVPixelBuffer){
32+
let rtcPixelBuffer = RTCCVPixelBuffer(pixelBuffer: pixelBuffer)
33+
let timeStampNs = nanoseconds * kNanosecondsPerSecond
34+
35+
let rtcVideoFrame = RTCVideoFrame(buffer: rtcPixelBuffer, rotation: RTCVideoRotation._90, timeStampNs: Int64(timeStampNs))
36+
self.delegate?.capturer(self, didCapture: rtcVideoFrame)
37+
nanoseconds += 1
38+
}
2939
}

SimpleWebRTC/WebRTC/WebRTCClient.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ class WebRTCClient: NSObject, RTCPeerConnectionDelegate, RTCVideoViewDelegate, R
191191
}
192192
}
193193

194+
func captureCurrentFrame(sampleBuffer: CVPixelBuffer){
195+
if let capturer = self.videoCapturer as? RTCCustomFrameCapturer {
196+
capturer.capture(sampleBuffer)
197+
}
198+
}
199+
194200
// MARK: - Private functions
195201
// MARK: - Setup
196202
private func setupPeerConnection() -> RTCPeerConnection{

0 commit comments

Comments
 (0)