4
votes

I have a video AVCaptureDevice (AVMediaTypeVideo), am decreasing the exposure briefly using setExposureTargetBias:completionHandler and then restoring it again. I need to know exactly which buffer in captureOutput:didOutputSampleBuffer:fromConnection: corresponds to the first frame with decreased exposure.

The docs say:

The block receives a timestamp which matches that of the first buffer to which the setting has been applied. The timestamp is synchronized to the device clock, and thus must be converted to the master clock prior to comparison with the timestamps of buffers delivered via an AVCaptureVideoDataOutput instance.

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureDevice_Class/#//apple_ref/occ/instm/AVCaptureDevice/setExposureTargetBias:completionHandler:

How do I get the "device clock"? I have done the following in the completionHandler, although the host time clock seems to coincide with the master clock.

CMClockRef masterClock = self.captureSession.masterClock;  
CMClockRef deviceClock = CMClockGetHostTimeClock();  
syncTimeConverted = CMSyncConvertTime( syncTime, deviceClock, masterClock );

I intend on doing the following in captureOutput:didOutputSampleBuffer:fromConnection: to test whether a buffer is the one I want

CMTime bufferTime = CMSampleBufferGetPresentationTimeStamp( sampleBuffer );  
bool isDroppedExposureFrame = CMTimeCompare( bufferTime, syncTimeConverted ) == 0;  

Am I on the right track?

2

2 Answers

2
votes

In AVCaptureSession.h, where CMClockRef masterClock is defined, I found a solution which works in the other direction:

"

For example, if you want to reverse synchronize the output timestamps to the original timestamps, you can do the following:

In captureOutput:didOutputSampleBuffer:fromConnection:

AVCaptureInputPort *port = [[connection inputPorts] objectAtIndex:0];
CMClockRef originalClock = [port clock];
CMTime syncedPTS = CMSampleBufferGetPresentationTime( sampleBuffer );
CMTime originalPTS = CMSyncConvertTime( syncedPTS, [session masterClock], originalClock );

"

0
votes

Dickson's answer in swift:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

        let port = connection.inputPorts[0]
        let originalClock = port.clock
        let syncedPTS = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
        let originalPTS = CMSyncConvertTime( syncedPTS, from: session.masterClock!, to: originalClock!)
        let result = CMTimeCompare(originalPTS, self.timeStampOfFirstMatchinBuffer)
        switch result {
        case 0:
            print("Timing match!")
        default:
            return
        }
    }

where timeStampOfFirstMatchinBuffer is the CMTime value you get when you set

setExposureTargetBias(_ bias: Float, 
         completionHandler handler: ((CMTime) -> Void)? = nil)