iOS 视频:可以同时使用超过 4 个 AVAssetReader 吗?

发布于 2024-11-08 14:55:39 字数 1680 浏览 0 评论 0原文

我想同时在多个视图上渲染多个 H264 mp4 视频。目标是阅读大约 8 个短视频,每个短视频的大小为 100x100 像素,并让它们同时在屏幕上的多个位置显示内容。

想象一下屏幕上有 24 个方块,每个方块显示 8 个视频中的一个视频。

MoviePlayer 不起作用,因为它只显示一个全屏视频。具有多个 AVPlayerLayers 的 AVPlayer 是有限的,因为只有最近创建的图层才会在屏幕上显示其内容(根据文档和我的测试)。

因此,我编写了一个简短的视频类,并为包中的每个 .mp4 文件创建了一个实例,使用 AVAssetReader 读取其内容。更新时,每个视频帧都会根据视频的帧速率检索转换为 UIImage 并显示。此外,这些图像被缓存以便在循环时快速访问。

- (id) initWithAsset:(AVURLAsset*)asset withTrack:(AVAssetTrack*)track
{
    self = [super init];
    if (self)
    {
        NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA], (NSString*)kCVPixelBufferPixelFormatTypeKey, nil];

        mOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:settings];
        mReader = [[AVAssetReader alloc] initWithAsset:asset error:nil];

        [mReader addOutput:mOutput];

        BOOL status = [mReader startReading];
    }

    return self;
}


- (void) update:(double)elapsed
{
  CMSampleBufferRef buffer = [mOutput copyNextSampleBuffer];

  if (buffer) 
  {
    UIImage* image = [self imageFromSampleBuffer:sampleBuffer];
  }

  [...]
}

实际上这效果很好,但只适用于 4 个视频。第五个人始终没有出现。首先我想到了内存问题,但我在以下设备上进行了测试:

  • iPhone 3GS
  • iPhone 4
  • iPad
  • iPad 2

我在每台设备上都有相同的行为:4 个视频平稳循环播放,没有差异。

如果是内存问题,我预计至少 iPad 2 会显示 5 或 6 个视频(因为它的硬件更好),或者 3GS 只会显示 1 个或在某处崩溃。

不过,模拟器会显示所有视频。

设备上的调试显示,

BOOL status = [mReader startReading]; 

视频 5、6、7 和 8 返回 false。

那么,是否存在某种硬件设置(或限制)不允许同时使用超过 4 个 AVAssetReader?因为,我无法真正解释这种行为。我不认为所有设备都具有完全相同的视频内存量。

I would like to render multiple H264 mp4 videos on multiple views at the same time. Target is to read about 8 short videos, each at a size of 100x100 pixels and let them display their content on multiple positions on the screen, simultaneously.

Imagine 24 squares on the screen, each showing one video out of pool of 8 videos.

MoviePlayer doesn't work, for it's only showing one fullscreen video. An AVPlayer with multiple AVPlayerLayers is limited, because only the most-recently-created Layer will show it's content on screen (according to the documentation and my testing).

So, i wrote a short video class and created an instance for every .mp4 file in my package, using AVAssetReader to read it's content. On update, every videoframe is retreived converted to an UIImage and displayed, according to the video's framerate. Furthermore, these images are cached for a fast access on looping.

- (id) initWithAsset:(AVURLAsset*)asset withTrack:(AVAssetTrack*)track
{
    self = [super init];
    if (self)
    {
        NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA], (NSString*)kCVPixelBufferPixelFormatTypeKey, nil];

        mOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:settings];
        mReader = [[AVAssetReader alloc] initWithAsset:asset error:nil];

        [mReader addOutput:mOutput];

        BOOL status = [mReader startReading];
    }

    return self;
}


- (void) update:(double)elapsed
{
  CMSampleBufferRef buffer = [mOutput copyNextSampleBuffer];

  if (buffer) 
  {
    UIImage* image = [self imageFromSampleBuffer:sampleBuffer];
  }

  [...]
}

Actually this works pretty well, but only for 4 videos. The fifth one never shows up. First I thought of memory issues, but I tested it on the following devices:

  • iPhone 3GS
  • iPhone 4
  • iPad
  • iPad 2

I had the same behaviour on each device: 4 videos playing in a smooth loop, no differences.

If it would have been a memory issue, I would have expect at least either the iPad 2 to show 5 or 6 videos (due to it's better hardware) or the 3GS to show only 1 or a crash somewhere.

The simulator shows all videos, though.

Debugging on the device shows, that

BOOL status = [mReader startReading]; 

returns false for video 5,6,7 and 8.

So, is there some kind of hardware setting (or restriction) that doesn't allow more than 4 simultaneous AVAssetReaders? Because, I can't really explain this behaviour. I don't think that all devices have the exact same amount of video memory.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故事未完 2024-11-15 14:55:39

是的,iOS 对一次可以解码的视频数量有上限。虽然您的方法很好,但我不知道有什么方法可以解决这个上限,只要同时激活那么多 h.264 解码器即可。如果你有兴趣,请看看我对这个问题的解决方案,这是一个名为 烟花。基本上,这个演示展示了将一堆 Alpha 通道视频解码到磁盘,然后通过将视频文件的一部分映射到内存来播放每个视频。这种方法可以同时解码 4 部以上的电影,而不会耗尽所有系统内存,也不会遇到 h.264 解码器对象数量的硬限制。

Yes, iOS has an upper limit on the number of videos that can be decoded at one time. While your approach is good, I don't know of any way to work around this upper limit as far as having that many h.264 decoders active at once. If you are interested, please have a look at my solution to this problem, this is an xcode project called Fireworks. Basically, this demo shows decoding a bunch of alpha channel videos to disk, then each one is played by mapping a portion of the video files into memory. This approach makes it possible to decode more than 4 movies at the same time without using up all the system memory and without running into the hard limit of the number of h.264 decoder objects.

贱人配狗天长地久 2024-11-15 14:55:39

您是否尝试过为每个 AVPlayerLayer 基于相同的 AVAsset 创建单独的 AVPlayerItems ?

Have you tried creating separate AVPlayerItems based on the same AVAsset for each AVPlayerLayer?

眼眸里的那抹悲凉 2024-11-15 14:55:39

这是我的最新迭代的完美平滑滚动集合视图,具有实时视频预览(一次最多 16 个):

https: //youtu.be/7QlaO7WxjGg

它甚至使用封面流自定义布局和“反射”视图来完美反映视频预览。源代码在这里:

http://www.mediafire.com/download/ivecygnlhqxwynr/VideoWallCollectionView .zip

Here's my latest iteration of a perfectly smooth-scrolling collection view with real-time video previews (up to 16 at a time):

https://youtu.be/7QlaO7WxjGg

It even uses a cover flow custom layout and "reflection" view that mirrors the video preview perfectly. The source code is here:

http://www.mediafire.com/download/ivecygnlhqxwynr/VideoWallCollectionView.zip

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文