Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit748d654

Browse files
authored
Merge pull request#28173 from satyam102006:fix/issue-28165-videoio-ios-crash
videoio(ios): fix NSInvalidArgumentException in VideoWriter release#28173SummaryFixes a crash on iOS when calling `VideoWriter::release()` in OpenCV 4.12.0.IssueFixes#28165Detailed DescriptionThis PR resolves a regression where an `NSInvalidArgumentException` was thrown with the message ` -[NSAutoreleasePool retain]: Cannot retain an autorelease pool`.The crash was caused by the manual usage of `NSAutoreleasePool` in the `~CvVideoWriter_AVFoundation` destructor. The local pool variable was being captured by the completion handler block passed to `[mMovieWriter finishWritingWithCompletionHandler:]`. Since `NSAutoreleasePool` instances cannot be retained, capturing them in a block causes a crash.Changes:- Replaced manual `NSAutoreleasePool` allocation and draining with modern `@autoreleasepool` blocks in `CvVideoWriter_AVFoundation`.- applied this modernization to the Constructor, Destructor, and `write` methods.- Specifically in the destructor, an inner `@autoreleasepool` is now used inside the completion block, ensuring no pool object needs to be captured from the outer scope.
1 parentc5d70a7 commit748d654

File tree

1 file changed

+157
-187
lines changed

1 file changed

+157
-187
lines changed

‎modules/videoio/src/cap_avfoundation.mm‎

