2011-05-17 11 views
7

Şu anda kodluyorum, bir Quartz Composer renderer (NSImage nesneleri) anlık görüntü görüntüleri alıyorum ve ben bunları kullanarak 720 * 480 boyutunda, 25 fps ve H264 codec bir QTMovie kodlamak istiyorum addImage: yöntemi. O inşaatQTKit tabanlı görüntü kodlama uygulamam neden bu kadar yavaş? Bir cocoa uygulamasında

qRenderer = [[QCRenderer alloc] initOffScreenWithSize:NSMakeSize(720,480) colorSpace:CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) composition:[QCComposition compositionWithFile:qcPatchPath]]; // define an "offscreen" Quartz composition renderer with the right image size 


imageAttrs = [NSDictionary dictionaryWithObjectsAndKeys: @"avc1", // use the H264 codec 
       QTAddImageCodecType, nil]; 

qtMovie = [[QTMovie alloc] initToWritableFile: outputVideoFile error:NULL]; // initialize the output QT movie object 

long fps = 25; 
frameNum = 0; 

NSTimeInterval renderingTime = 0; 
NSTimeInterval frameInc = (1./fps); 
NSTimeInterval myMovieDuration = 70; 
NSImage * myImage; 
while (renderingTime <= myMovieDuration){ 
    if(![qRenderer renderAtTime: renderingTime arguments:NULL]) 
     NSLog(@"Rendering failed at time %.3fs", renderingTime); 
    myImage = [qRenderer snapshotImage]; 
    [qtMovie addImage:myImage forDuration: QTMakeTimeWithTimeInterval(frameInc) withAttributes:imageAttrs]; 
    [myImage release]; 
    frameNum ++; 
    renderingTime = frameNum * frameInc; 
} 
[qtMovie updateMovieFile]; 
[qRenderer release]; 
[qtMovie release]; 

Ben QuickTime Yayıncı H264 gerçek zamanlı görüntüleri kodlamak biliyorum ederken, ancak başvurum Pro benim yeni MacBook o gerçek zamanlı olarak yapmak mümkün değildir: Burada kodun gelen parçasıdır Aynı bilgisayar üzerinde kullandığım daha yüksek bir kaliteye sahip.

Peki neden? Sorun nedir burada? Bu bir donanım yönetimi sorunu mu (çok çekirdekli iş parçacığı, GPU, ...) veya bir şey özlüyor muyum? vb bana elma gelişme dünyada yeni (uygulama 2 hafta), hem nesnel-C, kakao, X-kod, Quicktime ve Quartz Composer kütüphanelerde olduğumu önsöz olsun herhangi bir yardım için

Teşekkür

+0

25fps hızında 720x480 istediğinizden emin misiniz? Bunun 29.97 fps'de 720x480 veya 25 fps'de 720x576 olması gerekmez mi? Hız sorununuzu çözeceğinden şüphe duyuyorum, ancak garip bir format gibi görünüyor. – user1118321

cevap

5

AVFoundation, QuartzComposer animasyonunu H.264 video akışına dönüştürmenin daha verimli bir yoludur. Benim bu test ederken

size_t width = 640; 
size_t height = 480; 

const char *outputFile = "/tmp/Arabesque.mp4"; 

QCComposition *composition = [QCComposition compositionWithFile:@"/System/Library/Screen Savers/Arabesque.qtz"]; 
QCRenderer *renderer = [[QCRenderer alloc] initOffScreenWithSize:NSMakeSize(width, height) 
                 colorSpace:CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB) composition:composition]; 

unlink(outputFile); 
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:@(outputFile)] fileType:AVFileTypeMPEG4 error:NULL]; 

NSDictionary *videoSettings = @{ AVVideoCodecKey : AVVideoCodecH264, AVVideoWidthKey : @(width), AVVideoHeightKey : @(height) }; 
AVAssetWriterInput* writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; 

[videoWriter addInput:writerInput]; 
[writerInput release]; 

AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:NULL]; 

int framesPerSecond = 30; 
int totalDuration = 30; 
int totalFrameCount = framesPerSecond * totalDuration; 

[videoWriter startWriting]; 
[videoWriter startSessionAtSourceTime:kCMTimeZero]; 

__block long frameNumber = 0; 

dispatch_queue_t workQueue = dispatch_queue_create("com.example.work-queue", DISPATCH_QUEUE_SERIAL); 

NSLog(@"Starting."); 
[writerInput requestMediaDataWhenReadyOnQueue:workQueue usingBlock:^{ 
    while ([writerInput isReadyForMoreMediaData]) { 
     NSTimeInterval frameTime = (float)frameNumber/framesPerSecond; 
     if (![renderer renderAtTime:frameTime arguments:NULL]) { 
      NSLog(@"Rendering failed at time %.3fs", frameTime); 
      break; 
     } 

     CVPixelBufferRef frame = (CVPixelBufferRef)[renderer createSnapshotImageOfType:@"CVPixelBuffer"]; 
     [pixelBufferAdaptor appendPixelBuffer:frame withPresentationTime:CMTimeMake(frameNumber, framesPerSecond)]; 
     CFRelease(frame); 

     frameNumber++; 
     if (frameNumber >= totalFrameCount) { 
      [writerInput markAsFinished]; 
      [videoWriter finishWriting]; 
      [videoWriter release]; 
      [renderer release]; 
      NSLog(@"Rendered %ld frames.", frameNumber); 
      break; 
     } 

    } 
}]; 


QTKit kullanan yayınlanmıştır kod kadar hızlı etrafında iki katı. En büyük gelişme, yazılımda gerçekleştirilmek yerine GPU'ya dağıtılan H.264 kodlamasından geliyor. Bir profildeki hızlı bir bakışta, kalan darboğazların kompozisyonun kendisinin oluşturulması ve oluşturulan verilerin bir GPU'dan bir piksel tamponuna geri okunması olduğu anlaşılmaktadır. Açıkçası, kompozisyonunuzun karmaşıklığının bunun üzerinde bir etkisi olacaktır. QCRenderer 'ün anlık görüntülerini CVOpenGLBufferRef s olarak sağlama yeteneği sayesinde, bunu kareyi daha sonra kodlayıcıya aktarmak yerine tekrar GPU üzerinde tutabildiği için, bunu daha da optimize etmek mümkün olabilir. Buna çok fazla bakmamıştım.

İlgili konular