2014-04-06 21 views
6

Tôi đang sử dụng AVCaptureStillImageOutput hiện có bị ràng buộc với AVCaptureSession để tải hình ảnh tĩnh. Sau đó, tôi cần phải ghi chúng vào AVAssetWriter và cuối cùng nhận được tệp video chứa đầy khung hình trong khoảng thời gian 1 giây.AVAssetWriter bỏ qua giá trị chuyển đổi

Mọi thứ hoạt động tốt trừ thứ nguyên video đầu ra ở chế độ dọc. Khi thiết bị ở chế độ ngang - mọi thứ đều ổn, vì captureStillImageAsynchronouslyFromConnection tạo CMSampleBuffer với kích thước 1920x1080 (ví dụ), nhưng khi thiết bị ở chế độ dọc, nó vẫn tạo ra CMSampleBuffer xoay với cùng kích thước (1920x1080). Tôi có thể xoay video đầu ra cuối cùng bằng thuộc tính .transform của AVAssetWriterInput và nó hoạt động tốt, nhưng video cuối cùng có kích thước sai (1920x1080), nhưng phải là 1080x1920.

Tôi đã tìm ra sự cố đó là trong captureStillImageAsynchronouslyFampleampleBuffer của CMS kết nối, luôn có kích thước ngang. Sau đó, đầu vào của AVAssetWriter bỏ qua chiều rộng và chiều cao được cấu hình và sử dụng kích thước của CMSampleBuffer.

Có ai biết cách khắc phục điều đó không?

CHÚ Ý: Tôi biết rằng có thể xoay bộ đệm đã chụp với các chức năng đồ họa vImage hoặc lõi đồ họa, nhưng tôi muốn tránh phương pháp này do cân nhắc hiệu suất. Vấn đề của tôi trông giống như vấn đề cấu hình hoặc lỗi trong iOS ...

- (void) setupLongLoopWriter 
{ 
self.currentFragment.filename2 = [VideoCapture getFilenameForNewFragment]; 
NSString *path = [NSString stringWithFormat:@"%@/%@", [GMConfig getVideoCapturesPath], self.currentFragment.filename2]; 

CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(self.currentCamera.activeFormat.formatDescription); 

CGSize videoWriterFrameSize = CGSizeMake(dimensions.width, dimensions.height); 

float rotationAngle = 0.0; 

switch ((UIDeviceOrientation)[self.currentFragment.orientation unsignedIntValue]) 
{ 
    case UIDeviceOrientationUnknown: 
    case UIDeviceOrientationPortrait: 
    case UIDeviceOrientationFaceUp: 
    case UIDeviceOrientationFaceDown: 
     rotationAngle = DEGREES_TO_RADIANS(90); 
     videoWriterFrameSize = CGSizeMake(dimensions.height, dimensions.width); 
     break; 

    case UIDeviceOrientationPortraitUpsideDown: 
     rotationAngle = DEGREES_TO_RADIANS(-90.0); 
     videoWriterFrameSize = CGSizeMake(dimensions.height, dimensions.width); 
     break; 

    case UIDeviceOrientationLandscapeLeft: 
     rotationAngle = 0.0; 
     break; 

    case UIDeviceOrientationLandscapeRight: 
     rotationAngle = DEGREES_TO_RADIANS(180.0); 
     break; 
} 

    // NSLog(@"%.0fx%.0f", videoWriterFrameSize.width, videoWriterFrameSize.height); 

NSError *error = nil; 

self.currentFragment.longLoopWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] 
                 fileType:AVFileTypeQuickTimeMovie 
                  error:&error]; 
NSParameterAssert(self.currentFragment.longLoopWriter); 

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           AVVideoCodecH264, AVVideoCodecKey, 
           AVVideoScalingModeResizeAspect, AVVideoScalingModeKey, 
           [NSNumber numberWithInt:videoWriterFrameSize.width], AVVideoWidthKey, 
           [NSNumber numberWithInt:videoWriterFrameSize.height], AVVideoHeightKey, 
           nil]; 

AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo 
                    outputSettings:videoSettings]; 
writerInput.expectsMediaDataInRealTime = YES; 

if (rotationAngle != 0.0) 
    writerInput.transform = CGAffineTransformMakeRotation (rotationAngle); 


NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 
                 [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil]; 

self.currentFragment.longLoopWriterAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary]; 

NSParameterAssert(writerInput); 
NSParameterAssert([self.currentFragment.longLoopWriter canAddInput:writerInput]); 


[self.currentFragment.longLoopWriter addInput:writerInput]; 

if([self.currentFragment.longLoopWriter startWriting] == NO) 
    NSLog(@"Failed to start long loop writing!"); 

[self.currentFragment.longLoopWriter startSessionAtSourceTime:kCMTimeZero]; 
} 

- (void) captureLongLoopFrame 
{ 
if ([GMConfig sharedConfig].longLoopFrameDuration == 0.0) { 
    [self.longLoopCaptureTimer invalidate]; 
    self.longLoopCaptureTimer = nil; 

    return; 
} 

if (self.captureSession.isRunning == NO || self.currentFragment.longLoopWriterAdaptor == nil) 
    return; 

[self.shutterOutput captureStillImageAsynchronouslyFromConnection:[self.shutterOutput.connections objectAtIndex:0] 
               completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { 
    if (imageDataSampleBuffer != NULL && error == nil) { 
     /* 
     CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(CMSampleBufferGetFormatDescription(imageDataSampleBuffer)); 
     CGSize videoWriterFrameSize = CGSizeMake(dimensions.width, dimensions.height); 

     NSLog(@"Image buffer size: %.0fx%.0f", videoWriterFrameSize.width, videoWriterFrameSize.height); 
     */ 

     double offset = [[NSDate date] timeIntervalSinceDate:self.currentFragment.start]; 
     CMTime presentationTime = CMTimeMake(offset*1000, 1000); 

     CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(imageDataSampleBuffer); 




     if (self.currentFragment.longLoopWriterAdaptor.assetWriterInput.readyForMoreMediaData == YES) { 
      if([self.currentFragment.longLoopWriterAdaptor appendPixelBuffer:imageBuffer withPresentationTime:presentationTime] == NO) { 
       NSLog(@"Error adding frame to long loop!"); 
      } 
     } 

     NSLog(@"Long loop updated at %0.1f", CMTimeGetSeconds(presentationTime)); 
    } 
}]; 
} 
+0

Bạn đã tìm thấy giải pháp chưa? – tna0y

+0

Bạn đã kiểm tra xem định hướng có đang được phát hiện đúng không? Bạn có thể kiểm tra [[UIDevice currentDevice] orientation] nếu nó không được phát hiện đúng cách. – Rami

+0

là tính năng này hoạt động tốt cho các khung hình ngang và không chỉ cho các khung hình dọc? Hay đó là cách khác? – uchiha

Trả lời

1

tôi ghi lại ở chế độ dọc chỉ và tôi đã có thể để tránh vấn đề này bằng cách nhận dữ liệu pixel xoay trực tiếp từ máy ảnh sử dụng setVideoOrientation trên AVCaptureConnection để chuyển đến AVAssetWriter (xem https://developer.apple.com/library/ios/qa/qa1744/_index.html)

for (AVCaptureConnection *connection in [videoOutput connections]) { 
      for (AVCaptureInputPort *port in [connection inputPorts]) { 
       if ([[port mediaType] isEqual:AVMediaTypeVideo]) { 

        [connection setVideoOrientation:AVCaptureVideoOrientationPortrait]; 

       } 
      } 
} 
+0

Bạn đã so sánh việc chụp ảnh bằng AVCaptureStillImageOutput và chỉ cố gắng trích xuất ảnh tĩnh từ video (có lẽ bạn đang tạo bằng AVAssetWriter)? – Crashalot

Các vấn đề liên quan