iOS17 VideoToolBox video encode h264 file set average bitrate not work?

I use VTCompressionSession and set the average bit rate by kVTCompressionPropertyKey_AverageBitRate and kVTCompressionPropertyKey_DataRateLimits. The code like this:

    
    VTCompressionSessionRef vtSession = session;
    if (vtSession == NULL) {
        vtSession = _encoderSession;
    }
    
    if (vtSession == nil) {
        return;
    }
    
    int tmp         = bitrate;
    int bytesTmp    = tmp * 0.15; 
    int durationTmp = 1;
    
    CFNumberRef bitrateRef   = CFNumberCreate(NULL, kCFNumberSInt32Type, &tmp);
    CFNumberRef bytes        = CFNumberCreate(NULL, kCFNumberSInt32Type, &bytesTmp);
    CFNumberRef duration     = CFNumberCreate(NULL, kCFNumberSInt32Type, &durationTmp);

    if ([self isSupportPropertyWithSession:vtSession key:kVTCompressionPropertyKey_AverageBitRate]) {
        [self setSessionPropertyWithSession:vtSession key:kVTCompressionPropertyKey_AverageBitRate value:bitrateRef];
    }else {
        NSLog(@"Video Encoder: set average bitRate error");
    }
    
    NSLog(@"Video Encoder: set bitrate bytes = %d, _bitrate = %d",bytesTmp, bitrate);
    
    CFMutableArrayRef limit = CFArrayCreateMutable(NULL, 2, &kCFTypeArrayCallBacks);
    CFArrayAppendValue(limit, bytes);
    CFArrayAppendValue(limit, duration);
    if([self isSupportPropertyWithSession:vtSession key:kVTCompressionPropertyKey_DataRateLimits]) {
        OSStatus ret = VTSessionSetProperty(vtSession, kVTCompressionPropertyKey_DataRateLimits, limit);
        if(ret != noErr){
            NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:ret userInfo:nil];
            NSLog(@"Video Encoder: set DataRateLimits failed with %s",error.description.UTF8String);
        }
    }else {
        NSLog(@"Video Encoder: set data rate limits error");
    }
    CFRelease(bitrateRef);
    CFRelease(limit);
    CFRelease(bytes);
    CFRelease(duration);
}

This work fine on iOS16 and below. But on iOS17 the bitrate of the generate video file is much lower than the value I set. For exmaple, I set biterate 600k but on iOS17 the encoded video bitrate is lower than 150k. What went wrong?

Accepted Reply

already solved. no related to the api. event thing works fine!

Replies

already solved. no related to the api. event thing works fine!

I'm experiencing a similar situation, may I ask if it's not API related, what kind of problem is it related to?

  • I have resolved the issue I encountered.

    In iOS 17, the encoder seems to be more sensitive to the time intervals of incoming frames. When the frame rate is set to 30, if the interval between incoming frames exceeds 200ms, it causes a decrease in the encoder's bit rate. Even if the subsequent intervals return to 0.03333 sec, the encoder's output bit rate does not recover to the set value.

    The impact of this behavior in iOS 16 was not as pronounced as in iOS 17.

  • I seem to have the same issue. May I ask how you solved this problem? Ensure that the time interval of the frame is approximately equal to 1/FPS?

  • @Nan2886 Yes, you are right. The way I used to do it was to send the images captured by the camera to the encoder. The bug occurred when, in certain situations, I reduced the number of frames being sent, resulting in too long of an interval between two frames.

Add a Comment

I used CMSampleBufferCreateForImageBuffer to create CMSampleBufferRef from CVPixelBufferRef. Then use VTCompressionSessionEncodeFrame to encode CMSampleBufferRef. This may cause the LOW bitrate on iOS17.
So I changed the way, directly encode the CVPixelBufferRef instead of CMSampleBufferRef.

    OSStatus status = VTCompressionSessionEncodeFrame(compressionSession, **pixelBuffer,** kCMTimeInvalid, kCMTimeInvalid, (__bridge CFDictionaryRef)properties, (__bridge_retained void *)timeNumber, NULL);

then the encoded file has the desired bitrate.