AVAssetExportSession SLOW - ios

I am using AVAssetExportSession to export audio files. It is working, though in a speed that is practical for use. I am setting up my exporter, getting my AVAsset, and starting the export. Here is the code. Any suggestions or insight will help.
[exporter exportAsynchronouslyWithCompletionHandler:^{
NSLog(#"we are now exporting");
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed: {
// log error to text view
NSError *exportError = exporter.error;
NSLog (#"AVAssetExportSessionStatusFailed: %#", exportError);
break;
}
case AVAssetExportSessionStatusCompleted: {
NSLog (#"AVAssetExportSessionStatusCompleted");
// set up AVPlayer
NSData *data = [NSData dataWithContentsOfURL:exportURL];
break;
}
case AVAssetExportSessionStatusUnknown: { NSLog (#"AVAssetExportSessionStatusUnknown"); break;}
case AVAssetExportSessionStatusExporting: { NSLog (#"AVAssetExportSessionStatusExporting"); break;}
case AVAssetExportSessionStatusCancelled: { NSLog (#"AVAssetExportSessionStatusCancelled"); break;}
case AVAssetExportSessionStatusWaiting: { NSLog (#"AVAssetExportSessionStatusWaiting"); break;}
default: { NSLog (#"didn't get export status"); break;}
}
[exporter release];
[exportURL release];
}];

You're probably causing some kind of conversion - that will be slow (not that much faster than realtime). Make sure you're using the passthrough preset, AVAssetExportPresetPassthrough.

Related

How to send large file as chunks via MCSession NSOutputStream

I want to send large video file to connected peer in chunks via NSOutputStream
I am using below code.
NSError *error;
self.outputStream = [_appDelegate.mcManager.session startStreamWithName:#"Mystream" toPeer:[[_appDelegate.mcManager.session connectedPeers] objectAtIndex:0] error:&error];
At receiver side NSStream delegate not receiving entire send data.
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
switch(eventCode) {
case NSStreamEventEndEncountered:
break;
case NSStreamEventHasBytesAvailable:
if ([aStream isKindOfClass:[NSInputStream class]]) {
}
break;
case NSStreamEventErrorOccurred:
break;
case NSStreamEventHasSpaceAvailable:
break;
case NSStreamEventNone:
break;
case NSStreamEventOpenCompleted:
break;
}
}

AFNetworkReachabilityManager return NO all the time

[[AFNetworkReachabilityManager sharedManager] startMonitoring];
AFNetworkReachabilityManager*manger =[AFNetworkReachabilityManager sharedManager];
BOOL is=[manger isReachable];
Why does it return NO all the time? I do know I connect the internet with wifi.
Requires some time to Determine network status.
So,isReachable right after startMonitoring will always return false.
You need check isReachable inside setReachabilityStatusChangeBlock ;
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){
NSLog(#"network staus changed");
//check for network related flag
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring] will take little bit time to return proper value.
I'm using this code and this works for me!
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Rechability : %#", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusNotReachable:
{
// NO Internet Connection.
break;
}
case AFNetworkReachabilityStatusReachableViaWWAN:
{
break;
}
case AFNetworkReachabilityStatusReachableViaWiFi:
{
break;
}
case AFNetworkReachabilityStatusUnknown:
{
break;
}
default: break;
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
Do following steps, this is working code in my project.
Step 1:
//AppDelegate.m
[self startMonitoringTheNetwork];// Call this method didFinishLaunchingWithOptions
Step 2:
#pragma mark - Interenet Connection Status
-(void)startMonitoringTheNetwork {
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
//available
break;
case AFNetworkReachabilityStatusNotReachable:
//not available
break;
default:
break;
}
}];
//start monitoring
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
}
Step 3:
Add following class level method to CommonClass.h
+ (BOOL) isInternetConnected;
Step 4:
And implement above method to CommonClass.m
+(BOOL) isInternetConnected {
BOOL isConnected = NO;
if (!isConnected) {
isConnected = [AFNetworkReachabilityManager sharedManager].reachable;
}
return isConnected;
}
Step 5:
Now you are ready to access to the internet status everywhere by importing that CommonClass.h i.e #import "CommonClass.h"
Bool isInternetConnected = [CommonClass isInternetConnected];
Note : Step 3 & 4 are not compulsory, you can directly access if you want.
In the latest Version of AFNetworking,
Reachability should be monitered when the app is launched,ie
you should write the below code in the AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method, so that the Rechability manager starts monitering the status when the application starts.
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Rechability : %#", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusNotReachable:
{
// NO Internet Connection.
break;
}
case AFNetworkReachabilityStatusReachableViaWWAN:
{
break;
}
case AFNetworkReachabilityStatusReachableViaWiFi:
{
break;
}
case AFNetworkReachabilityStatusUnknown:
{
break;
}
default: break;
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
If you want to know the status before performing some operation you can use:
[[AFNetworkReachabilityManager sharedManager] isReachable];
If you want to know immediately if network is cut off, then you can post a NSNotification so that you can receive it anywhere and perform some operation

Writing to NSOutputStream cause high cpu usage

While instrumenting my app I found that CPU usage jumps to 90% when writing data to output stream. Specifically, when network speed is very high. When I profile it With Timer instrument, found that most of the cpu is used for NSStream delegate call. Please Help to optimize writing technic as to low down the cpu usage.
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventOpenCompleted: {
_isConnected = YES;
if([self.delegate respondsToSelector:#selector(isFTPConnectionFoundForUpload:)])
[self.delegate performSelector:#selector(isFTPConnectionFoundForUpload:) withObject:_isConnected?#"YES":#"NO"];
} break;
case NSStreamEventHasSpaceAvailable: {
bytesWritten = [self.producerStream write:&self.buffer[0] maxLength:512];
if (bytesWritten == -1) {
[self stopSendWithStatus:#"Network write error"];
}
} break;
case NSStreamEventErrorOccurred: {
NSLog(#"producer stream error %#", [aStream streamError]);
[self stopSendWithStatus:#"Stream open error"];
} break;
case NSStreamEventEndEncountered: {
} break;
default: {
} break;
}
}

AVAssetExportSession send cancel export

I am making a video app where I create a new video using AVAssetExportSession. While the video is being created I want to give the user ability to cancel video creation. The problem I have is that I do not know how can I send a cancellation request to AVAssetExportSession as I assume it's running on the main thread. Once it starts I have no idea how can I send a stop request?
I tried this but it doesn't work
- (IBAction) startBtn
{
....
// Export
exportSession = [[AVAssetExportSession alloc] initWithAsset:[composition copy] presetName:AVAssetExportPresetHighestQuality];
[exportSession setOutputFileType:#"com.apple.quicktime-movie"];
exportSession.outputURL = outputMovieURL;
exportSession.videoComposition = mainComposition;
//NSLog(#"Went Here 7 ...");
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status])
{
case AVAssetExportSessionStatusCancelled:
NSLog(#"Canceled ...");
break;
case AVAssetExportSessionStatusCompleted:
{
NSLog(#"Complete ... %#",outputURL); // moview url
break;
}
case AVAssetExportSessionStatusFailed:
{
NSLog(#"Faild=%# ...",exportSession.error);
break;
}
case AVAssetExportSessionStatusExporting:
NSLog(#"Exporting.....");
break;
}
}];
}
- (IBAction) cancelBtn
{
exportSession = nil;
}
You can cancel an export session by sending it the message cancelExport.
To accomplish this, you simply need to have an ivar (or property) which holds the current active export session:
#property (nonatomic, strong) AVAssetExportSession* exportSession;
Initialize the property:
- (IBAction) startBtn {
if (self.exportSession == nil) {
self.exportSession = [[AVAssetExportSession alloc] initWithAsset:[composition copy]
presetName:AVAssetExportPresetHighestQuality];
...
[self.exportSession exportAsynchronouslyWithCompletionHandler:^{
self.exportSession = nil;
....
}];
}
else {
// there is an export session already
}
}
In order to cancel the session:
- (IBAction) cancelBtn
{
[self.exportSession cancelExport];
self.exportSession = nil;
}
Hint: For a better user experience, you should disable/enable "Cancel" and "Start Export" buttons accordingly.

AVAssetExportSession progress gets stuck on ipad but not on simulator

This piece of code works fine on the simulator. However, when I try to run the export on my iPad, it always hangs at progress value 0.14583-ish. Can somebody help me figure out why? been stuck on this for quite awhile.
Here is my code:
NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:composition];
if ([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) {
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:composition presetName:AVAssetExportPresetLowQuality];
exportSession.outputURL = [NSURL fileURLWithPath:[[ShowDAO getUserDocumentDir] stringByAppendingString:exportFilename]];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
CMTime start = CMTimeMakeWithSeconds(0, 1);
CMTime duration = CMTimeMakeWithSeconds(1000, 1);
CMTimeRange range = CMTimeRangeMake(start, duration);
exportSession.timeRange = range;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch ([exportSession status]) {
case AVAssetExportSessionStatusCompleted:
NSLog(#"Export Completed");
break;
case AVAssetExportSessionStatusFailed:
NSLog(#"Export failed: %#", [[exportSession error] localizedDescription]);
break;
case AVAssetExportSessionStatusCancelled:
NSLog(#"Export cancelled");
break;
default:
break;
}
}];
while(exportSession.progress != 1.0){
NSLog(#"loading... : %f",exportSession.progress);
sleep(1);
}
[exportSession release];
}
while(exportSession.progress != 1.0){
NSLog(#"loading... : %f",exportSession.progress);
sleep(1);
}
This while loop is blocking the main thread. The NSLog might not be able to fire properly. Try it without the while loop?

Resources