在 OSX Lion 中使用 AVAssetReader 顺序读取视频文件失败
我有读取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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试在调用 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.