Skip to content

Commit ebede72

Browse files
author
xianing
committed
fix custom video render
1 parent 0ee3217 commit ebede72

5 files changed

Lines changed: 75 additions & 62 deletions

File tree

iOS/APIExample/Common/ExternalVideo/AgoraMetalRender.swift

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
import CoreMedia
1010
import Metal
1111

12-
//TODO
13-
#if false
14-
1512

1613
#if os(iOS) && (!arch(i386) && !arch(x86_64))
1714
import MetalKit
@@ -22,6 +19,17 @@ protocol AgoraMetalRenderMirrorDataSource: NSObjectProtocol {
2219
func renderViewShouldMirror(renderView: AgoraMetalRender) -> Bool
2320
}
2421

22+
enum AgoraVideoRotation:Int {
23+
/** 0: No rotation */
24+
case rotationNone = 0
25+
/** 1: 90 degrees */
26+
case rotation90 = 1
27+
/** 2: 180 degrees */
28+
case rotation180 = 2
29+
/** 3: 270 degrees */
30+
case rotation270 = 3
31+
}
32+
2533
class AgoraMetalRender: UIView {
2634
weak var mirrorDataSource: AgoraMetalRenderMirrorDataSource?
2735

@@ -64,48 +72,39 @@ class AgoraMetalRender: UIView {
6472
}
6573
}
6674