Lines changed: 157 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,228 +1155,198 @@ -(bool) updateImage {
11551155
double fps,const cv::Size& frame_size,
11561156
int is_color) {
11571157

1158-
NSAutoreleasePool* localpool = [[NSAutoreleasePoolalloc]init];
1159-
1160-
1161-
frameCount =0;
1162-
movieFPS = fps;
1163-
movieSize = frame_size;
1164-
movieColor = is_color;
1165-
argbimage =cv::Mat(movieSize, CV_8UC4);
1166-
path = [[[NSStringstringWithCString:filenameencoding:NSASCIIStringEncoding]stringByExpandingTildeInPath]retain];
1167-
1158+
@autoreleasepool {
1159+
frameCount =0;
1160+
movieFPS = fps;
1161+
movieSize = frame_size;
1162+
movieColor = is_color;
1163+
argbimage =cv::Mat(movieSize, CV_8UC4);
1164+
path = [[[NSStringstringWithCString:filenameencoding:NSASCIIStringEncoding]stringByExpandingTildeInPath]retain];
11681165

1169-
/*
1170-
AVFileTypeQuickTimeMovie
1171-
UTI for the QuickTime movie file format.
1172-
The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions.
1166+
/*
1167+
AVFileTypeQuickTimeMovie
1168+
UTI for the QuickTime movie file format.
1169+
The value of this UTI is com.apple.quicktime-movie. Files are identified with the .mov and .qt extensions.
11731170
1174-
AVFileTypeMPEG4
1175-
UTI for the MPEG-4 file format.
1176-
The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension.
1171+
AVFileTypeMPEG4
1172+
UTI for the MPEG-4 file format.
1173+
The value of this UTI is public.mpeg-4. Files are identified with the .mp4 extension.
11771174
1178-
AVFileTypeAppleM4V
1179-
UTI for the iTunes video file format.
1180-
The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension.
1175+
AVFileTypeAppleM4V
1176+
UTI for the iTunes video file format.
1177+
The value of this UTI is com.apple.mpeg-4-video. Files are identified with the .m4v extension.
11811178
1182-
AVFileType3GPP
1183-
UTI for the 3GPP file format.
1184-
The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions.
1185-
*/
1179+
AVFileType3GPP
1180+
UTI for the 3GPP file format.
1181+
The value of this UTI is public.3gpp. Files are identified with the .3gp, .3gpp, and .sdv extensions.
1182+
*/
11861183

1187-
NSString *fileExt =[[[pathpathExtension]lowercaseString]copy];
1188-
if ([fileExtisEqualToString:@"mov"] || [fileExtisEqualToString:@"qt"]){
1189-
fileType = [AVFileTypeQuickTimeMoviecopy];
1190-
}elseif ([fileExtisEqualToString:@"mp4"]){
1191-
fileType = [AVFileTypeMPEG4copy];
1192-
}elseif ([fileExtisEqualToString:@"m4v"]){
1193-
fileType = [AVFileTypeAppleM4Vcopy];
1184+
NSString *fileExt =[[[pathpathExtension]lowercaseString]copy];
1185+
if ([fileExtisEqualToString:@"mov"] || [fileExtisEqualToString:@"qt"]){
1186+
fileType = [AVFileTypeQuickTimeMoviecopy];
1187+
}elseif ([fileExtisEqualToString:@"mp4"]){
1188+
fileType = [AVFileTypeMPEG4copy];
1189+
}elseif ([fileExtisEqualToString:@"m4v"]){
1190+
fileType = [AVFileTypeAppleM4Vcopy];
11941191
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
1195-
}elseif ([fileExtisEqualToString:@"3gp"] || [fileExtisEqualToString:@"3gpp"] || [fileExtisEqualToString:@"sdv"] ){
1196-
fileType = [AVFileType3GPPcopy];
1192+
}elseif ([fileExtisEqualToString:@"3gp"] || [fileExtisEqualToString:@"3gpp"] || [fileExtisEqualToString:@"sdv"]){
1193+
fileType = [AVFileType3GPPcopy];
11971194
#endif
1198-
}else{
1199-
fileType = [AVFileTypeMPEG4copy];//default mp4
1200-
}
1201-
[fileExtrelease];
1202-
1203-
char cc[5];
1204-
cc[0] = fourcc &255;
1205-
cc[1] = (fourcc >>8) &255;
1206-
cc[2] = (fourcc >>16) &255;
1207-
cc[3] = (fourcc >>24) &255;
1208-
cc[4] =0;
1209-
int cc2 =CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
1210-
if (cc2!=fourcc) {
1211-
std::cout <<"WARNING: Didn't properly encode FourCC. Expected" << fourcc
1212-
<<" but got" << cc2 <<"." << std::endl;
1213-
//exception;
1214-
}
1195+
}else {
1196+
fileType = [AVFileTypeMPEG4copy];//default mp4
1197+
}
1198+
[fileExtrelease];
1199+
1200+
char cc[5];
1201+
cc[0] = fourcc &255;
1202+
cc[1] = (fourcc >>8) &255;
1203+
cc[2] = (fourcc >>16) &255;
1204+
cc[3] = (fourcc >>24) &255;
1205+
cc[4] =0;
1206+
int cc2 =CV_FOURCC(cc[0], cc[1], cc[2], cc[3]);
1207+
if (cc2 != fourcc) {
1208+
std::cout <<"WARNING: Didn't properly encode FourCC. Expected" << fourcc
1209+
<<" but got" << cc2 <<"." << std::endl;
1210+
}
12151211

1216-
// Three codec supported AVVideoCodecTypeH264 AVVideoCodecTypeJPEG AVVideoCodecTypeHEVC
1217-
// On iPhone 3G H264 is not supported.
1218-
if (fourcc ==CV_FOURCC('J','P','E','G') || fourcc ==CV_FOURCC('j','p','e','g') ||
1219-
fourcc ==CV_FOURCC('M','J','P','G') || fourcc ==CV_FOURCC('m','j','p','g')){
1220-
codec = [AVVideoCodecTypeJPEGcopy];// Use JPEG codec if specified, otherwise H264
1221-
}elseif(fourcc ==CV_FOURCC('H','2','6','4') || fourcc ==CV_FOURCC('a','v','c','1')){
1222-
codec = [AVVideoCodecTypeH264copy];
1212+
// Three codec supported AVVideoCodecTypeH264 AVVideoCodecTypeJPEG AVVideoCodecTypeHEVC
1213+
// On iPhone 3G H264 is not supported.
1214+
if (fourcc ==CV_FOURCC('J','P','E','G') || fourcc ==CV_FOURCC('j','p','e','g') ||
1215+
fourcc ==CV_FOURCC('M','J','P','G') || fourcc ==CV_FOURCC('m','j','p','g')){
1216+
codec = [AVVideoCodecTypeJPEGcopy];// Use JPEG codec if specified, otherwise H264
1217+
}elseif(fourcc ==CV_FOURCC('H','2','6','4') || fourcc ==CV_FOURCC('a','v','c','1')){
1218+
codec = [AVVideoCodecTypeH264copy];
12231219
// Available since iOS 11
12241220
#if TARGET_OS_VISION || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000)
1225-
}elseif(fourcc ==CV_FOURCC('H','2','6','5') || fourcc ==CV_FOURCC('h','v','c','1') ||
1226-
fourcc ==CV_FOURCC('H','E','V','C') || fourcc ==CV_FOURCC('h','e','v','c')){
1227-
if (@available(iOS11, *)) {
1228-
codec = [AVVideoCodecTypeHEVCcopy];
1221+
}elseif (fourcc ==CV_FOURCC('H','2','6','5') || fourcc ==CV_FOURCC('h','v','c','1') ||
1222+
fourcc ==CV_FOURCC('H','E','V','C') || fourcc ==CV_FOURCC('h','e','v','c')) {
1223+
if (@available(iOS11, *)) {
1224+
codec = [AVVideoCodecTypeHEVCcopy];
1225+
}else {
1226+
codec = [AVVideoCodecTypeH264copy];
1227+
}
1228+
#endif
12291229
}else {
1230-
codec = [AVVideoCodecTypeH264copy];
1230+
codec = [AVVideoCodecTypeH264copy];// default canonical H264.
12311231
}
1232-
#endif
1233-
}else{
1234-
codec = [AVVideoCodecTypeH264copy];// default canonical H264.
1235-
}
1236-
1237-
//NSLog(@"Path: %@", path);
12381232

1239-
NSError *error =nil;
1233+
NSError *error =nil;
12401234

1235+
// Wire the writer:
1236+
// Supported file types:
1237+
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
12411238

1242-
// Make sure the file does not already exist. Necessary to overwrite??
1243-
/*
1244-
NSFileManager *fileManager = [NSFileManager defaultManager];
1245-
if ([fileManager fileExistsAtPath:path]){
1246-
[fileManager removeItemAtPath:path error:&error];
1247-
}
1248-
*/
1239+
mMovieWriter = [[AVAssetWriteralloc]initWithURL:[NSURLfileURLWithPath:path]
1240+
fileType:fileType
1241+
error:&error];
12491242

1250-
// Wire the writer:
1251-
// Supported file types:
1252-
// AVFileTypeQuickTimeMovie AVFileTypeMPEG4 AVFileTypeAppleM4V AVFileType3GPP
1243+
NSDictionary *videoSettings = [NSDictionarydictionaryWithObjectsAndKeys:
1244+
codec, AVVideoCodecKey,
1245+
[NSNumbernumberWithInt:movieSize.width], AVVideoWidthKey,
1246+
[NSNumbernumberWithInt:movieSize.height], AVVideoHeightKey,
1247+
nil];
12531248

1254-
mMovieWriter = [[AVAssetWriteralloc]initWithURL:[NSURLfileURLWithPath:path]
1255-
fileType:fileType
1256-
error:&error];
1257-
//NSParameterAssert(mMovieWriter);
1249+
mMovieWriterInput = [[AVAssetWriterInput
1250+
assetWriterInputWithMediaType:AVMediaTypeVideo
1251+
outputSettings:videoSettings]retain];
12581252

1259-
NSDictionary *videoSettings = [NSDictionarydictionaryWithObjectsAndKeys:
1260-
codec, AVVideoCodecKey,
1261-
[NSNumbernumberWithInt:movieSize.width], AVVideoWidthKey,
1262-
[NSNumbernumberWithInt:movieSize.height], AVVideoHeightKey,
1263-
nil];
1253+
[mMovieWriteraddInput:mMovieWriterInput];
12641254

1265-
mMovieWriterInput = [[AVAssetWriterInput
1266-
assetWriterInputWithMediaType:AVMediaTypeVideo
1267-
outputSettings:videoSettings]retain];
1255+
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptoralloc]initWithAssetWriterInput:mMovieWriterInputsourcePixelBufferAttributes:nil];
12681256

1269-
//NSParameterAssert(mMovieWriterInput);
1270-
//NSParameterAssert([mMovieWriter canAddInput:mMovieWriterInput]);
1257+
//Start a session:
1258+
[mMovieWriterstartWriting];
1259+
[mMovieWriterstartSessionAtSourceTime:kCMTimeZero];
12711260

1272-
[mMovieWriteraddInput:mMovieWriterInput];
1273-
1274-
mMovieWriterAdaptor = [[AVAssetWriterInputPixelBufferAdaptoralloc]initWithAssetWriterInput:mMovieWriterInputsourcePixelBufferAttributes:nil];
1275-
1276-
1277-
//Start a session:
1278-
[mMovieWriterstartWriting];
1279-
[mMovieWriterstartSessionAtSourceTime:kCMTimeZero];
1280-
1281-
1282-
if(mMovieWriter.status == AVAssetWriterStatusFailed){
1283-
NSLog(@"%@", [mMovieWriter.errorlocalizedDescription]);
1284-
// TODO: error handling, cleanup. Throw exception?
1285-
// return;
1261+
if (mMovieWriter.status == AVAssetWriterStatusFailed) {
1262+
NSLog(@"%@", [mMovieWriter.errorlocalizedDescription]);
1263+
// TODO: error handling, cleanup. Throw exception?
1264+
}
12861265
}
1287-
1288-
[localpooldrain];
12891266
}
12901267

