2012-03-13 3 views
2

AVPlayerLayer (CALayer의 하위 클래스)가 있는데 QCRenderer (QCRenderer가 NSImages 및 CIImages를 사용할 수 있음)로 전달할 수있는 이미지 유형을 가져와야합니다. CALayer를 CGImageRef와 그 것을 NSImage에 전달하지만 내용은 항상 명확합니다.AVPlayer가 AVPlayerLayer로 렌더링되지 않습니다.

  1. 내가 제대로 NSImage를 생성하고 있지 않다 :

    나는 두 가지 이유 중 하나로 좁혀했습니다.

  2. AVPlayer가 AVPlayerLayer로 렌더링되지 않습니다.

오류 메시지가 나타나면 CALayers 변환에 대한 몇 가지 문서를 찾았습니다. 또한 AVPlayerLayer를 NSView에 추가했습니다. NSView는 비어 있으므로 2가 문제라고 생각합니다.

Apple의 AVPlayerDemo의 AVPlayerDemoPlaybackViewController 수정 버전을 사용하고 있습니다. 인터페이스 코드를 모두 제거한 이후 NSObject로 바꿨습니다. withKeys :

난 prepareToPlayAsset을 (보이드)에 AVPlayerLayer을 만드는 방법 I는 AVPlayer를 생성 할 때, (I 만이 작동하는지 테스트하는 NSView의 상기 층을 추가하고있다.)

if (![self player]) 
{ 
    /* Get a new AVPlayer initialized to play the specified player item. */ 
    [self setPlayer:[AVPlayer playerWithPlayerItem:self.mPlayerItem]]; 

    /* Observe the AVPlayer "currentItem" property to find out when any 
    AVPlayer replaceCurrentItemWithPlayerItem: replacement will/did 
    occur.*/ 
    [self.player addObserver:self 
        forKeyPath:kCurrentItemKey 
        options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew 
        context:AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext]; 
    mPlaybackView = [AVPlayerLayer playerLayerWithPlayer:self.player]; 
    [self.theView setWantsLayer:YES]; 
    [mPlaybackView setFrame:self.theView.layer.bounds]; 
    [self.theView.layer addSublayer:mPlaybackView]; 
} 

: 여기
framegrabTimer = [NSTimer timerWithTimeInterval:(1/30) target:self selector:@selector(grabFrameFromMovie) userInfo:nil repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:framegrabTimer forMode:NSDefaultRunLoopMode]; 

는 I 프레임을 잡아서 QCRenderer 처리 클래스에 전달하는 데 사용하는 코드이다 : I는 초당 AVPlayerLayer 30 배의 프레임을 잡기 위해 NSRunLoop을 만들 0
-(void)grabFrameFromMovie { 
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
CGContextRef theContext = CGBitmapContextCreate(NULL, mPlaybackView.frame.size.width, mPlaybackView.frame.size.height, 8, 4*mPlaybackView.frame.size.width, colorSpace, kCGImageAlphaPremultipliedLast); 
[mPlaybackView renderInContext:theContext]; 
CGImageRef CGImage = CGBitmapContextCreateImage(theContext); 
NSImage *image = [[NSImage alloc] initWithCGImage:CGImage size:NSMakeSize(mPlaybackView.frame.size.width, mPlaybackView.frame.size.height)]; 
[[NSNotificationCenter defaultCenter] postNotificationName:@"AVPlayerLoadedNewFrame" object:[image copy]]; 
CGContextRelease(theContext); 
CGColorSpaceRelease(colorSpace); 
CGImageRelease(CGImage); } 

왜 내가 명확 해지는 지 알 수 없습니다. OS X 용 충분한 AVFoundation 문서가 아니므로 이것에 어떤 도움을 크게, 감사

나를 위해
+0

안녕하세요. 이 문제에 대해 행운이 있습니까? 어떻게 든 해결 되었습니까? AVPlayerLayer에서 스크린 샷을 찍고 싶습니다만, 지금까지 renderInContext는 저에게 효과가 없었습니다. – superjos

+3

나는 그것이 당신의 문제와 어떻게 관련이 있는지 모르겠다. 그러나'timerWithTimeInterval : (1/30)'은 당신이 생각하는대로하지 않는다. 두 피연산자 모두 정수이므로 '1/30'은 0으로 평가되므로'1./30. '을 사용하여 0.0333333 double 값을 가져와야합니다. – 0xced

답변

0

의 작품 :

AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:[[[self player] currentItem] asset]]; 
CGImageRef capture = [gen copyCGImageAtTime:self.player.currentTime actualTime:NULL error:NULL]; 
NSImage *img = [[NSImage alloc] initWithCGImage:capture size:self.playerView.frame.size]; 
0

당신은 CVPixelBufferRef를 쿼리에 copyPixelBufferForItemTime을 AVPlayerItem에 AVPlayerItemVideoOutput을 추가 한 다음 호출 할 수 있습니다 지정된 시간 프레임을 포함하는 객체, 여기에 샘플 코드입니다 :

NSDictionary *pixBuffAttributes = @{                      
    (id)kCVPixelBufferWidthKey:@(nWidth),         
    (id)kCVPixelBufferHeightKey:@(nHeight),         
    (id)kCVPixelBufferCGImageCompatibilityKey:@YES, 
}; 
m_output = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:pixBuffAttributes]; 

... 

m_buffer = [m_output copyPixelBufferForItemTime:time itemTimeForDisplay:NULL]; 

CVPixelBufferLockBaseAddress(m_buffer, 0); 
auto *buffer = CVPixelBufferGetBaseAddress(m_buffer); 
frame->width = CVPixelBufferGetWidth(m_buffer); 
frame->height = CVPixelBufferGetHeight(m_buffer); 
frame->widthbytes = CVPixelBufferGetBytesPerRow(m_buffer); 
frame->bufferlen = frame->widthbytes * (uint32)CVPixelBufferGetHeight(m_buffer); 

auto &videoInfo = m_info.video; 
CGDataProviderRef dp = CGDataProviderCreateWithData(nullptr, buffer, frame->bufferlen, nullptr); 
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); 
m_image = CGImageCreate(frame->width, 
         frame->height, 
         8, 
         videoInfo.pixelbits, 
         frame->widthbytes, 
         cs, 
         kCGImageAlphaNoneSkipFirst, 
         dp, 
         nullptr, 
         true, 
         kCGRenderingIntentDefault); 
CGColorSpaceRelease(cs); 
CGDataProviderRelease(dp); 

그리고 당신은 애플의 공식 샘플 체크 아웃 할 수 있습니다

을3210

Real-timeVideoProcessingUsingAVPlayerItemVideoOutput

관련 문제