MPMoviePlayerController not working properly - objective-c

I am making an application in which i am trying to play a video. The video starts properly but the video screen changes in black color after 4 sec. I dont know what is the problem.
also when i am setting player.movieplayer.shouldautoplay = NO, there is no effect of this line, video starts automatically.
Here is Code:
NSString *urlString = [[NSBundle mainBundle] pathForResource:#"Movie" ofType:#"m4v"];
NSURL *urlObj = [NSURL fileURLWithPath:urlString];
UIGraphicsBeginImageContext(CGSizeMake(1,1));
MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:urlObj];
UIGraphicsEndImageContext();
[player.view setBounds:self.view.bounds];
// when playing from server source type shoud be MPMovieSourceTypeStreaming
[player.moviePlayer setMovieSourceType:MPMovieSourceTypeStreaming];
[player.moviePlayer setScalingMode:MPMovieScalingModeAspectFill];
player.moviePlayer.shouldAutoplay = NO;
[self.view addSubview:player.view];
[player.moviePlayer play];
Am i missing something here??
I tried to get the total duration of video (using duration property of mpmovieplayercontroller) but its showing 0.0. how to get the duration of video??

NSString *urlString = [[NSBundle mainBundle] pathForResource:#"Movie" ofType:#"m4v"];
NSURL *urlObj = [NSURL fileURLWithPath:urlString];
UIGraphicsBeginImageContext(CGSizeMake(1,1));
MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:urlObj];
UIGraphicsEndImageContext();
[player.view setBounds:self.view.bounds];
// when playing from server source type shoud be MPMovieSourceTypeStreaming
[player.moviePlayer setMovieSourceType:MPMovieSourceTypeStreaming]; // I was missing this line therefore video was not playing
[player.moviePlayer setScalingMode:MPMovieScalingModeAspectFill];
[self.view addSubview:player.view];
[player.moviePlayer play];

There are several issues here:
For this type of usage (integrating the player into your view), you should be using MPMoviePlayerController, not MPMoviePlayerViewController. Use MPMoviePlayerViewController when you want to have a self-contained view controller which can be presented using presentMoviePlayerViewControllerAnimated:.
Assuming you are using ARC, the main problem is that nothing is keeping a reference to your player object. As a consequence, the player is disappearing shortly after you create it. You should keep a reference to it by assigning it to a property or instance variable of your view controller.
For a full example of this, see Till's excellent answer to a similar question.
I'm not sure what your intended purpose of the UIGraphicsBeginImageContext and UIGraphicsEndImageContext calls are, but I can't see that they're needed here.
As for shouldAutoplay = NO, the video is still starting because you are calling play immediately afterwards.
The player's duration property only contains a useful value after a MPMovieDurationAvailableNotification has been received. You'll need to do something similar to the following to have access to the actual duration:
__weak MediaPlayerController *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:MPMovieDurationAvailableNotification object:self.player queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
NSLog(#"Movie duration: %lf", weakSelf.player.duration);
}];
Use removeObserver:name:object: to remove the observer when you are done.

Related

Objective C iOS WKWebView Background

