@@ -114,6 +114,8 @@ struct HapCodecCompressTask
114114 ICMMutableEncodedFrameRef encodedFrame ;
115115 void * encodedFrameBaseAddress ;
116116 unsigned long encodedFrameActualSize ;
117+ HapCodecBufferRef formatConvertBuffer ;
118+ HapCodecBufferRef dxtBuffer ;
117119 ComponentResult error ;
118120 HapCodecBufferRef next ; // Used to queue finished tasks
119121};
@@ -145,7 +147,11 @@ struct HapCodecCompressTask
145147#endif
146148
147149static void Background_Encode (void * info );
148- static void releaseTaskFrames (HapCodecCompressTask * task );
150+ /*
151+ createTask() returns a complete task or NULL on error (which is likely to be due to buffer allocation failure)
152+ */
153+ static HapCodecBufferRef createTask (HapCompressorGlobals glob , ICMCompressorSourceFrameRef sourceFrame , ICMMutableEncodedFrameRef encodedFrame );
154+ static void disposeTask (HapCodecCompressTask * task );
149155static ComponentResult finishFrame (HapCodecBufferRef buffer );
150156static void queueEncodedFrame (HapCompressorGlobals glob , HapCodecBufferRef frame );
151157static HapCodecBufferRef dequeueNextFrameOut (HapCompressorGlobals glob );
@@ -261,7 +267,7 @@ Hap_CClose(
261267 HapCodecBufferRef next ;
262268 if (task )
263269 {
264- releaseTaskFrames (task );
270+ disposeTask (task );
265271 next = task -> next ;
266272 }
267273 else
@@ -585,8 +591,6 @@ Hap_CPrepareToCompressFrames(
585591
586592static void Background_Encode (void * info )
587593{
588- HapCodecBufferRef formatConvertBuffer = NULL ;
589- HapCodecBufferRef dxtBuffer = NULL ;
590594 HapCodecCompressTask * task = (HapCodecCompressTask * )HapCodecBufferGetBaseAddress ((HapCodecBufferRef )info );
591595 HapCompressorGlobals glob = task -> glob ;
592596
@@ -641,22 +645,14 @@ static void Background_Encode(void *info)
641645 // If necessary, convert the pixels to a format the encoder can ingest
642646 if (wantedPixelFormat != sourcePixelFormat )
643647 {
644- formatConvertBuffer = HapCodecBufferCreate (glob -> formatConvertPool );
645-
646- if (formatConvertBuffer == NULL )
647- {
648- err = memFullErr ;
649- goto bail ;
650- }
651-
652648 // for all these we pass 0 as last argument so we don't tile, we are already multithreaded
653649 switch (wantedPixelFormat )
654650 {
655651 case kHapCVPixelFormat_CoCgXY :
656652 if (sourcePixelFormat == k32BGRAPixelFormat )
657653 {
658654 ConvertBGR_ToCoCg_Y8888 ((uint8_t * )sourceBaseAddress ,
659- (uint8_t * )HapCodecBufferGetBaseAddress (formatConvertBuffer ),
655+ (uint8_t * )HapCodecBufferGetBaseAddress (task -> formatConvertBuffer ),
660656 glob -> width ,
661657 glob -> height ,
662658 sourceBytesPerRow ,
@@ -666,7 +662,7 @@ static void Background_Encode(void *info)
666662 else
667663 {
668664 ConvertRGB_ToCoCg_Y8888 ((uint8_t * )sourceBaseAddress ,
669- (uint8_t * )HapCodecBufferGetBaseAddress (formatConvertBuffer ),
665+ (uint8_t * )HapCodecBufferGetBaseAddress (task -> formatConvertBuffer ),
670666 glob -> width ,
671667 glob -> height ,
672668 sourceBytesPerRow ,
@@ -680,7 +676,7 @@ static void Background_Encode(void *info)
680676 uint8_t permuteMap [] = {2 , 1 , 0 , 3 };
681677 ImageMath_Permute8888 (sourceBaseAddress ,
682678 sourceBytesPerRow ,
683- HapCodecBufferGetBaseAddress (formatConvertBuffer ),
679+ HapCodecBufferGetBaseAddress (task -> formatConvertBuffer ),
684680 glob -> formatConvertBufferBytesPerRow ,
685681 glob -> width ,
686682 glob -> height ,
@@ -699,7 +695,7 @@ static void Background_Encode(void *info)
699695 break ;
700696 }
701697
702- encode_src = HapCodecBufferGetBaseAddress (formatConvertBuffer );
698+ encode_src = HapCodecBufferGetBaseAddress (task -> formatConvertBuffer );
703699 encode_src_bytes_per_row = glob -> formatConvertBufferBytesPerRow ;
704700 }
705701 else // wantedPixelFormat == sourcePixelFormat
@@ -710,18 +706,11 @@ static void Background_Encode(void *info)
710706
711707 // Encode the DXT frame
712708
713- dxtBuffer = HapCodecBufferCreate (glob -> dxtBufferPool );
714- if (dxtBuffer == NULL )
715- {
716- err = memFullErr ;
717- goto bail ;
718- }
719-
720709 result = glob -> dxtEncoder -> encode_function (glob -> dxtEncoder ,
721710 encode_src ,
722711 encode_src_bytes_per_row ,
723712 wantedPixelFormat ,
724- HapCodecBufferGetBaseAddress (dxtBuffer ),
713+ HapCodecBufferGetBaseAddress (task -> dxtBuffer ),
725714 glob -> width ,
726715 glob -> height );
727716
@@ -742,11 +731,11 @@ static void Background_Encode(void *info)
742731#endif
743732
744733 // Return the format conversion buffer as soon as we can to minimise the number created
745- HapCodecBufferReturn (formatConvertBuffer );
746- formatConvertBuffer = NULL ;
734+ HapCodecBufferReturn (task -> formatConvertBuffer );
735+ task -> formatConvertBuffer = NULL ;
747736
748- codec_src = HapCodecBufferGetBaseAddress (dxtBuffer );
749- codec_src_length = HapCodecBufferGetSize (dxtBuffer );
737+ codec_src = HapCodecBufferGetBaseAddress (task -> dxtBuffer );
738+ codec_src_length = HapCodecBufferGetSize (task -> dxtBuffer );
750739 }
751740
752741 hapResult = HapEncode (codec_src ,
@@ -774,9 +763,11 @@ static void Background_Encode(void *info)
774763bail :
775764 debug_print_err (glob , err );
776765 if (task -> sourceBuffer ) CVPixelBufferUnlockBaseAddress (task -> sourceBuffer , kHapCodecCVPixelBufferLockFlags );
777- HapCodecBufferReturn (formatConvertBuffer );
778- HapCodecBufferReturn (dxtBuffer );
779-
766+ HapCodecBufferReturn (task -> formatConvertBuffer );
767+ task -> formatConvertBuffer = NULL ;
768+ HapCodecBufferReturn (task -> dxtBuffer );
769+ task -> dxtBuffer = NULL ;
770+
780771 task -> error = err ;
781772
782773 // Queue the encoded frame for output
@@ -798,8 +789,7 @@ Hap_CEncodeFrame(
798789
799790 CVPixelBufferRef sourcePixelBuffer = ICMCompressorSourceFrameGetPixelBuffer (sourceFrame );
800791 OSType sourceFormat = CVPixelBufferGetPixelFormatType (sourcePixelBuffer );
801- HapCodecBufferRef buffer ;
802- HapCodecCompressTask * task ;
792+ HapCodecBufferRef buffer = NULL ;
803793 ICMMutableEncodedFrameRef encodedFrame = NULL ;
804794
805795 if (!isDXTPixelFormat (sourceFormat ))
@@ -869,31 +859,40 @@ Hap_CEncodeFrame(
869859
870860 }
871861 }
872-
862+
873863 // Create an empty encoded frame
874864 err = ICMEncodedFrameCreateMutable (glob -> session , sourceFrame , glob -> maxEncodedDataSize , & encodedFrame );
875- if (err )
876- goto bail ;
865+ if (err != noErr )
866+ encodedFrame = NULL ;
877867
878- // Create a task and dispatch it
879- buffer = HapCodecBufferCreate (glob -> compressTaskPool );
880- task = (HapCodecCompressTask * )HapCodecBufferGetBaseAddress (buffer );
881- if (task == NULL )
868+ if (err == noErr )
869+ {
870+ buffer = createTask (glob , sourceFrame , encodedFrame );
871+ if (buffer == NULL )
872+ err = memFullErr ;
873+ }
874+
875+ if (err == memFullErr )
876+ {
877+ // in case of memory allocation failure, finish all pending tasks and try again
878+ Hap_CCompleteFrame (glob , NULL , 0 );
879+
880+ if (encodedFrame == NULL )
881+ err = ICMEncodedFrameCreateMutable (glob -> session , sourceFrame , glob -> maxEncodedDataSize , & encodedFrame );
882+
883+ if (err == noErr )
884+ buffer = createTask (glob , sourceFrame , encodedFrame );
885+ }
886+
887+ ICMEncodedFrameRelease (encodedFrame );
888+ encodedFrame = NULL ;
889+
890+ if (buffer == NULL )
882891 {
883892 err = memFullErr ;
884893 goto bail ;
885894 }
886-
887- task -> sourceFrame = ICMCompressorSourceFrameRetain (sourceFrame );
888- task -> sourceBuffer = ICMCompressorSourceFrameGetPixelBuffer (sourceFrame );
889- task -> glob = glob ;
890- task -> error = noErr ;
891- task -> encodedFrame = encodedFrame ;
892- task -> encodedFrameBaseAddress = ICMEncodedFrameGetDataPtr (encodedFrame );
893- task -> next = NULL ;
894-
895- encodedFrame = NULL ;
896-
895+
897896 HapCodecTasksAddTask (glob -> taskGroup , buffer );
898897
899898 // Dequeue and deliver any encoded frames
@@ -959,12 +958,14 @@ Hap_CCompleteFrame(
959958 return err ;
960959}
961960
962- static void releaseTaskFrames (HapCodecCompressTask * task )
961+ static void disposeTask (HapCodecCompressTask * task )
963962{
964963 if (task )
965964 {
966965 ICMCompressorSourceFrameRelease (task -> sourceFrame );
967966 ICMEncodedFrameRelease (task -> encodedFrame );
967+ HapCodecBufferReturn (task -> dxtBuffer );
968+ HapCodecBufferReturn (task -> formatConvertBuffer );
968969 }
969970}
970971
@@ -999,7 +1000,7 @@ static ComponentResult finishFrame(HapCodecBufferRef buffer)
9991000 {
10001001 ICMCompressorSessionDropFrame (task -> glob -> session , task -> sourceFrame );
10011002 }
1002- releaseTaskFrames (task );
1003+ disposeTask (task );
10031004 }
10041005 return err ;
10051006}
@@ -1051,3 +1052,55 @@ static HapCodecBufferRef dequeueNextFrameOut(HapCompressorGlobals glob)
10511052 }
10521053 return found ;
10531054}
1055+
1056+ static HapCodecBufferRef createTask (HapCompressorGlobals glob , ICMCompressorSourceFrameRef sourceFrame , ICMMutableEncodedFrameRef encodedFrame )
1057+ {
1058+ HapCodecBufferRef buffer = HapCodecBufferCreate (glob -> compressTaskPool );
1059+ if (buffer )
1060+ {
1061+ HapCodecCompressTask * task = (HapCodecCompressTask * )HapCodecBufferGetBaseAddress (buffer );
1062+
1063+ task -> sourceFrame = ICMCompressorSourceFrameRetain (sourceFrame );
1064+ task -> sourceBuffer = ICMCompressorSourceFrameGetPixelBuffer (sourceFrame );
1065+ task -> glob = glob ;
1066+ task -> encodedFrame = (ICMMutableEncodedFrameRef )ICMEncodedFrameRetain (encodedFrame );
1067+ task -> encodedFrameBaseAddress = ICMEncodedFrameGetDataPtr (task -> encodedFrame );
1068+ task -> error = noErr ;
1069+ task -> next = NULL ;
1070+ task -> formatConvertBuffer = NULL ;
1071+ task -> dxtBuffer = NULL ;
1072+
1073+ if (task -> error == noErr )
1074+ {
1075+ // Create any necessary temporary buffers
1076+ OSType sourcePixelFormat = CVPixelBufferGetPixelFormatType (task -> sourceBuffer );
1077+ if (!isDXTPixelFormat (sourcePixelFormat ))
1078+ {
1079+ OSType wantedPixelFormat = glob -> dxtEncoder -> pixelformat_function (glob -> dxtEncoder , sourcePixelFormat );
1080+
1081+ if (wantedPixelFormat != sourcePixelFormat )
1082+ {
1083+ task -> formatConvertBuffer = HapCodecBufferCreate (glob -> formatConvertPool );
1084+
1085+ if (task -> formatConvertBuffer == NULL )
1086+ task -> error = memFullErr ;
1087+ }
1088+
1089+ if (task -> error == noErr )
1090+ {
1091+ task -> dxtBuffer = HapCodecBufferCreate (glob -> dxtBufferPool );
1092+
1093+ if (task -> dxtBuffer == NULL )
1094+ task -> error = memFullErr ;
1095+ }
1096+ }
1097+ }
1098+ if (task -> error != noErr )
1099+ {
1100+ disposeTask (task );
1101+ HapCodecBufferReturn (buffer );
1102+ buffer = NULL ;
1103+ }
1104+ }
1105+ return buffer ;
1106+ }
0 commit comments