Domanda

I tested the export method on an iOS application and it works fine. But when I moved it to a command line project the method exportAsynchronouslyWithCompletionHandler doesn't work.

I know the possible cause is the command line tool cannot handle asynchronous because it returns immediately. The method is pretty straightforward. It just take the address of the video, specify the quality, and output video to the output path. And here is my code.

void exportVideo(NSString *source, NSString *quality, NSString *filePath) {

NSString *preset = nil;

if ([quality isEqualToString:@"high"]) {
    preset = AVAssetExportPreset960x540; // 16:9 recommended resolution for iPhone 4
} else if ([quality isEqualToString:@"middle"]) {
    preset = AVAssetExportPresetAppleM4VWiFi; // 16:9 recommended resolution for iPhone 3GS
}

// Creat the asset from path
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:source] options:nil];    
if (!asset) NSLog(@"There is no video in the asset");

//NSLog(@"Print all presets: %@", [AVAssetExportSession allExportPresets]);
//NSLog(@"Print all presets compatible with the asset: %@", [AVAssetExportSession exportPresetsCompatibleWithAsset:asset]);

NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
//NSLog(@"All available presets: %@", compatiblePresets);

if ([compatiblePresets containsObject:preset]) {
    // create export session
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:preset]; 
    exportSession.outputURL = [NSURL fileURLWithPath:filePath]; // output path
    if (preset == AVAssetExportPreset960x540) {
        exportSession.outputFileType = AVFileTypeQuickTimeMovie;
    } else if (preset == AVAssetExportPresetAppleM4VWiFi) {
        exportSession.outputFileType = AVFileTypeAppleM4V; 
    }

    dispatch_semaphore_t sema = dispatch_semaphore_create(0); // Add this line

    // In command line tool, it doesn't execute this method 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        if (exportSession.status == AVAssetExportSessionStatusCompleted) {
            NSLog(@"AVAssetExportSessionStatusCompleted");
        } else if (exportSession.status == AVAssetExportSessionStatusFailed) {
            NSLog(@"AVAssetExportSessionStatusFailed");
            NSLog (@"FAIL %@", exportSession.error);
        } else {
            NSLog(@"Export Session Status: %ld", exportSession.status);
        }
        dispatch_semaphore_signal(sema); // Add this line
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); // Add this line
    dispatch_release(sema); // Add this line
} else {
    NSLog(@"Requested quality is not available.");
}

}

int main(int argc, const char * argv[])
{

@autoreleasepool {

    NSLog(@"Input the source file path:");
    char str[100];
    scanf("%s", str);
    NSString *inputSource = [NSString stringWithUTF8String:str];
    NSLog(@"Print the input source: %@", inputSource);

    NSLog(@"Input the output video quality:");
    scanf("%s", str);
    NSString *quality = [NSString stringWithUTF8String:str];
    NSLog(@"Print the quality: %@", quality);

    NSLog(@"Input the output file path:");
    scanf("%s", str);
    NSString *outputPath = [NSString stringWithUTF8String:str];
    NSLog(@"Print the output path: %@", outputPath);

    exportVideo(inputSource, quality, outputPath);
}
return 0;
}

**The usage of dispatch_semaphore_t works for my case. I got this idea from an answer from stackoverflow. Thanks for all you guys help so I share all the code.

È stato utile?

Soluzione

That is correct, you need to block your main function from returning until the asynch method is complete. The simplest way to do it is with wait flags. Either have a static boolean, or pass a boolean pointer to your export video function. Then while the boolean is false, sleep your main function. This is a terrible practice though, and is only relevant to this small situation since main only does this one thing. Don't do it in general.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top