67-
extension AgoraMetalRender: AgoraVideoSinkProtocol {
68-
func shouldInitialize() -> Bool {
69-
initializeRenderPipelineState()
70-
return true
71-
}
72-
73-
func shouldStart() {
74-
#if os(iOS) && (!arch(i386) && !arch(x86_64))
75-
metalView.delegate = self
76-
#endif
77-
}
78-
79-
func shouldStop() {
80-
#if os(iOS) && (!arch(i386) && !arch(x86_64))
81-
metalView.delegate = nil
82-
#endif
83-
}
84-
85-
func shouldDispose() {
86-
_ = semaphore.wait(timeout: .distantFuture)
87-
textures = nil
88-
vertexBuffer = nil
89-
#if os(macOS) || (os(iOS) && (!arch(i386) && !arch(x86_64)))
90-
metalView.delegate = nil
91-
textureCache = nil
92-
#endif
93-
commandQueue = nil
94-
semaphore.signal()
95-
}
96-
97-
func bufferType() -> AgoraVideoBufferType {
98-
return .pixelBuffer
75+
func getAgoraRotation(rotation: Int32) -> AgoraVideoRotation? {
76+
switch rotation {
77+
case 0:
78+
return .rotationNone
79+
case 90:
80+
return .rotation90
81+
case 180:
82+
return .rotation180
83+
case 270:
84+
return .rotation270
85+
default:
86+
return nil
9987
}
100-
101-
func pixelFormat() -> AgoraVideoPixelFormat {
102-
return .NV12
88+
}
89+
90+
extension AgoraMetalRender: AgoraVideoFrameDelegate {
91+
func onCapture(_ videoFrame: AgoraOutputVideoFrame) -> Bool {
92+
93+
94+
return true
10395
}
10496

105-
func renderPixelBuffer(_ pixelBuffer: CVPixelBuffer, rotation: AgoraVideoRotation) {
106-
#if os(iOS) && (!arch(i386) && !arch(x86_64))
97+
func onRenderVideoFrame(_ videoFrame: AgoraOutputVideoFrame, uid: UInt, connectionId: UInt) -> Bool {
98+
99+
guard let rotation = getAgoraRotation(rotation: videoFrame.rotation) else {
100+
return false
101+
}
102+
103+
guard let pixelBuffer = videoFrame.pixelBuffer else {
104+
return false
105+
}
107106
guard CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly) == kCVReturnSuccess else {
108-
return
107+
return false
109108
}
110109
defer {
111110
CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly)
@@ -128,7 +127,17 @@ extension AgoraMetalRender: AgoraVideoSinkProtocol {
128127
let uvTexture = texture(pixelBuffer: pixelBuffer, textureCache: textureCache, planeIndex: 1, pixelFormat: .rg8Unorm) {
129128
self.textures = [yTexture, uvTexture]
130129
}
131-
#endif
130+
return false
131+
}
132+
133+
func getVideoFrameProcessMode() -> AgoraVideoFrameProcessMode {
134+
initializeRenderPipelineState()
135+
metalView.delegate = self
136+
return .readOnly
137+
}
138+
139+
func getVideoPixelFormatPreference() -> AgoraVideoFormat {
140+
return .cvPixel
132141
}
133142
}
134143

@@ -255,7 +264,7 @@ extension AgoraVideoRotation {
255264
guard viewSize.width > 0, viewSize.height > 0, videoSize.width > 0, videoSize.height > 0 else {
256265
return nil
257266
}
258-
267+
259268
let widthAspito: Float
260269
let heightAspito: Float
261270
if self == .rotation90 || self == .rotation270 {
@@ -265,7 +274,7 @@ extension AgoraVideoRotation {
265274
widthAspito = Float(videoSize.width / viewSize.width)
266275
heightAspito = Float(videoSize.height / viewSize.height)
267276
}
268-
277+
269278
let x: Float
270279
let y: Float
271280
if widthAspito < heightAspito {
@@ -275,12 +284,12 @@ extension AgoraVideoRotation {
275284
x = widthAspito / heightAspito
276285
y = 1
277286
}
278-
287+
279288
let A = float4( x, -y, 0.0, 1.0 )
280289
let B = float4( -x, -y, 0.0, 1.0 )
281290
let C = float4( x, y, 0.0, 1.0 )
282291
let D = float4( -x, y, 0.0, 1.0 )
283-
292+
284293
switch self {
285294
case .rotationNone:
286295
if mirror {
@@ -309,5 +318,3 @@ extension AgoraVideoRotation {
309318
}
310319
}
311320
}
312-
313-
#endif

iOS/APIExample/Common/VideoView.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ class VideoView: UIView {
7676

7777
class MetalVideoView: UIView {
7878
@IBOutlet weak var placeholder: UILabel!
79-
//TODO
80-
// @IBOutlet weak var videoView: AgoraMetalRender!
79+
@IBOutlet weak var videoView: AgoraMetalRender!
8180
@IBOutlet weak var infolabel: UILabel!
8281

8382
override func awakeFromNib() {

iOS/APIExample/Common/VideoViewMetal.xib

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
<connections>
5656
<outlet property="infolabel" destination="2sO-zb-ccE" id="HQi-ln-8x0"/>
5757
<outlet property="placeholder" destination="jNO-yh-cWz" id="3n3-sG-STN"/>
58+
<outlet property="videoView" destination="z6G-aL-Ut4" id="Jfc-RP-ol4"/>
5859
</connections>
5960
<point key="canvasLocation" x="261" y="208"/>
6061
</view>

iOS/APIExample/Examples/Advanced/CustomVideoRender/CustomVideoRender.swift

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class CustomVideoRenderEntry : UIViewController
3434
}
3535

3636
class CustomVideoRenderMain: BaseViewController {
37-
var localVideo = Bundle.loadView(fromNib: "VideoViewMetal", withType: MetalVideoView.self)
37+
var localVideo = Bundle.loadVideoView(type: .local, audioOnly: false)
3838
var remoteVideo = Bundle.loadView(fromNib: "VideoViewMetal", withType: MetalVideoView.self)
3939

4040
@IBOutlet weak var container: AGEVideoContainer!
@@ -72,15 +72,22 @@ class CustomVideoRenderMain: BaseViewController {
7272
bitrate: AgoraVideoBitrateStandard,
7373
orientationMode: .adaptative, mirrorMode: .auto))
7474

75-
//TODO
76-
// set up your own render
77-
// if let customRender = localVideo.videoView {
78-
// agoraKit.setLocalVideoRenderer(customRender)
79-
// }
75+
76+
8077

8178
// Set audio route to speaker
8279
agoraKit.setDefaultAudioRouteToSpeakerphone(true)
8380

81+
// set up local video to render your local camera preview
82+
let videoCanvas = AgoraRtcVideoCanvas()
83+
videoCanvas.uid = 0
84+
// the view to be binded
85+
videoCanvas.view = localVideo.videoView
86+
videoCanvas.renderMode = .hidden
87+
agoraKit.setupLocalVideo(videoCanvas)
88+
// you have to call startPreview to see local video
89+
agoraKit.startPreview()
90+
8491
// start joining channel
8592
// 1. Users can only see each other after they join the
8693
// same channel successfully using the same app id.
@@ -155,10 +162,9 @@ extension CustomVideoRenderMain: AgoraRtcEngineDelegate {
155162
// tutorial. Here we check if there exists a surface
156163
// view tagged as this uid.
157164
// set up your own render
158-
//TODO
159-
// if let customRender = remoteVideo.videoView {
160-
// agoraKit.setRemoteVideoRenderer(customRender, forUserId: uid)
161-
// }
165+
if let customRender = remoteVideo.videoView {
166+
agoraKit.setVideoFrameDelegate(customRender)
167+
}
162168
}
163169

164170
/// callback when a remote user is leaving the channel, note audience in live broadcast mode will NOT trigger this event

iOS/APIExample/ViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ class ViewController: AGViewController {
3333
MenuItem(name: "RTMP Streaming".localized, storyboard: "RTMPStreaming", controller: "RTMPStreaming"),
3434
MenuItem(name: "Video Metadata".localized, storyboard: "VideoMetadata", controller: "VideoMetadata".localized),
3535
MenuItem(name: "Voice Changer".localized, storyboard: "VoiceChanger", controller: ""),
36-
MenuItem(name: "Custom Audio Source".localized, storyboard: "CustomAudioSource", controller: "CustomAudioSource"),
36+
// MenuItem(name: "Custom Audio Source".localized, storyboard: "CustomAudioSource", controller: "CustomAudioSource"),
3737
MenuItem(name: "Custom Audio Source(PCM)".localized, storyboard: "CustomPcmAudioSource", controller: "CustomPcmAudioSource"),
3838
MenuItem(name: "Custom Audio Render".localized, storyboard: "CustomAudioRender", controller: "CustomAudioRender"),
3939
MenuItem(name: "Custom Video Source(Push)".localized, storyboard: "CustomVideoSourcePush", controller: "CustomVideoSourcePush"),
40-
// MenuItem(name: "Custom Video Render".localized, storyboard: "CustomVideoRender", controller: "CustomVideoRender"),
40+
MenuItem(name: "Custom Video Render".localized, storyboard: "CustomVideoRender", controller: "CustomVideoRender"),
4141
MenuItem(name: "Raw Media Data".localized, storyboard: "RawMediaData", controller: "RawMediaData"),
4242
MenuItem(name: "Simple Filter Extension".localized, storyboard: "SimpleFilter", controller: "SimpleFilter"),
4343
MenuItem(name: "Quick Switch Channel".localized, controller: "QuickSwitchChannel"),

0 commit comments

Comments
 (0)