//
|
// TZVideoPlayerController.m
|
// TZImagePickerController
|
//
|
// Created by 谭真 on 16/1/5.
|
// Copyright © 2016年 谭真. All rights reserved.
|
//
|
|
#import "TZVideoPlayerController.h"
|
#import <MediaPlayer/MediaPlayer.h>
|
#import "UIView+TZLayout.h"
|
#import "TZImageManager.h"
|
#import "TZAssetModel.h"
|
#import "TZImagePickerController.h"
|
#import "TZPhotoPreviewController.h"
|
#import "TZVideoCropController.h"
|
|
@interface TZVideoPlayerController () {
|
AVPlayer *_player;
|
AVPlayerLayer *_playerLayer;
|
UIButton *_playButton;
|
UIImage *_playButtonNormalImage;
|
UIImage *_cover;
|
NSString *_outputPath;
|
NSString *_errorMsg;
|
|
UIView *_toolBar;
|
UIButton *_doneButton;
|
UIButton *_editButton;
|
UIProgressView *_progress;
|
|
UIStatusBarStyle _originStatusBarStyle;
|
}
|
@property (assign, nonatomic) BOOL needShowStatusBar;
|
|
// iCloud无法同步提示UI
|
@property (nonatomic, strong) UIView *iCloudErrorView;
|
|
@end
|
|
#pragma clang diagnostic push
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
@implementation TZVideoPlayerController
|
|
- (void)viewDidLoad {
|
[super viewDidLoad];
|
self.needShowStatusBar = ![UIApplication sharedApplication].statusBarHidden;
|
self.view.backgroundColor = [UIColor blackColor];
|
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
|
if (tzImagePickerVc) {
|
self.navigationItem.title = tzImagePickerVc.previewBtnTitleStr;
|
}
|
[self configMoviePlayer];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:UIApplicationWillResignActiveNotification object:nil];
|
}
|
|
- (void)viewWillAppear:(BOOL)animated {
|
[super viewWillAppear:animated];
|
_originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
|
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
|
}
|
|
- (void)viewWillDisappear:(BOOL)animated {
|
[super viewWillDisappear:animated];
|
if (self.needShowStatusBar) {
|
[UIApplication sharedApplication].statusBarHidden = NO;
|
}
|
[UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle;
|
}
|
|
- (void)configMoviePlayer {
|
[[TZImageManager manager] getPhotoWithAsset:_model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
|
BOOL iCloudSyncFailed = !photo && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]];
|
self.iCloudErrorView.hidden = !iCloudSyncFailed;
|
if (!isDegraded && photo) {
|
self->_cover = photo;
|
self->_doneButton.enabled = YES;
|
self->_editButton.enabled = YES;
|
}
|
}];
|
[[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {
|
dispatch_async(dispatch_get_main_queue(), ^{
|
self->_player = [AVPlayer playerWithPlayerItem:playerItem];
|
self->_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self->_player];
|
self->_playerLayer.frame = self.view.bounds;
|
[self.view.layer addSublayer:self->_playerLayer];
|
[self addProgressObserver];
|
[self configPlayButton];
|
[self configBottomToolBar];
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:AVPlayerItemDidPlayToEndTimeNotification object:self->_player.currentItem];
|
});
|
}];
|
}
|
|
/// Show progress,do it next time / 给播放器添加进度更新,下次加上
|
- (void)addProgressObserver{
|
AVPlayerItem *playerItem = _player.currentItem;
|
UIProgressView *progress = _progress;
|
[_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
|
float current = CMTimeGetSeconds(time);
|
float total = CMTimeGetSeconds([playerItem duration]);
|
if (current) {
|
[progress setProgress:(current/total) animated:YES];
|
}
|
}];
|
}
|
|
- (void)configPlayButton {
|
_playButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
[_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal];
|
[_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted];
|
[_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside];
|
[self.view addSubview:_playButton];
|
}
|
|
- (void)configBottomToolBar {
|
_toolBar = [[UIView alloc] initWithFrame:CGRectZero];
|
CGFloat rgb = 34 / 255.0;
|
_toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7];
|
|
_doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
_doneButton.titleLabel.font = [UIFont systemFontOfSize:16];
|
if (!_cover) {
|
_doneButton.enabled = NO;
|
}
|
[_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside];
|
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
|
if (tzImagePickerVc) {
|
[_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal];
|
[_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
|
} else {
|
[_doneButton setTitle:[NSBundle tz_localizedStringForKey:@"Done"] forState:UIControlStateNormal];
|
[_doneButton setTitleColor:[UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0] forState:UIControlStateNormal];
|
}
|
[_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled];
|
[_toolBar addSubview:_doneButton];
|
[self.view addSubview:_toolBar];
|
|
if (tzImagePickerVc && tzImagePickerVc.allowEditVideo && roundf(self.model.asset.duration) > 1) {
|
_editButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
_editButton.titleLabel.font = [UIFont systemFontOfSize:16];
|
if (!_cover) {
|
_editButton.enabled = NO;
|
}
|
[_editButton addTarget:self action:@selector(editButtonClick) forControlEvents:UIControlEventTouchUpInside];
|
[_editButton setTitle:tzImagePickerVc.editBtnTitleStr forState:UIControlStateNormal];
|
[_editButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
|
[_editButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled];
|
[_toolBar addSubview:_editButton];
|
}
|
|
if (tzImagePickerVc.videoPreviewPageUIConfigBlock) {
|
tzImagePickerVc.videoPreviewPageUIConfigBlock(_playButton, _toolBar, _editButton, _doneButton);
|
}
|
}
|
|
- (UIStatusBarStyle)preferredStatusBarStyle {
|
TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController;
|
if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) {
|
return tzImagePicker.statusBarStyle;
|
}
|
return [super preferredStatusBarStyle];
|
}
|
|
#pragma mark - Layout
|
|
- (void)viewDidLayoutSubviews {
|
[super viewDidLayoutSubviews];
|
TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
|
|
BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height;
|
CGFloat statusBarHeight = isFullScreen ? [TZCommonTools tz_statusBarHeight] : 0;
|
CGFloat statusBarAndNaviBarHeight = statusBarHeight + self.navigationController.navigationBar.tz_height;
|
_playerLayer.frame = self.view.bounds;
|
CGFloat toolBarHeight = 44 + [TZCommonTools tz_safeAreaInsets].bottom;
|
_toolBar.frame = CGRectMake(0, self.view.tz_height - toolBarHeight, self.view.tz_width, toolBarHeight);
|
[_doneButton sizeToFit];
|
_doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, MAX(44, _doneButton.tz_width), 44);
|
_playButton.frame = CGRectMake(0, statusBarAndNaviBarHeight, self.view.tz_width, self.view.tz_height - statusBarAndNaviBarHeight - toolBarHeight);
|
if (tzImagePickerVc.allowEditVideo) {
|
_editButton.frame = CGRectMake(12, 0, 44, 44);
|
[_editButton sizeToFit];
|
_editButton.tz_height = 44;
|
}
|
if (tzImagePickerVc.videoPreviewPageDidLayoutSubviewsBlock) {
|
tzImagePickerVc.videoPreviewPageDidLayoutSubviewsBlock(_playButton, _toolBar, _editButton, _doneButton);
|
}
|
}
|
|
#pragma mark - Click Event
|
|
- (void)playButtonClick {
|
CMTime currentTime = _player.currentItem.currentTime;
|
CMTime durationTime = _player.currentItem.duration;
|
if (_player.rate == 0.0f) {
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"TZ_VIDEO_PLAY_NOTIFICATION" object:_player];
|
if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)];
|
[_player play];
|
[self.navigationController setNavigationBarHidden:YES];
|
_toolBar.hidden = YES;
|
_playButtonNormalImage = [_playButton imageForState:UIControlStateNormal];
|
[_playButton setImage:nil forState:UIControlStateNormal];
|
[UIApplication sharedApplication].statusBarHidden = YES;
|
} else {
|
[self pausePlayerAndShowNaviBar];
|
}
|
}
|
|
- (void)editButtonClick {
|
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
|
TZVideoCropController *videoCropVc = [[TZVideoCropController alloc] init];
|
videoCropVc.model = self.model;
|
videoCropVc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
|
videoCropVc.modalPresentationStyle = UIModalPresentationFullScreen;
|
videoCropVc.modalPresentationCapturesStatusBarAppearance = YES;
|
videoCropVc.imagePickerVc = imagePickerVc;
|
[self presentViewController:videoCropVc animated:YES completion:nil];
|
}
|
|
- (void)doneButtonClick {
|
if ([[TZImageManager manager] isAssetCannotBeSelected:_model.asset]) {
|
return;
|
}
|
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
|
if (imagePickerVc.allowEditVideo) {
|
[imagePickerVc showProgressHUD];
|
[[TZImageManager manager] getVideoOutputPathWithAsset:_model.asset presetName:imagePickerVc.presetName success:^(NSString *outputPath) {
|
[imagePickerVc hideProgressHUD];
|
self->_outputPath = outputPath;
|
[self dismissAndCallDelegateMethod];
|
} failure:^(NSString *errorMessage, NSError *error) {
|
[imagePickerVc hideProgressHUD];
|
self->_errorMsg = errorMessage;
|
[self dismissAndCallDelegateMethod];
|
}];
|
} else {
|
[self dismissAndCallDelegateMethod];
|
}
|
}
|
|
- (void)dismissAndCallDelegateMethod {
|
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
|
if (!imagePickerVc) {
|
[self dismissViewControllerAnimated:YES completion:nil];
|
return;
|
}
|
if (imagePickerVc.autoDismiss) {
|
[imagePickerVc dismissViewControllerAnimated:YES completion:^{
|
[self callDelegateMethod];
|
}];
|
} else {
|
[self callDelegateMethod];
|
}
|
}
|
|
- (void)callDelegateMethod {
|
TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
|
if (imagePickerVc.allowEditVideo) {
|
if (_outputPath) {
|
if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingAndEditingVideo:outputPath:error:)]) {
|
[imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingAndEditingVideo:self->_cover outputPath:self->_outputPath error:nil];
|
}
|
if (imagePickerVc.didFinishPickingAndEditingVideoHandle) {
|
imagePickerVc.didFinishPickingAndEditingVideoHandle(self->_cover, self->_outputPath, nil);
|
}
|
} else {
|
if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingAndEditingVideo:outputPath:error:)]) {
|
[imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingAndEditingVideo:nil outputPath:nil error:self->_errorMsg];
|
}
|
if (imagePickerVc.didFinishPickingAndEditingVideoHandle) {
|
imagePickerVc.didFinishPickingAndEditingVideoHandle(nil, nil, self->_errorMsg);
|
}
|
}
|
} else {
|
if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingVideo:sourceAssets:)]) {
|
[imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingVideo:_cover sourceAssets:_model.asset];
|
}
|
if (imagePickerVc.didFinishPickingVideoHandle) {
|
imagePickerVc.didFinishPickingVideoHandle(_cover,_model.asset);
|
}
|
}
|
}
|
|
#pragma mark - Notification Method
|
|
- (void)pausePlayerAndShowNaviBar {
|
[_player pause];
|
_toolBar.hidden = NO;
|
[self.navigationController setNavigationBarHidden:NO];
|
UIImage *normalImage = _playButtonNormalImage ?: [UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"];
|
[_playButton setImage:normalImage forState:UIControlStateNormal];
|
|
if (self.needShowStatusBar) {
|
[UIApplication sharedApplication].statusBarHidden = NO;
|
}
|
}
|
|
#pragma mark - lazy
|
- (UIView *)iCloudErrorView{
|
if (!_iCloudErrorView) {
|
_iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_statusBarHeight] + 44 + 10, self.view.tz_width, 28)];
|
UIImageView *icloud = [[UIImageView alloc] init];
|
icloud.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"];
|
icloud.frame = CGRectMake(20, 0, 28, 28);
|
[_iCloudErrorView addSubview:icloud];
|
UILabel *label = [[UILabel alloc] init];
|
label.frame = CGRectMake(53, 0, self.view.tz_width - 63, 28);
|
label.font = [UIFont systemFontOfSize:10];
|
label.textColor = [UIColor whiteColor];
|
label.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];
|
[_iCloudErrorView addSubview:label];
|
[self.view addSubview:_iCloudErrorView];
|
_iCloudErrorView.hidden = YES;
|
}
|
return _iCloudErrorView;
|
}
|
|
- (void)dealloc {
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
}
|
|
#pragma clang diagnostic pop
|
|
@end
|