Проблемы с созданием большого количества миниатюр с помощью AVAssetImageGenerator с ARC - PullRequest
5 голосов
/ 24 февраля 2012

Я просмотрел каждый список, который я могу найти для идей по этому вопросу, но застрял на пару дней, так что надеемся ...

Я пытаюсь создать множество миниатюр видео (около 100) одновременно, используя AVAssetImageGenerator. Во время тестирования я всегда использую одни и те же файлы фильмов, но процесс (на первый взгляд) случайно или неудачно завершается, плюс теперь я загружаю все фильмы в физическую память одновременно, что мне не нужно. Я, очевидно, делаю что-то не так, но не могу понять, что - и в ARC не может вручную управлять памятью.

Фон; Это видеоплеер AVFoundation, использующий ARC (Xcode 4.2.1, OSX 10.7.2, MBP 2,4 ГГц i5, 4 ГБ ОЗУ). Он имеет интерфейс стиля списка воспроизведения, позволяющий перетаскивать в него папки с файлами фильмов. Он рекурсивно просматривает пути, которые ему дают, вынимает действительные фильмы и добавляет их в список. Фильмы представлены классом Movie, в котором переменная-член AVAsset (movieAsset) инициализирована с помощью пути к файлу. Пока все хорошо - все работает, фильмы можно воспроизводить, только воспроизводимый фильм находится в физической памяти. Я добавил метод -createThumbnail в класс Movie, который вызывается в методе init фильма (фрагмент кода ниже). С добавлением этого кода я получаю несколько вариантов поведения, которые я не могу искоренить - ничего из этого не произойдет, если я не вызову приведенный ниже код -createThumbnail. Есть идеи, где я иду не так?

  1. Каждый фильм, добавленный в список воспроизведения, немедленно загружается в физическую память - поэтому объем памяти приложений значительно увеличился (без кода миниатюры = 40 МБ для 100 фильмов, с миниатюрами (NSImages при 32x18 пикселях) 750 МБ для те же 100 фильмов).

  2. Глядя на Activity Monitor-> Open Files and Ports, все файлы фильмов отображаются в списке даже после завершения создания эскиза. Этого раньше не было - в списке был только воспроизводимый фильм.

  3. Создание миниатюр полностью блокирует мою машину, пока она не будет завершена - даже если я вызываю AVAssetImageGenerator в асинхронном блоке - (загрузка ЦП никогда не превышает 35%). Может ли это быть проблема с доступом к диску, когда вы пытаетесь прочитать 100 фильмов одновременно?

  4. Создание эскизов очень нестабильно. Иногда все миниатюры создаются, но часто случайные 30-70% не создаются. Может также проблема с доступом к диску?

Я очень новичок в ООП и Obj-C, поэтому, вероятно, допустил ошибку новичка - но я просто не могу отследить ее ...

Также стоит отметить, что NSLogs «Ошибка создания эскиза» и «Продолжительность поиска ошибки» никогда не вызываются ...

-(void)createThumbnail{
        NSArray *keys = [NSArray arrayWithObject:@"duration"];
        [movieAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^() {
            NSError *error = nil;
            AVKeyValueStatus valueStatus = [movieAsset statusOfValueForKey:@"duration" error:&error];
            switch (valueStatus) {
                case AVKeyValueStatusLoaded:
                    if ([movieAsset tracksWithMediaCharacteristic:AVMediaTypeVideo]) {
                    AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:movieAsset];
                        Float64 movieDuration = CMTimeGetSeconds([movieAsset duration]);
                        CMTime middleFrame = CMTimeMakeWithSeconds(movieDuration/2.0, 600);

                        CGImageRef imageForThumbnail = [imageGenerator copyCGImageAtTime:middleFrame actualTime:NULL error:NULL];

                        if (imageForThumbnail != NULL) {                            
                            NSSize sizeOption = NSMakeSize(32, 18);
                            self.thumbnail = [[NSImage alloc] initWithCGImage:imageForThumbnail size:sizeOption];
                            NSLog(@"Thumbnail created for %@", [self filenameString]);
                        }
                        else{
                            NSLog(@"-----Error creating thumbnail for %@", [self filenameString]);
                        }
                        CGImageRelease(imageForThumbnail);
                    }
                    break;
                case AVKeyValueStatusFailed:
                    NSLog(@"Error finding duration");
                    break;
                case AVKeyValueStatusCancelled:
                    NSLog(@"Cancelled finding duration");
                    break;
            }
        }];
    }

(Примечание: я использовал те же самые несколько папок файлов фильмов для разработки приложения за последний месяц или около того. Все они являются локальными действительными файлами, которые успешно воспроизводятся в приложении. Некоторые из этих папок, которые были отброшены, содержат более сотни файлов фильмов, вложенных в различные подпапки).

Большое спасибо, если кто-нибудь может помочь. Чес.

1 Ответ

0 голосов
/ 24 апреля 2012

У меня были некоторые странные проблемы при использовании AVAssetImageGenerator таким образом (по крайней мере, на iOS).Мне кажется, что он, по крайней мере, несколько сломан, когда используется в сочетании с API-интерфейсом block / GCD.Вместо того, чтобы загружать все асинхронно, попробуйте создать одну очередь / цикл, которая работает в одном фоновом потоке, и таким образом просматривайте фильмы.Это также должно помочь уменьшить использование памяти.

...