标签: core-video

iOS:在附加到AVAssetWriterInput之前裁剪CMSampleBufferRef

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

我的流程如下:

  1. 使用AVCaptureSession捕获Feed
  2. 从捕获输出中获取CMSampleBufferRef并获取CVPixelBufferRef
  3. 获取CVPixelBufferRef的基地址,并使用基地址作为其数据创建CGBitmapContext(因此我们可以覆盖它)
  4. 将CVPixelBufferRef转换为CIImage(使用其中一个CIImage构造函数)
  5. 将过滤器应用于CIImage
  6. 将CIImage转换为CGImageRef
  7. 将CGImageRef绘制到CGBitmapContext(导致样本缓冲区内容被覆盖)
  8. 将CMSampleBufferRef附加到AVAssetWriterInput.

没有将CGImageRef绘制到上下文中,这就是我得到的:

在此输入图像描述

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

在此输入图像描述

理想情况下,我只想告诉CMSampleBufferRef它有新的维度,以便省略附加信息.但我想知道我是否必须完全创建一个新的CMSampleBufferRef.

任何帮助将不胜感激!

core-graphics avfoundation core-video ios avassetwriter

7
推荐指数
0
解决办法
1448
查看次数

如何直接更新像素 - 使用CGImage和直接CGDataProvider

实际问题

几个答案将解决我的问题:

  1. 我可以强制a CGImage从直接数据提供程序(创建时CGDataProviderCreateDirect)重新加载其数据CGContextDrawImage吗?或者是否有其他方法可以设置self.layer.contents来做到这一点?
  2. 有没有CGContext配置,或技巧,我可以使用至少30 fps渲染1024x768图像CGContextDrawImage.
  3. 有没有人能够成功使用CVOpenGLESTextureCacheCreateTextureFromImage自己的纹理数据进行实时缓冲更新?我认为我最大的问题是创建一个,CVImageBuffer因为我从Apples的文档中复制了纹理的其他属性.如果有人有任何关于此的更多信息,那将是非常棒的.
  4. 关于如何以30 fps的速度将内存中的图像添加到屏幕上的任何其他指导.

背景(手):

我正在开发一个项目,我需要实时修改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找到演示此技术的源代码.

opengl-es core-graphics objective-c core-video ios

7
推荐指数
1
解决办法
3352
查看次数

如何使用AVMediaTypeText类型实例化AVMutableCompositionTrack

我正在尝试放置一些我正在创建的视频的一部分文本.我意识到我可以使用CALayers在视频的整个长度上使用带有文本的图层,但是如何仅对部分视频执行此操作?经过一些研究,我发现你可以创建一个AVMediaTypeText类型的AVMutableCompositionTrack,看起来这可能就是这个伎俩; 但是,我找不到任何关于如何声明,实例化这样一个轨道的例子?

我这样声明:

AVMutableCompositionTrack *textTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeText preferredTrackID:kCMPersistentTrackID_Invalid];
Run Code Online (Sandbox Code Playgroud)

现在我如何实际添加文本或用字符串实例化?

任何投入赞赏.

avfoundation core-video avcomposition ios7

7
推荐指数
1
解决办法
614
查看次数

从 CVPixelBuffer 创建一个 CMSampleBuffer

我从 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 中提取它?

avfoundation core-video core-media arkit

7
推荐指数
1
解决办法
6383
查看次数

CVPixelBuffer 与 CVImageBuffer,以及一般的缓冲区

什么之间的区别CVImageBuffer这是由返回CMSampleBufferGetmageBufferCVPixelBuffer?我只想检索图像平面 (RGBA),但我不知道如何从 CVImageBuffer 检索此信息。我正在使用斯威夫特。

谢谢。

core-image core-video swift

7
推荐指数
1
解决办法
1639
查看次数

如何选择与AVAssetReader一起使用的像素格式类型(kCVPixelBufferPixelFormatTypeKey)?

我们正在使用AVAssetReader使用AVAssetWriter的视频编码中AVAssetWriter提到的样式- CRASHES基本上是从视频库/资产库中读取视频,然后以不同的比特率写入以减小其大小(用于最终的网络上传) .

让它为我们工作的诀窍是kCVPixelBufferPixelFormatTypeKeyoutputSettingson中指定一个键和值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_32BGRAkCVPixelBufferPixelFormatTypeKey键的值.

但显然我们可以选择许多可能的像素格式类型.在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)

core-video ios avassetwriter avassetreader

6
推荐指数
1
解决办法
1万
查看次数

CVPixelBuffer到CIImage总是返回nil

我试图将从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)

core-image avfoundation core-video ios

6
推荐指数
1
解决办法
4243
查看次数

在录制视频时将动态文本渲染到CVPixelBufferRef上

我正在使用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)
  1. 在这里,我抓住像素缓冲区,就像馅饼一样容易.
  2. 我使用核心图形将文本写入空白的UIImage(就是createTextImage这样.我能够验证这一步是否有效;我保存了一个带有文本的图像到我的照片中.
  3. 我从像素缓冲区创建一个CGImage.
  4. 我制作了一个CIFilter …

objective-c core-image avfoundation core-video ios

6
推荐指数
1
解决办法
2737
查看次数

在 Swift 中创建 CMSampleBuffer 的副本会返回 OSStatus -12743(无效媒体格式)

我正在尝试执行深度克隆CMSampleBuffer来存储AVCaptureSession. kCMSampleBufferError_InvalidMediaFormat (OSStatus -12743)当我运行该函数时收到错误CMSampleBufferCreateForImageBuffer。我不明白我是如何CVImageBufferCMSampleBuffer格式描述不匹配的。有人知道我哪里出错了吗?她是我的测试代码。

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)

core-video core-media ios avcapturesession cmsamplebuffer

6
推荐指数
1
解决办法
1869
查看次数

如何在CoreVideo直播流会话中添加交互式UIView(例如倒数计时器)

我正在关注从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 swift

6
推荐指数
1
解决办法
298
查看次数