Утечка памяти из-за зацикливания 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 отличная. Кроме того, нет утечек памяти с этим кодом.

Другие вопросы по тегам