3

Here has new hardwrare decode methods from iOS8,

we can use "VTDecompressionSessionDecodeFrame" to decode h264 from iOS8,

I try to coding a program which able to print the fps of hardware decode,

but here has a problem, the callback is asynchronously,

so how can I calculate the fps exactly?

I found a method "VTDecompressionSessionWaitForAsynchronousFrames"

Is it what I want ?

Decode Function

- (void)render:(CMSampleBufferRef)sampleBuffer
{
    if (_isDecoding == NO) {

        _isDecoding = YES;

        _lastTime = [NSDate date];

    }

    VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;

    VTDecodeInfoFlags flagOut;

    VTDecompressionSessionDecodeFrame(_decompression, sampleBuffer, flags, NULL, &flagOut);

    VTDecompressionSessionWaitForAsynchronousFrames(_decompression);

    if (_gotFrame == YES) {

        _gotFrame = NO;

        _isDecoding = NO;

    }

    CFRelease(sampleBuffer);
}

Decode Callback Function

void didDecompress( void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration ){

    VideoView* THIS = (__bridge VideoView*)decompressionOutputRefCon;

    THIS->_gotFrame = YES;

    NSDate* currentTime = [NSDate date];

    NSTimeInterval runTime = currentTime.timeIntervalSince1970 - THIS->_lastTime.timeIntervalSince1970;

    THIS->_totalTime += runTime;

    THIS->_counts++;

    THIS->_lastTime = currentTime;

}
PatrickSCLin
  • 1,419
  • 3
  • 17
  • 45

1 Answers1

1

We can set a NSDate to be sourceRefCon, then access the timestamp from callback to get the exactly decode time.

void * sourceFrameRefCon in VTDecompressionSessionDecodeFrame

VTDecompressionSessionDecodeFrame(
    VTDecompressionSessionRef       session,
    CMSampleBufferRef               sampleBuffer,
    VTDecodeFrameFlags              decodeFlags, // bit 0 is enableAsynchronousDecompression
    void *                          sourceFrameRefCon,
    VTDecodeInfoFlags               *infoFlagsOut /* may be NULL */ )

Decode Method

- (void)render:(CMSampleBufferRef)sampleBuffer
{
    VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;

    VTDecodeInfoFlags flagOut;

    NSDate* currentTime = [NSDate date];

    VTDecompressionSessionDecodeFrame(_decompression, sampleBuffer, flags, (void*)CFBridgingRetain(currentTime), &flagOut);

    CFRelease(sampleBuffer);
}

Decode Callback Method

void didDecompress( void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration ){

    NSDate* currentTime = (__bridge NSDate *)sourceFrameRefCon;

    if (currentTime != nil) {

        //Do something

    }
}
PatrickSCLin
  • 1,419
  • 3
  • 17
  • 45
  • Do you have a Swift equivalent of this? I'm struggling to pass data through using `sourceFrameRefCon` and then casting it on the other side using Swift's `UnsafeMutableRawPointer` – LLooggaann Sep 04 '21 at 00:39