Media Picker: Support preview for selected video

This commit is contained in:
giomfo
2016-01-20 11:24:58 +01:00
parent 092ac321f4
commit d141268548
+235 -59
View File
@@ -57,7 +57,10 @@ static void *RecordingContext = &RecordingContext;
NSMutableArray *userAlbums;
MXKImageView* imageValidationView;
MXKImageView* validationView;
MPMoviePlayerController *videoPlayer;
UIButton *videoPlayerControl;
}
@property (nonatomic) UIBackgroundTaskIdentifier backgroundRecordingID;
@@ -102,11 +105,8 @@ static void *RecordingContext = &RecordingContext;
// Adjust camera preview ratio
[self handleScreenOrientation];
if (!_mediaTypes)
{
// Set default media type
self.mediaTypes = @[(NSString *)kUTTypeImage];
}
// Force UI refresh according to selected media types - Set default media type if none.
self.mediaTypes = _mediaTypes ? _mediaTypes : @[(NSString *)kUTTypeImage];
// Check camera access before set up AV capture
[self checkDeviceAuthorizationStatus];
@@ -236,6 +236,48 @@ static void *RecordingContext = &RecordingContext;
}];
}
#pragma mark -
- (void)setMediaTypes:(NSArray *)mediaTypes
{
if ([mediaTypes indexOfObject:(NSString *)kUTTypeImage] != NSNotFound)
{
if ([mediaTypes indexOfObject:(NSString *)kUTTypeMovie] != NSNotFound)
{
self.cameraModeButton.hidden = NO;
isVideoCaptureMode = NO;
}
else
{
self.cameraModeButton.hidden = YES;
isVideoCaptureMode = NO;
}
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_capture"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_capture"] forState:UIControlStateHighlighted];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_video"] forState:UIControlStateNormal];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_video"] forState:UIControlStateHighlighted];
}
else if ([mediaTypes indexOfObject:(NSString *)kUTTypeMovie] != NSNotFound)
{
self.cameraModeButton.hidden = YES;
isVideoCaptureMode = YES;
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateHighlighted];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_picture"] forState:UIControlStateNormal];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_picture"] forState:UIControlStateHighlighted];
}
if (_mediaTypes != mediaTypes)
{
_mediaTypes = mediaTypes;
[self reloadRecentCapturesCollection];
[self reloadUserLibraryAlbums];
}
}
#pragma mark - Navigation bar handling
- (void)scrollToCameraPreview
@@ -278,36 +320,7 @@ static void *RecordingContext = &RecordingContext;
}
}
#pragma mark -
- (void)setMediaTypes:(NSArray *)mediaTypes
{
_mediaTypes = mediaTypes;
if ([_mediaTypes indexOfObject:(NSString *)kUTTypeImage] != NSNotFound)
{
if ([_mediaTypes indexOfObject:(NSString *)kUTTypeMovie] != NSNotFound)
{
self.cameraModeButton.hidden = NO;
isVideoCaptureMode = NO;
}
else
{
self.cameraModeButton.hidden = YES;
isVideoCaptureMode = NO;
}
}
else if ([_mediaTypes indexOfObject:(NSString *)kUTTypeMovie] != NSNotFound)
{
self.cameraModeButton.hidden = YES;
isVideoCaptureMode = YES;
}
[self reloadRecentCapturesCollection];
[self reloadUserLibraryAlbums];
}
#pragma mark -
#pragma mark - UI Refresh/Update
- (void)reloadRecentCapturesCollection
{
@@ -435,10 +448,13 @@ static void *RecordingContext = &RecordingContext;
if (isVideoCaptureMode)
{
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateHighlighted];
}
self.cameraCaptureButton.enabled = YES;
}
#pragma mark - Validation step
- (void)didSelectAsset:(PHAsset *)asset
{
PHContentEditingInputRequestOptions *editOptions = [[PHContentEditingInputRequestOptions alloc] init];
@@ -448,24 +464,44 @@ static void *RecordingContext = &RecordingContext;
if (contentEditingInput.mediaType == PHAssetMediaTypeImage)
{
[self validateSelectedImage:contentEditingInput.displaySizeImage responseHandler:^(BOOL isValidated) {
if (isValidated)
{
// Here the fullSizeImageURL is related to a local file path
NSData *data = [NSData dataWithContentsOfURL:contentEditingInput.fullSizeImageURL];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
// Use displaySizeImage to validate the selection
[self validateSelectedImage:contentEditingInput.displaySizeImage responseHandler:^(BOOL isValidated) {
// Send the original image by considering its asset url
[self.delegate mediaPickerController:self didSelectImage:image withURL:contentEditingInput.fullSizeImageURL];
}
}];
if (isValidated)
{
// Retrieve the fullSizeImage thanks to its local file path
NSData *data = [NSData dataWithContentsOfURL:contentEditingInput.fullSizeImageURL];
UIImage *image = [UIImage imageWithData:data];
// Send the original image
[self.delegate mediaPickerController:self didSelectImage:image withURL:contentEditingInput.fullSizeImageURL];
}
}];
});
}
else if (contentEditingInput.mediaType == PHAssetMediaTypeVideo)
{
if ([contentEditingInput.avAsset isKindOfClass:[AVURLAsset class]])
{
AVURLAsset *avURLAsset = (AVURLAsset*)contentEditingInput.avAsset;
[self.delegate mediaPickerController:self didSelectVideo:[avURLAsset URL]];
dispatch_async(dispatch_get_main_queue(), ^{
// Validate first the selected video
[self validateSelectedVideo:[avURLAsset URL] responseHandler:^(BOOL isValidated) {
if (isValidated)
{
[self.delegate mediaPickerController:self didSelectVideo:[avURLAsset URL]];
}
}];
});
}
else
{
@@ -480,11 +516,11 @@ static void *RecordingContext = &RecordingContext;
// Add a preview to let the user validates his selection
__weak typeof(self) weakSelf = self;
imageValidationView = [[MXKImageView alloc] initWithFrame:CGRectZero];
imageValidationView.stretchable = YES;
validationView = [[MXKImageView alloc] initWithFrame:CGRectZero];
validationView.stretchable = YES;
// the user validates the image
[imageValidationView setRightButtonTitle:[NSBundle mxk_localizedStringForKey:@"ok"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
[validationView setRightButtonTitle:[NSBundle mxk_localizedStringForKey:@"ok"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
// Dismiss the image view
@@ -494,7 +530,7 @@ static void *RecordingContext = &RecordingContext;
}];
// the user wants to use an other image
[imageValidationView setLeftButtonTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
[validationView setLeftButtonTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
// dismiss the image view
@@ -503,17 +539,117 @@ static void *RecordingContext = &RecordingContext;
handler (NO);
}];
imageValidationView.image = selectedImage;
[imageValidationView showFullScreen];
validationView.image = selectedImage;
[validationView showFullScreen];
}
- (void)validateSelectedVideo:(NSURL*)selectedVideoURL responseHandler:(void (^)(BOOL isValidated))handler
{
// Add a preview to let the user validates his selection
__weak typeof(self) weakSelf = self;
validationView = [[MXKImageView alloc] initWithFrame:CGRectZero];
validationView.stretchable = NO;
// the user validates the image
[validationView setRightButtonTitle:[NSBundle mxk_localizedStringForKey:@"ok"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
// Dismiss the image view
[strongSelf dismissImageValidationView];
handler (YES);
}];
// the user wants to use an other image
[validationView setLeftButtonTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
// dismiss the image view
[strongSelf dismissImageValidationView];
handler (NO);
}];
// Display first video frame
videoPlayer = [[MPMoviePlayerController alloc] initWithContentURL:selectedVideoURL];
if (videoPlayer)
{
[videoPlayer setShouldAutoplay:NO];
videoPlayer.scalingMode = MPMovieScalingModeAspectFit;
videoPlayer.controlStyle = MPMovieControlStyleNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayerThumbnailImageRequestDidFinishNotification:)
name:MPMoviePlayerThumbnailImageRequestDidFinishNotification
object:nil];
[videoPlayer requestThumbnailImagesAtTimes:@[@0.0f] timeOption:MPMovieTimeOptionNearestKeyFrame];
}
videoPlayerControl = [UIButton buttonWithType:UIButtonTypeCustom];
[videoPlayerControl addTarget:self action:@selector(controlVideoPlayer) forControlEvents:UIControlEventTouchUpInside];
videoPlayerControl.frame = CGRectMake(0, 0, 44, 44);
[videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateNormal];
[videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateHighlighted];
[validationView addSubview:videoPlayerControl];
videoPlayerControl.autoresizingMask = (UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
[validationView showFullScreen];
videoPlayerControl.center = validationView.center;
}
- (void)dismissImageValidationView
{
if (imageValidationView)
if (validationView)
{
[imageValidationView dismissSelection];
[imageValidationView removeFromSuperview];
imageValidationView = nil;
if (videoPlayer)
{
[videoPlayer stop];
[videoPlayer.view removeFromSuperview];
videoPlayer = nil;
[videoPlayerControl removeFromSuperview];
videoPlayerControl = nil;
}
[validationView dismissSelection];
[validationView removeFromSuperview];
validationView = nil;
}
}
- (void)controlVideoPlayer
{
// Check whether the video player is already playing
if (videoPlayer.view.superview)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[videoPlayer stop];
[videoPlayer.view removeFromSuperview];
[videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateNormal];
[videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateHighlighted];
}
else
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayerPlaybackDidFinishNotification:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
CGRect frame = validationView.imageView.frame;
frame.origin = CGPointZero;
videoPlayer.view.frame = frame;
videoPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[validationView.imageView addSubview:videoPlayer.view];
[videoPlayer play];
[videoPlayerControl setImage:[UIImage imageNamed:@"camera_stop"] forState:UIControlStateNormal];
[videoPlayerControl setImage:[UIImage imageNamed:@"camera_stop"] forState:UIControlStateHighlighted];
[validationView bringSubviewToFront:videoPlayerControl];
}
}
@@ -884,13 +1020,17 @@ static void *RecordingContext = &RecordingContext;
if (isVideoCaptureMode)
{
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_capture"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_capture"] forState:UIControlStateHighlighted];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_video"] forState:UIControlStateNormal];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_video"] forState:UIControlStateHighlighted];
isVideoCaptureMode = NO;
}
else
{
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateHighlighted];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_picture"] forState:UIControlStateNormal];
[self.cameraModeButton setImage:[UIImage imageNamed:@"camera_picture"] forState:UIControlStateHighlighted];
isVideoCaptureMode = YES;
}
}
@@ -1016,6 +1156,8 @@ static void *RecordingContext = &RecordingContext;
// Reload recent pictures collection
[self reloadRecentCapturesCollection];
// Reload user albums display
[self reloadUserLibraryAlbums];
} failure:nil];
}
@@ -1074,11 +1216,13 @@ static void *RecordingContext = &RecordingContext;
self.cameraModeButton.enabled = NO;
self.cameraSwitchButton.enabled = NO;
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_stop"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_stop"] forState:UIControlStateHighlighted];
self.cameraCaptureButton.enabled = YES;
}
else
{
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateNormal];
[self.cameraCaptureButton setImage:[UIImage imageNamed:@"camera_record"] forState:UIControlStateHighlighted];
self.cameraCaptureButton.enabled = YES;
}
});
@@ -1102,16 +1246,29 @@ static void *RecordingContext = &RecordingContext;
lockInterfaceRotation = NO;
[MXKMediaManager saveMediaToPhotosLibrary:outputFileURL isImage:NO success:^(NSURL *assetURL) {
[MXKMediaManager saveMediaToPhotosLibrary:outputFileURL isImage:NO success:^(NSURL *videoURL) {
// Remove the temporary file
[[NSFileManager defaultManager] removeItemAtURL:outputFileURL error:nil];
// Validate the new captured video
[self validateSelectedVideo:videoURL responseHandler:^(BOOL isValidated) {
if (isValidated)
{
// Send the original image by considering its asset url
[self.delegate mediaPickerController:self didSelectVideo:videoURL];
}
}];
// Relaunch preview
[self reset];
// Reload recent pictures collection
[self reloadRecentCapturesCollection];
// Reload user albums display
[self reloadUserLibraryAlbums];
} failure:nil];
@@ -1309,4 +1466,23 @@ static void *RecordingContext = &RecordingContext;
[self didSelectAsset:asset];
}
#pragma mark - Movie player observer
- (void)moviePlayerThumbnailImageRequestDidFinishNotification:(NSNotification *)notification
{
if (validationView)
{
validationView.image = [[notification userInfo] objectForKey:MPMoviePlayerThumbnailImageKey];
[validationView bringSubviewToFront:videoPlayerControl];
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerThumbnailImageRequestDidFinishNotification object:nil];
}
- (void)moviePlayerPlaybackDidFinishNotification:(NSNotification *)notification
{
// Remove player view from superview
[self controlVideoPlayer];
}
@end