2

В настоящее время, используя iPhone 5s/6, я могу захватить 120 (iPhone 5) или 240 (iPhone 6) кадров в секунду в CMSampleBufferRef. Однако возвращаемый мне AVCaptureDeviceFormat обеспечивает только эти высокоскоростные частоты кадров с разрешением 1280x720.Capture 120/240 fps с использованием AVCaptureVideoDataOutput в буфер кадра с низким разрешением

Я хотел бы зафиксировать это в нижнем разрешении (640x480 или ниже), так как я буду помещать его в круглый буфер для целей хранения. Хотя я могу уменьшить разрешение в методе делегата didOutputSampleBuffer, я хотел бы знать, есть ли какой-либо способ для CMSampleBufferRef предоставить мне более низкое разрешение непосредственно путем настройки устройства или настройки вместо того, чтобы принимать изображение 720p и опускать с помощью CVPixelBuffer.

Мне нужно сохранить изображения в буфере для последующей обработки и вы хотите применить минимальную обработку, или я начну отбрасывать кадры. Если я могу избежать изменения размера и получить CMSampleBuffer с низким разрешением из метода делегата didOutputSampleBuffer напрямую, это было бы идеально.

При скорости 240 кадров в секунду, мне нужно обработать каждое изображение в течение 5 мс, и процедура изменения размера не сможет идти в ногу с уменьшением масштаба изображения с этой скоростью. Тем не менее, я хотел бы сохранить его в круговой буфер для последующей обработки (например, выписывая фильм с использованием AVAssetWriter), но требуя более низкого разрешения.

Кажется, что единственный размер изображения, поддерживаемый в записи с высокой частотой кадров, составляет 1280x720. Помещение нескольких изображений этого разрешения в буфер кадра вызовет давление памяти, поэтому я хочу захватить изображение с низким разрешением непосредственно из didOutputSampleBuffer, если это вообще возможно сохранить в памяти и не отставать от частоты кадров.

Благодарим за помощь.

ответ

1
// core image use GPU to all image ops, crop/transform/... 

// --- create once --- 
EAGLContext *glCtx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 
CIContext *ciContext = [CIContext contextWithEAGLContext:glCtx options:@{kCIContextWorkingColorSpace:[NSNull null]}]; 
// use rgb faster 3x 
CGColorSpaceRef ciContextColorSpace = CGColorSpaceCreateDeviceRGB(); 
OSType cvPixelFormat = kCVPixelFormatType_32BGRA; 

// create compression session 
VTCompressionSessionRef compressionSession; 
NSDictionary* pixelBufferOptions = @{(__bridge NSString*) kCVPixelBufferPixelFormatTypeKey:@(cvPixelFormat), 
            (__bridge NSString*) kCVPixelBufferWidthKey:@(outputResolution.width), 
            (__bridge NSString*) kCVPixelBufferHeightKey:@(outputResolution.height), 
            (__bridge NSString*) kCVPixelBufferOpenGLESCompatibilityKey : @YES, 
            (__bridge NSString*) kCVPixelBufferIOSurfacePropertiesKey : @{}}; 

OSStatus ret = VTCompressionSessionCreate(kCFAllocatorDefault, 
              outputResolution.width, 
              outputResolution.height, 
              kCMVideoCodecType_H264, 
              NULL, 
              (__bridge CFDictionaryRef)pixelBufferOptions, 
              NULL, 
              VTEncoderOutputCallback, 
              (__bridge void*)self, 
              &compressionSession); 

CVPixelBufferRef finishPixelBuffer; 
// I'm use VTCompressionSession pool, you can use AVAssetWriterInputPixelBufferAdaptor 
CVReturn res = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, VTCompressionSessionGetPixelBufferPool(compressionSession), &finishPixelBuffer); 
// ------------------- 

// ------ scale ------ 
// new buffer comming... 
// - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); 

CIImage *baseImg = [CIImage imageWithCVPixelBuffer:pixelBuffer]; 
CGFloat outHeight = 240; 
CGFloat scale = 1/(CVPixelBufferGetHeight(pixelBuffer)/outHeight); 
CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale); 

// result image not changed after 
CIImage *resultImg = [baseImg imageByApplyingTransform:transform]; 
// resultImg = [resultImg imageByCroppingToRect:...]; 

// CIContext applies transform to CIImage and draws to finish buffer 
[ciContext render:resultImg toCVPixelBuffer:finishPixelBuffer bounds:resultImg.extent colorSpace:ciContextColorSpace]; 
CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); 

// [videoInput appendSampleBuffer:CMSampleBufferCreateForImageBuffer(... finishPixelBuffer...)] 
VTCompressionSessionEncodeFrame(compressionSession, finishPixelBuffer, CMSampleBufferGetPresentationTimeStamp(sampleBuffer), CMSampleBufferGetDuration(sampleBuffer), NULL, sampleBuffer, NULL); 
// ------------------- 
+0

Можете ли вы поделиться этим кодом в качестве образца проекта? Где вы получаете сеанс сжатия в этой строке: 'CVReturn res = CVPixelBufferPoolCreatePixelBuffer (kCFAllocatorDefault, VTCompressionSessionGetPixelBufferPool (compressionSession), & finishPixelBuffer);' –

+0

добавлен сеанс сжатия init –

+0

Спасибо. Возможно ли это использовать на iOS. 'VTEncoderOutputCallback' не распознан в моем проекте xcode. Im не хорошо без надлежащей документации об этом материале редактирования видео. –

 Смежные вопросы

  • Нет связанных вопросов^_^