0

У меня есть утечка памяти, которую я не могу диагностировать. Я попробовал несколько подходов к созданию бесшовно зацикленного видео. Помимо AVPlayerLooper, все подходы, с которыми я столкнулся, и попытались привлечь наблюдателя для просмотра AVPlayerItemDidPlayToEndTimeNotification, а затем либо поиск начала видео (в случае AVPlayer), либо вставляя видео в петлю в очередь видео (в случае AVQueuePlayer). Оба, похоже, имеют схожую производительность, но оба имеют постоянную память, связанную с методом seekToTime (в случае с AVPlayer) и методом insertItem (в случае с AVQueuePlayer). Моя конечная цель - создать подкласс SKVideoNode, который по умолчанию будет циклически. Ниже приведен код для подкласса:Утечка памяти из петли 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]; 
+0

Еще одна странная вещь, которую я заметил - эта утечка памяти проявляется только на устройстве - при запуске на симуляторе утечки памяти нет. –

ответ

2

Короткий ответ, вы не сможете получить, что работать с AVPlayer. Поверь мне, я попробовал. Вместо этого можно сделать бесшовный цикл, используя аппаратное обеспечение H264 для декодирования, а затем повторно закодировать каждый видеокадр в качестве ключевого кадра, github link here. Я также создал бесшовный цикл, поддерживающий полный альфа-канал. Производительность даже для полноэкранного видео на 1x1 и для iPad или iPad - отлично. Кроме того, с этим кодом не происходит утечки памяти.

+0

Спасибо за ответ! Это ваш проект? Я загрузил и просмотрел этот проект ранее сегодня - цикл очень велик, но знаете ли вы способ вставить это зацикленное видео в SKVideoNode? Желаемый эффект, который я собираюсь сделать, - это видео-фон в комплекте Sprite. –

+0

Выполнение цикла по приведенному выше коду работает хорошо, но инициализация SKVideoNode с помощью AVQueuePlayer и добавление видео в очередь вызывает связь с памятью на каждом видеокоде. –

+0

Нет, вы не можете напрямую вставлять это в SKVideoNode. Но вы можете декодировать, а затем визуализировать видеокадр в буфер пикселей, а затем установить этот буфер пикселей в качестве текстуры для обычного узла SKSpriteNode. Для минимального использования памяти можно использовать SKMutableTexture и ждать, пока обратный вызов async будет скопирован поверх содержимого буфера пикселов. – MoDJ

Смежные вопросы