From 7b3ecfffc59d2d980d9f7628365b64c20fe015be Mon Sep 17 00:00:00 2001
From: Runt <qingingrunt2010@qq.com>
Date: Sun, 27 Jul 2025 09:42:03 +0000
Subject: [PATCH] 多个小窗缩放问题修复

---
 LiveProject/activity/stream/LiveViewModel.swift |  148 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/LiveProject/activity/stream/LiveViewModel.swift b/LiveProject/activity/stream/LiveViewModel.swift
index e69de29..bb31219 100644
--- a/LiveProject/activity/stream/LiveViewModel.swift
+++ b/LiveProject/activity/stream/LiveViewModel.swift
@@ -0,0 +1,148 @@
+//
+//  LiveViewModel.swift
+//  LiveProject
+//
+//  Created by 倪路朋 on 6/27/25.
+//
+import UIKit
+import AVFoundation
+
+class LiveViewModel: ObservableObject {
+    @Published var pixelBuffer: CVPixelBuffer?
+    
+    //let encoder = H264Encoder(width: 1080, height: 1920, fps: 30, bitrate: 1_000_000)
+    var frameIndex: Int64 = 0
+    //let encodeQueue = DispatchQueue(label: "encoder.queue")
+
+    lazy var camera = CameraCapture()
+    var timestamp = Int(Date().timeIntervalSince1970 * 1000)
+    
+    func newWindowAction(minidata:MiniWindowData,completion: @escaping (Bool) -> Void = {b in}){
+        switch minidata.streamType{
+        case StreamType.CAMERA:
+            requestCameraPermission(mediaType: .video){ staus in
+                if(staus){
+                    var ts1 =  Int(Date().timeIntervalSince1970 * 1000)
+                    self.camera.onFrame = {  [weak self]  buffer in
+                        guard let self = self else { return }
+
+                        let width = CVPixelBufferGetWidth(buffer)
+                        let height = CVPixelBufferGetHeight(buffer)
+
+                        guard width > 0 && height > 0 else {
+                            print("Invalid pixel buffer size: \(width)x\(height)")
+                            return
+                        }
+                        if(minidata.size.width != CGFloat(width) || minidata.size.height != CGFloat(height)){
+                            minidata.size = CGSize(width:width,height:height);
+                        }
+                        self.frameIndex += 1
+                        let ts =  Int(Date().timeIntervalSince1970 * 1000)
+
+                        self.timestamp = ts;
+                        let cmTime = CMTimeMake(value: Int64(CACurrentMediaTime() * 1000), timescale: 1000);
+                        //self.encoder.encode(pixelBuffer: buffer, pts: cmTime)
+                        DispatchQueue.main.async {
+                            minidata.pixelBuffer = buffer;
+                            
+                        }
+                        //print("画面更新")
+                    }
+                    DispatchQueue.global(qos: .userInitiated).async {
+                        self.camera.start()
+                    }
+                    print("启动相机")
+                    /*self.encoder.onEncoded = { (data: Data, ctime: CMTime, isKey: Bool) in
+                        let timestamp2 = Int(Date().timeIntervalSince1970 * 1000)
+                        print("编码时间2 \(timestamp2 - self.timestamp)")
+                        print("Encoded NALU size: \(data.count), key frame: \(isKey)")
+
+                    }*/
+                }else{
+                    
+                }
+                completion(staus)
+            }
+            break;
+        default:
+            completion(true)
+            break;
+        }
+    }
+    
+    func closeWindowAction(miniData:MiniWindowData){
+        switch miniData.streamType{
+        case StreamType.CAMERA:
+            print("关闭相机")
+            camera.stop();
+            break;
+        default:
+            break;
+        }
+    }
+    
+    
+    
+    func requestCameraPermission(mediaType: AVMediaType,completion: @escaping (Bool) -> Void) {
+        let status = AVCaptureDevice.authorizationStatus(for: mediaType)
+        switch status {
+        case .authorized:
+            completion(true)
+        case .notDetermined:
+            AVCaptureDevice.requestAccess(for: .video) { granted in
+                DispatchQueue.main.async {
+                    completion(granted)
+                }
+            }
+        default:
+            // denied / restricted
+            completion(false)
+        }
+    }
+    
+    func copyPixelBuffer(_ src: CVPixelBuffer) -> CVPixelBuffer? {
+        let width = CVPixelBufferGetWidth(src)
+        let height = CVPixelBufferGetHeight(src)
+        let pixelFormat = CVPixelBufferGetPixelFormatType(src)
+
+        var dst: CVPixelBuffer?
+        let attrs: [String: Any] = [
+            kCVPixelBufferIOSurfacePropertiesKey as String: [:]
+        ]
+
+        let status = CVPixelBufferCreate(
+            kCFAllocatorDefault,
+            width,
+            height,
+            pixelFormat,
+            attrs as CFDictionary,
+            &dst
+        )
+
+        guard status == kCVReturnSuccess, let dstBuffer = dst else {
+            print("❌ 复制 PixelBuffer 失败")
+            return nil
+        }
+
+        CVPixelBufferLockBaseAddress(src, .readOnly)
+        CVPixelBufferLockBaseAddress(dstBuffer, [])
+
+        let planeCount = CVPixelBufferGetPlaneCount(src)
+        for i in 0..<planeCount {
+            let srcAddr = CVPixelBufferGetBaseAddressOfPlane(src, i)
+            let dstAddr = CVPixelBufferGetBaseAddressOfPlane(dstBuffer, i)
+
+            let height = CVPixelBufferGetHeightOfPlane(src, i)
+            let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(src, i)
+
+            memcpy(dstAddr, srcAddr, height * bytesPerRow)
+        }
+
+        CVPixelBufferUnlockBaseAddress(src, .readOnly)
+        CVPixelBufferUnlockBaseAddress(dstBuffer, [])
+
+        return dstBuffer
+    }
+    
+
+}

--
Gitblit v1.9.1