我目前正在尝试使用CoreImage,学习如何将CIFilters应用于相机Feed.目前我已经成功地拍摄了相机,应用过滤器并以视频的形式将Feed写入AVAssetWriter,但我遇到的一个问题是,在过滤过程中,我实际裁剪了图像数据所以它总是有方形尺寸(项目的其他方面需要)
我的流程如下:
没有将CGImageRef绘制到上下文中,这就是我得到的:

在将CGImageRef绘制到上下文之后,这就是我得到的:

理想情况下,我只想告诉CMSampleBufferRef它有新的维度,以便省略附加信息.但我想知道我是否必须完全创建一个新的CMSampleBufferRef.
任何帮助将不胜感激!
实际问题
几个答案将解决我的问题:
CGImage从直接数据提供程序(创建时CGDataProviderCreateDirect)重新加载其数据CGContextDrawImage吗?或者是否有其他方法可以设置self.layer.contents来做到这一点?CGContext配置,或技巧,我可以使用至少30 fps渲染1024x768图像CGContextDrawImage.CVOpenGLESTextureCacheCreateTextureFromImage自己的纹理数据进行实时缓冲更新?我认为我最大的问题是创建一个,CVImageBuffer因为我从Apples的文档中复制了纹理的其他属性.如果有人有任何关于此的更多信息,那将是非常棒的.背景(手):
我正在开发一个项目,我需要实时修改NPOT图像数据的像素(至少30 fps)并在iOS屏幕上绘制.
我的第一个想法是使用OpenGL glTexSubimage2D进行更新,不幸的是,最终速度非常慢(在iPad上为6 fps),因为驱动程序在每帧都将我的RGB数据转换为BGR.因此,请将它发送到您说的BGR中,我也是如此,但出于某种原因,您无法glTexSubImage2D使用GL_BGRgo figure 调用.我知道一些缓慢是因为它不是2图像数据的力量,但我的要求决定了这一点.
更多阅读引导我,CVOpenGLESTextureCacheCreateTextureFromImage但所有的例子是使用直接相机输入来获得CVImageBufferRef我尝试使用文档(没有官方但只是标题注释)来使我自己的CVImageBuffer形成我的图像数据,但它不适用于此(不错误只是调试器中的空纹理),这让我觉得Apple专门为处理实时摄像机数据而构建它,并且除了IDK之外,它还没有在这个区域之外进行过多次测试.
无论如何在通过倾倒OpenGL并将我的想法转换为CoreGraphics放弃我的尊严后,我被引导到这个问题最快的方法在iphone上绘制屏幕缓冲区
,建议使用CGImage支持CGDataProviderCreateDirect,这允许您返回指向图像数据的指针CGImage需要它,真棒吗?好吧,它似乎没有像宣传的那样工作.如果我使用,CGContextDrawImage那么一切正常.我可以修改像素缓冲区,每次绘制时,它都应该从我的数据提供者那里请求图像数据,调用方法CGDataProviderDirectCallbacks(Note:它们似乎有内置优化,如果它具有与之相同的地址,则忽略更新的指针透水).CGContextDrawImage不是超快(大约18 fps),即使使用禁用插值也会超过6 fps.Apple的文档告诉我使用self.layer.contents将比快得多CGContextDrawImage.使用self.layer.contents第一次分配的工作,但从CGImage不请求从数据提供者重新加载,就像CGContextDrawImage我做的那样,即使我打电话[layer setNeedsDisplay].在我引用的SO问题中,用户通过每帧从数据源创建和销毁新的CGImage来展示他对问题的解决方案,这是一个绝对缓慢的过程(是的,我确实尝试过),所以是真正问题的时间.
注意:我已经分析了所有这些操作,并且知道问题确实是glTexSubImage针对OpenGL的,CGContextDrawImage并且确实是CoreGraphics的问题所以没有"go profile"的答案.
EDIT现在可以在http://github.com/narpas/image-sequence-streaming找到演示此技术的源代码.
我正在尝试放置一些我正在创建的视频的一部分文本.我意识到我可以使用CALayers在视频的整个长度上使用带有文本的图层,但是如何仅对部分视频执行此操作?经过一些研究,我发现你可以创建一个AVMediaTypeText类型的AVMutableCompositionTrack,看起来这可能就是这个伎俩; 但是,我找不到任何关于如何声明,实例化这样一个轨道的例子?
我这样声明:
AVMutableCompositionTrack *textTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeText preferredTrackID:kCMPersistentTrackID_Invalid];
Run Code Online (Sandbox Code Playgroud)
现在我如何实际添加文本或用字符串实例化?
任何投入赞赏.
我从 ARSessionDelegate 得到一个 CVPixelBuffer:
func session(_ session: ARSession, didUpdate frame: ARFrame) {
frame.capturedImage // CVPixelBufferRef
}
Run Code Online (Sandbox Code Playgroud)
但是我的应用程序的另一部分(我无法更改)使用 CMSampleBuffer。
CMSampleBuffer 是 CVPixelBuffer 的容器。
为了创建一个 CMSampleBuffer 我可以使用这个函数:
func CMSampleBufferCreateReadyWithImageBuffer(_ allocator: CFAllocator?,
_ imageBuffer: CVImageBuffer,
_ formatDescription: CMVideoFormatDescription,
_ sampleTiming: UnsafePointer<CMSampleTimingInfo>,
_ sBufOut: UnsafeMutablePointer<CMSampleBuffer?>) -> OSStatus
Run Code Online (Sandbox Code Playgroud)
我唯一缺少的参数是sampleTiming- 如何从 CVPixelBuffer 中提取它?
什么之间的区别CVImageBuffer这是由返回CMSampleBufferGetmageBuffer和CVPixelBuffer?我只想检索图像平面 (RGBA),但我不知道如何从 CVImageBuffer 检索此信息。我正在使用斯威夫特。
谢谢。
我们正在使用AVAssetReader和使用AVAssetWriter的视频编码中AVAssetWriter提到的样式- CRASHES基本上是从视频库/资产库中读取视频,然后以不同的比特率写入以减小其大小(用于最终的网络上传) .
让它为我们工作的诀窍是kCVPixelBufferPixelFormatTypeKey在outputSettingson中指定一个键和值AVAssetReaderTrackOutput,如下所示:
NSDictionary *outputSettings = [NSDictionary
dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
readerTrackOutput =
[[AVAssetReaderTrackOutput alloc] initWithTrack:src_track
outputSettings:outputSettings];
Run Code Online (Sandbox Code Playgroud)
所以基本上我们使用kCVPixelFormatType_32BGRA了kCVPixelBufferPixelFormatTypeKey键的值.
但显然我们可以选择许多可能的像素格式类型.在iOS 6.0.1 iPhone设备上运行技术问答QA1501:核心视频 - 可用像素格式中记录的代码,以下是它显示的支持像素格式类型列表:
Core Video Supported Pixel Format Types:
Core Video Pixel Format Type: 32
Core Video Pixel Format Type: 24
Core Video Pixel Format Type: 16
Core Video Pixel Format Type (FourCC): L565
Core Video Pixel Format Type (FourCC): 2vuy …Run Code Online (Sandbox Code Playgroud) 我试图将从AVPlayerItemVideoOutput提取的pixelBuffer转换为CIImage但总是为零.
代码
if([videoOutput_ hasNewPixelBufferForItemTime:player_.internalPlayer.currentItem.currentTime])
{
CVPixelBufferRef pixelBuffer = [videoOutput_ copyPixelBufferForItemTime:player_.internalPlayer.currentItem.currentTime
itemTimeForDisplay:nil];
CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer]; // Always image === nil
CIFilter *filter = [FilterCollection filterSepiaForImage:image];
image = filter.outputImage;
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgimg = [context createCGImage:image fromRect:[image extent]];
[pipLayer_ setContents:(id)CFBridgingRelease(cgimg)];
}
Run Code Online (Sandbox Code Playgroud)
下面是pixelBuffer用于创建CIImage的详细信息(总是导致nil):
$0 = 0x09b48720 <CVPixelBuffer 0x9b48720 width=624 height=352 bytesPerRow=2496 pixelFormat=BGRA iosurface=0x0 attributes=<CFBasicHash 0x98241d0 [0x1d244d8]>{type = immutable dict, count = 3,
entries =>
0 : <CFString 0x174cf4 [0x1d244d8]>{contents = "Height"} = <CFNumber 0x9a16e70 [0x1d244d8]>{value = …Run Code Online (Sandbox Code Playgroud) 我正在使用AVCaptureVideoDataOutput和记录视频和音频,AVCaptureAudioDataOutput并且在captureOutput:didOutputSampleBuffer:fromConnection:委托方法中,我想在我从视频连接接收的每个单独的样本缓冲区上绘制文本.文本随着每一帧(它是一个秒表标签)而变化,我希望将其记录在捕获的视频数据之上.
这是我到目前为止所能提出的:
//1.
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
//2.
UIImage *textImage = [self createTextImage];
CIImage *maskImage = [CIImage imageWithCGImage:textImage.CGImage];
//3.
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSDictionary *options = [NSDictionary dictionaryWithObject:(__bridge id)colorSpace forKey:kCIImageColorSpace];
CIImage *inputImage = [CIImage imageWithCVPixelBuffer:pixelBuffer options:options];
//4.
CIFilter *filter = [CIFilter filterWithName:@"CIBlendWithMask"];
[filter setValue:inputImage forKey:@"inputImage"];
[filter setValue:maskImage forKey:@"inputMaskImage"];
CIImage *outputImage = [filter outputImage];
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
//5.
[self.renderContext render:outputImage toCVPixelBuffer:pixelBuffer bounds:[outputImage extent] colorSpace:CGColorSpaceCreateDeviceRGB()];
//6.
[self.pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:timestamp];
Run Code Online (Sandbox Code Playgroud)
createTextImage这样.我能够验证这一步是否有效;我保存了一个带有文本的图像到我的照片中.我正在尝试执行深度克隆CMSampleBuffer来存储AVCaptureSession. kCMSampleBufferError_InvalidMediaFormat (OSStatus -12743)当我运行该函数时收到错误CMSampleBufferCreateForImageBuffer。我不明白我是如何CVImageBuffer与CMSampleBuffer格式描述不匹配的。有人知道我哪里出错了吗?她是我的测试代码。
func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
let allocator: CFAllocator = CFAllocatorGetDefault().takeRetainedValue()
func cloneImageBuffer(imageBuffer: CVImageBuffer!) -> CVImageBuffer? {
CVPixelBufferLockBaseAddress(imageBuffer, 0)
let bytesPerRow: size_t = CVPixelBufferGetBytesPerRow(imageBuffer)
let width: size_t = CVPixelBufferGetWidth(imageBuffer)
let height: size_t = CVPixelBufferGetHeight(imageBuffer)
let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)
let pixelFormatType = CVPixelBufferGetPixelFormatType(imageBuffer)
let data = NSMutableData(bytes: baseAddress, length: bytesPerRow * height)
CVPixelBufferUnlockBaseAddress(imageBuffer, 0)
var clonedImageBuffer: CVPixelBuffer?
let refCon = NSMutableData()
if …Run Code Online (Sandbox Code Playgroud) 我正在关注从iPhone启动Facebook直播会话的示例快速代码:
override func viewDidLoad() {
super.viewDidLoad()
liveButton.layer.cornerRadius = 15
session = VCSimpleSession(videoSize: CGSize(width: 1280, height: 720), frameRate: 30, bitrate: 4000000, useInterfaceOrientation: false)
contentView.addSubview(session.previewView)
session.previewView.frame = contentView.bounds
session.delegate = self
}
func startFBLive() {
if FBSDKAccessToken.current() != nil {
FBLiveAPI.shared.startLive(privacy: livePrivacy) { result in
guard let streamUrlString = (result as? NSDictionary)?.value(forKey: "stream_url") as? String else {
return
}
let streamUrl = URL(string: streamUrlString)
guard let lastPathComponent = streamUrl?.lastPathComponent,
let query = streamUrl?.query else {
return
}
self.session.startRtmpSession(
withURL: "rtmp://rtmp-api.facebook.com:80/rtmp/",
andStreamKey: "\(lastPathComponent)?\(query)" …Run Code Online (Sandbox Code Playgroud) core-video ×10
ios ×6
avfoundation ×5
core-image ×3
core-media ×2
objective-c ×2
swift ×2
arkit ×1
ios7 ×1
opengl-es ×1