簡體   English   中英

如何將 AVPlayerLooper 與 AVPlayerItemVideoOutput 一起使用?

[英]How to use AVPlayerLooper with AVPlayerItemVideoOutput?

AVPlayerLooper接受模板AVPlayerItemAVQueuePlayer作為設置參數,然后它在內部操作隊列的項目,並且播放器不斷更改其currentItem

這與AVPlayerLayer完美配合,它接受這個循環播放器作為參數並只渲染它,但是我如何將它與AVPlayerItemVideoOutput一起使用,它附加到AVPlayerItem ,播放器內部有多個? 如何在內部重現AVPlayerLayer所做的相同事情?

文檔中的AVPlayerLooper設置示例

NSString *videoFile = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"mov"];
NSURL *videoURL = [NSURL fileURLWithPath:videoFile];

_playerItem = [AVPlayerItem playerItemWithURL:videoURL];
_player = [AVQueuePlayer queuePlayerWithItems:@[_playerItem]];
_playerLooper = [AVPlayerLooper playerLooperWithPlayer:_player templateItem:_playerItem];
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
_playerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:_playerLayer];
[_player play];

這就是應該使用AVPlayerItemVideoOutput的方式

[item addOutput:_videoOutput];

我想出的唯一解決方法是觀察currentItem的變化,每次從舊項目中分離視頻 output 並將其附加到新項目,如下例所示,但這顯然抵消了我正在嘗試的無縫播放達到。

- (void)observeValueForKeyPath:(NSString*)path
                      ofObject:(id)object
                        change:(NSDictionary*)change
                       context:(void*)context {
   if (context == currentItemContext) {
      AVPlayerItem* newItem = [change objectForKey:NSKeyValueChangeNewKey];
      AVPlayerItem* oldItem = [change objectForKey:NSKeyValueChangeOldKey];
      if(oldItem.status == AVPlayerItemStatusReadyToPlay) {
          [newItem removeOutput:_videoOutput];
      }
      if(newItem.status == AVPlayerItemStatusReadyToPlay) {
          [newItem addOutput:_videoOutput];
      }
      [self removeItemObservers:oldItem];
      [self addItemObservers:newItem];
   }
}

有關更多上下文,我正在嘗試解決顫振的 video_player 插件https://github.com/flutter/flutter/issues/72878

插件的代碼可以在這里找到https://github.com/flutter/plugins/blob/172338d02b177353bf517e5826cf6a25b5f0d887/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m

您可以通過AVQueuePlayer (yay OOP) 並根據需要在那里創建和添加AVPlayerItemVideoOutput來做到這一點。 我以前從未見過多個AVPlayerItemVideoOutput ,但 memory 的消耗似乎是合理的,一切正常。

@interface OutputtingQueuePlayer : AVQueuePlayer
@end

@implementation OutputtingQueuePlayer

- (void)insertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
{
    if (item.outputs.count == 0) {
        NSLog(@"Creating AVPlayerItemVideoOutput");
        AVPlayerItemVideoOutput *videoOutput = [[AVPlayerItemVideoOutput alloc] initWithOutputSettings:nil]; // or whatever
        [item addOutput:videoOutput];
    }
    [super insertItem:item afterItem:afterItem];
}
@end

當前 output 的訪問方式如下:

AVPlayerItemVideoOutput *videoOutput = _player.currentItem.outputs.firstObject;
CVPixelBufferRef pixelBuffer = [videoOutput copyPixelBufferForItemTime:_player.currentTime itemTimeForDisplay:nil];
// do something with pixelBuffer here
CVPixelBufferRelease(pixelBuffer);

配置變為:

_playerItem = [AVPlayerItem playerItemWithURL:videoURL];
_player = [OutputtingQueuePlayer queuePlayerWithItems:@[_playerItem]];
_playerLooper = [AVPlayerLooper playerLooperWithPlayer:_player templateItem:_playerItem];
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
[self.view.layer addSublayer:_playerLayer];
[_player play];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM