IOS:Camera的特性分析与使用3_OPENGL特效
来源:互联网 发布:响应式网站整站源码 编辑:程序博客网 时间:2024/06/06 15:35
本来想用2个篇幅结束Camera软件部分的介绍,后来发现,非常重要的一点OpenGL还没介绍,所以又增加了这一篇。
这篇主要描述一下几个方面的内容:
(1)录像界面OPENGL展示
(2)录像实时特效处理
(3)视频等比例缩放、旋转 如:等比例、16:9 4:3 1:1等
这个部分我思来想去缺失不太好讲,设计到的知识太多,尤其是OpenGL的一些专业知识,通过一篇博客普及OpenGL的知识显然不科学,所以只能了解一个流程,至于里面到底是怎么回事,请大家找本OpenGL的书看看,我想等这几个博客完工之后,也写几篇OpenGL的博客呵呵。
我们的整个流程是,首先从AVCaptureSession拿到视频拍摄时候的数据流,然后特效处理(特效这块可以参考另一个Image&Animation专栏),然后初始化OpenGL开始进行纹理贴图。
(1)如何拿到视频数据流?
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
if ( videooutput == captureOutput ) {
OSStatus err = CMBufferQueueEnqueue(previewBufferQueue, sampleBuffer);
if ( !err ) {
dispatch_async(dispatch_get_main_queue(), ^{
CMSampleBufferRef sbuf = (CMSampleBufferRef)CMBufferQueueDequeueAndRetain(previewBufferQueue);
if (sbuf) {
CVImageBufferRef pixBuf = CMSampleBufferGetImageBuffer(sbuf);
if (effectflag) {
特效处理
}
OpenGL纹理展示
CFRelease(sbuf);
}
});
}
}
}
AVCaptureSession初始化完成之后我们可以设置一个回调方法,在这个回调方法中,可以很方便的拿到我们需要处理的图像数据。(2)如何进行图片的特效处理
这又是一个非常复杂的内容,我也专门为此写了另外一篇博客:
这中间牵扯到各种图像处理算法,neon、汇编优化,ARM内部寄存器的使用等等。
这里我们只说如何吧ImageBuffer转化为RGBA像素:
unsignedchar *pixel = (unsignedchar *)CVPixelBufferGetBaseAddress(pixelBuffer);
这里pixel存放的就是图片的RGBA像素值。(3)OpenGL纹理贴图
3.1//在使用Opengles的时候需要重构CAEAGLLayer图层
+ (Class)layerClass
{
return [CAEAGLLayerclass];
}
3.2// 设置CAEAGLLayer
CAEAGLLayer*eaglLayer = (CAEAGLLayer *)self.layer;
3.3设置CAEAGLLayer层的属性RGBA8
3.4// 使用opengl2.0创建图像绘制上下文
oglContext = [[EAGLContextalloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
3.5// 设置oglContext为当前上下文
3.2 // glEnable(GL_DEPTH_TEST):用来开启更新深度缓冲区的功能
3.3 // 创建帧缓冲区
3.4 // 讲帧缓冲区绑定在绘图管线上
3.5 // 创建绘图缓冲区
3.6 // 讲绘图缓冲区绑定在管线上
3.7 // 为绘图缓冲区(或者叫渲染缓冲区分配空间)
3.8 // 获取当前绘图缓冲区(渲染缓冲区的)宽和高
3.9 // 讲渲染缓冲区与帧缓冲区绑定在一起
3.10 // 检查当前帧缓冲区的状态是否有效
3.11 // 创建一个opengl的纹理对象
3.12 // 加载定点和片段着色器
3.13 // 创建并初始化这个工程对象
对应代码如下://在使用Opengles的时候需要重构CAEAGLLayer图层
+ (Class)layerClass
{
return [CAEAGLLayerclass];
}
- (BOOL)initializeBuffers
{
// 设置oglContext为当前上下文
if ([EAGLContextcurrentContext] != oglContext) {
if ([EAGLContextsetCurrentContext:oglContext]) {
NSLog(@"setCurrentContext error... ...");
}
}
BOOL success =YES;
// 设置图层的frame和bounds
CGRect rtFullscreem = [[UIScreenmainScreen] bounds];
CGRect rtCurrframe = self.layer.frame;
CGRect rtCurrbounds = self.layer.bounds;
self.layer.frame = rtFullscreem;
self.layer.bounds = rtFullscreem;
NSLog(@"size{%f %f %f %f}", rtFullscreem.origin.x, rtFullscreem.origin.x, rtFullscreem.size.width, rtFullscreem.size.height);
// glEnable(GL_DEPTH_TEST):用来开启更新深度缓冲区的功能,也就是,如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作。启动它,OpenGL就可以跟踪再Z轴上的像素,这样,它只会再那个像素前方没有东西时,才会绘画这个像素。
// 一般这个功能开启之后绘制3D效果比较好
glDisable(GL_DEPTH_TEST);
// 创建帧缓冲区
glGenFramebuffers(1, &frameBufferHandle);
// 讲帧缓冲区绑定在绘图管线上
glBindFramebuffer(GL_FRAMEBUFFER,frameBufferHandle);
// 创建绘图缓冲区
glGenRenderbuffers(1, &colorBufferHandle);
// 讲绘图缓冲区绑定在管线上
glBindRenderbuffer(GL_RENDERBUFFER,colorBufferHandle);
// 为绘图缓冲区(或者叫渲染缓冲区分配空间)
[oglContextrenderbufferStorage:GL_RENDERBUFFERfromDrawable:(CAEAGLLayer *)self.layer];
// 获取当前绘图缓冲区(渲染缓冲区的)宽和高
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_WIDTH, &renderBufferWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER,GL_RENDERBUFFER_HEIGHT, &renderBufferHeight);
// 讲渲染缓冲区与帧缓冲区绑定在一起
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,colorBufferHandle);
// 检查当前帧缓冲区的状态是否有效
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"Failure with framebuffer generation 0x%X",glCheckFramebufferStatus(GL_FRAMEBUFFER));
success =NO;
}
// Create a new CVOpenGLESTexture cache
// 创建一个opengl的纹理对象
// 在oglContext 中创建纹理对象
CVReturn err =CVOpenGLESTextureCacheCreate(kCFAllocatorDefault,NULL, oglContext, NULL, &videoTextureCache);
if (err) {
NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err);
success =NO;
}
// Load vertex and fragment shaders
// 加载定点和片段着色器
constGLchar *vertSrc =str_passThrough_v;//[self readFile:@"passThrough.vsh"];
constGLchar *fragSrc =str_passThrough_f;// [self readFile:@"passThrough.fsh"];
// attributes
GLint attribLocation[NUM_ATTRIBUTES] = {
ATTRIB_VERTEX,ATTRIB_TEXTUREPOSITON,
};
GLchar *attribName[NUM_ATTRIBUTES] = {
"position","textureCoordinate",
};
// 创建并初始化这个工程对象
glueCreateProgram(vertSrc, fragSrc,
NUM_ATTRIBUTES, (constGLchar **)&attribName[0], attribLocation,
0,0, 0,// we don't need to get uniform locations in this example
&passThroughProgram);
if (!passThroughProgram)
success =NO;
self.layer.frame = rtCurrframe;
self.layer.bounds = rtCurrbounds;
return success;
}
最后我们再来看看如何对所播放的视频屏幕进行等比例缩放,16:9等缩放这里我们首先需要设置一个属性:
glVertexAttribPointer(ATTRIB_TEXTUREPOSITON,2,GL_FLOAT,0,0,textureVertices);
而textureVertices 是一个数组,用于进行纹理贴图时画面设置:全屏幕播放
GLfloat squareVertices0[8] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
等比例拉伸GLfloat squareVertices1[8] = {
-0.5625f, -1.0f,
0.5625f, -1.0f,
-0.5625f, 1.0f,
0.5625f, 1.0f
};
这个数据是啥意思呢?看下面两个图屏幕拍摄为1920*1080,所以1080/1920=0.5625.注意拍摄时候 宽高倒置。
- IOS:Camera的特性分析与使用3_OPENGL特效
- IOS:Camera的特性分析与使用
- IOS:Camera的特性分析与使用2_AVCapture
- camera 3d特效 详解与进阶
- iOS - WKWebView的新特性与使用
- 【iOS】WKWebView的新特性与使用
- android camera 3d特效 详解与进阶
- IOS 特性CALayer的使用
- IOS 特性CALayer的使用
- IOS 特性CALayer的使用
- IOS 特性CALayer的使用
- IOS 特性CALayer的使用
- S3C2440的camera接口特性
- Matrix与graphics.Camera的使用
- Voodoo Camera Tracker 的介绍与使用
- IOS UIDynamicAnimator动力特效使用
- iOS---使用CAEmitterLayer制作发射粒子的特效
- RecyclerView的基本使用,特性分析
- /bin,/sbin,/usr/sbin,/usr/bin 目录之间的简单区别
- 不独立事件的条件概率选取——[即时]抽取【JAVA SE】
- 拷贝构造函数和赋值操作符
- Sublime Text 安装GIt 插件--SublimeGit
- 二层与三层转发的简单介绍
- IOS:Camera的特性分析与使用3_OPENGL特效
- 伟大程序员的十大特质
- eclipse CDT写c++使用文件作为输入源(输入重定向)
- eclipse使用jpa实现数据库反向生成Hibernate实体
- qtobject简介
- Python 标准库 BaseHTTPServer 中文翻译
- hdu 1070 Milk
- Unity3D研究院transform.parent = parent坐标就乱了
- android 双服务常驻后台:防止意见清理