I'm trying to understand how a CALayer (AVSampleBufferDisplayLayer, specifically) can adjust its scaling to fit within the bounds of a UIView I've added it to. I'm working on a project that uses a C++ library to write data into CMSampleBuffer and enqueue those to be displayed by a AVSampleBufferDisplayLayer. I'm using SwiftUI to do the frontend code, so the UIView is being wrapped to allow for that.
The problem I'm having is that the UIView scales down to fit within the screen correctly, but the CALayer that is added to it does not scale to match the view, and therefore most of the video that's being played runs outside the bounds of the view and ends up being clipped by the iPhone screen.
My goal is to have the CALayer scale to fill whatever the bounds of the view its in are, so that I can shrink or enlarge the view and the video playing in the CALayer scales to match.
I'm creating the view with the following:
struct VideoPlayer: UIViewRepresentable {
var player: AVSampleBufferDisplayLayer
var view: some UIView {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 1920, height: 1080))
player.frame = view.bounds
player.bounds = view.bounds
player.videoGravity = .resizeAspect
view.layer.addSublayer(player)
return view
}
func makeUIView(context: Context) -> UIView {
return view
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
}
And setting it up with this code so that it regularly calls the library function to fill the buffers with new data:
struct VideoView: View {
let timer = Timer.publish(every: 0.015, on: .main, in: .common).autoconnect()
var body: some View {
let sampleLayer = AVSampleBufferDisplayLayer()
let player = VideoPlayer(player: sampleLayer)
return player.onReceive(timer) { _ in
let buffer = retrieve_video_buffers()
if buffer != nil {
player.player.enqueue(buffer!)
}
}
}
}
Lastly, to display the view in SwiftUI, I'm using the following.
struct ContentView: View {
var body: some View {
VStack {
VideoView()
.aspectRatio(CGSize(width: 1920, height: 1080),
contentMode: ContentMode.fit)
}
}
}
To see where the clipping is happening, I added background colors to the UIView and CALayer. The UIView is green, and the CALayer is pink.
iPhone Simulator in Portrait mode showing CALayer extending past View bounds
iPhone Simulator in Landscape mode showing CALayer extending past View bounds
Any help at all is appreciated! I feel quite stuck being unable to figure this out.