2017-03-10 26 views
4

화면의 데이터로 H.264 압축 세션을 만들려고합니다. 그래서 같은 CGDisplayStreamRef 인스턴스를 생성 한 : 나는 내 화면에서 데이터를 변환 할 수있는 방법을 이해하기 위해 노력하고있어CGDisplayStream을 사용하여 H.264 압축 세션을 인코딩하는 중

- (void) encode:(CMSampleBufferRef)sampleBuffer { 
    CVImageBufferRef imageBuffer = (CVImageBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer); 
    CMTime presentationTimeStamp = CMTimeMake(frameID++, 1000); 
    VTEncodeInfoFlags flags; 
    OSStatus statusCode = VTCompressionSessionEncodeFrame(EncodingSession, 
                  imageBuffer, 
                  presentationTimeStamp, 
                  kCMTimeInvalid, 
                  NULL, NULL, &flags); 
    if (statusCode != noErr) { 
     NSLog(@"H264: VTCompressionSessionEncodeFrame failed with %d", (int)statusCode); 

     VTCompressionSessionInvalidate(EncodingSession); 
     CFRelease(EncodingSession); 
     EncodingSession = NULL; 
     return; 
    } 
    NSLog(@"H264: VTCompressionSessionEncodeFrame Success"); 
} 

:

다음
displayStream = CGDisplayStreamCreateWithDispatchQueue(0, 100, 100, k32BGRAPixelFormat, nil, self.screenCaptureQueue, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) { 
    //Call encoding session here 
}); 

내가 현재 인코딩 기능 설정을하는 방법입니다 CMSampleBufferRef에 삽입하면 인코딩 기능을 제대로 호출 할 수 있습니다. 지금까지, 나는 이것이 가능한지 또는 내가하려고하는 것에 대한 올바른 접근 방식을 결정할 수 없었습니다. 누구든지 어떤 제안이 있습니까?

편집 : 나는 왔 내 IOSurfaceCMBlockBuffer로 변환하지만, 아직 CMSampleBufferRef 해당 변환하는 방법을 알아 냈하지 않은 :

void *mem = IOSurfaceGetBaseAddress(frameSurface); 
size_t bytesPerRow = IOSurfaceGetBytesPerRow(frameSurface); 
size_t height = IOSurfaceGetHeight(frameSurface); 
size_t totalBytes = bytesPerRow * height; 

CMBlockBufferRef blockBuffer; 

CMBlockBufferCreateWithMemoryBlock(kCFAllocatorNull, mem, totalBytes, kCFAllocatorNull, NULL, 0, totalBytes, 0, &blockBuffer); 

편집 2

일부 진행률 :

CMSampleBufferRef *sampleBuffer; 

OSStatus sampleStatus = CMSampleBufferCreate(
          NULL, blockBuffer, TRUE, NULL, NULL, 
          NULL, 1, 1, NULL, 
          0, NULL, sampleBuffer); 

[self encode:*sampleBuffer]; 

답변

0

아마도 조금 늦었 겠지만 다른 사람에게 도움이 될 수 있습니다.

CGDisplayStreamCreateWithDispatchQueue(CGMainDisplayID(), 100, 100, k32BGRAPixelFormat, nil, self.screenCaptureQueue, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) { 
    // The created pixel buffer retains the surface object. 
    CVPixelBufferRef pixelBuffer; 
    CVPixelBufferCreateWithIOSurface(NULL, frameSurface, NULL, &pixelBuffer); 

    // Create the video-type-specific description for the pixel buffer. 
    CMVideoFormatDescriptionRef videoFormatDescription; 
    CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuffer, &videoFormatDescription); 

    // All the necessary parts for creating a `CMSampleBuffer` are ready. 
    CMSampleBufferRef sampleBuffer; 
    CMSampleTimingInfo timingInfo; 
    CMSampleBufferCreateReadyWithImageBuffer(NULL, pixelBuffer, videoFormatDescription, &timingInfo, &sampleBuffer); 

    // Do the stuff 

    // Release the resources to let the frame surface be reused in the queue 
    // `kCGDisplayStreamQueueDepth` is responsible for the size of the queue 
    CFRelease(sampleBuffer); 
    CFRelease(pixelBuffer); 
});