Утечка памяти из-за зацикливания SKVideoNode (только на реальном устройстве)
У меня утечка памяти, которую я не могу диагностировать. Я попробовал несколько подходов к созданию плавно зацикленного видео - кроме AVPlayerLooper, все подходы, с которыми я сталкивался и пытался, включают создание наблюдателя для просмотра. AVPlayerItemDidPlayToEndTimeNotification
и затем либо поиск в начале видео (в случае AVPlayer), либо вставка видео, которое должно быть зациклено, в очередь видео (в случае AVQueuePlayer). Кажется, что оба имеют одинаковую производительность, но оба также имеют согласованное сохранение памяти, связанное с методом seekToTime (в случае AVPlayer) и методом insertItem (в случае AVQueuePlayer). Моя конечная цель - создать подкласс SKVideoNode, который будет работать по умолчанию. Ниже мой код для подкласса:
#import "SDLoopingVideoNode.h"
#import <AVFoundation/AVFoundation.h>
@interface SDLoopingVideoNode()
@property AVQueuePlayer *avQueuePlayer;
@property AVPlayerLooper *playerLooper;
@end
@implementation SDLoopingVideoNode
-(instancetype)initWithPathToResource:(NSString *)path withFiletype:(NSString *)filetype
{
if(self == [super init])
{
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:path ofType:filetype];
NSURL *videoURL = [NSURL fileURLWithPath:resourcePath];
AVAsset *videoAsset = [AVAsset assetWithURL:videoURL];
AVPlayerItem * videoItem = [AVPlayerItem playerItemWithAsset:videoAsset];
self.avQueuePlayer = [[AVQueuePlayer alloc] initWithItems:@[videoItem]];
NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
[noteCenter addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
AVPlayerItem *video = [[AVPlayerItem alloc] initWithURL:videoURL];
[self.avQueuePlayer insertItem:video afterItem:nil];
NSLog(@"Video changed");
}];
self = (SDLoopingVideoNode*)[[SKVideoNode alloc] initWithAVPlayer: self.avQueuePlayer];
return self;
}
return nil;
}
@end
И вот как подкласс инициализируется в didMoveToView:
SDLoopingVideoNode *videoNode = [[SDLoopingVideoNode alloc]initWithPathToResource:@"147406" withFiletype:@"mp4"];
[videoNode setSize:CGSizeMake(self.size.width, self.size.height)];
[videoNode setAnchorPoint:CGPointMake(0.5, 0.5)];
[videoNode setPosition:CGPointMake(0, 0)];
[self addChild:videoNode];
[videoNode play];
1 ответ
Короткий ответ: вы не сможете добиться этого, работая с AVPlayer. Поверьте мне, я пытался. Вместо этого можно выполнить бесшовную петлю, используя аппаратное обеспечение H264 для декодирования, а затем перекодировать каждый видеокадр в качестве ключевого кадра, ссылка на github здесь. Я также создал слой с бесшовной петлей, который поддерживает полный альфа-канал. Производительность даже для полноэкранного видео 1x1 и iPad или iPad pro отличная. Кроме того, нет утечек памяти с этим кодом.