LiveProject/data/DeviceInfo.swift | patch | view | raw | blame | history | |
LiveProject/enum/StreamType.swift | patch | view | raw | blame | history | |
LiveProject/shape/IconBack.swift | ●●●●● patch | view | raw | blame | history | |
LiveProject/tool/MetalRenderer.swift | ●●●●● patch | view | raw | blame | history | |
LiveProject/views/FlowLayout.swift | ●●●●● patch | view | raw | blame | history | |
LiveProject/views/TitleBarView.swift | ●●●●● patch | view | raw | blame | history | |
LiveProject/views/VideoRendererView.swift | ●●●●● patch | view | raw | blame | history |
LiveProject/data/DeviceInfo.swift
LiveProject/enum/StreamType.swift
LiveProject/shape/IconBack.swift
New file @@ -0,0 +1,8 @@ // // IconBack.swift // LiveProject // // Created by 倪路朋 on 6/26/25. // import Foundation LiveProject/tool/MetalRenderer.swift
New file @@ -0,0 +1,78 @@ // // Renderer.swift // LiveProject // 渲染工具 // Created by 倪路朋 on 6/26/25. // import Metal import MetalKit class Renderer: NSObject, MTKViewDelegate { static var shared: Renderer? private var device: MTLDevice! private var commandQueue: MTLCommandQueue! private var pipelineState: MTLRenderPipelineState! private var texture: MTLTexture? private var textureDescriptor: MTLTextureDescriptor! private var currentData: [UInt8]? private var textureWidth = 0 private var textureHeight = 0 weak var mtkView: MTKView? { didSet { guard let view = mtkView else { return } device = view.device commandQueue = device.makeCommandQueue() let library = device.makeDefaultLibrary() let pipelineDesc = MTLRenderPipelineDescriptor() pipelineDesc.vertexFunction = library?.makeFunction(name: "vertexShader") pipelineDesc.fragmentFunction = library?.makeFunction(name: "fragmentShader") pipelineDesc.colorAttachments[0].pixelFormat = view.colorPixelFormat pipelineState = try? device.makeRenderPipelineState(descriptor: pipelineDesc) Renderer.shared = self } } func updateFrame(data: [UInt8], width: Int, height: Int) { currentData = data textureWidth = width textureHeight = height } func draw(in view: MTKView) { guard let drawable = view.currentDrawable, let descriptor = view.currentRenderPassDescriptor, let data = currentData else { return } if texture == nil || texture?.width != textureWidth || texture?.height != textureHeight { textureDescriptor = MTLTextureDescriptor.texture2DDescriptor( pixelFormat: .rgba8Unorm, width: textureWidth, height: textureHeight, mipmapped: false ) textureDescriptor.usage = [.shaderRead, .shaderWrite] texture = device.makeTexture(descriptor: textureDescriptor) } let region = MTLRegionMake2D(0, 0, textureWidth, textureHeight) data.withUnsafeBytes { ptr in texture?.replace(region: region, mipmapLevel: 0, withBytes: ptr.baseAddress!, bytesPerRow: textureWidth * 4) } let commandBuffer = commandQueue.makeCommandBuffer() let encoder = commandBuffer?.makeRenderCommandEncoder(descriptor: descriptor) encoder?.setRenderPipelineState(pipelineState) encoder?.setFragmentTexture(texture, index: 0) encoder?.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4) encoder?.endEncoding() commandBuffer?.present(drawable) commandBuffer?.commit() } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} } LiveProject/views/FlowLayout.swift
New file @@ -0,0 +1,7 @@ // // Untitled.swift // LiveProject // // Created by 倪路朋 on 6/26/25. // LiveProject/views/TitleBarView.swift
New file @@ -0,0 +1,44 @@ // // TitleBarView.swift // aones // // Created by 倪路朋 on 2/16/23. // import SwiftUI struct TitleBarView: View { @Environment(\.presentationMode) var presentationMode var title = "" var imgLeft = "IconBack"; var imgRight = ""; var titleColor = "ColorText" var body: some View { HStack(spacing: 0){ Spacer().frame(width: 16) Button(action: { print("Click back button") self.presentationMode.wrappedValue.dismiss() }) { Image(imgLeft) .frame(width: 28,height: 28) } Spacer() Text(title).foregroundColor(Color.init(titleColor)) .bold().font(Font.system(size: 16)) Spacer() Image(imgRight).frame(width: 28,height: 28) Spacer().frame(width: 16) }.frame(height: 48) } } struct TitleBarView_Previews: PreviewProvider { static var previews: some View { TitleBarView(title: "标题") } } LiveProject/views/VideoRendererView.swift
New file @@ -0,0 +1,63 @@ // // MetalVideoView.swift // LiveProject // 视频绘制 // Created by 倪路朋 on 6/26/25. // import SwiftUI import MetalKit struct MetalVideoRenderView: UIViewRepresentable { // 统一接口,接收各种视频源的帧数据 var frameData: VideoFrameData? func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> MTKView { let mtkView = MTKView() mtkView.device = context.coordinator.device mtkView.delegate = context.coordinator mtkView.framebufferOnly = false mtkView.colorPixelFormat = .bgra8Unorm mtkView.autoResizeDrawable = true return mtkView } func updateUIView(_ uiView: MTKView, context: Context) { // 更新帧数据 context.coordinator.updateFrame(frameData) } class Coordinator: NSObject, MTKViewDelegate { var parent: MetalVideoRenderView var device: MTLDevice var commandQueue: MTLCommandQueue var pipelineState: MTLRenderPipelineState var textureCache: CVMetalTextureCache? // YUV转RGB的着色器 var yuvConversionPipeline: MTLComputePipelineState? init(_ parent: MetalVideoRenderView) { self.parent = parent self.device = MTLCreateSystemDefaultDevice()! self.commandQueue = device.makeCommandQueue()! // 初始化Metal资源 // (这里需要设置渲染管线和纹理缓存) } func updateFrame(_ frameData: VideoFrameData?) { // 根据不同的帧数据格式(YUV/RGBA)进行处理 // 将数据转换为Metal纹理 } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} func draw(in view: MTKView) { // 执行Metal绘制命令 } } }