Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #import <AVKit/AVKit.h>
- #import "C8VideoPlaybackController.h"
- #import "C8PlayerView.h"
- #import "C8AppDelegate.h"
- static void *C8VideoPlaybackControllerRateObservationContext = &C8VideoPlaybackControllerRateObservationContext;
- static void *C8VideoPlaybackControllerStatusObservationContext = &C8VideoPlaybackControllerStatusObservationContext;
- static void *C8VideoPlaybackControllerCurrentItemObservationContext = &C8VideoPlaybackControllerCurrentItemObservationContext;
- static NSTimeInterval const kHideControlsAnimationDuration = 1.0;
- static NSTimeInterval const kAutoHideControlsInterval = 2.0;
- @interface C8VideoPlaybackController ()<AVPlayerViewControllerDelegate>
- @property (nonatomic, weak) IBOutlet UIButton *closeButton;
- @property (nonatomic, weak) IBOutlet C8PlayerView *playerView;
- @property (weak, nonatomic) IBOutlet UIView *controlsView;
- @property (nonatomic) AVPlayer *player;
- @property (nonatomic,strong) C8AppDelegate *appDelegate;
- @property (weak, nonatomic) IBOutlet UISlider *progressControl;
- @property (strong, nonatomic) IBOutlet UIButton *playButton;
- @property (strong, nonatomic) IBOutlet UIButton *pauseButton;
- @property (weak, nonatomic) IBOutlet UIView *playPausePlaceholder;
- @property (nonatomic) id playerTimeObserver;
- @property (nonatomic) float previousRate;
- @property (nonatomic) BOOL isSeeking;
- @property (nonatomic, nullable) NSTimer *autoHideControlsViewTimer;
- @end
- @implementation C8VideoPlaybackController
- + (instancetype)instantiate {
- UIStoryboard *story = [UIStoryboard storyboardWithName:@"C8VideoPlayback" bundle:[CSDKSetup sdkBundle]];
- C8VideoPlaybackController *controller = (C8VideoPlaybackController *)[story instantiateViewControllerWithIdentifier:@"C8VideoPlaybackController"];
- [AVAudioSession.sharedInstance setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:NULL];
- [AVAudioSession.sharedInstance setActive:YES error:NULL];
- return controller;
- }
- -(void)viewDidLayoutSubviews{
- self.playerView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
- }
- - (void)setPlayer:(AVPlayer *)player {
- NSLog(@"assett percentageinY 7 c8prefetching 2 dataListItem 2: %@ - %@",[self.appDelegate.globalAvPlayers objectForKey:_videoURL],_videoURL);
- // NSMutableDictionary * myDictionary = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"dictionaryForAvPlayers"] mutableCopy];
- // NSLog(@"c8prefetching 1 dataListItem: %@ - %@ - %lu",[myDictionary objectForKey:_videoURL],_videoURL,(unsigned long)myDictionary.count);
- // if (nil == _videoURL) {
- // return;
- // }
- //
- // if(_videoURL){
- // self.appDelegate = (C8AppDelegate *)[UIApplication sharedApplication].delegate;
- //
- // NSLog(@"c8prefetching 2 dataListItem 0: %@ - %@",[self.appDelegate.globalAvPlayers objectForKey:_videoURL],_videoURL);
- // player=[self.appDelegate.globalAvPlayers objectForKey:_videoURL];
- // player = [myDictionary objectForKey:_videoURL];
- self.playerView.player = player;
- //(AVPlayer*)[self.appDelegate.globalAvPlayers objectForKey:_videoURL];
- // }
- }
- - (AVPlayer *)player {
- NSLog(@"assett percentageinY 6 c8prefetching 2 dataListItem 2: %@ - %@",[self.appDelegate.globalAvPlayers objectForKey:_videoURL],_videoURL);
- // if(_videoURL){
- // self.appDelegate = (C8AppDelegate *)[UIApplication sharedApplication].delegate;
- // self.playerView.player = [self.appDelegate.globalAvPlayers objectForKey:_videoURL];
- return self.playerView.player;
- // }
- }
- - (void)setVideoURL:(NSURL *)videoURL {
- NSLog(@"assett return before before %@ - %@",_videoURL,videoURL);
- if (_videoURL != videoURL){
- [self invalidateObservingForCurrentPlayer];
- NSLog(@"assett return before %@",_videoURL);
- _videoURL = [videoURL copy];
- if (nil == _videoURL) {
- NSLog(@"assett return %@",_videoURL);
- return;
- }
- self.appDelegate = (C8AppDelegate *)[UIApplication sharedApplication].delegate;
- // AVPlayerItem *tempItem = (AVPlayerItem*)[[self.appDelegate.globalAvPlayers objectForKey:_videoURL] currentItem];
- // [AVURLAsset URLAssetWithURL:_videoURL options:nil];
- // AVURLAsset *asset = (AVURLAsset *)tempItem.asset;
- AVURLAsset *asset=[AVURLAsset URLAssetWithURL:_videoURL options:nil];
- NSArray *requestedKeys = @[@"playable"];
- NSLog(@"assett percentageinY 8 c8prefetching 2 dataListItem 1: %@ - _videoURL:%@ - videoURL:%@",[self.appDelegate.globalAvPlayers objectForKey:_videoURL],_videoURL,videoURL);
- /* Tells the asset to load the values of any of the specified keys that are not already loaded. */
- [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
- ^{
- dispatch_async( dispatch_get_main_queue(), ^{
- NSLog(@"assett return prepareToPlayAsset %@ - %@",self.videoURL,[self.appDelegate.globalAvPlayers objectForKey:self.videoURL]);
- /* IMPORTANT: Must dispatch to main queue in order to operate on the AVPlayer and AVPlayerItem. */
- // if (self.player == nil) {
- [self prepareToPlayAsset:asset withKeys:requestedKeys];
- // }
- });
- }];
- }
- }
- - (UIStatusBarStyle)preferredStatusBarStyle
- {
- return UIStatusBarStyleLightContent;
- }
- - (AVLayerVideoGravity)videoGravity {
- return self.playerView.playerLayer.videoGravity;
- }
- - (void)setVideoGravity:(AVLayerVideoGravity)videoGravity {
- self.playerView.playerLayer.videoGravity = videoGravity;
- }
- - (BOOL)playbackControlHidden {
- return self.playPausePlaceholder.isHidden;
- }
- - (void)setPlaybackControlHidden:(BOOL)playbackControlHidden {
- self.playPausePlaceholder.hidden = playbackControlHidden;
- }
- - (BOOL)progressControlHidden {
- return self.progressControl.isHidden;
- }
- - (void)setProgressControlHidden:(BOOL)progressControlHidden {
- self.progressControl.hidden = progressControlHidden;
- if (!progressControlHidden && nil == self.playerTimeObserver) {
- [self setupPlayerTimeObserver];
- }
- }
- - (void)setProgressControlEnabled:(BOOL)progressControlEnabled {
- _progressControlEnabled = progressControlEnabled;
- if (_progressControlEnabled) {
- if (self.player.currentItem.status == AVPlayerItemStatusReadyToPlay)
- self.progressControl.enabled = YES;
- } else {
- self.progressControl.enabled = NO;
- }
- }
- - (BOOL)closeButtonHidden {
- (void)self.view;
- return self.closeButton.hidden;
- }
- - (void)setCloseButtonHidden:(BOOL)closeButtonHidden {
- (void)self.view;
- self.closeButton.hidden = closeButtonHidden;
- }
- - (BOOL)skipButtonHidden {
- (void)self.view;
- return self.skipButton.hidden;
- }
- - (void)setSkipButtonHidden:(BOOL)skipButtonHidden {
- (void)self.view;
- self.skipButton.hidden = skipButtonHidden;
- }
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.playPausePlaceholder.exclusiveTouch = YES;
- self.progressControl.exclusiveTouch = YES;
- }
- - (void)videoDidPlayToEnd:(NSNotification *)notification {
- if (notification.object != self.player.currentItem) {
- return;
- }
- dispatch_async(dispatch_get_main_queue(), ^{
- [self.delegate playbackControllerVideoDidPlayToEnd:self];
- });
- }
- - (void)viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
- }
- - (void)viewDidDisappear:(BOOL)animated {
- [super viewDidDisappear:animated];
- [self.player pause];
- }
- - (BOOL)playing {
- return self.player.rate > 0.0f && self.player.error == nil;
- }
- #pragma mark - actions
- - (IBAction)handleTapOnPlayerView:(id)sender {
- [self invalidateAutoHideControlsTimer];
- [self presentControls:YES];
- [self scheduleAutoHideControls];
- }
- - (IBAction)handleClose:(id)sender {
- [self.player pause];
- if ([self.delegate playbackControllerShouldClose:self]) {
- [self dismissViewControllerAnimated:YES completion:nil];
- }
- }
- - (IBAction)handleSkip:(id)sender {
- [self.player replaceCurrentItemWithPlayerItem:nil];
- if (nil!=self.delegate) {
- [self.delegate playbackControllerVideoSkippedVideo:self];
- }
- }
- - (IBAction)play:(id)sender {
- [self.player play];
- }
- - (IBAction)pause:(id)sender {
- [self.player pause];
- }
- #pragma mark - controls
- - (CMTime)playerItemDuration
- {
- AVPlayerItem *thePlayerItem = self.player.currentItem;
- if (thePlayerItem.status == AVPlayerItemStatusReadyToPlay)
- {
- return thePlayerItem.duration;
- }
- return kCMTimeInvalid;
- }
- #pragma mark - hide/present controls
- - (void)scheduleAutoHideControls {
- self.autoHideControlsViewTimer = [NSTimer scheduledTimerWithTimeInterval:kAutoHideControlsInterval target:self selector:@selector(autoHideControlsTimerFired:) userInfo:nil repeats:NO];
- }
- - (void)invalidateAutoHideControlsTimer {
- [self.autoHideControlsViewTimer invalidate];
- self.autoHideControlsViewTimer = nil;
- }
- - (void)autoHideControlsTimerFired:(NSTimer *)timer {
- NSAssert(timer == self.autoHideControlsViewTimer, @"");
- [self hideControls:YES];
- }
- - (void)presentControls:(BOOL)animated {
- self.controlsView.hidden = NO;
- if (animated) {
- self.controlsView.alpha = 0.0;
- [UIView animateWithDuration:kHideControlsAnimationDuration animations:
- ^{
- self.controlsView.alpha = 1.0;
- }];
- }
- }
- - (void)hideControls:(BOOL)animated {
- [self invalidateAutoHideControlsTimer];
- if (animated) {
- [UIView animateWithDuration:kHideControlsAnimationDuration animations:^{
- self.controlsView.alpha = 0.0;
- } completion:^(BOOL finished) {
- self.controlsView.hidden = YES;
- self.controlsView.alpha = 1.0;
- }];
- } else {
- self.controlsView.hidden = YES;
- }
- }
- #pragma mark - movie progress control
- -(void)setupPlayerTimeObserver
- {
- double interval = .1f;
- CMTime playerDuration = [self playerItemDuration];
- if (CMTIME_IS_INVALID(playerDuration))
- {
- return;
- }
- double duration = CMTimeGetSeconds(playerDuration);
- if (isfinite(duration))
- {
- interval = duration / 100.f;
- }
- @weakify(self)
- self.playerTimeObserver = [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC) queue:NULL usingBlock:^(CMTime time) {
- @strongify(self)
- [self syncProgressControl];
- }];
- }
- - (void)syncProgressControl
- {
- CMTime playerDuration = [self playerItemDuration];
- if (CMTIME_IS_INVALID(playerDuration))
- {
- self.progressControl.minimumValue = 0.0;
- return;
- }
- double duration = CMTimeGetSeconds(playerDuration);
- if (isfinite(duration))
- {
- float minValue = [self.progressControl minimumValue];
- float maxValue = [self.progressControl maximumValue];
- double time = CMTimeGetSeconds([self.player currentTime]);
- [self.progressControl setValue:(maxValue - minValue) * time / duration + minValue animated:YES];
- }
- }
- // The user is dragging the movie controller thumb to scrub through the movie.
- - (IBAction)beginScrubbing:(id)sender
- {
- self.previousRate = [self.player rate];
- [self.player setRate:0.f];
- /* Remove previous timer. */
- [self removePlayerTimeObserver];
- }
- // Set the player current time to match the scrubber position.
- - (IBAction)scrub:(id)sender
- {
- if ([sender isKindOfClass:[UISlider class]] && !self.isSeeking)
- {
- self.isSeeking = YES;
- UISlider* slider = sender;
- CMTime playerDuration = [self playerItemDuration];
- if (CMTIME_IS_INVALID(playerDuration)) {
- return;
- }
- double duration = CMTimeGetSeconds(playerDuration);
- if (isfinite(duration))
- {
- float minValue = [slider minimumValue];
- float maxValue = [slider maximumValue];
- float value = [slider value];
- double time = duration * (value - minValue) / (maxValue - minValue);
- [self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC) completionHandler:^(BOOL finished) {
- dispatch_async(dispatch_get_main_queue(), ^{
- self.isSeeking = NO;
- });
- }];
- }
- }
- }
- // The user has released the movie thumb control to stop scrubbing through the movie.
- - (IBAction)endScrubbing:(id)sender
- {
- if (nil == self.playerTimeObserver)
- {
- [self setupPlayerTimeObserver];
- }
- [self.player setRate:self.previousRate];
- self.previousRate = 0.f;
- }
- - (BOOL)isScrubbing
- {
- return self.previousRate > 0.f;
- }
- #pragma mark -
- #pragma mark Play, Stop buttons
- // Show the stop button in the movie player controller.
- - (void)showStopButton
- {
- UIView *presentingControl = [self.playPausePlaceholder subviews].firstObject;
- [presentingControl removeFromSuperview];
- [self.playPausePlaceholder addSubview:self.pauseButton];
- [self.playPausePlaceholder mas_makeConstraints:^(MASConstraintMaker *make) {
- make.edges.equalTo(self.pauseButton).with.insets(UIEdgeInsetsZero);
- }];
- }
- // Show the play button in the movie player controller.
- - (void)showPlayButton
- {
- UIView *presentingControl = [self.playPausePlaceholder subviews].firstObject;
- [presentingControl removeFromSuperview];
- [self.playPausePlaceholder addSubview:self.playButton];
- [self.playPausePlaceholder mas_makeConstraints:^(MASConstraintMaker *make) {
- make.edges.equalTo(self.playButton).with.insets(UIEdgeInsetsZero);
- }];
- }
- // If the media is playing, show the stop button; otherwise, show the play button.
- - (void)syncPlayPauseButtons
- {
- if (self.playing)
- {
- [self showStopButton];
- }
- else
- {
- [self showPlayButton];
- }
- }
- - (void)enablePlayerButtons
- {
- self.playButton.enabled = YES;
- self.pauseButton.enabled = YES;
- }
- - (void)disablePlayerButtons
- {
- self.playButton.enabled = NO;
- self.pauseButton.enabled = NO;
- }
- #pragma mark -
- -(void)removePlayerTimeObserver
- {
- if (self.playerTimeObserver)
- {
- [self.player removeTimeObserver:self.playerTimeObserver];
- self.playerTimeObserver = nil;
- }
- }
- - (void)invalidateObservingForCurrentPlayer {
- self.appDelegate = (C8AppDelegate *)[UIApplication sharedApplication].delegate;
- @try{
- // if ([self observationInfo]){
- NSLog(@"assett invalidate");
- [self invalidateAutoHideControlsTimer];
- [self removePlayerTimeObserver];
- [self.player removeObserver:self forKeyPath:@"rate"];
- [self.player.currentItem removeObserver:self forKeyPath:@"status"];
- [self.player pause];
- // self.playerView =nil;
- // self.controller
- self.player = nil;
- // }
- }
- @catch (NSException *e){
- NSLog(@"exception e: %@",e.description);
- }
- }
- #pragma mark -
- - (void)observeValueForKeyPath:(NSString*) path
- ofObject:(id)object
- change:(NSDictionary*)change
- context:(void*)context
- {
- /* AVPlayerItem "status" property value observer. */
- if (context == C8VideoPlaybackControllerStatusObservationContext)
- {
- [self syncPlayPauseButtons];
- AVPlayerItemStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
- switch (status)
- {
- /* Indicates that the status of the player is not yet known because
- it has not tried to load new media resources for playback */
- case AVPlayerItemStatusUnknown:
- {
- [self removePlayerTimeObserver];
- [self syncProgressControl];
- self.progressControl.enabled = NO;
- [self disablePlayerButtons];
- }
- break;
- case AVPlayerItemStatusReadyToPlay:
- {
- // NSArray<AVAssetTrack*>* tracks = self.player.currentItem.asset.tracks;
- // NSLog(@"tracks: %lu", tracks.count);
- /* Once the AVPlayerItem becomes ready to play, i.e.
- [playerItem status] == AVPlayerItemStatusReadyToPlay,
- its duration can be fetched from the item. */
- if ([self.delegate respondsToSelector:@selector(playbackControllerShouldAutoplay:)]) {
- if ([self.delegate playbackControllerShouldAutoplay:self]) {
- NSString *isEightFeedVisible = [[NSUserDefaults standardUserDefaults] stringForKey:@"isEightFeedVisible"];
- if ([isEightFeedVisible isEqualToString:@"YES"] )
- {
- [self.player play];
- }
- }
- }
- if ([self.delegate respondsToSelector:@selector(playbackControllerShouldStartMuted:)]) {
- self.player.muted = [self.delegate playbackControllerShouldStartMuted:self];
- }
- if (!self.progressControlHidden) {
- [self setupPlayerTimeObserver];
- }
- self.progressControl.enabled = self.progressControlEnabled;
- [self enablePlayerButtons];
- }
- break;
- case AVPlayerItemStatusFailed:
- {
- AVPlayerItem *playerItem = (AVPlayerItem *)object;
- [self assetFailedToPrepareForPlayback:playerItem.error];
- NSLog(@"failed to play: %@ - %@ - %@",playerItem.error.description,playerItem.error.localizedDescription,playerItem.error.debugDescription);
- }
- break;
- }
- }
- /* AVPlayer "rate" property value observer. */
- else if (context == C8VideoPlaybackControllerRateObservationContext)
- {
- if (self.progressControlHidden) { return; }
- NSAssert([NSThread currentThread].isMainThread, @"");
- [self syncPlayPauseButtons];
- if (!self.playing) {
- [self invalidateAutoHideControlsTimer];
- [self presentControls:YES];
- } else {
- [self hideControls:YES];
- }
- }
- else
- {
- [super observeValueForKeyPath:path ofObject:object change:change context:context];
- }
- }
- #pragma mark - error handling
- -(void)assetFailedToPrepareForPlayback:(NSError *)error
- {
- [self removePlayerTimeObserver];
- [self syncProgressControl];
- self.progressControl.enabled = NO;
- [self disablePlayerButtons];
- UIAlertController *alert = [UIAlertController alertControllerWithTitle:error.localizedDescription message:error.localizedFailureReason preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:NULL];
- [alert addAction:action];
- //[self presentViewController:alert animated:YES completion:NULL];
- }
- #pragma mark -
- - (void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
- {
- /* Make sure that the value of each key has loaded successfully. */
- for (NSString *thisKey in requestedKeys)
- {
- NSError *error = nil;
- AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
- if (keyStatus == AVKeyValueStatusFailed)
- {NSLog(@"assett not playable 1");
- [self assetFailedToPrepareForPlayback:error];
- return;
- }
- }
- /* Use the AVAsset playable property to detect whether the asset can be played. */
- if (!asset.playable)
- {NSLog(@"assett not playable");
- /* Generate an error describing the failure. */
- NSString *localizedDescription = NSLocalizedString(@"Item cannot be played", nil);
- NSString *localizedFailureReason = NSLocalizedString(@"The assets tracks were loaded, but can not be palyed", nil);
- NSDictionary *errorDict = @{
- NSLocalizedDescriptionKey: localizedDescription,
- NSLocalizedFailureReasonErrorKey: localizedFailureReason
- };
- NSError *assetCannotBePlayedError = [NSError errorWithDomain:@"StitchedStreamPlayer" code:0 userInfo:errorDict];
- [self assetFailedToPrepareForPlayback:assetCannotBePlayedError];
- return;
- }else{
- NSLog(@"assett return playable %@",_videoURL);
- }
- // Create a new instance of AVPlayerItem from the now successfully loaded AVAsset.
- self.appDelegate = (C8AppDelegate *)[UIApplication sharedApplication].delegate;
- AVPlayerItem *temp_playerItem=[AVPlayerItem playerItemWithAsset:asset];
- // AVPlayerItem *temp_playerItem= (AVPlayerItem*)[[self.appDelegate.globalAvPlayers objectForKey:_videoURL] currentItem];
- //AVPlayerItem *playerItem =temp_playerItem;// [AVPlayerItem playerItemWithAsset:asset];
- [temp_playerItem addObserver:self
- forKeyPath:@"status"
- options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
- context:C8VideoPlaybackControllerStatusObservationContext];
- // When the player item has played to its end time we'll toggle
- // the movie controller Pause button to be the Play button
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoDidPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:temp_playerItem];
- AVPlayer *temp_player=(AVPlayer*)[self.appDelegate.globalAvPlayers objectForKey:_videoURL];
- self.player = [AVPlayer playerWithPlayerItem:temp_playerItem];
- //self.player = temp_player;
- NSLog(@"assett return c8prefetching 2 dataListItem 3: %@ - %@ - self.player.currentItem:%@ - temp_playerItem: %@",[self.appDelegate.globalAvPlayers objectForKey:_videoURL],_videoURL,self.player.currentItem,temp_playerItem);
- //s Observe the AVPlayer "rate" property to update the scrubber control
- [self.player addObserver:self
- forKeyPath:@"rate"
- options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
- context:C8VideoPlaybackControllerRateObservationContext];
- //self.playerView.player = self.player;
- [self syncPlayPauseButtons];
- [self.progressControl setValue:0.0];
- }
- #pragma mark -
- - (void)dealloc {
- [self invalidateObservingForCurrentPlayer];
- }
- @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement