在 OSX Lion 中使用 AVAssetReader 顺序读取视频文件失败

发布于 2024-12-28 07:22:39 字数 2417 浏览 1 评论 0原文

我有读取H264视频文件的功能。我想用它来顺序读取许多视频文件。它似乎对一个文件有效(随机时间),对几个文件部分失败(读取一些而不是所有帧),然后完全失败(读取 0 帧)。我通过循环相同的视频文件对此进行了测试,因此这种不确定性很奇怪。

我收到的错误消息是:

Error Domain=AVFoundationErrorDomain Code=-11800“操作无法完成”UserInfo=0x105d07480 {NSLocalizedFailureReason=发生未知错误(-6662),NSLocalizedDescription=操作无法完成,NSUnderlyingError=0x100159350 “操作无法完成。(OSStatus 错误-6662.)"}

我使用 ARC 和 OSX Lion。非常感谢任何帮助:

void uncompressMovie(NSString *moviePath) { 
AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:moviePath]];

NSArray* video_tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack *video_track = [video_tracks objectAtIndex:0];

// Decompress to ARGB with the asset reader
NSDictionary *decompressionVideoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                            [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB], (id)kCVPixelBufferPixelFormatTypeKey,
                                            [NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey,
                                            nil];
AVAssetReaderTrackOutput *asset_reader_output = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:video_track outputSettings:decompressionVideoSettings];

NSError *error = [[NSError alloc] init];
AVAssetReader *asset_reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; 

if ([asset_reader canAddOutput:asset_reader_output]) {
    [asset_reader addOutput:asset_reader_output];

    if ([asset_reader startReading] == YES) {
        int count = 0;

        while ( [asset_reader status]==AVAssetReaderStatusReading ) {
            sampleBuffer = [asset_reader_output copyNextSampleBuffer];
            if (sampleBuffer == NULL) {
                if ([asset_reader status] == AVAssetReaderStatusFailed) 
                    break;
                else    
                    continue;
            }
            count++;

            // Will do some work here            

            CFRelease(sampleBuffer);
        }

        if (count == 0) {
            NSLog(@"I am doomed %@", [asset_reader error]);
            exit(1);
        }

        NSLog(@"Processed %d frames from %@", count, moviePath);
    } else
        NSLog(@"Couldn't start");
}

if ([asset_reader status] != AVAssetReaderStatusCompleted)
    [asset_reader cancelReading];
// unlink([moviePath UTF8String]);
}

I have a function to read H264 video files. I want to use it to sequentially read many video files. It seems to work for a files (random time), fails partially for a few files (reads some and not all the frames) and then completely fails (reading 0 frames). I tested this by looping over the same video file and so this uncertainty is strange.

The error message I get is:

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x105d07480 {NSLocalizedFailureReason=An unknown error occurred (-6662), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x100159350 "The operation couldn’t be completed. (OSStatus error -6662.)"}

I use ARC and OSX Lion. Any help is much appreciated:

void uncompressMovie(NSString *moviePath) { 
AVAsset *asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:moviePath]];

NSArray* video_tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack *video_track = [video_tracks objectAtIndex:0];

// Decompress to ARGB with the asset reader
NSDictionary *decompressionVideoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                            [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB], (id)kCVPixelBufferPixelFormatTypeKey,
                                            [NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey,
                                            nil];
AVAssetReaderTrackOutput *asset_reader_output = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:video_track outputSettings:decompressionVideoSettings];

NSError *error = [[NSError alloc] init];
AVAssetReader *asset_reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; 

if ([asset_reader canAddOutput:asset_reader_output]) {
    [asset_reader addOutput:asset_reader_output];

    if ([asset_reader startReading] == YES) {
        int count = 0;

        while ( [asset_reader status]==AVAssetReaderStatusReading ) {
            sampleBuffer = [asset_reader_output copyNextSampleBuffer];
            if (sampleBuffer == NULL) {
                if ([asset_reader status] == AVAssetReaderStatusFailed) 
                    break;
                else    
                    continue;
            }
            count++;

            // Will do some work here            

            CFRelease(sampleBuffer);
        }

        if (count == 0) {
            NSLog(@"I am doomed %@", [asset_reader error]);
            exit(1);
        }

        NSLog(@"Processed %d frames from %@", count, moviePath);
    } else
        NSLog(@"Couldn't start");
}

if ([asset_reader status] != AVAssetReaderStatusCompleted)
    [asset_reader cancelReading];
// unlink([moviePath UTF8String]);
}

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

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

发布评论

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

评论(1

拥抱没勇气 2025-01-04 07:22:39

尝试在调用 copyNextSampleBuffer 之后添加 CMSampleBufferMakeDataReady() 可能会很有趣。当您要使用数据时通常会调用此函数,但我想知道某些解码器需要调用此函数才能正确处理后续块。

您还应该尝试在 Instruments 中对此进行分析,并查看在此循环中内存是否在增长。看起来您正在示例缓冲区上正确调用 CFRelease,但 AVAssetReaderOutput 中可能存在一些正在构建的大型自动释放对象。如果看起来内存确实在累积,那么您可以尝试在循环中放入 NSAutoreleasePool 来清理内存。

It might be interesting to try to add CMSampleBufferMakeDataReady() after the call to copyNextSampleBuffer. This is typically called when you are going to use the data but I am wondering of some of the decoders need this to be called to properly handle subsequent blocks.

You should also try profiling this in Instruments and see if memory is growing while in this loop. It looks like you are properly calling CFRelease on the sample buffer but there might be some large autoreleased objects in the AVAssetReaderOutput that are building up. If it does look like memory is building up then you might try to put an NSAutoreleasePool inside the loop to clean this up.

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