11#import " XCWH264Encoder.h"
22
3+ #import < CoreImage/CoreImage.h>
34#import < CoreMedia/CoreMedia.h>
45#import < os/lock.h>
56#import < QuartzCore/QuartzCore.h>
@@ -232,14 +233,11 @@ static int32_t XCWRoundToEvenDimension(double value) {
232233}
233234
234235static CGSize XCWScaledDimensionsForSourceSize (int32_t width, int32_t height, XCWVideoEncoderMode mode) {
236+ (void )mode;
235237 if (width <= 0 || height <= 0 ) {
236238 return CGSizeZero;
237239 }
238240
239- if (mode == XCWVideoEncoderModeH264Software) {
240- return CGSizeMake (width, height);
241- }
242-
243241 int32_t longestEdge = MAX (width, height);
244242 if (longestEdge <= XCWMaximumEncodedDimension) {
245243 return CGSizeMake (width, height);
@@ -345,6 +343,7 @@ @implementation XCWH264Encoder {
345343 int32_t _height;
346344 uint64_t _timestampOriginUs;
347345 VTPixelTransferSessionRef _pixelTransferSession;
346+ CIContext *_scalingContext;
348347 CVPixelBufferRef _scaledPixelBuffer;
349348 OSType _scaledPixelFormat;
350349 XCWVideoEncoderMode _encoderMode;
@@ -681,6 +680,12 @@ - (nullable CVPixelBufferRef)copyScaledPixelBufferIfNeeded:(CVPixelBufferRef)pix
681680 return pixelBuffer;
682681 }
683682
683+ if (_encoderMode == XCWVideoEncoderModeH264Software) {
684+ return [self copyCoreImageScaledPixelBuffer: pixelBuffer
685+ targetWidth: targetWidth
686+ targetHeight: targetHeight];
687+ }
688+
684689 if (_pixelTransferSession == NULL ) {
685690 OSStatus sessionStatus = VTPixelTransferSessionCreate (kCFAllocatorDefault , &_pixelTransferSession);
686691 if (sessionStatus != noErr || _pixelTransferSession == NULL ) {
@@ -738,6 +743,67 @@ - (nullable CVPixelBufferRef)copyScaledPixelBufferIfNeeded:(CVPixelBufferRef)pix
738743 return _scaledPixelBuffer;
739744}
740745
746+ - (nullable CVPixelBufferRef)copyCoreImageScaledPixelBuffer : (CVPixelBufferRef)pixelBuffer
747+ targetWidth : (int32_t )targetWidth
748+ targetHeight : (int32_t )targetHeight {
749+ OSType sourcePixelFormat = CVPixelBufferGetPixelFormatType (pixelBuffer);
750+ BOOL needsNewBuffer = (_scaledPixelBuffer == NULL )
751+ || ((int32_t )CVPixelBufferGetWidth (_scaledPixelBuffer) != targetWidth)
752+ || ((int32_t )CVPixelBufferGetHeight (_scaledPixelBuffer) != targetHeight)
753+ || (_scaledPixelFormat != sourcePixelFormat);
754+ if (needsNewBuffer) {
755+ if (_scaledPixelBuffer != NULL ) {
756+ CVPixelBufferRelease (_scaledPixelBuffer);
757+ _scaledPixelBuffer = NULL ;
758+ }
759+
760+ NSDictionary *attributes = @{
761+ (__bridge NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{},
762+ };
763+ CVPixelBufferRef scaledPixelBuffer = NULL ;
764+ OSStatus bufferStatus = CVPixelBufferCreate (kCFAllocatorDefault ,
765+ targetWidth,
766+ targetHeight,
767+ sourcePixelFormat,
768+ (__bridge CFDictionaryRef)attributes,
769+ &scaledPixelBuffer);
770+ if (bufferStatus != noErr || scaledPixelBuffer == NULL ) {
771+ _lastScaleStatus = bufferStatus;
772+ return NULL ;
773+ }
774+ _scaledPixelBuffer = scaledPixelBuffer;
775+ _scaledPixelFormat = sourcePixelFormat;
776+ }
777+
778+ if (_scalingContext == nil ) {
779+ _scalingContext = [CIContext contextWithOptions: @{
780+ kCIContextUseSoftwareRenderer : @YES ,
781+ }];
782+ }
783+
784+ CIImage *image = [CIImage imageWithCVPixelBuffer: pixelBuffer];
785+ if (image == nil ) {
786+ _lastScaleStatus = -1 ;
787+ return NULL ;
788+ }
789+
790+ CGFloat scaleX = (CGFloat)targetWidth / MAX ((CGFloat)CVPixelBufferGetWidth (pixelBuffer), 1.0 );
791+ CGFloat scaleY = (CGFloat)targetHeight / MAX ((CGFloat)CVPixelBufferGetHeight (pixelBuffer), 1.0 );
792+ CIImage *scaledImage = [image imageByApplyingTransform: CGAffineTransformMakeScale (scaleX, scaleY)];
793+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB ();
794+ [_scalingContext render: scaledImage
795+ toCVPixelBuffer: _scaledPixelBuffer
796+ bounds: CGRectMake (0 , 0 , targetWidth, targetHeight)
797+ colorSpace: colorSpace];
798+ if (colorSpace != NULL ) {
799+ CGColorSpaceRelease (colorSpace);
800+ }
801+
802+ _lastScaleStatus = noErr;
803+ CVPixelBufferRetain (_scaledPixelBuffer);
804+ return _scaledPixelBuffer;
805+ }
806+
741807- (void )invalidateScalingResourcesLocked {
742808 if (_scaledPixelBuffer != NULL ) {
743809 CVPixelBufferRelease (_scaledPixelBuffer);
@@ -749,6 +815,7 @@ - (void)invalidateScalingResourcesLocked {
749815 CFRelease (_pixelTransferSession);
750816 _pixelTransferSession = NULL ;
751817 }
818+ _scalingContext = nil ;
752819}
753820
754821- (void )handleEncodedSampleBuffer : (CMSampleBufferRef)sampleBuffer
0 commit comments