我遇到的问题是当我的应用程序尝试获取 CVPixelBufferRef
时,我使用 iOS9 sdk 编译我的应用程序来自 AVPlayerItemVideoOutput
与 - copyPixelBufferForItemTime:itemTimeForDisplay:
函数在加载视频并创建所有实例时,我不时得到一个空值。
使用 iOS 8 我的应用程序运行良好,但是使用 iOS9 给我带来了问题,即使我的应用程序版本在应用程序商店中可供下载且使用 iOS 8 SDK 编译时,在安装时也给了我同样的问题IOS9.
当问题发生时,我得到一个空值 getCVPixelBufferRef
,如果我按下主页按钮并且当我再次打开应用程序并激活应用程序时应用程序进入后台AVPlayerItemVideoOutput
给我空值的实例 CVPixelBufferRef
开始工作正常,问题解决了。
这是我在其中复制问题的 YouTube 视频:
https://www.youtube.com/watch?v=997zG08_DMM&feature=youtu.be
以下是用于创建所有项目实例的示例代码:
NSURL *url ;
url = [[NSURL alloc] initFileURLWithPath:[_mainVideo objectForKey:@"file"]];
NSDictionary *pixBuffAttributes = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)};
_videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:pixBuffAttributes];
_myVideoOutputQueue = dispatch_queue_create("myVideoOutputQueue", DISPATCH_QUEUE_SERIAL);
[_videoOutput setDelegate:self queue:_myVideoOutputQueue];
_player = [[AVPlayer alloc] init];
// Do not take mute button into account
NSError *error = nil;
BOOL success = [[AVAudioSession sharedInstance]
setCategory:AVAudioSessionCategoryPlayback
error:&error];
if (!success) {
// NSLog(@"Could not use AVAudioSessionCategoryPlayback", nil);
}
asset = [AVURLAsset URLAssetWithURL:url options:nil];
if(![[NSFileManager defaultManager] fileExistsAtPath:[[asset URL] path]]) {
// NSLog(@"file does not exist");
}
NSArray *requestedKeys = [NSArray arrayWithObjects:kTracksKey, kPlayableKey, nil];
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
dispatch_async( dispatch_get_main_queue(),
^{
/* Make sure that the value of each key has loaded successfully. */
for (NSString *thisKey in requestedKeys)
{
NSError *error = nil;
AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
if (keyStatus == AVKeyValueStatusFailed)
{
[self assetFailedToPrepareForPlayback:error];
return;
}
}
NSError* error = nil;
AVKeyValueStatus status = [asset statusOfValueForKey:kTracksKey error:&error];
if (status == AVKeyValueStatusLoaded)
{
//_playerItem = [AVPlayerItem playerItemWithAsset:asset];
[_playerItem addOutput:_videoOutput];
[_player replaceCurrentItemWithPlayerItem:_playerItem];
[_videoOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ONE_FRAME_DURATION];
/* When the player item has played to its end time we'll toggle
the movie controller Pause button to be the Play button */
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:_playerItem];
seekToZeroBeforePlay = NO;
[_playerItem addObserver:self
forKeyPath:kStatusKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:AVPlayerDemoPlaybackViewControllerStatusObservationContext];
[_player addObserver:self
forKeyPath:kCurrentItemKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext];
[_player addObserver:self
forKeyPath:kRateKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:AVPlayerDemoPlaybackViewControllerRateObservationContext];
[self initScrubberTimer];
[self syncScrubber];
}
else
{
// NSLog(@"%@ Failed to load the tracks.", self);
}
});
}];
这是给我空像素缓冲区的示例代码
CVPixelBufferRef pixelBuffer =
[_videoOutput
copyPixelBufferForItemTime:[_playerItem currentTime]
itemTimeForDisplay:nil];
NSLog(@"the pixel buffer is %@", pixelBuffer);
NSLog (@"the _videoOutput is %@", _videoOutput.description);
CMTime dataTime = [_playerItem currentTime];
//NSLog(@"the current time is %f", dataTime);
return pixelBuffer;
最佳答案
我遇到了同样的问题,并在此线程中找到了答案:https://forums.developer.apple.com/thread/27589#128476
在添加输出之前,您必须等待视频准备好播放,否则它将失败并返回 nil。我的快速代码如下所示:
func retrievePixelBufferToDraw() -> CVPixelBuffer? {
guard let videoItem = player.currentItem else { return nil }
if videoOutput == nil || self.videoItem !== videoItem {
videoItem.outputs.flatMap({ return $0 as? AVPlayerItemVideoOutput }).forEach {
videoItem.remove($0)
}
if videoItem.status != AVPlayerItemStatus.readyToPlay {
// see https://forums.developer.apple.com/thread/27589#128476
return nil
}
let pixelBuffAttributes = [
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
] as [String: Any]
let videoOutput = AVPlayerItemVideoOutput.init(pixelBufferAttributes: pixelBuffAttributes)
videoItem.add(videoOutput)
self.videoOutput = videoOutput
self.videoItem = videoItem
}
guard let videoOutput = videoOutput else { return nil }
let time = videoItem.currentTime()
if !videoOutput.hasNewPixelBuffer(forItemTime: time) { return nil }
return videoOutput.copyPixelBuffer(forItemTime: time, itemTimeForDisplay: nil)
}
关于ios9 - - copyPixelBufferForItemTime :itemTimeForDisplay: null value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33036609/