美文网首页
Replaykit 日志/文件获取问题

Replaykit 日志/文件获取问题

作者: Cocojiang | 来源:发表于2021-05-27 09:46 被阅读0次

    关于Replaykit日志/写入文件的问题的问题.

    1.replaykit写入的文件怎么获取...

    思路:利用Appgroup. 先把文件写入到沙盒,然后在扩展还在运行的时候,把扩展的日志copy到沙盒.
    扩展代码:

    #import <Foundation/Foundation.h>
    #import <AVFoundation/AVFoundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface TImage : NSObject
    
    @property(nonatomic, assign) NSTimeInterval lastTime;
    @property(nonatomic, assign) BOOL isBG;
    
    + (void)saveToImage:(CMSampleBufferRef)sampleBuffer;
    + (void)saveToFile:(NSString *)fileName;
    + (void)savePixel:(CMSampleBufferRef)sampleBuffer;
    + (void)stopFile;
    
    @end
    
    #import "TImage.h"
    #import <UIKit/UIKit.h>
    #import <CoreFoundation/CoreFoundation.h>
    
    static NSFileHandle *fielHandle11 = nil;
    static NSURL *fileWriteUrl = nil;
    static NSInteger imageCount = 0;
    
    
    @implementation TImage
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                            (__bridge const void *)(self),
                                            onDarwinReplayKit2PushStart,
                                            CFSTR("ddd"),
                                            NULL,
                                            CFNotificationSuspensionBehaviorDeliverImmediately);
    
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleReplayKit2PushStartNotification:) name:@"Cocoa_ReplayKit2_Push_Start" object:nil];
        }
        return self;
    }
    
    static void onDarwinReplayKit2PushStart(CFNotificationCenterRef center,
                                          void *observer, CFStringRef name,
                                          const void *object, CFDictionaryRef
                                          userInfo)
    {
    //转到 cocoa 层框架处理
      [[NSNotificationCenter defaultCenter] postNotificationName:@"Cocoa_ReplayKit2_Push_Start" object:nil];
    }
    
    - (void)handleReplayKit2PushStartNotification:(NSNotification*)noti
    {
        NSLog(@"lasttime begin");
        self.lastTime = [NSDate timeIntervalSinceReferenceDate];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
              //2.0秒后追加任务代码到主队列,并开始执行
            self.lastTime = 0;
              NSLog(@"lasttime end");
          });
        
        self.isBG = !self.isBG;
    
    }
    
    + (void)saveToImage:(CMSampleBufferRef)sampleBuffer {
        
        if (imageCount > 0) {
            [fielHandle11 closeFile];
            return;
        }
        CVImageBufferRef buffer;
        buffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        UIImage *image = [[self class] CVPixelBufferToImage:buffer rotation:0];
        NSData *data = UIImageJPEGRepresentation(image, 1);
        [fielHandle11 writeData:data];
        [fielHandle11 seekToEndOfFile];    
    }
    
    + (UIImage *)CVPixelBufferToImage:(CVPixelBufferRef)pixelBuffer rotation:(int)rotation {
        size_t width, height;
        CGImagePropertyOrientation orientation;
        switch (rotation) {
            case 0:
                width = CVPixelBufferGetWidth(pixelBuffer);
                height = CVPixelBufferGetHeight(pixelBuffer);
                orientation = kCGImagePropertyOrientationUp;
                break;
            case 90:
                width = CVPixelBufferGetHeight(pixelBuffer);
                height = CVPixelBufferGetWidth(pixelBuffer);
                orientation = kCGImagePropertyOrientationRight;
                break;
            case 180:
                width = CVPixelBufferGetWidth(pixelBuffer);
                height = CVPixelBufferGetHeight(pixelBuffer);
                orientation = kCGImagePropertyOrientationDown;
                break;
            case 270:
                width = CVPixelBufferGetHeight(pixelBuffer);
                height = CVPixelBufferGetWidth(pixelBuffer);
                orientation = kCGImagePropertyOrientationLeft;
                break;
            default:
                return nil;
        }
        CIImage *coreImage = [[CIImage imageWithCVPixelBuffer:pixelBuffer] imageByApplyingOrientation:orientation];
        CIContext *temporaryContext = [CIContext contextWithOptions:nil];
        CGImageRef videoImage = [temporaryContext createCGImage:coreImage
                                                       fromRect:CGRectMake(0, 0, width, height)];
        
        
        UIImage *finalImage = [[UIImage alloc] initWithCGImage:videoImage];
        CGImageRelease(videoImage);
        return finalImage;
    }
    
    + (void)saveToFile:(NSString *)sourcePath {
        
    //    NSFileManager * fileManager = [NSFileManager defaultManager];
    //    [fileManager createFileAtPath:sourcePath contents:nil attributes:nil];
        
        NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"你们的APPGroup"];
        NSURL *fileURL = [groupURL URLByAppendingPathComponent:@"Library/Caches/system.yuv"]; //Library/Caches/system.yuv
        NSLog(@"%@", fileURL.path);
        
    
         //写入文件
    //     [@"text" writeToURL:fileURL atomically:YES encoding:NSUTF8StringEncoding error:nil];
    //    NSData *data = [@"fuck you111" dataUsingEncoding:NSUTF8StringEncoding];
    //    [data writeToURL:fileURL atomically:YES];
        
    
        NSFileManager * fileManager = [NSFileManager defaultManager];
        [fileManager createFileAtPath:fileURL.path contents:nil attributes:nil];
    
        NSFileHandle *fielHandle = [NSFileHandle fileHandleForUpdatingAtPath:fileURL.path];
        fielHandle11 = fielHandle;
        [fielHandle seekToEndOfFile];
    
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(50 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
              //2.0秒后追加任务代码到主队列,并开始执行
              //打印当前线程
            [self stopFile];
              NSLog(@"stop saving to file");
          });
    }
    + (void)stopFile {
        imageCount = 1;
    }
    
    + (void)savePixel:(CMSampleBufferRef)sampleBuffer {
        
        if (imageCount > 0) {
            [fielHandle11 closeFile];
            return;
        }
        
        CVImageBufferRef texBuf = CMSampleBufferGetImageBuffer(sampleBuffer);
        
        const int kFlags = 0;
        if (CVPixelBufferLockBaseAddress(texBuf, kFlags) != kCVReturnSuccess) {
            printf("failed to lock base address\n");
            return;
        }
        
        const int kYPlaneIndex = 0;
        const int kUVPlaneIndex = 1;
        uint8_t* ybuf          = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(texBuf, kYPlaneIndex);
        int yPlaneBytesPerRow  = (int)CVPixelBufferGetBytesPerRowOfPlane(texBuf, kYPlaneIndex);
        int yPlaneWidth        = (int)CVPixelBufferGetWidthOfPlane      (texBuf, kYPlaneIndex);
        int yPlaneHeight       = (int)CVPixelBufferGetHeightOfPlane     (texBuf, kYPlaneIndex);
        uint8_t* cbuf          = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(texBuf, kUVPlaneIndex);
        int uvPlaneBytesPerRow = (int)CVPixelBufferGetBytesPerRowOfPlane(texBuf, kUVPlaneIndex);
        
        NSLog(@"%@, %@, %@, %@", @(yPlaneBytesPerRow), @(yPlaneWidth), @(yPlaneHeight), @(uvPlaneBytesPerRow));
        NSData *data = [NSData dataWithBytes:ybuf length:yPlaneHeight * yPlaneBytesPerRow];
        
        [fielHandle11 writeData:data];
        [fielHandle11 seekToEndOfFile];
        data = [NSData dataWithBytes:cbuf length:yPlaneHeight * uvPlaneBytesPerRow / 2];
        [fielHandle11 writeData:data];
        [fielHandle11 seekToEndOfFile];
        CVPixelBufferUnlockBaseAddress(texBuf, kFlags);
    }
    

    因为我是录屏写入buffer 数据的,所以,我在录屏开始的时候调用了

    saveToFile
    

    然后我在每一帧回调的时候都调用了.起到保存每一帧的问题..

    + (void)savePixel:(CMSampleBufferRef)sampleBuffer
    

    延时结束是因为录制的yuv 数据很大.我们在实际开发者中可根据这个做修改.
    最后在主进程进行文件的copy动作.切记 一定要扩展进程活跃的时候执行copy
    最好是在主进程写一个按钮,点一下这个按钮就执行copy的动作!

    -(void)copyBufferFile{
        NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"你们的APPgroupID"];
        NSString *fileURL = [groupURL URLByAppendingPathComponent:@"Library/Caches/system.yuv"].path;
        BOOL a =   [[NSFileManager defaultManager] fileExistsAtPath:fileURL isDirectory:nil];
        if (!a) {
            return;
        }
        NSString *distDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
        NSString * dispatch = [NSString stringWithFormat:@"%@/system.yuv",distDirectory];
        [[NSFileManager defaultManager]removeItemAtPath:dispatch error:nil];
        NSError *error = nil;
        [[NSFileManager defaultManager]moveItemAtPath:fileURL toPath:dispatch error:&error];
        if (error) {
            NSLog(@"%@",error);
        }
    }
    

    这样就可以在主进程的沙盒文件拿到扩展进程的日志或者资源了.另说一句.Replaykit 有很多坑.后续我会慢慢整理出来. 因为就2个文件,就不上传git了.大佬们见谅一下.不过代码我已经完整的贴出来了.至于APPGroup 怎么搞,顺便说一句
    选中项目的 targets 然后 点击 +capability 然后选择 appGroup 即可 图就不截了

    相关文章

      网友评论

          本文标题:Replaykit 日志/文件获取问题

          本文链接:https://www.haomeiwen.com/subject/nxersltx.html