2012-12-07 13 views
7

いくつかの写真からムービーを作成しようとしています。これはhd画像({720、1280})以下の解像度でうまく動作します。しかし、フルHD画像(1080、1920)でムービーを作成しようとすると、ビデオがスクランブルされます。それはどのように見えるかを見るためのリンクです。http://www.youtube.com/watch?v=BfYldb8e_18私が間違っているかもしれないアイデアはありますか?iPhone - AVAssetWriter - 写真からムービーを作成する際のエラー1920×1080ピクセル

- (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]; 
} 
} 

*編集。 [[MovieWritter sharedMovieWritter] pixelBufferFromCGImage:]これはHWの制限やバグのいずれかであることを

- (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

の倍数でなければならないためのコードを投稿してくださいあまりにも。 –

+0

それはクールなthoを見ます –

答えて

2

かなり確信してここのコードです。レーダーを提出してください。

+0

私はこの問題を自分で実行しました。そして、これはシミュレータが期待通りに機能するので、これはハードウェアの制限の90%です。 –

2

どのように取得するには、このようなものについてピクセルバッファ

//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

あなたはまた高いが、通常は適しているが、設定がプリセットキャプチャを設定することもできますし、それは、キャプチャ設定のプリセットを定義するデフォルト */ 定数であります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; */

//このようにそれを設定し

self.captureSession.sessionPreset = AVCaptureSessionPreset1920x1080。

//または、このようなあなたがavcapturesession

[self.captureSession setSessionPreset:AVCaptureSessionPreset1920x1080]を定義します。

+1

これは最も無関係です。私の同僚と私はこの問題を、AVAssetWriterInputPixelBufferAdaptorにFULL HDイメージを送るときに修正する必要があります。画像はカメラロールから取ることができます...FULL HD解像度をスイートにリサイズしています。カメラのバッファからフレームをキャプチャしていますが、AVAssetWriterInputPixelBufferAdaptorを使用しても動作しません。おそらく、これはAVAssetWriterInputPixelBufferAdaptorのバグまたは制限です。 –

+1

プリセットを設定しないうちに問題を抱えているので、私はそれを言いました。悪い姿勢を取れば、より速く役立つことはありません。ピクセルフォーマットが間違っている可能性がありますkCVPixelFormatType_32ARGBをkCVPixelFormatType_32BGRAに変更しようとすると、サンプルで表示されるように –

+0

ピクセルフォーマットはここで何もしません。 appendPixelBuffer ...メソッドは、YES応答も返します。サイズ、設定、すべてを確認しましたが、まだ動作していません。 –

3

私は同じ問題を抱えていたとthis answerはそれを解決:[MovieWritter sharedMovieWritter] pixelBufferFromCGImage::ビデオのサイズは16

+0

ありがとう!これの様々なビットで数日間苦労してきました。ばかばかしい要件だが、アップルはそれに満ちている。 – Linuxios

関連する問題