[英]How to use AVPlayerLooper with AVPlayerItemVideoOutput?
AVPlayerLooper
接受模板AVPlayerItem
和AVQueuePlayer
作為設置參數,然后它在內部操作隊列的項目,並且播放器不斷更改其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
您可以通過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.