iOS   发布时间:2022-03-30  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了ios – 修改CMSampleBuffer内容的最有效方法大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我想修改CMSampleBuffer的内容,然后将其写入具有AVAssetWriter / AVAssetWriterInput的文件.

我这样做的方法是创建一个Core Graphics位图上下文然后绘制它,但它太慢了.具体来说,我需要将图像绘制到缓冲区中.

那么可以提供某种关于如何更有效地做到这一点的提示或建议吗?

我想过使用OpenGL来实现它,即首先从CMSampleBuffer创建一个纹理A.然后将从我想要绘制的图像创建的纹理B渲染到纹理A中,然后从OpenGL检索支持纹理A的数据,最后将该数据移交给AVAssetWriter / AVAssetWriterInput.但是文档说,将纹理数据从GPU传输回cpu有点贵.

那么,有关如何处理的任何建议?

提前致谢

解决方法

OpenGL可能就是这样.但是,渲染到屏幕外的帧缓冲区而不是纹理可能稍微有点效率.

要从样本缓冲区中提取纹理:

// Note the caller is responsible for calling gldeleteTextures on the return value.
- (GLuint)textureFromSampleBuffer:(CMSampleBufferRef)sampleBuffer {
    GLuint texture = 0;

    glGentextures(1,&texturE);
    glBindTexture(GL_TEXTURE_2D,texturE);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);

    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(pixelBuffer,0);
    int width = CVPixelBufferGetWidth(pixelBuffer);
    int height = CVPixelBufferGetHeight(pixelBuffer);
    glTexImage2D(GL_TEXTURE_2D,GL_RGBA,width,height,GL_BGRA,GL_UNSIGNED_BYTE,CVPixelBufferGetBaseAddress(pixelBuffer));
    CVPixelBufferUnlockBaseAddress(pixelBuffer,0);

    return texture;
}

要通过OpenGL处理​​纹理,您可以执行以下操作:

// This function exists to free the malloced data when the CGDataProviderRef is
// eventually freed.
void dataProviderFreeData(void *info,const void *data,size_t sizE){
    free((void *)data);
}

// Returns an autoreleased CGImageRef.
- (CGImageRef)processTexture:(GLuint)texture width:(int)width height:(int)height {
    CGImageRef newImage = NULL;

    // Set up framebuffer and renderbuffer.
    GLuint framebuffer;
    glGenFramebuffers(1,&framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);

    GLuint colorRenderbuffer;
    glGenRenderbuffers(1,&colorRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER,colorRenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8_OES,height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,colorRenderbuffer);

    GLenum status = glcheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"Failed to create OpenGL frame buffer: %x",status);
    } else {
        glViewport(0,height);
        glClearColor(0.0,0.0,1.0);
        glClear(GL_COLOR_BUFFER_BIT);

        // Do whatever is necessary to actually draw the texture to the framebuffer
        [self renderTextureToCurrentFrameBuffer:texture];

        // Read the pixels out of the framebuffer
        void *data = malloc(width * height * 4);
        glReadPixels(0,data);

        // Convert the data to a CGImageRef. Note that CGDataProviderRef takes
        // ownership of our malloced data buffer,and the CGImageRef internally
        // retains the CGDataProviderRef. Hence the callBACk above,to free the data
        // buffer when the provider is finally released.
        CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL,data,width * height * 4,dataProviderFreeData);
        CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
        newImage = CGImageCreate(width,8,32,width*4,colorspace,kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,dataProvider,NULL,true,kCGRenderingIntentDefault);
        CFRelease(dataProvider);
        CGColorSpaceRelease(colorspacE);

        // Autorelease the CGImageRef
        newImage = (CGImageRef)[NsmakeCollectable(newImagE) autorelease];
    }

    // Clean up the framebuffer and renderbuffer.
    gldeleteRenderbuffers(1,&colorRenderbuffer);
    gldeleteFramebuffers(1,&framebuffer);

    return newImage;
}

大佬总结

以上是大佬教程为你收集整理的ios – 修改CMSampleBuffer内容的最有效方法全部内容,希望文章能够帮你解决ios – 修改CMSampleBuffer内容的最有效方法所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。