首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >iOS广播上传扩展、框架与应用程序之间的通信

iOS广播上传扩展、框架与应用程序之间的通信
EN

Stack Overflow用户
提问于 2020-02-18 23:09:32
回答 2查看 3K关注 0票数 4

我有一个ViewController.swiftBroadcast Upload app Extension的示例应用程序。在我的项目中,我创建了两个框架:

  1. MySDK,是一个快速的框架,用于分析和处理CMSampleBuffer,以避免广播应用程序扩展占用太多内存。这个SDK有一个单例、一个变量func analyzeSampleBuffer(_ sampleBuffer: CMSampleBuffer)
  2. Broadcaster,、函数func initializefunc initialize,它是一个快速的框架,用于调用MySDK调用来分析和处理CMSampleBuffer (是的,听起来像是与MySDK的重复,但我不能这样做,我需要这两个框架)。此SDK具有单例功能,并具有以下功能:func processSampleBuffer(_ sampleBuffer: CMSampleBuffer)

func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?)

在这个项目中,我添加了一个名为Broadcast Upload App ExtensionBroadcastExtension。在他的主文件SampleHandler.swift中,在processSampleBuffer函数中,我使用我的Broadcaster SDK提供从应用程序扩展到Broadcaster SDK的响应性,以及从应用程序扩展名:Broadcaster.shared.processSampleBuffer(sampleBuffer)接收到的MySDK到流CMSampleBuffer的响应能力。最后,MySDK成功地分析和处理了CMSampleBuffer,但是我的广播上传应用程序扩展占用了太多的内存,并且在屏幕共享后的X分钟后崩溃(应用程序扩展最大50 max )。如何在应用程序扩展时使用更少的内存?

这是我的档案:

MySDK.swift:

代码语言:javascript
运行
复制
import Foundation
import ReplayKit

@objcMembers public class MySDK {
    public static let shared = MySDK()
    public var isReady = false

    public func initialize() {
        // Init SDK
    }

    public func analyzeSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
        // Analyze
    }
}

Broadcaster.swift:

代码语言:javascript
运行
复制
import Foundation
import ReplayKit
import MySDK

@objcMembers public class Broadcaster: NSObject, Codable {
    public static let shared = Broadcaster()

    public func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
        MySDK.shared.isReady = true
    }

    public func processSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
        if MySDK.shared.isReady {
            MySDK.shared.analyzeSampleBuffer(sampleBuffer)
        }
    }
}

SampleHandler.swift:

代码语言:javascript
运行
复制
import ReplayKit
import Broadcaster

class SampleHandler: RPBroadcastSampleHandler {

    override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) {
        // User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
        Broadcaster.shared.broadcastStarted(withSetupInfo: setupInfo)
    }

    override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
        switch sampleBufferType {
        case RPSampleBufferType.video:
            // Handle video sample buffer
            Broadcaster.shared.processSampleBuffer(sampleBuffer)
            break
        case RPSampleBufferType.audioApp:
            break
        case RPSampleBufferType.audioMic:
            break
        @unknown default:
            fatalError("Unknown type of sample buffer")
        }
    }
}

我希望在应用程序中使用相同的共享实例,但在应用程序扩展中使用。我试图在应用程序和应用程序扩展之间放置组应用程序,并使用与组id对应的UserdefaultssuiteName来发送共享实例,但是当我在应用程序扩展中接收到时,地址内存就不一样了,从而创建了对象的另一个实例(我希望在应用程序和应用程序扩展之间有一个真正的独立实例)。我不知道如何在应用程序扩展上节省内存,以及如何在两个框架、应用程序扩展和应用程序之间进行通信,以便在项目的每个部分使用相同的单例。

下面是我的项目的层次结构:

EN

回答 2

Stack Overflow用户

发布于 2020-05-21 08:14:29

但是我的广播上传应用程序扩展占用了太多的内存,在屏幕共享后的X分钟就崩溃了(50 max用于应用程序扩展)。如何在应用程序扩展时使用更少的内存?

避免广播上传扩展中的繁重计算和50 to内存限制的一种方法是在AVAssetWriter中使用SampleHandler,当它完成时您只需关闭它。之后,您可以使用共享文件夹从AVAssetWriter复制(视频/音频)。

代码语言:javascript
运行
复制
NSURL* url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"your group name"];

NSString* sharedVideoPath = [NSString stringWithFormat:@"%@/video.mp4", url.path];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSError* error;
if([fileManager moveItemAtPath:PATH_TO_FILE_FROM_AVASSETWRITER toPath:sharedVideoPath error:&error])
{
    NSLog(@"Successfully moved to shared folder!");
}

在此之后,您只需使用NSUserDefaults告诉主应用程序sharedVideoPath和主应用程序将能够访问它。

票数 1
EN

Stack Overflow用户

发布于 2021-08-23 20:18:28

如果您只需要将屏幕共享视频保存到“文件”中,这是很容易的。您应该在之间进行通信,该框架使用AVAssetWriter将缓冲区保存到共享容器路径( App )。当广播开始并在Sample上发送缓冲区时,只需在广播停止时将缓冲区传递到AVAssetWriter中,然后使用finishWriting AVAssetWriter完成写入。如果您想了解BroadCastExtension中的视频状态或进程,可以使用日志管理器将日志写入共享容器。例如:

代码语言:javascript
运行
复制
    func append(_ sample: CMSampleBuffer, with bufferType: RPSampleBufferType) -> Bool {
    
    guard self.state == .recording else{return false}
    
    guard assetWriter != nil else{return false}
    
    guard sample.isReady else {
        LogManager.shared.e(self,"Buffer Data Is not Ready")
        return true
    }
    
    LogManager.shared.i(self,"Assets Writer Status : \(assetWriter.status.description)")
    
    switch assetWriter.status {
    case .failed:
        LogManager.shared.e(self,"Error occured, status = \(assetWriter.status), \(assetWriter.error!.localizedDescription) \(String(describing: assetWriter.error))")
        return false
    default:
        break
    }
    
    switch bufferType{
    
    case .video:
        self.lastVideoTime = sample.time
        if let lastSampleBuffer = self.lastSampleBuffer {
            videoInput.appendIfPossible(lastSampleBuffer.with(updated: sample.time))
        }
    case .audioMic:
        if self.audioEnabled{
            micInput.appendIfPossible(lastVideoTime != nil ? sample.with(updated: lastVideoTime) : sample)
        }
        
    case .audioApp:
        if self.audioEnabled{
            audioInput.appendIfPossible(lastVideoTime != nil ? sample.with(updated: lastVideoTime) : sample)
        }
    @unknown default:
        LogManager.shared.e(self,"Unkown buffer type")
    }
    return true
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60290757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档