12911268

12921269
CvVideoWriter_AVFoundation::~CvVideoWriter_AVFoundation() {
1293-
NSAutoreleasePool* localpool = [[NSAutoreleasePoolalloc]init];
1294-
1295-
[mMovieWriterInputmarkAsFinished];
1296-
[mMovieWriterfinishWritingWithCompletionHandler:^() {
1297-
[mMovieWriterrelease];
1298-
[mMovieWriterInputrelease];
1299-
[mMovieWriterAdaptorrelease];
1300-
[pathrelease];
1301-
[codecrelease];
1302-
[fileTyperelease];
1303-
argbimage.release();
1304-
1305-
[localpooldrain];
1306-
}];
1270+
@autoreleasepool {
1271+
[mMovieWriterInputmarkAsFinished];
1272+
[mMovieWriterfinishWritingWithCompletionHandler:^() {
1273+
@autoreleasepool {
1274+
[mMovieWriterrelease];
1275+
[mMovieWriterInputrelease];
1276+
[mMovieWriterAdaptorrelease];
1277+
[pathrelease];
1278+
[codecrelease];
1279+
[fileTyperelease];
1280+
argbimage.release();
1281+
}
1282+
}];
1283+
}
13071284
}
13081285

13091286
voidCvVideoWriter_AVFoundation::write(cv::InputArray image) {
1310-
NSAutoreleasePool* localpool = [[NSAutoreleasePoolalloc]init];
1311-
1312-
// writer status check
1313-
if (![mMovieWriterInputisReadyForMoreMediaData] ||mMovieWriter.status != AVAssetWriterStatusWriting ) {
1314-
NSLog(@"[mMovieWriterInput isReadyForMoreMediaData] Not ready for media data or ...");
1315-
NSLog(@"mMovieWriter.status:%d. Error:%@", (int)mMovieWriter.status, [mMovieWriter.error localizedDescription]);
1316-
[localpooldrain];
1317-
return;
1318-
}
1287+
@autoreleasepool {
1288+
// writer status check
1289+
if (![mMovieWriterInputisReadyForMoreMediaData] ||mMovieWriter.status != AVAssetWriterStatusWriting) {
1290+
NSLog(@"[mMovieWriterInput isReadyForMoreMediaData] Not ready for media data or ...");
1291+
NSLog(@"mMovieWriter.status:%d. Error:%@", (int)mMovieWriter.status, [mMovieWriter.error localizedDescription]);
1292+
return;
1293+
}
13191294

1320-
BOOL success =FALSE;
1295+
BOOL success =FALSE;
13211296

1322-
if (image.size().height!=movieSize.height || image.size().width!=movieSize.width){
1323-
std::cout<<"Frame size does not match video size."<<std::endl;
1324-
[localpooldrain];
1325-
return;
1326-
}
1297+
if (image.size().height != movieSize.height || image.size().width != movieSize.width) {
1298+
std::cout <<"Frame size does not match video size." << std::endl;
1299+
return;
1300+
}
13271301

1328-
if (movieColor) {
1329-
//assert(image->nChannels == 3);
1330-
cv::cvtColor(image, argbimage, cv::COLOR_BGR2BGRA);
1331-
}else{
1332-
//assert(image->nChannels == 1);
1333-
cv::cvtColor(image, argbimage, cv::COLOR_GRAY2BGRA);
1334-
}
1335-
//IplImage -> CGImage conversion
1336-
CGColorSpaceRef colorSpace =CGColorSpaceCreateDeviceRGB();
1337-
NSData *nsData = [NSDatadataWithBytes:argbimage.datalength:argbimage.total() * argbimage.elemSize()];
1338-
CGDataProviderRef provider =CGDataProviderCreateWithCFData((CFDataRef)nsData);
1339-
CGImageRef cgImage =CGImageCreate(argbimage.size().width, argbimage.size().height,
1340-
8,32, argbimage.step[0],
1341-
colorSpace,kCGImageAlphaLast|kCGBitmapByteOrderDefault,
1342-
provider,NULL,false,kCGRenderingIntentDefault);
1343-
1344-
//CGImage -> CVPixelBufferRef conversion
1345-
CVPixelBufferRef pixelBuffer =NULL;
1346-
CFDataRef cfData =CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
1347-
int status =CVPixelBufferCreateWithBytes(NULL,
1348-
movieSize.width,
1349-
movieSize.height,
1350-
kCVPixelFormatType_32BGRA,
1351-
(void*)CFDataGetBytePtr(cfData),
1352-
CGImageGetBytesPerRow(cgImage),
1353-
NULL,
1354-
0,
1355-
NULL,
1356-
&pixelBuffer);
1357-
if(status ==kCVReturnSuccess){
1358-
success = [mMovieWriterAdaptorappendPixelBuffer:pixelBuffer
1359-
withPresentationTime:CMTimeMake(frameCount, movieFPS)];
1360-
}
1302+
if (movieColor) {
1303+
cv::cvtColor(image, argbimage, cv::COLOR_BGR2BGRA);
1304+
}else {
1305+
cv::cvtColor(image, argbimage, cv::COLOR_GRAY2BGRA);
1306+
}
13611307

1362-
//cleanup
1363-
CFRelease(cfData);
1364-
CVPixelBufferRelease(pixelBuffer);
1365-
CGImageRelease(cgImage);
1366-
CGDataProviderRelease(provider);
1367-
CGColorSpaceRelease(colorSpace);
1308+
//IplImage -> CGImage conversion
1309+
CGColorSpaceRef colorSpace =CGColorSpaceCreateDeviceRGB();
1310+
NSData *nsData = [NSDatadataWithBytes:argbimage.datalength:argbimage.total() * argbimage.elemSize()];
1311+
CGDataProviderRef provider =CGDataProviderCreateWithCFData((CFDataRef)nsData);
1312+
CGImageRef cgImage =CGImageCreate(argbimage.size().width, argbimage.size().height,
1313+
8,32, argbimage.step[0],
1314+
colorSpace,kCGImageAlphaLast|kCGBitmapByteOrderDefault,
1315+
provider,NULL,false,kCGRenderingIntentDefault);
1316+
1317+
//CGImage -> CVPixelBufferRef conversion
1318+
CVPixelBufferRef pixelBuffer =NULL;
1319+
CFDataRef cfData =CGDataProviderCopyData(CGImageGetDataProvider(cgImage));
1320+
int status =CVPixelBufferCreateWithBytes(NULL,
1321+
movieSize.width,
1322+
movieSize.height,
1323+
kCVPixelFormatType_32BGRA,
1324+
(void*)CFDataGetBytePtr(cfData),
1325+
CGImageGetBytesPerRow(cgImage),
1326+
NULL,
1327+
0,
1328+
NULL,
1329+
&pixelBuffer);
1330+
if (status ==kCVReturnSuccess) {
1331+
success = [mMovieWriterAdaptorappendPixelBuffer:pixelBuffer
1332+
withPresentationTime:CMTimeMake(frameCount, movieFPS)];
1333+
}
13681334

1369-
[localpooldrain];
1335+
//cleanup
1336+
CFRelease(cfData);
1337+
CVPixelBufferRelease(pixelBuffer);
1338+
CGImageRelease(cgImage);
1339+
CGDataProviderRelease(provider);
1340+
CGColorSpaceRelease(colorSpace);
13701341

1371-
if (success) {
1372-
frameCount++;
1373-
//NSLog(@"Frame #%d", frameCount);
1374-
return;
1375-
}else{
1376-
NSLog(@"Frame appendPixelBuffer failed.");
1377-
return;
1342+
if (success) {
1343+
frameCount++;
1344+
return;
1345+
}else {
1346+
NSLog(@"Frame appendPixelBuffer failed.");
1347+
return;
1348+
}
13781349
}
1379-
13801350
}
13811351

1382-
#pragma clang diagnostic pop
1352+
#pragma clang diagnostic pop

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp