2012-12-07 46 views
7

Tôi đang cố gắng tạo phim từ một số ảnh. Nó hoạt động tốt với hình ảnh hd ({720, 1280}) hoặc độ phân giải thấp hơn. Nhưng khi tôi cố gắng để tạo ra bộ phim với hình ảnh hd đầy đủ {1080, 1920}, video được tranh giành. Đây là một liên kết để xem nó trông như thế nào http://www.youtube.com/watch?v=BfYldb8e_18. Bạn có bất kỳ ý tưởng những gì tôi có thể làm sai?iPhone - AVAssetWriter - Lỗi tạo phim từ ảnh ở 1920 × 1080 pixel

- (void) createMovieWithOptions:(NSDictionary *) options 
{ 
@autoreleasepool { 
    NSString *path = [options valueForKey:@"path"]; 
    CGSize size = [(NSValue *)[options valueForKey:@"size"] CGSizeValue]; 
    NSArray *imageArray = [options valueForKey:@"pictures"]; 
    NSInteger recordingFPS = [[options valueForKey:@"fps"] integerValue]; 
    BOOL success=YES; 
    NSError *error = nil; 

    AVAssetWriter *assetWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] 
                  fileType:AVFileTypeQuickTimeMovie 
                   error:&error]; 
    NSParameterAssert(assetWriter); 

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
            AVVideoCodecH264, AVVideoCodecKey, 
            [NSNumber numberWithFloat:size.width], AVVideoWidthKey, 
            [NSNumber numberWithFloat:size.height], AVVideoHeightKey, 
            nil]; 

    AVAssetWriterInput *videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo 
                       outputSettings:videoSettings]; 

    // Configure settings for the pixel buffer adaptor. 
    NSDictionary* bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: 
             [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil]; 

    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput 
                                sourcePixelBufferAttributes:bufferAttributes]; 

    NSParameterAssert(videoWriterInput); 
    NSParameterAssert([assetWriter canAddInput:videoWriterInput]); 

    videoWriterInput.expectsMediaDataInRealTime = NO; 
    [assetWriter addInput:videoWriterInput]; 

    //Start a session: 
    [assetWriter startWriting]; 
    [assetWriter startSessionAtSourceTime:kCMTimeZero]; 

    CVPixelBufferRef buffer = NULL; 

    //convert uiimage to CGImage. 

    int frameCount = 0; 
    float progress = 0; 
    float progressFromFrames = _progressView.progress; //only for create iflipbook movie 

    for(UIImage * img in imageArray) 
    { 
     if([[NSThread currentThread] isCancelled]) 
     { 
      [NSThread exit]; 
     } 

     [condCreateMovie lock]; 
     if(isCreateMoviePaused) 
     { 
      [condCreateMovie wait]; 
     } 

     uint64_t totalFreeSpace=[Utils getFreeDiskspace]; 
     if(((totalFreeSpace/1024ll)/1024ll)<50) 
     { 
      success=NO; 
      break; 
     } 

     //  @autoreleasepool { 
     NSLog(@"size:%@",NSStringFromCGSize(img.size)); 

     buffer = [[MovieWritter sharedMovieWritter] pixelBufferFromCGImage:[img CGImage] andSize:size]; 

     BOOL append_ok = NO; 
     int j = 0; 
     while (!append_ok && j < 60) 
     { 
      if(adaptor.assetWriterInput.readyForMoreMediaData) 
      { 
       CMTime frameTime = CMTimeMake(frameCount, recordingFPS); 
       append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime]; 

       CVPixelBufferRelease(buffer); 

       [NSThread sleepForTimeInterval:0.1]; 


       if(isCreatingiFlipBookFromImported) 
        progress = (float)frameCount/(float)[imageArray count]/2.0 + progressFromFrames; 
       else 
        progress = (float)frameCount/(float)[imageArray count]; 

       [[NSNotificationCenter defaultCenter] postNotificationName:@"movieCreationProgress" object:[NSNumber numberWithFloat:progress]]; 
      } 
      else 
      { 
       [NSThread sleepForTimeInterval:0.5]; 
      } 
      j++; 
     } 
     if (!append_ok) 
     { 
      NSLog(@"error appending image %d times %d\n", frameCount, j); 
     } 
     frameCount++; 

     [condCreateMovie unlock]; 
    } 

    //Finish the session: 
    [videoWriterInput markAsFinished]; 
    [assetWriter finishWriting]; 

    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:success], @"success", 
          path, @"path", nil]; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"movieCreationFinished" object:dict]; 
} 
} 

* Chỉnh sửa. Đây là mã cho [[MovieWritter sharedMovieWritter] pixelBufferFromCGImage:]

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image andSize:(CGSize) size 
{ 
@autoreleasepool { 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 
          nil]; 
    CVPixelBufferRef pxbuffer = NULL; 

    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width, 
              size.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 
              &pxbuffer); 
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 
    NSParameterAssert(pxdata != NULL); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, size.width, 
               size.height, 8, 4*size.width, rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 
    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
} 
} 
+1

