mirror of
https://github.com/blanking003/cx-cocos.git
synced 2025-04-23 15:29:00 +00:00
414 lines
13 KiB
Plaintext
414 lines
13 KiB
Plaintext
|
||
#import "videoImpl.h"
|
||
|
||
#import <AVKit/AVKit.h>
|
||
#import "AppController.h"
|
||
#import "videoIntf.h"
|
||
|
||
@implementation VideoView
|
||
{
|
||
UIViewController* contentController;
|
||
|
||
//contentController 包含以下内容
|
||
AVPlayerViewController* moviePlayer;
|
||
UIView* tapView;
|
||
UIView* actionView;
|
||
|
||
//actionView 包含以下内容
|
||
UILabel* lblTimelen;
|
||
UILabel* lblTimelenTotal;
|
||
UIButton* btnPause;
|
||
UIButton* btnResume;
|
||
UIButton* btnClose;
|
||
UISlider* slider;
|
||
|
||
bool defaultShowBar; //默认是否显示控制栏,默认false
|
||
bool sliderTouchDown;
|
||
bool seekDisabled;
|
||
|
||
int currTime;
|
||
int priorTime;
|
||
bool playing;
|
||
|
||
NSTimer* timer;
|
||
}
|
||
|
||
-(id) initWithFrame:(CGRect)frame
|
||
{
|
||
[super initWithFrame:frame];
|
||
|
||
CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);
|
||
|
||
moviePlayer = [[AVPlayerViewController alloc] init];
|
||
moviePlayer.showsPlaybackControls = NO;
|
||
moviePlayer.view.frame = rect;
|
||
|
||
contentController = [[UIViewController alloc] init];
|
||
contentController.view.frame = rect;
|
||
[contentController addChildViewController:moviePlayer];
|
||
[contentController.view addSubview:moviePlayer.view];
|
||
[self addSubview:contentController.view];
|
||
|
||
self.userInteractionEnabled = false;
|
||
|
||
moviePlayer.view.backgroundColor = [UIColor colorWithRed:0.01f green:0.01f blue:0.01f alpha:1.0f];
|
||
|
||
return self;
|
||
}
|
||
|
||
-(void) setPosition:(float)left top:(float)top
|
||
{
|
||
[self setCenter: CGPointMake(left + self.bounds.size.width/2, top + self.bounds.size.height/2)];
|
||
}
|
||
|
||
-(void) setFullScreen:(bool)value
|
||
{
|
||
if (value)
|
||
{
|
||
[AppController.ins addView:contentController.view];
|
||
[AppController.ins.rootViewController setBarHideStatus:true];
|
||
if (!defaultShowBar)
|
||
[self showBar:true];
|
||
|
||
//获取视频宽度尺寸
|
||
CGSize videoSize = CGSizeZero;
|
||
NSArray *array = moviePlayer.player.currentItem.tracks;
|
||
for (AVPlayerItemTrack* track in array)
|
||
{
|
||
if ([track.assetTrack.mediaType isEqualToString:AVMediaTypeVideo])
|
||
{
|
||
videoSize = track.assetTrack.naturalSize;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//如果宽大于高,自动横屏
|
||
CGSize screen = UIScreen.mainScreen.bounds.size;
|
||
if (videoSize.width > videoSize.height)
|
||
{
|
||
[self updateViewSize:CGRectMake(0,0, screen.height, screen.width)];
|
||
contentController.view.center = CGPointMake(screen.width/2, screen.height/2);
|
||
CGAffineTransform transform = CGAffineTransformIdentity;
|
||
transform = CGAffineTransformRotate(transform, M_PI_2);
|
||
contentController.view.transform = transform;
|
||
}
|
||
else
|
||
{
|
||
[self updateViewSize:UIScreen.mainScreen.bounds];
|
||
contentController.view.center = CGPointMake(screen.width/2, screen.height/2);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
[AppController.ins.rootViewController setBarHideStatus:false];
|
||
CGAffineTransform transform = CGAffineTransformIdentity;
|
||
transform = CGAffineTransformRotate(transform, 0);
|
||
contentController.view.transform = transform;
|
||
[self addSubview:contentController.view];
|
||
[self updateViewSize:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
|
||
contentController.view.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
|
||
if (!defaultShowBar)
|
||
[self showBar:false];
|
||
}
|
||
}
|
||
|
||
-(void) updateViewSize:(CGRect)rect
|
||
{
|
||
contentController.view.frame = rect;
|
||
moviePlayer.view.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
|
||
tapView.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
|
||
actionView.frame = CGRectMake(0, rect.size.height-40, rect.size.width, 40);
|
||
|
||
int d = rect.size.width*0.1f;
|
||
btnClose.frame = CGRectMake(d-40, 0, 40, 40);
|
||
btnPause.frame = CGRectMake(rect.size.width-d, 0, 40, 40);
|
||
btnResume.frame = CGRectMake(rect.size.width-d, 0, 40, 40);
|
||
lblTimelen.frame = CGRectMake(d, 0, 60, 40);
|
||
lblTimelenTotal.frame = CGRectMake(rect.size.width-d-60, 0, 60, 40);
|
||
slider.frame = CGRectMake(d+70, 15, rect.size.width-d-70 - d-70, 10);
|
||
}
|
||
|
||
-(void) createBarView
|
||
{
|
||
if (actionView)
|
||
return;
|
||
|
||
//点击层
|
||
tapView = [[UIView alloc] init];
|
||
tapView.backgroundColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:0.0f];
|
||
tapView.userInteractionEnabled = YES;
|
||
[tapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(movieClick)]];
|
||
|
||
//操作栏
|
||
actionView = [[UIView alloc] init];
|
||
actionView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6f];
|
||
|
||
//进度条
|
||
slider = [[UISlider alloc] init];
|
||
slider.minimumTrackTintColor = [UIColor whiteColor];
|
||
slider.maximumTrackTintColor = [UIColor grayColor];
|
||
slider.minimumValue = 1;
|
||
slider.maximumValue = 10000;
|
||
slider.enabled = !seekDisabled;
|
||
[slider addTarget:self action:@selector(onSliderValueChanged) forControlEvents:UIControlEventValueChanged];
|
||
[slider addTarget:self action:@selector(onSliderTouchDown) forControlEvents:UIControlEventTouchDown];
|
||
[slider addTarget:self action:@selector(onSliderTouchUp) forControlEvents:UIControlEventTouchUpInside];
|
||
[slider addTarget:self action:@selector(onSliderTouchUp) forControlEvents:UIControlEventTouchUpOutside];
|
||
|
||
//当前播放时间
|
||
lblTimelen = [[UILabel alloc] init];
|
||
lblTimelen.text = @"";
|
||
lblTimelen.font = [UIFont fontWithName:@"Helvetica-Bold" size:14];
|
||
lblTimelen.textColor = [UIColor colorWithRed:200/255.0 green:200/255.0 blue:200/255.0 alpha:1];
|
||
lblTimelen.textAlignment = NSTextAlignmentRight;
|
||
|
||
//总时长
|
||
lblTimelenTotal = [[UILabel alloc] init];
|
||
lblTimelenTotal.text = @"00:00";
|
||
lblTimelenTotal.font = [UIFont fontWithName:@"Helvetica-Bold" size:14];
|
||
lblTimelenTotal.textColor = [UIColor colorWithRed:200/255.0 green:200/255.0 blue:200/255.0 alpha:1];
|
||
lblTimelenTotal.textAlignment = NSTextAlignmentLeft;
|
||
|
||
//关闭按钮
|
||
btnClose = [self createButton:@"statics/video_stop.png"];
|
||
[btnClose addTarget:self action:@selector(closeClick) forControlEvents:UIControlEventTouchUpInside];
|
||
|
||
//暂停按钮
|
||
btnPause = [self createButton:@"statics/video_pause.png"];
|
||
[btnPause addTarget:self action:@selector(pause) forControlEvents:UIControlEventTouchUpInside];
|
||
|
||
//继续按钮
|
||
btnResume = [self createButton:@"statics/video_play.png"];
|
||
[btnResume addTarget:self action:@selector(resume) forControlEvents:UIControlEventTouchUpInside];
|
||
btnResume.hidden = YES;
|
||
|
||
[actionView addSubview:slider];
|
||
[actionView addSubview:lblTimelen];
|
||
[actionView addSubview:lblTimelenTotal];
|
||
[actionView addSubview:btnClose];
|
||
[actionView addSubview:btnPause];
|
||
[actionView addSubview:btnResume];
|
||
|
||
[contentController.view addSubview:tapView];
|
||
[contentController.view addSubview:actionView];
|
||
|
||
[self updateViewSize:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
|
||
}
|
||
|
||
-(void) play:(NSString*)url listenProgress:(bool)listenProgress;
|
||
{
|
||
currTime = 0;
|
||
playing = true;
|
||
|
||
if (moviePlayer.player)
|
||
[moviePlayer.player release];
|
||
|
||
if ([[url substringToIndex:4] caseInsensitiveCompare:@"http"] == NSOrderedSame)
|
||
{
|
||
moviePlayer.player = [AVPlayer playerWithURL:[NSURL URLWithString:url]];
|
||
}
|
||
else //from statics
|
||
{
|
||
NSString* fileName = [url substringToIndex:url.length-4];
|
||
NSString* filePath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"statics/%@", fileName] ofType:@".mp4"];
|
||
moviePlayer.player = [AVPlayer playerWithURL:[NSURL fileURLWithPath:filePath]];
|
||
}
|
||
[moviePlayer.player play];
|
||
|
||
if (listenProgress)
|
||
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateClock:) userInfo:nil repeats:YES];
|
||
}
|
||
|
||
-(void) seekToTime:(int)seconds
|
||
{
|
||
if (moviePlayer)
|
||
[moviePlayer.player seekToTime:CMTimeMake(seconds*10000, 10000) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
|
||
}
|
||
|
||
-(void) onSliderTouchDown
|
||
{
|
||
sliderTouchDown = true;
|
||
}
|
||
|
||
-(void) onSliderTouchUp
|
||
{
|
||
sliderTouchDown = false;
|
||
}
|
||
|
||
-(void) onSliderValueChanged
|
||
{
|
||
int value = round(slider.value);
|
||
int total = round(moviePlayer.player.currentItem.duration.value/moviePlayer.player.currentItem.duration.timescale);
|
||
int curr = round((double)value/10000.0f*(double)total);
|
||
int delta = priorTime - curr;
|
||
if (delta >= 1 || delta <= -1)
|
||
{
|
||
priorTime = curr;
|
||
[self seekToTime:curr];
|
||
lblTimelen.text = [self formatTime:curr];
|
||
}
|
||
}
|
||
|
||
-(void) updateClock:(NSTimer *)timer
|
||
{
|
||
if (!playing)
|
||
return;
|
||
int total = round(moviePlayer.player.currentItem.duration.value/moviePlayer.player.currentItem.duration.timescale);
|
||
if (total <= 0)
|
||
return;
|
||
int curr = round(moviePlayer.player.currentTime.value/moviePlayer.player.currentTime.timescale);
|
||
//NSLog(@"%lld, %d, %d", moviePlayer.player.currentTime.value, moviePlayer.player.currentTime.timescale, curr);
|
||
if (actionView != NULL && !sliderTouchDown)
|
||
{
|
||
lblTimelen.text = [self formatTime:curr];
|
||
if ([lblTimelenTotal.text isEqualToString:@"00:00"])
|
||
lblTimelenTotal.text = [self formatTime:total];
|
||
[slider setValue:round((double)curr/(double)total*10000.0f)];
|
||
}
|
||
if (curr > currTime)
|
||
currTime = curr;
|
||
|
||
VideoIntf::ins()->callJs(8, std::to_string(currTime));
|
||
|
||
if (curr >= total)
|
||
[self videoFinished];
|
||
}
|
||
|
||
-(NSString*) formatTime:(double)d
|
||
{
|
||
int c = (int)d;
|
||
int c_m = c/60;
|
||
int c_s = c%60;
|
||
return [NSString stringWithFormat:@"%s%d:%s%d", c_m < 10 ? "0" : "" , c_m, c_s < 10 ? "0" : "", c_s];
|
||
}
|
||
|
||
-(void) showBar:(bool)value
|
||
{
|
||
[self createBarView];
|
||
[actionView setHidden:!value];
|
||
}
|
||
|
||
-(void) lockSeek:(bool)value
|
||
{
|
||
seekDisabled = !value;
|
||
if (slider)
|
||
slider.enabled = !value;
|
||
}
|
||
|
||
-(void) pause
|
||
{
|
||
if (playing)
|
||
{
|
||
playing = false;
|
||
if (actionView)
|
||
{
|
||
btnPause.hidden = true;
|
||
btnResume.hidden = false;
|
||
}
|
||
if (moviePlayer)
|
||
[moviePlayer.player pause];
|
||
}
|
||
}
|
||
|
||
-(void) resume
|
||
{
|
||
if (!playing)
|
||
{
|
||
playing = true;
|
||
if (actionView)
|
||
{
|
||
btnPause.hidden = false;
|
||
btnResume.hidden = true;
|
||
}
|
||
if (moviePlayer)
|
||
{
|
||
int total = round(moviePlayer.player.currentItem.duration.value/moviePlayer.player.currentItem.duration.timescale);
|
||
int curr = round(moviePlayer.player.currentTime.value/moviePlayer.player.currentTime.timescale);
|
||
if (total > 0 && curr >= total)
|
||
[self seekToTime:0];
|
||
[moviePlayer.player play];
|
||
}
|
||
}
|
||
}
|
||
|
||
-(void) movieClick
|
||
{
|
||
if (actionView)
|
||
[actionView setHidden:!actionView.isHidden];
|
||
}
|
||
|
||
-(void) closeClick
|
||
{
|
||
[self setFullScreen:false];
|
||
}
|
||
|
||
-(void) close
|
||
{
|
||
[timer invalidate];
|
||
timer = nil;
|
||
playing = false;
|
||
|
||
[moviePlayer.player pause];
|
||
[moviePlayer.view removeFromSuperview];
|
||
[self removeFromSuperview];
|
||
}
|
||
|
||
-(void) videoFinished
|
||
{
|
||
playing = false;
|
||
if (actionView)
|
||
{
|
||
[actionView setHidden:false];
|
||
[btnPause setHidden:true];
|
||
[btnResume setHidden:false];
|
||
}
|
||
currTime = (int)moviePlayer.player.currentTime.value/moviePlayer.player.currentTime.timescale;
|
||
VideoIntf::ins()->callJs(3, std::to_string(currTime));
|
||
}
|
||
|
||
-(UIButton*)createButton:(NSString*)img
|
||
{
|
||
UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
|
||
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||
btn.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
|
||
|
||
UIImage *image = [UIImage imageNamed:img];
|
||
[btn setImage:image forState:UIControlStateNormal];
|
||
[btn setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
|
||
|
||
return btn;
|
||
}
|
||
|
||
-(void) playStateChange
|
||
{
|
||
// MPMoviePlaybackState state = [moviePlayer playbackState];
|
||
// switch (state)
|
||
// {
|
||
// case MPMoviePlaybackStatePaused:
|
||
// //mediaPlayerIntf->mediaCallback(1, 0);
|
||
// break;
|
||
// case MPMoviePlaybackStateStopped:
|
||
// //mediaPlayerIntf->mediaCallback(2, 0);
|
||
// break;
|
||
// case MPMoviePlaybackStatePlaying:
|
||
// if (currTime > [moviePlayer currentPlaybackTime])
|
||
// {
|
||
// [moviePlayer setCurrentPlaybackTime:currTime];
|
||
// currTime = (int)[moviePlayer currentPlaybackTime];
|
||
// }
|
||
// //mediaPlayerIntf->mediaCallback(0, 0);
|
||
// break;
|
||
// case MPMoviePlaybackStateInterrupted:
|
||
// break;
|
||
// case MPMoviePlaybackStateSeekingBackward:
|
||
// break;
|
||
// case MPMoviePlaybackStateSeekingForward:
|
||
// break;
|
||
// default:
|
||
// break;
|
||
// }
|
||
}
|
||
|
||
|
||
@end
|