Morgan
Morgan

Reputation: 1897

Mind boggling QTMovie export crash

Hey guys... I'm at my wits end here. I've been focusing on this issue for the last 3 days it seems, and I'm still no closer to solving it. I've got a queue of videos that I'm converting one after the other in a background thread. Most of the time it works as expected, but every so often, I get a weird crash, always at the same point. I can't for the life of me figure out why it's happening. I've got garbage collection enabled. Here is my conversion code.

Here is the stack trace.

Edit: After a bit more debugging, I am back to the conclusion that maybe it is garbage collector related. If I place the following line just before the line that converts the video, I get a drastic increase in the amount of these errors that I see...

[[NSGarbageCollector defaultCollector] collectExhaustively];

NSInvalidArgumentException

-[NSPathStore2 objectForKey:]: unrecognized selector sent to instance 0x1073570

(
    0   CoreFoundation                      0x92fc16ba __raiseError + 410
    1   libobjc.A.dylib                     0x901b4509 objc_exception_throw + 56
    2   CoreFoundation                      0x9300e90b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x92f67c36 ___forwarding___ + 950
    4   CoreFoundation                      0x92f67802 _CF_forwarding_prep_0 + 50
    5   QTKit                               0x903d3280 MovieProgressProc + 62
    6   QuickTime                           0x95a66062 convertFileProgress + 212
    7   QuickTime3GPP                       0x1e7bcaa2 Spit3GP2_Progress + 180
    8   QuickTime3GPP                       0x1e7c01d8 Spit3GP2_FromProceduresToDataRef + 3438
    9   CarbonCore                          0x90b0d054 _ZL38CallComponentFunctionCommonWithStoragePPcP19ComponentParametersPFlvEm + 54
    10  QuickTime3GPP                       0x1e7be33d Spit3GP2_ComponentDispatch + 129
    11  CarbonCore                          0x90b057c9 CallComponentDispatch + 29
    12  QuickTime                           0x95befb97 MovieExportFromProceduresToDataRef + 49
    13  QuickTime3GPP                       0x1e7bdf84 Spit3GP2_ToDataRef + 1987
    14  CarbonCore                          0x90b1865d callComponentStorage_4444444 + 63
    15  CarbonCore                          0x90b0d054 _ZL38CallComponentFunctionCommonWithStoragePPcP19ComponentParametersPFlvEm + 54
    16  QuickTime3GPP                       0x1e7be33d Spit3GP2_ComponentDispatch + 129
    17  CarbonCore                          0x90b057c9 CallComponentDispatch + 29
    18  QuickTime                           0x95befbe2 MovieExportToDataRef + 73
    19  QuickTime                           0x95a6e9bb ConvertMovieToDataRef_priv + 1690
    20  QuickTime                           0x95bdc591 ConvertMovieToDataRef + 71
    21  QTKit                               0x903e0954 -[QTMovie_QuickTime writeToDataReference:withAttributes:error:] + 2692
    22  QTKit                               0x903c5110 -[QTMovie_QuickTime writeToFile:withAttributes:error:] + 111
    23  Mevee                               0x0005871d -[ConversionQueue convertVideo:] + 509
    24  Mevee                               0x00058341 -[ConversionQueue startConvertingItems] + 145
    25  Foundation                          0x9520fbf0 -[NSThread main] + 45
    26  Foundation                          0x9520fba0 __NSThread__main__ + 1499
    27  libSystem.B.dylib                   0x9475a85d _pthread_start + 345
    28  libSystem.B.dylib                   0x9475a6e2 thread_start + 34
)

- (id) init
        {
            if(!(self = [super init])) return self;

            convertingIndex = 0;
            conversionPaths = [[NSMutableArray alloc] init];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/2 Fast 2 Furious/2 Fast 2 Furious.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/101 Dalmations/101 Dalmations.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/300/300.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/1408/1408.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/A Few Good Men/A Few Good Men.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/A Goofy Movie/A Goofy Movie.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/A Single Man/A Single Man.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/A View to a Kill/A View to a Kill.mp4"];
            [conversionPaths addObject:@"/Users/Morgan/Desktop/Convertable Media/Movies/Across the Universe/Across the Universe.mp4"];

            backgroundThread = [[NSThread alloc] initWithTarget:self selector:@selector(startConvertingItems) object:nil];
            [backgroundThread start];

            return self;
        }

        - (void) startProcessingQueue
        {

        }

        - (void) startConvertingItems
        {
            NSInteger iterations = 0;
            while(iterations < 100)
            {
                NSString* nextPath = [conversionPaths objectAtIndex:convertingIndex];

                NSLog(@"ITERATION %d", iterations);
                [self convertVideo:nextPath];

                convertingIndex += 1;
                if(convertingIndex >= [conversionPaths count])
                    convertingIndex = 0;

                iterations += 1;
            }
        }

        - (void) openMovieOnMainThread:(NSString*)path
        {
            NSError* error = nil;
            movie = [[QTMovie alloc] initWithFile:path error:&error];

            if(movie == nil || error != nil || ![movie detachFromCurrentThread])
                movie = nil;
        }

        - (void) closeMovieOnMainThread
        {
            //[movie attachToCurrentThread];
            //[movie release];
        }

        - (BOOL) convertVideo: (NSString*)path
        {
            [self performSelectorOnMainThread:@selector(openMovieOnMainThread:) withObject:path waitUntilDone:YES];

            if(movie == nil) {
                NSLog(@"ERROR OPENING MOVIE");
                return NO;
            }

            [QTMovie enterQTKitOnThreadDisablingThreadSafetyProtection];
            [movie attachToCurrentThread];
            [movie setDelegate:self];

            NSString* tempItemPath = @"/Users/Morgan/Desktop/test.mp4";

            NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithBool:YES], QTMovieExport,
                                   [NSNumber numberWithLong:'3gpp'], QTMovieExportType,
                                   nil];

            NSError* error = nil;

            if(![movie writeToFile:tempItemPath withAttributes:attrs error:&error]) {
                NSLog(@"ERROR CONVERTING MOVIE");
                return NO;
            }

            [movie invalidate];
            [movie detachFromCurrentThread];

            [QTMovie exitQTKitOnThread];
            [self performSelectorOnMainThread:@selector(closeMovieOnMainThread) withObject:nil waitUntilDone:YES];

            return YES;
        }

        - (BOOL)movie:(QTMovie *)aMovie shouldContinueOperation:(NSString *)op withPhase:(QTMovieOperationPhase)phase atPercent:(NSNumber *)percent withAttributes:(NSDictionary *)attributes
        {
            switch (phase) 
            {
                case QTMovieOperationBeginPhase:
                    NSLog(@"Conversion started");
                    break;
                case QTMovieOperationUpdatePercentPhase:
                    NSLog(@"Conversion progress: %f", [percent floatValue]);
                    break;
                case QTMovieOperationEndPhase:
                    NSLog(@"Conversion finished.");
                    break;
            }

            return YES;
        }

Upvotes: 1

Views: 366

Answers (1)

Morgan
Morgan

Reputation: 1897

Ahhh... I found out it was the stupid garbage collector. Reworked my app to work with reference counting rather than garbage collection, and smooth sailing. Has anyone else come across similar garbage collection bugs? I had a strong reference to a root object for my movie file, so I don't think that was the problem.

Upvotes: 1

Related Questions