Xin vui lòng gửi mã cho: [MovieWritter sharedMovieWritter] pixelBufferFromCGImage: quá. –

+0

Điều đó có vẻ mát mẻ tho –

Trả lời

2

Chắc chắn rằng đây là giới hạn HW hoặc lỗi. Vui lòng gửi Radar.

+0

Tôi đã chạy vào vấn đề này bản thân mình và có điều này là 90% một giới hạn phần cứng kể từ khi Simulator hoạt động như mong đợi. –

2

thế nào về một cái gì đó như thế này để có được điểm ảnh đệm

//you could use a cgiimageref here instead 
    CFDataRef imageData= CGDataProviderCopyData(CGImageGetDataProvider(imageView.image.CGImage)); 
    NSLog (@"copied image data"); 
    cvErr = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 
             FRAME_WIDTH, 
             FRAME_HEIGHT, 
             kCVPixelFormatType_32BGRA, 
             (void*)CFDataGetBytePtr(imageData), 
             CGImageGetBytesPerRow(imageView.image.CGImage), 
             NULL, 
             NULL, 
             NULL, 
             &pixelBuffer); 
    NSLog (@"CVPixelBufferCreateWithBytes returned %d", cvErr); 

    CFAbsoluteTime thisFrameWallClockTime = CFAbsoluteTimeGetCurrent(); 
    CFTimeInterval elapsedTime = thisFrameWallClockTime - firstFrameWallClockTime; 
    NSLog (@"elapsedTime: %f", elapsedTime); 
    CMTime presentationTime = CMTimeMake(elapsedTime * TIME_SCALE, TIME_SCALE); 

    // write the sample 
    BOOL appended = [assetWriterPixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentationTime]; 
    CVPixelBufferRelease(pixelBuffer); 
    CFRelease(imageData); 
    if (appended) { 
     NSLog (@"appended sample at time %lf", CMTimeGetSeconds(presentationTime)); 
    } else { 
     NSLog (@"failed to append"); 
     [self stopRecording]; 
     self.startStopButton.selected = NO; 
    } 
-1

Bạn cũng có thể muốn thiết lập chụp các thiết lập cài đặt trước, mặc dù cao thường là phù hợp và đó là mặc định */ Constants để xác định thiết lập chụp cài đặt trước bằng cách sử dụng thuộc tính sessionPreset.

NSString * const AVCaptureSessionPresetPhoto;

NSString * const AVCaptureSessionPresetHigh;

NSString * const AVCaptureSessionPresetMedium;

NSString * const AVCaptureSessionPresetLow;

NSString * const AVCaptureSessionPreset352x288;

NSString * const AVCaptureSessionPreset640x480;

NSString * const AVCaptureSessionPreset1280x720;

NSString * const AVCaptureSessionPreset1920x1080;

NSString * const AVCaptureSessionPresetiFrame960x540;

NSString * const AVCaptureSessionPresetiFrame1280x720; */

// thiết lập nó như thế này

self.captureSession.sessionPreset = AVCaptureSessionPreset1920x1080;

// hoặc như thế này khi bạn xác định avcapturesession

[self.captureSession setSessionPreset: AVCaptureSessionPreset1920x1080];

+1

điều này là không thích hợp nhất. Đồng nghiệp của tôi và tôi cần khắc phục sự cố này khi chúng tôi đang cho hình ảnh FULL HD vào AVAssetWriterInputPixelBufferAdaptor. Có thể chụp ảnh từ Camera Roll ...chúng tôi đang thay đổi kích thước chúng để phân giải độ phân giải Full HD. Chúng tôi cũng đang chụp khung từ bộ đệm máy ảnh nhưng chúng vẫn không hoạt động bằng cách sử dụng AVAssetWriterInputPixelBufferAdaptor. Có thể đây là lỗi hoặc giới hạn với AVAssetWriterInputPixelBufferAdaptor. –

+1

Tôi có một số vấn đề trước khi không cài đặt giá trị đặt trước, vì vậy tôi đã đề cập đến nó, có thái độ xấu sẽ không giúp bạn nhanh hơn. định dạng pixel có thể sai thay đổi kCVPixelFormatType_32ARGB thành kCVPixelFormatType_32BGRA như trong ví dụ tôi hiển thị định dạng pixel –

+0

không có gì để làm ở đây. phương thức appendPixelBuffer ... cũng trả về một đáp ứng YES. Chúng tôi đã kiểm tra kích thước, cài đặt, mọi thứ, nhưng nó vẫn không hoạt động. –

3

tôi đã cùng một vấn đề và giải quyết nó this answer: kích thước của video phải là một bội số của 16.

+0

Cảm ơn bạn rất nhiều! Đã đấu tranh với các bit khác nhau này trong nhiều ngày. Một yêu cầu vô lý, nhưng đầy đủ của Apple của những người. – Linuxios