【发布时间】:2016-04-30 13:38:51
【问题描述】:
我正在尝试为音频和视频连接执行 CMSampleBufferRef 的深层复制?我需要使用此缓冲区进行延迟处理。有人可以通过指向示例代码来帮助这里吗?
谢谢
【问题讨论】:
标签: ios objective-c avfoundation video-processing core-video
我正在尝试为音频和视频连接执行 CMSampleBufferRef 的深层复制?我需要使用此缓冲区进行延迟处理。有人可以通过指向示例代码来帮助这里吗?
谢谢
【问题讨论】:
标签: ios objective-c avfoundation video-processing core-video
我解决了这个问题
我需要长时间访问样本数据。
尝试多种方式:
CVPixelBufferRetain -----> 程序坏了
CVPixelBufferPool -----> 程序坏了
CVPixelBufferCreateWithBytes ----> 可以解决这个程序,但是会降低性能,不建议苹果这样做
CMSampleBufferCreateCopy --->还可以,苹果推荐了。
列表:为了保持最佳性能,一些样本缓冲区直接引用可能需要由设备系统和其他捕获输入重用的内存池。对于未压缩的设备本机捕获,这种情况经常发生,其中内存块被复制得越少越好。如果多个样本缓冲区引用此类内存池的时间过长,则输入将不再能够将新样本复制到内存中,并且这些样本将被丢弃。如果您的应用程序由于保留提供的 CMSampleBuffer 对象太久而导致样本被丢弃,但它需要长时间访问样本数据,请考虑将数据复制到新缓冲区,然后在样本缓冲区上调用 CFRelease (如果它以前被保留)以便它引用的内存可以被重用。
REF:https://developer.apple.com/reference/avfoundation/avcapturefileoutputdelegate/1390096-captureoutput
这可能是你需要的:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
if (connection == m_videoConnection) {
/* if you did not read m_sampleBuffer ,here you must CFRelease m_sampleBuffer, it is causing samples to be dropped
*/
if (m_sampleBuffer) {
CFRelease(m_sampleBuffer);
m_sampleBuffer = nil;
}
OSStatus status = CMSampleBufferCreateCopy(kCFAllocatorDefault, sampleBuffer, &m_sampleBuffer);
if (noErr != status) {
m_sampleBuffer = nil;
}
NSLog(@"m_sampleBuffer = %p sampleBuffer= %p",m_sampleBuffer,sampleBuffer);
}
}
- (ACResult) readVideoFrame: (CVPixelBufferRef *)pixelBuffer{
while (1) {
dispatch_sync(m_readVideoData, ^{
if (!m_sampleBuffer) {
_readDataSuccess = NO;
return;
}
CMSampleBufferRef sampleBufferCopy = nil;
OSStatus status = CMSampleBufferCreateCopy(kCFAllocatorDefault, m_sampleBuffer, &sampleBufferCopy);
if ( noErr == status)
{
CVPixelBufferRef buffer = CMSampleBufferGetImageBuffer(sampleBufferCopy);
*pixelBuffer = buffer;
_readDataSuccess = YES;
NSLog(@"m_sampleBuffer = %p ",m_sampleBuffer);
CFRelease(m_sampleBuffer);
m_sampleBuffer = nil;
}
else{
_readDataSuccess = NO;
CFRelease(m_sampleBuffer);
m_sampleBuffer = nil;
}
});
if (_readDataSuccess) {
_readDataSuccess = NO;
return ACResultNoErr;
}
else{
usleep(15*1000);
continue;
}
}
}
那么你可以这样使用它:
-(void)getCaptureVideoDataToEncode{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){
while (1) {
CVPixelBufferRef buffer = NULL;
ACResult result= [videoCapture readVideoFrame:&buffer];
if (ACResultNoErr == result) {
ACResult error = [videoEncode encoder:buffer outputPacket:&streamPacket];
if (buffer) {
CVPixelBufferRelease(buffer);
buffer = NULL;
}
if (ACResultNoErr == error) {
NSLog(@"encode success");
}
}
}
});
}
【讨论】:
我这样做。 CMSampleBufferCreateCopy确实可以深拷贝
但是出现了一个新问题
captureOutput 委托不起作用
【讨论】: