Question

  1. I am trying to get an array of images from video. It is working well but I have a doubt that In which thread the completion handler get called.

  2. I called this method(generateCGImagesAsynchronouslyForTimes:) in new operation and I updated the UI in the completion handler. The UI get updated.

  3. But typically the UI updation doesn't happen in secondary thread?. My doubt is the completion handler called in current calling thread or main thread?

My Code is:

__block unsigned int i = 0;
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){

    i++;
    if(result == AVAssetImageGeneratorSucceeded){

        //Create a block to save the image in disk
        NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
            NSFileManager *fileMgr = [NSFileManager defaultManager];
            NSString *documentsDirectory = [NSHomeDirectory()
                                            stringByAppendingPathComponent:@"Documents"];
            NSError *error = nil;

            //Create file path for storing the image
            NSString *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"VideoFrames%i.png", i]];

            //Delete if already any image exist 
            if ([fileMgr fileExistsAtPath:videoOutputPath]){
                if ([fileMgr removeItemAtPath:videoOutputPath error:&error] != YES)
                    NSLog(@"Unable to delete file: %@", [error localizedDescription]);
            }

            //Convert the CGImageRef to UIImage
            UIImage *image = [UIImage imageWithCGImage:im];//**This line gives error: EXE_BAD_ACCESS**

            //Save the image
            if(![UIImagePNGRepresentation(image) writeToFile:videoOutputPath options:NSDataWritingFileProtectionNone error:&error])
                NSLog(@"Failed to save image at path %@", videoOutputPath);
        }];

        //Add the operation to the queue
        [self.imageWritingQueue addOperation:operation];
    }
   }
};
Was it helpful?

Solution 2

IIRC, yes. But you can test it, and to be safe you can wrap your code in a block which dispatches it to the main thread.

Generally speaking, the callback has to return to the main thread as the thread it's started from can't be guaranteed to be running a run loop if it isn't the main thread.

Unless you're scheduling the block you're creating in relation to other operations (dependencies) then I'm not sure what advantage the block gives you as the image loading is asynchronous so you can trigger it from the main thread without blocking anything.


From your comment, in that case you should switch your code around. Create the block operation inside the completion block which provides you with the image. Add each block operation to your queue. The block operation just takes the image and saves it to disk.

OTHER TIPS

The documentation states it clearly:

Concurrent Programming with AV Foundation

Callouts from AV Foundation—invocations of blocks, key-value observers, and notification handlers—are not guaranteed to be made on any particular thread or queue. Instead, AV Foundation invokes these handlers on threads or queues on which it performs its internal tasks. You are responsible for testing whether the thread or queue on which a handler is invoked is appropriate for the tasks you want to perform. If it’s not (for example, if you want to update the user interface and the callout is not on the main thread), you must redirect the execution of your tasks to a safe thread or queue that you recognize, or that you create for the purpose.

See also: AV Foundation Programming Guide

Edit:

The problem is, that you don't retain/release the CGImageRef image provided in parameter im since you use it in a NSBlockOperation later. You need to retain it outside the block (from the NSBlockOperation) before you invoke the block, and release it before the block returns (within the block).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top