使用带有ARC的AVAssetImageGenerator创建大量缩略图的问题

时间:2012-02-24 11:40:08

标签: objective-c avfoundation automatic-ref-counting thumbnails

我已经查看了我能找到的关于此的想法的每个列表,但现在已经停留了几天所以这里希望......

我正在尝试使用AVAssetImageGenerator一次创建大量视频缩略图(100左右)。 虽然测试我总是使用相同的电影文件,但过程(看似)随机成功或失败,加上我现在将所有电影一次性加载到物理内存中,这是我不想要的。我显然做错了什么但无法弄清楚是什么 - 并且在ARC下无法手动管理内存。

背景; 它是一个使用ARC(Xcode 4.2.1,OSX 10.7.2,MBP 2.4GHz i5,4GB RAM)的AVFoundation视频播放器。 它有一个播放列表样式界面,允许您将电影文件的文件夹拖到它。它通过它给出的路径进行递归,然后输出有效的电影并将它们添加到列表中。 电影由Movie类表示,该类具有使用文件路径初始化的AVAsset成员变量(movieAsset)。到目前为止一切都很好 - 一切正常,电影可以播放,只有正在播放的电影是在物理记忆中。 我在Movie类中添加了一个-createThumbnail方法,该方法在Movie的init方法中调用(下面的代码片段)。 随着这段代码的添加,我得到了一些我无法根除的行为 - 如果我不调用下面的-createThumbnail代码,则不会发生这些行为。我出错的任何想法?

  1. 添加到播放列表的每部电影现在都会立即加载到物理内存中 - 因此应用程序内存占用率已经上升(100个电影没有缩略图代码= 40MB,缩略图(NSImages为32x18像素)750MB同样的100部电影)。

  2. 查看活动监视器 - >打开文件和端口,即使缩略图创建完成后,也会列出所有电影文件。之前没有发生 - 只列出了正在播放的电影。

  3. 缩略图创建完全锁定我的机器直到它完成 - 即使我在异步块中调用AVAssetImageGenerator - (CPU使用率从未超过35%)。尝试一次阅读100部电影会出现磁盘访问问题吗?

  4. 缩略图创建非常不稳定。有时创建所有缩略图,但通常随机30-70%不是。也许还有磁盘访问问题?

  5. 我对OOP和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 :(得分:0)

以这种方式使用AVAssetImageGenerator时我也遇到了一些奇怪的问题(至少在iOS上)。在与blocks / GCD API结合使用时,在我看来至少会有点破碎。不是异步加载所有内容,而是尝试制作一个在单个后台线程中运行的队列/循环,并以这种方式浏览电影。这也应该有助于降低内存使用率。