2011-06-06 80 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