ios - 如何解决使用 iphone 4s、ipad 2 以 60fps 录制视频时出现的问题?

标签 ios iphone ipad gpuimage

问题简述:

尝试以 59fps 录制时出现异常。如何解决?

2014-09-16 15:16:27.740 RosyWriter[2294:60b] ** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The activeVideoMaxFrameDuration passed is not supported by the receiver's active format. Use -activeFormat.videoSupportedFrameRateRanges to discover valid ranges.

我的问题详情:

我想做什么?

尝试以 30+ fps(60 fps 或更高 fps)录制视频。

到目前为止我尝试了什么?

  1. 最初尝试使用“AVCaptureConnection”的属性,如下所示,后来了解到我使用的属性已贬值。

AVCaptureConnection *conn = [output connectionWithMediaType:AVMediaTypeVideo];

CMTimeShow(conn.videoMinFrameDuration);
CMTimeShow(conn.videoMaxFrameDuration);

if (conn.isVideoMinFrameDurationSupported)
    conn.videoMinFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
if (conn.isVideoMaxFrameDurationSupported)
    conn.videoMaxFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);

引用: 根据头文件(AVCaptureSession.h),

此属性在 iOS 上已弃用,其中使用 activeVideoMinFrameDuration 和 activeVideoMaxFrameDuration 属性专门在 AVCaptureDevice 上应用最小和最大帧速率调整。

  1. 然后,我尝试使用“AVCaptureDevice”,如下所示:

    -(void)setupCaptureSession
    {
        if ( _captureSession ) {
            return;
        }
    
        _captureSession = [[AVCaptureSession alloc] init];  
    
        AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
      ....................................
      ....................................
    
    _videoConnection = [videoOut connectionWithMediaType:AVMediaTypeVideo];
    
    int frameRate;
    NSString *sessionPreset = AVCaptureSessionPreset640x480;
    CMTime frameDuration = kCMTimeInvalid;
    // For single core systems like iPhone 4 and iPod Touch 4th Generation wI 
    //use a lower resolution and framerate to maintain real-time performance.
    if ( [[NSProcessInfo processInfo] processorCount] == 1 )
    {
        if ( [_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720] ) {
            sessionPreset = AVCaptureSessionPreset1280x720;
        }
        frameRate = 59;
    }
    else
    {
        // USE_GPU_RENDERER is set in the project's build settings
     #if ! use_gpu_renderer
        // When using the CPU renderer we lower the resolution to 720p so that all devices can maintain real-time performance (this is primarily for A5 based devices like iPhone 4s and iPod Touch 5th Generation).
        if ( [_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480] ) {
            sessionPreset = AVCaptureSessionPreset640x480;
        }
     #endif // ! use_gpu_renderer
    
        frameRate = 59;
    }
    
    _captureSession.sessionPreset = sessionPreset;
    
    frameDuration = CMTimeMake( 1, frameRate );
    
    
    
    NSError *error = nil;
    
    if ( [videoDevice lockForConfiguration:&error] ) {
        videoDevice.activeFormat = bestFormat;
        [**videoDevice setActiveVideoMaxFrameDuration:frameDuration];
        [videoDevice setActiveVideoMinFrameDuration:frameDuration**];
        [videoDevice unlockForConfiguration];
    }
    else {
        NSLog(@"videoDevice lockForConfiguration returned error %@", error);
    }
    
    self.videoOrientation = [_videoConnection videoOrientation];
    
    [videoOut release];
    
    return;
    

    我的问题:

    1. 我得到了异常

2014-09-16 15:16:27.740 RosyWriter[2294:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The activeVideoMaxFrameDuration passed is not supported by the receiver's active format.  Use -activeFormat.videoSupportedFrameRateRanges to discover valid ranges.'
        *** First throw call stack:
        (0x2da2ff83 0x385d2ccf 0x2c919e4f 0xb4c7d 0xb4317 0x38aba81f 0x38ac07cb 0xb42b1 0xb2539 0x302676df 0x30258e89 0x3025864d 0x302584bf 0x30257fe5 0x30255827 0x302bf33d 0x302bbfad 0x302b656b 0x302526e9 0x30251851 0x302b5ca9 0x3288baed 0x3288b6d7 0x2d9faa67 0x2d9faa03 0x2d9f91d7 0x2d963ebf 0x2d963ca3 0x302b4ed1 0x302b014d 0xb1b4d 0x38adfab7)
        libc++abi.dylib: terminating with uncaught exception of type NSException

我是不是做错了什么?

  1. 后来,我把代码改成了


      AVCaptureDeviceFormat *bestFormat = nil;
      AVFrameRateRange *bestFrameRateRange = nil;
      for ( AVCaptureDeviceFormat *format in [videoDevice formats] ) {
        for ( AVFrameRateRange *range in format.videoSupportedFrameRateRanges ) {
            if ( range.maxFrameRate > bestFrameRateRange.maxFrameRate ) {
                bestFormat = format;
                bestFrameRateRange = range;
            }
        }
    }
    NSError *error = nil;
    
    if ( bestFormat ) {
    if ( [videoDevice lockForConfiguration:&error] ) {
        videoDevice.activeFormat = bestFormat;
        videoDevice.activeVideoMinFrameDuration = bestFrameRateRange.minFrameDuration;
        videoDevice.activeVideoMaxFrameDuration = bestFrameRateRange.maxFrameDuration;
        [videoDevice unlockForConfiguration];
        }}
    

但我得到的视频以 30fps 和 bestFrameRateRange 录制,但不是 59fps..

最佳答案

这是一个如何使用更高帧率的工作示例:

查找并设置事件模式以使用可用的最大帧速率。

float maxFrameRate = 0.0;
int maxIndex = 0;
for(int i=0;i<_videoCaptureDevice.formats.count;i++) {
    AVCaptureDeviceFormat *format = [_videoCaptureDevice.formats objectAtIndex:i];
    AVFrameRateRange *frameRateRange = [format.videoSupportedFrameRateRanges firstObject];
//You can add hard coded checking for specific format like if(frameRateRange.maxFrameRate == 240) etc I am using the max one
    if(maxFrameRate<frameRateRange.maxFrameRate) {
        maxFrameRate = frameRateRange.maxFrameRate;
        maxIndex = i;
    }
}

AVCaptureDeviceFormat *format = [_videoCaptureDevice.formats objectAtIndex:maxIndex];
AVFrameRateRange *frameRateRange = [format.videoSupportedFrameRateRanges firstObject];
[self.videoCaptureDevice lockForConfiguration:nil];
self.videoCaptureDevice.activeFormat = format;
self.videoCaptureDevice.activeVideoMinFrameDuration = frameRateRange.minFrameDuration;
self.videoCaptureDevice.activeVideoMaxFrameDuration = frameRateRange.maxFrameDuration;
[self.videoCaptureDevice  unlockForConfiguration];

然后改变帧率

if(YourFrameRate<=frameRateRange.maxFrameRate && YourFrameRate>=frameRateRange.minFrameRate) {
    if([device lockForConfiguration:&error]) {
        [device setActiveVideoMinFrameDuration:CMTimeMake(1, YourFrameRate)];
        [device setActiveVideoMaxFrameDuration:CMTimeMake(1, YourFrameRate)];
        [device unlockForConfiguration];
    } else {
        [self passError:error];
    }
}

here得到答案

关于ios - 如何解决使用 iphone 4s、ipad 2 以 60fps 录制视频时出现的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25868191/

相关文章:

ios - 将栏按钮项目添加到 View Storyboard 中的导航栏

iphone - iOS 代码签名身份

javascript - 纯 javascript 在 iPad 上拖动不流畅

ios - 为什么 Metal 没有 rgb8Unorm MTLPixelFormat?

ios - 如何使用 XCode 的查找工具查找不是 IBOUtlet 的弱属性?

iphone - 核心图 CPT ScatterPlot 'Line Graph' 未显示

ios - iOS 应用的动态内容

iphone - 如何以编程方式在 iPhone 中创建包含字符串和图像的 .CSV 文件?

php - 如何格式化 PHP 中的列表以用作 Objective C 中的 NSArray?

Android/iOS 设置设备热点IP地址