2011-06-06 58 views
5

我正在使用AVFoundation为iOS设置自定义视频播放器。这个想法是能够用手势切换到不同的视频(点击,轻扫,无论)。 现在玩家在模拟器上完美地工作,但是当我在实际设备上测试它时,视图在3或4次滑动后变为空白。我甚至为我的播放器创建了播放控件,当视图变为空白时,这些控件正确加载,但什么都不做。任何想法家伙? 这是玩家的初始化使用AVPlayer在iPhone上播放许多不同的视频

  - (id)initWithContentURL:(NSString *)aContentURL delegate:(id)aDelegate { 
     self = [super initWithNibName:@"NoCashMoviePlayer" bundle:nil]; 
     if (self == nil) 
      return nil; 
     delegate = aDelegate; 
     systemPath = [aContentURL retain]; 
     contentURL = [[NSURL alloc]initFileURLWithPath:systemPath]; 
     asset = [AVURLAsset URLAssetWithURL:contentURL options:nil]; 
     playerItem = [AVPlayerItem playerItemWithAsset:asset]; 
     isPaused = false; 
     controlsHidden = false; 
     self.player = [[AVPlayer playerWithPlayerItem:playerItem] retain]; 
     duration = self.player.currentItem.asset.duration; 

     return self; 
    } 

这是播放视频的代码:

-(void)playMovie{ 

     UITapGestureRecognizer *tapRecon = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(toggleControls:)]; 
     [tapRecon setNumberOfTapsRequired:2]; 
     [self.movieContainer addGestureRecognizer:tapRecon]; 
     [tapRecon release]; 

     NSLog(@"Playing item: %@",contentURL); 
     playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; 
     [movieContainer.layer addSublayer:playerLayer]; 
     playerLayer.frame = movieContainer.layer.bounds; 
     playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; 
     self.seeker.alpha = 1.0; 
     [self.view addSubview:movieContainer]; 
     [self.movieContainer addSubview:controls]; 
     [self setSlider]; 
     [player play]; 
     player.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

     [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(playerItemDidReachEnd:) 
              name:AVPlayerItemDidPlayToEndTimeNotification 
              object:[player currentItem]]; 


    } 

代码选择剪辑播放:

-(void)viewSelect: (double) curTime{ 
     self.myView.backgroundColor = [UIColor blackColor]; 
     UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)]; 
     swipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight; 
     [self.myView addGestureRecognizer:swipeRecognizer]; 
     [swipeRecognizer release]; 

     UISwipeGestureRecognizer *leftRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFromLeft:)]; 
     swipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft; 
     [self.myView addGestureRecognizer:leftRecognizer]; 
     [leftRecognizer release]; 


     if(isMain){ 
      [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationTransitionFlipFromLeft animations:^{ 
       self.myView.alpha = 1.0; 
       moviePlayer = [[NoCashMoviePlayer alloc]initWithContentURL:[self movieURL:vidIndex] delegate:self]; 
       self.moviePlayer.view.frame = self.myView.bounds; 
       self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight; 
       [self.myView addSubview:moviePlayer.view]; 

      }completion:^(BOOL finished) { 
       [self.moviePlayer.player seekToTime:CMTimeMake(curTime, 1)]; 
       [self.moviePlayer playMovie]; 
      }]; 
     }else{ 

      [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationTransitionFlipFromLeft animations:^{ 
       self.otherView.alpha = 1.0; 
       moviePlayer = [[NoCashMoviePlayer alloc]initWithContentURL:[self movieURL:vidIndex] delegate:self]; 
       self.moviePlayer.view.frame = self.otherView.bounds; 
       self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight; 
       [self.otherView addSubview:moviePlayer.view]; 

      }completion:^(BOOL finished) { 

       [self.moviePlayer.player seekToTime:CMTimeMake(curTime, 1)]; 
       [self.moviePlayer playMovie]; 
      }]; 
     } 
    } 

而去年手势动作:

- (void)handleSwipeFromLeft:(UISwipeGestureRecognizer *)recognizer { 

     double elapsedTime = 0.0; 
     if(vidIndex==0){ 
      vidIndex = 3; 
     }else vidIndex = vidIndex --; 
     elapsedTime = [self.moviePlayer currentTimeInSeconds]; 
     [self.moviePlayer stopMovie]; 
     isMain = !isMain; 
     [self viewSelect: elapsedTime]; 

    } 

编辑:尝试使用不同的AVPlayerLayers为每个视频文件,相同的情况下,在模拟器,而不是在iPad上工作。编辑2:我运行乐器来分析核心动画表现,当视频播放时显示的帧速率约为30 fps,当播放器变为空白时,它一路下降到1或2 fps。这可能是ovibious,但仍然,如果它有助于给更多的光.....

编辑3:好吧,我终于到了某个地方,我知道什么问题是,我有一个核心动画内存泄漏,在模拟器中它“起作用”,因为电脑比iPad有更多的内存,但是由于iPad内存非常有限,它会很快停止工作。如果任何人有任何关于核心动画泄漏的建议,它将会很受欢迎。

回答

4

我最终解决了它。我的设计确实很差,它的内存管理非常糟糕,等等。我所做的是,我并没有释放所有可能的东西,包括视图,图层,玩家,资产等,我只是创建了一种方法来更新玩家的资产和物品,回收玩家,视图,图层等。

[player pause]; 
    contentURL = [[NSURL alloc] initFileURLWithPath:newPath]; 
    AVAsset *newAsset = [AVURLAsset URLAssetWithURL:contentURL options:nil]; 
    AVPlayerItem *newPlayerItem = [AVPlayerItem playerItemWithAsset:newAsset]; 
    [player replaceCurrentItemWithPlayerItem:newPlayerItem]; 
    [contentURL release]; 

现在它的工作奇迹。感谢大家的帮助。

1

代码中有2个地方保留了一个对象,并且我没有在您发布的代码中的任何地方看到相应的发布。我首先确定内存引用计数递增和递减都是适当平衡的。

第一个保留看起来对我很可疑。通常应先自动释放可变您要指派给,然后保留如下:

[systemPath autorelease]; 
systemPath = [aContentURL retain] 

在上面的代码很容易地看到,保留/释放匹配被维持,并且远小于误差比其他方案更容易。请注意,如果systemPath == aContentURL该对象将不会被释放。

+0

所有保留的对象都在'dealloc'方法中释放。这足够吗?事实上,我曾经让玩家没有'保留'关键字,但它更糟糕,最终导致崩溃,因为对象在运行时的某个时刻被释放。 – Samssonart 2011-06-09 23:34:53

+0

不确定没有看到确切的代码。但第一次保留似乎并不遵循标准模式。 – 2011-06-09 23:47:40

+0

感谢您的帮助Himadri,我已经尝试了一些不同的内存/参考计数解决方案,但它不起作用。我尝试过使用仪器,有几次泄漏,我照顾它们,而且什么也没有。我会继续尝试。 – Samssonart 2011-06-10 15:47:32