Hopefully someone can help.
I've got an application that currently uses the UIWebview to play audio, which works even if the device is locked as I enable mediaPlaybackAllowsAirPlay.
However I started to move the code to use the new WKWebView and I've enabled mediaPlaybackAllowsAirPlay, However when I press the lock button, the WebView stops playing the audio.
Any ideas how I can get WKWebview to behave like the UIWebView?
Update, Here's an example of my code:
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
theConfiguration.userContentController = wkUController;
theConfiguration.allowsAirPlayForMediaPlayback = YES;
webViewActive = [[WKWebView alloc] initWithFrame:viewForWeb.frame configuration:theConfiguration];
webViewActive.navigationDelegate = self;
webViewActive.frame = viewForWeb.bounds;
[webViewActive setAutoresizingMask: UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
[viewForWeb addSubview:webViewActive];
NSURL *nsurl=[NSURL URLWithString:#"URL TO AUDIO"];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[webViewActive loadRequest:nsrequest];
Thanks

Handling UIActivityViewController

First I couldn't find anyone else having this problem. Working on a game in spritekit - there is a mainTitle.h/m and gamePlay.h/m files. Below is code for the share button to share your progress via text, fb, twitter, ect. The code below is located in the gamePlay.m inside a touch method. The code works however after the user selects to send his/her score view text message - the new message window slides up and then the game appears to restart and load mainTitle.m scene. Any ideas as to why this happens?
-(void)share {
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 1.0);
[self.view.drawViewHierarchyInRect:self.view.boundsafterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSString *message = [NSString stringWithFormat:#"messge"];
NSString *urlString = [NSString stringWithFormat#"www..."];
NSURL *gmURL = [NSURL URLWithString:urlString];
UIActivityViewController *actVC = [[UIActivityViewController alloc]
initWithActivityItems:#[message, gmURL, image] applicationActivites:nil];
actVC.excludedActivityTypes = #[UIActivityTypePrint, UIActivityTypeAriDrop];
UIViewController *viewControl = self.view.window.rootViewController;
[viewControl presentViewController:actVC animated:YES completion:nil];
}
-(void)touchBegins ... {
[self share];
}
Probably its not a good idea to call share method in touchBegan, since it might be fired multiple times in some conditions. Use i.e. UIButton instead

how to switch camera mode to video mode using GPUImage in ios

I am making app like Instagram .i am using GPUImage framework ,in this i have to take photos and videos and share. i able to capture photos using this framework and now i have to capture video but i am struggling how to change camera mode photos to video. any help and tutorial then its very good for me. I used this code camera for photos mode.
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
self.imagepicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
self.overlayView.frame = self.imagepicker.cameraOverlayView.frame;
self.imagepicker.cameraOverlayView = self.overlayView;
self.overlayView = nil;
CGSize result = [[UIScreen mainScreen] bounds].size;
self.imagepicker.showsCameraControls = NO;
self.imagepicker.allowsEditing = NO;
self.imagepicker.wantsFullScreenLayout = NO;
// self.imagepicker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
}
else{
self.imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
In my case, I'm using GPUImage to do both (pictures and videos). Therefore I've created two objects: one of type GPUImageStillCamera(pictures) and other of type GPUImageVideoCamera (videos).
So whenever you need to switch between cameras you basically stop the GPUImageStillCamera capture and initialize a video camera (note that you have to adapt this snippet to your project):
func initializeVideoCamera() {
// Stop the capture of GPUImageStillCamera
stillCamera.stopCameraCapture()
videoCamera = GPUImageVideoCamera.init(sessionPreset: AVCaptureSessionPreset1920x1080, cameraPosition: .Back)
videoCamera?.outputImageOrientation = .Portrait
videoCamera?.addTarget(filter)
// If a file already exists, AVAssetWriter won't let you record new frames, so delete the old movie
unlink(pathToMovieFile)
initializeWriteWithPath(pathToMovieFile)
videoCamera?.startCameraCapture()
}

ALAssetRepresentation fullResolutionImage never returns

I am writing a multithreaded application which needs to upload photos from the ALAssetsLibrary en masse in the background. So I have an NSOperation subclass which finds the appropriate ALAsset via the asset's URL and adds the image to an upload queue.
In the upload queue for the current ALAsset, I need to get the metadata from the image, but I've encountered a problem: both the -metadata and the -fullResolutionImage methods never return when they are called on the ALAssetRepresentation of the ALAsset. They simply hang there indefinitely. I tried printing the value of each of these methods in LLDB, but it hung the debugger up, and I ended up killing Xcode, signal 9 style. These methods are being called on a background queue.
I am testing these on an iPad 2. This is the method in which the ALAsset is added to the upload queue when it is found in the success block of -assetForURL:resultBlock:failureBlock:
- (void)addMediaToUploadQueue:(ALAsset *)media {
#autoreleasepool {
ALAssetRepresentation *defaultRepresentation = [media defaultRepresentation];
CGImageRef fullResolutionImage = [defaultRepresentation fullResolutionImage];
// Return if the user is trying to upload an image which has already been uploaded
CGFloat scale = [defaultRepresentation scale];
UIImageOrientation orientation = [defaultRepresentation orientation];
UIImage *i = [UIImage imageWithCGImage:fullResolutionImage scale:scale orientation:orientation];
if (![self isImageUnique:i]) return;
NSDictionary *imageDictionary = [self dictionaryForAsset:media withImage:i];
dispatch_async(self.background_queue, ^{
NSManagedObjectContext *ctx = [APPDELEGATE createManagedObjectContextForThread];
[ctx setUndoManager:nil];
[ctx performBlock:^{
ImageEntity *newImage = [NSEntityDescription insertNewObjectForEntityForName:#"ImageEntity"
inManagedObjectContext:ctx];
[newImage updateWithDictionary:imageDictionary
inManagedObjectContext:ctx];
[ctx save:nil];
[APPDELEGATE saveContext];
dispatch_async(dispatch_get_main_queue(), ^{
[self.fetchedResultsController performFetch:nil];
});
if (!currentlyUploading) {
currentlyUploading = YES;
[self uploadImage:newImage];
}
}];
});
}
}
I had a similar problem and I was tearing my hair out trying to figure it out.
Turns out while I had thought I setup a singleton for ALAssetsLibrary, my code was not calling it properly and some ALAssets were returning an empty 'fullResolutionImage'
In all of my NSLogs I must have missed the most important message from Xcode:
"invalid attempt to access ALAssetPrivate past the lifetime of its owning ALAssetsLibrary"
Follow this link
http://www.daveoncode.com/2011/10/15/solve-xcode-error-invalid-attempt-to-access-alassetprivate-past-the-lifetime-of-its-owning-alassetslibrary/
I hope that helps

How does NSImage's data retaining behaviour work?

I have a method that constantly loads new image data from the web. Whenever all data for an image has arrived, it is forwarded to a delegate like this:
NSImage *img = [[NSImage alloc] initWithData:dataDownloadedFromWeb];
if([[self delegate] respondsToSelector:#selector(imageArrived:)]) {
[[self delegate] imageArrived:img];
}
[img release];
In imageArrived: the image data is assigned to an NSImageView:
- (void)imageArrived:(NSImage *)img
{
[imageView1 setImage:img];
}
This works nicely, the image is being displayed and updated with every new download cycle. I have profiled my application with Instruments to ensure that there is no leaking - it doesn't show any leaking. However, if I check with Instruments' Activity Monitor, I can see my application grabbing more and more memory with time, roughly increasing by the size of the downloaded images. If I omit [imageView1 setImage:img], memory usage stays constant. My question is: how is that happening? Is my code leaking? How does the NSImage instance within NSImageView determine when to release its data? Thanks for your answers!
When you do initWithData, the retain count on the data is incremented by one. Releasing the image does not change the retain count on the data. That's where your memory is going. The image structures are coming and going the way you want, but the data chunks are accumulating.
save the data handle separately and clean that out after disposing of the nsimage, and all should be well:
(id) olddata = 0; // global or something with persistence
your_routine
{
(id) newdata = dataDownloadedFromWeb;
NSImage *img = [[NSImage alloc] initWithData: newdata];
if([[self delegate] respondsToSelector:#selector(imageArrived:)])
{
[[self delegate] imageArrived:img];
}
[img release];
if (olddata) [olddata release];
olddata = newdata;
}
cleanup
{
if (olddata) [olddata release];
olddata = 0;
}