簡體   English   中英

如何解決在使用 iphone 4s、ipad 2 以 60fps 錄制視頻時出現的問題?

[英]How to resolve the issue while recording a video at 60fps with iphone 4s, ipad 2?

問題簡而言之:

嘗試以 59fps 錄制時出現異常。 如何解決?

2014-09-16 15:16:27.740 RosyWriter[2294:60b] ** 由於未捕獲的異常“NSInvalidArgumentException”而終止應用程序,原因:“接收方的活動格式不支持傳遞的 activeVideoMaxFrameDuration。 使用 -activeFormat.videoSupportedFrameRateRanges 來發現有效范圍。

我的問題詳細:

我正在嘗試做什么?

嘗試以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]; }}

但是我得到的視頻是用 bestFrameRateRange 以 30fps 錄制的,但不是以 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];
    }
}

這里得到答案

您應該將有效格式設置為AVCaptureDevice

你可以這樣做

// get device what you like
let device = xxxxx

// list all default formats for this device
for format in device.formats {
    var founded = false

    // check what you want and pick a perfect format. 
    let formatDesc = format.formatDescription

    // mediaType / SubType
    let mediaType = format.mediaSubType
    // if your target is above(equal) iOS 13. use formatDesc.mediaSubType
    let mediaSubType = CMFormatDescriptionGetMediaSubType(formatDesc) 

    // dimensions
    // if your target is above(equal) iOS 13. use formatDesc.dimensions
    let dimensions = CMVideoFormatDescriptionGetDimensions(formatDesc) 

    // fps
    let ranges = format.videoSupportedFrameRateRanges.first
    for supportedFPSRange in ranges {
        if supportedFPSRange.maxFrameRate == 60 {
            founded = true
        }
    }

    // support Multi cam
    let isMultiCamSupported = format.isMultiCamSupported

    ....

    if founded {
        // Set activeFormat for device! Your capture device is up and loaded.
        do {
            try device.lockForConfiguration()
            device.activeFormat = format
            device.unlockForConfiguration()
        } catch {
            // catch some locking error
        }

        // Don't forget break the loop.:p
        break
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM