思想觉悟

其他

Opengl ES之矩阵变换(下)

如果不这样写会发生什么呢?例如顺这写,先写scaleM,然后是rotateM,最后写translateM,测试时就会出现问题,旋转超过180度之后再移动,就会出现移动方向相反的情况
2023年2月25日
其他

Opengl ES之矩阵变换(上)

glGetUniformLocation(program,"mvpMatrix");}MatrixTransformOpengl::~MatrixTransformOpengl()
2023年2月21日
其他

Opengl ES之踩坑记

);后来经过查阅资料发现是使用函数glTexImage3D时的第三个参数传递错误所致的,将第三个参数GL_RGB改为GLES30.GL_RGB16F即可,正确的代码如下:
2023年2月15日
其他

Opengl ES之RGB转NV21

2即可。为什么是这样的呢?虽然我们的目的是将RGB转换成YUV,但是我们的输入和输出时读取的类型GLenum是依然是RGBA,也就是说:width
2023年1月16日
其他

YUV转RGB的一些理论知识

你阳了没自广州疫情自全部放开,全力复工复产以后你阳了吗?疫情一放开,首先阳起来的就是那些做自媒体的,各种分享各种蹭流量,生怕错了几个亿一样,反正我是很看不起这些蹭流量的行为。。。因为很难找到做核酸的地方,也买不到抗原试纸做检测,因此我也不知道自己是否阳了。但是感觉该有的症状都有了,有个周末在家时反复高烧不断,干咳不止,咽痛,喉咙像刀割一样痛苦,说话声音嘶哑,甚至有时候很难说出话来。
2022年12月15日
其他

Opengl ES之YUV数据渲染

YUV回顾记得在音视频基础知识介绍中,笔者专门介绍过YUV的相关知识,可以参考:《音视频基础知识-YUV图像》YUV数据量相比RGB较小,因此YUV适用于传输,但是YUV图不能直接用于显示,需要转换为RGB格式才能显示,因而YUV数据渲染实际上就是使用Opengl
2022年11月23日
其他

Opengl ES之PBO

叨叨一句几句关于Opengl的系列已经有较长的一段时间没有更新了,然而这个系列还远没有到完毕地步,后续至少还有关于Opengl矩阵变换、YUV与RGB互转、Opengl水印贴图、Opengl转场动画等主题文章。断更的主要原因如果给自己找个借口的话可以说是工作比价忙,如果说的比较现实一点就是自己懒且没啥动力,毕竟写技术博客文章是一件时间成本投入很大,而收益产出极小的一件事情...进入正题...了解过Opengl的童鞋们都知道,在Opengl中存在这个各种O,例如VAO、VBO、FBO等,而出现各种各样的O一般都是因为考虑到性能的原因。今天我们要介绍的主角PBO,它和之前我们介绍VBO很像,了解完PBO之后童鞋们可以对比一下PBO与VBO的差异点。下面从两个方面介绍PBO,什么是PBO以及如何使用PBO。本文首发于微信公总号号:思想觉悟更多关于音视频、FFmpeg、Opengl、C++的原创文章请关注微信公众号:思想觉悟什么是PBOPBO(Pixel
2022年11月2日
其他

Opengl ES之FBO

FBO介绍FBO帧缓冲对象,它的主要作用一般就是用作离屏渲染,例如做Camera相机图像采集进行后期处理时就可能会用到FBO。假如相机出图的是OES纹理,为了方便后期处理,
2022年9月29日
其他

Opengl ES之EBO

glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
2022年9月27日
其他

Opengl ES之VBO和VAO

glBufferData(GL_ARRAY_BUFFER,sizeof(COLOR_ICES),COLOR_ICES,GL_STATIC_DRAW);主要绘制代码:
2022年9月23日
其他

Opengl ES之纹理贴图

纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上。一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据。所谓的纹理贴图,就是使用Opengl将这个纹理数据渲染出来,这个过程有点像装修工人给墙体贴瓷砖,而瓷砖好比作纹理。纹理坐标如果为了将一副纹理图贴到Opengl绘制的一个矩形上,那么就需要解决一个问题,如何知道矩形的具体某个点对应纹理图的某个点呢?为了解决这个问题就引出了纹理坐标,
2022年9月21日
其他

Opengl ES之四边形绘制

这个理解起来比较简单,笔者就不画说明图了。四个顶点绘制四边形使用四个顶点绘制两个三角形主要是复用了部分顶点,然后在glDrawArrays函数中使用绘制三角形带的方式进行绘制。//
2022年9月7日
其他

OpenglEs之三角形绘制

在前面我们已经在NDK层搭建好了EGL环境,也介绍了一些着色器相关的理论知识,那么这次我们就使用已经搭配的EGL绘制一个三角形吧。在Opengl
2022年9月5日
自由知乎 自由微博
其他

OpenglEs之着色器

//NDK_OPENGLES_LEARN_SHADERUTILS_H关于着色器的介绍就到这里,要想用好着色器,需要在弄懂GLSL语法之后多加实践...参考资料《LearnOpenGL
2022年9月3日
其他

OpenglEs之EGL环境搭建

前言前面我们发布了一系列的入门教程,例如C++系列的指针扫盲、多线程的使用等,JNI入门系列,ffmpeg入门系列等,有感兴趣的童鞋们可以关注往回自行查阅。今天我们的主题依然是音视频开发的范畴,做过音视频开发的都知道Opengl也是音视频开发中的一项重要技能,特别是涉及到视频录制、特效处理、画质渲染细分功能。因此后续笔者打算再出一系列的Opengl
2022年8月26日
其他

FFmpeg连载3-视频解码

avcodec_parameters_to_context(avCodecContext,avFormatContext->streams[video_index]->codecpar);
2022年4月17日
其他

FFmpeg连载2-分离视频和音频

前言前面我们搭建好了FFmpeg的开发环境,今天我们就来小试牛刀,使用FFmpeg库对mp4文件进行解封装,提取mp4中的视频流和音频流输出到单独的输出文件中。关于FFmpeg开发环境搭建可以看我之前的文章:所谓的分离视频和音频是我们通俗的说法,官方的说法叫解封装。与解封装对应的叫封装或复用器,也就是将多个视频流或音频流合并成一个多媒体文件就叫封装。API及数据结构介绍在FFmpeg中解封装的大致流程如下图所示:ffmpeg解封装流程图在这里需要注意的一个点是av_find_best_stream不一定能获取到你想要的流,比如你想通过av_find_best_stream获取音频流的索引,笔者开发中发现对于某些格式是无法获取成功的,
2022年4月16日
其他

FFmpeg连载1-开发环境搭建

前言之前笔者从事安卓开发的时候想要学习音视频实践,脑子里面想的是要是有专门针对安卓开发的FFmpeg教程就好了。慢慢地发现这个想法很不靠谱,因为那时关于音视频的相关教程本来就少,如果还要是针对安卓的就凤毛麟角了。后来为了学习FFmpeg,笔者也是断断续续的,从音视频的基础资料开始,从FFmpeg编译到实践,希望通过自己的学习可以一点一点地揭开FFmpeg的神秘面纱,直到今天笔者只敢说仅是音视频开发大军中的一个入门新手而已,虽说自己摸索挺久,
2022年4月15日
其他

JNI之常用技巧与陷阱

预告后续可能会推更一个FFmpeg系列的入门博客,大概涉及到FFmpeg解封装、FFmpeg编解码、FFmpeg进行音频重采样、使用FFMpeg将mp3转码成aac、使用FFmpeg合并拼接音视频等。另外如果有时间可能也会更新几篇关于ffplay的文章,敬请关注。本文将作为JNI系列的一个结尾,下面是笔者在学习使用JNI的所记录的一些笔记与技巧,还未怎么完善,后续可以继续更新...JNIEnv的线程限制一个JNIEnv指针仅在其相关联的线程中有效。你不能将这个指针从一个线程中传递给另一个线程,或者在多线程中缓存和使用它。Java虚拟机在同一个线程的连续调用中传递给本地方法相同的JNIEnv指针,但是从不同线程中调用本地方法时传递的是不同的JNIEnv指针。应当避免缓存一个线程的JNIEnv指针并在另一个线程中使用指针的常见错误。本地引用(局部引用)仅在创建它的线程中有效。你不能将本地引用从一个线程中传递到另一个线程。每当有多个线程可能使用相同引用的可能性时,应始终将本地引用转换为全局引用。JNIEnv是用作线程局部存储。因此,使用者不能在多线程间共享一个JNIEnv变量。如果在一段代码中没有其它办法获得它的JNIEnv,使用者可以共享JavaVM对象,使用GetEnv来取得该线程下的JNIEnv。如果你使用AttachCurrentThread连接(attach)了Native进程,正在运行的代码在线程分离(detach)之前绝不会自动释放局部引用。使用者创建的任何局部引用必须手动删除。通常,任何在循环中创建局部引用的Native代码可能都需要做一些手动删除。全局获取JNIEnv一个JNIEnv指针仅在与其相关联的线程中有效。对于本地方法,这通常不是问题,因为他们从虚拟机接受JNIEnv指针作为第一个参数。然而有时候可能不需要直接从虚拟机调用的本地代码来获取属于当前线程的JNIEnv接口指针。例如通过JNI在Native开启了一个子线程处理某些任务,在这些任务处理完毕后需要将处理结果回调给java层。这种情况可以通过缓存JavaVM获取当前线程的JNIEnv然后进行java方法的回调。当System加载一个本地库时,虚拟机会在本地库中查找下述的导出的程序入口:JNIEXPORT
2022年4月14日
其他

JNI之异常处理

前言本文所要介绍的异常处理是指通过JNI调用java层方法时产生的异常处理,并不是指JNI调用Native层函数时产生的异常处理,如果童鞋们想要了解Native层的异常处理可以参考笔者之前的文章《C++之异常处理》按照java的经验,当发生异常而又没有捕获时,异常后面的代码就得不到继续执行的机会,但是在JNI中不同,在JNI中如果调用java层的方法抛出了异常,依然会继续往后执行,但是这些行为往往会带来各种各样的"惊喜"。。。因此我们需要在异常发生时将这些异常及时进行处理。本文主要从捕获java层异常、向java层抛出异常两个方面介绍JNI中的异常处理机制。捕获java层异常当Native调用java层发生异常时可以通过函数ExceptionOccurred检测是否有发生异常,通过函数ExceptionDescribe输出异常描述信息,如果检测到异常处理完毕或者不进行异常处理又想让程序继续往下执行,那么通过函数ExceptionClear将异常清除即可。检测是否有异常时还可以使用函数ExceptionCheck,它与ExceptionOccurred函数的作用类似,不同之处在于ExceptionCheck函数不会返回异常对象的引用,而是返回一个异常是否发生的jboolean标识,当返回的标识为JNI_TRUE时代表有异常发生。当调用者不关心异常的类型,仅仅关心是否发生了异常的时候,使用它会更加方便而且高效。向java层抛出异常当希望将捕获到的异常向java层继续抛出时,可以通过JNI函数ThrowNew抛出一个异常,这个异常可以被java层的try
2022年4月13日
其他

JNI之缓存与引用

}}系列推荐JNI基础简介JNI之数组与字符串的使用JNI之动态注册与静态注册JNI之访问java属性和方法关注我,一起进步,人生不止coding!!!
2022年4月12日
其他

JNI之访问java属性和方法

env->SetObjectField(thiz,nameFielid,env->NewStringUTF("james"));}2、访问静态属性
2022年4月11日
其他

JNI之动态注册与静态注册

导读我们知道通过Java通过JNI可以调用C/C++代码,C/C++也可以通过JNI调用java代码,那么JNI是怎么将Java方法与Native的方法对应起来的呢?JVM查找Native方法有两种方式:1、按照JNI规范的命名规则进行查找,这种方式叫静态注册。2、调用JNI提供的RegisterNatives函数,将本地函数注册到JVM中,这种方式叫动态注册。静态注册所谓静态注册就是按照JNI规范书写函数名:java_类路径_方法名(路径用下划线分隔)当我们使用Android
2022年4月10日
其他

JNI之数组与字符串的使用

字符串和数组是JNI中常见的引用数据类型,本文将介绍符串和数组在JNI中的常见处理方式。JNI中字符串的处理1、Java字符串与原生字符串转换当从java层传递一个字符串过来之后,它的类型是jstring,同样如果需要返回一个字符串给java层,它的类型也是jstring。jstring代表着Java虚拟机中的一个字符串,并且不同于C++语言的string类型。如果原生代码需要处理jstring,需要通过JNIEnv将其转换为原生字符串才可以使用。通过JNI函数GetStringUTFChars来读取这个字符串中的内容,GetStringUTFChars函数可以通过JNIEnv接口指针调用,它将一个代表着Java虚拟机中的字符串jstring引用,转换成为一个UTF-8形式的C字符串。当原生代码使用完了通过GetStringUTFChars获取的原生字符串后应该使用ReleaseStringUTFChars释放它。调用ReleaseStringUTFChars标识着原生代码不再需要使用从GetStringUTFChars获取的UTF-8字符串了,这个UTF-8字符串所占用的空间就可以被释放了。如果不调用ReleaseStringUTFChars释放原生字符串的话将会导致内存泄露。我们看下函数GetStringUTFChars的原型是:const
2022年4月9日
其他

JNI基础简介

导读在前面的几篇文章中,笔者介绍了C++中的指针、引用、智能指针、多线程、类型转换、异常处理等相关知识点,如果想要熟练掌握,并能在实际项目中运用,光是看肯定是毫无用处,纸上谈兵永远比不上脚踏实地的实在。。。以下是前几篇文章的回顾:C++之RVO返回值优化C++之const关键字C++之指针扫盲C++之智能指针C++之指针与引用C++之右值引用C++之类型转换C++之多线程一C++之多线程二C++之异常处理从今天开始文章的内容将是一系列JNI入门的相关文章。JNIJNI是Java
2022年4月8日
其他

C++之异常处理

为什么引入异常在C语言中错误的处理,通常采用返回值的方式或是使用全局变量的方式。这就存在两个问题,一是如果返回值正是我们需要的数据,这就导致了返回数据同出错数据容错差不高。二是全局变量,在多线程中易引发竞争,而且,当错误发生时,上级函数要出错处理,层层上报,造成过多的出错处理代码,且传递的效率低下。因此C++引入了面向对象级别的异常处理机制。在C++中异常的处理和具体逻辑的处理不比在同一个函数中,这样就可以做到底层逻辑专注于功能的实现,具体错误处理交由上层业务逻辑去处理。异常如何使用?使用关键字throw
2022年4月7日
其他

C++之多线程(二)

导读做开发的人都知道多线程是一个很复杂的问题,一不下心就会出现莫名其妙的八哥,有句话调侃说:一个程序员碰到了一个问题,他决定用多线程来解决。现在他有了两个问题。。。在前面《C++之多线程(一)》
2022年4月3日
其他

C++之多线程(一)

导读终于,在万众期待之下,C++11有了自己的线程库,实现了真正意义上的跨平台,今天在了解C++11线程库的同时,也来温习下POSIX线程。POSIX线程在C++11之前因为没有C++语言没有语言级别的线程库,所以在Linux上用的都是POSIX线程,POSIX的相关API大概如下:POSIX函数功能pthread_create创建线程pthread_exit退出线程pthread_join等待线程退出pthread_cancel取消线程pthread_detach线程分离pthread_self获取线程idpthread_equal对比是否是同一线程,返回0是同一个线程1、创建线程
2022年4月1日
其他

C++之类型转换

指针转型为有类型指针,基类指针转型为派生类指针等。所谓静态类型,就是在编译器就能确定的类型,静态类型转换的使用格式是:static_cast(标识符)例如:int
2022年3月31日
其他

C++之右值引用

world",这个字符串,我们是可以通过取地址符号&获取到地址的。右值怎么用在语法上右值就是在左值的基础上增加了一个符号&,也就是使用&&表示右值引用:void
2022年3月30日
其他

C++之const关键字

const作用const关键字在C++中真是无处不在,无论是函数参数,还是函数返回值,还是函数末尾都经常会看到const关键字,这表明C++中的const关键字是非常灵活的,
2022年3月29日
其他

C++之智能指针

导读在《C++之指针扫盲》一文中我们对指针进行了讲解,虽然原始指针是几乎无所不能,的确是一把利器,但就是这样的一把利器让多少人既爱又恨,一不小心就杀敌一千,自损八百,无论你是
2022年3月24日
其他

C++之指针与引用

指针和引用的区别?在C++的编码中我们发现很多地方都大量地使用引用,能用指针实现的功能用引用几乎也能实现,甚至因为引用不需要拷贝的特性,使用起来比指针性能更高。
2022年3月23日
其他

C++之指针扫盲

就是一个指针数组,因为运算符[]的优先级运算符*的优先级高,所以p优先和[]组成数组,然后*和类型int组合成数组元素的类型。例如以下程序就是一个指针数组的示例:main.c#include
2022年3月22日
其他

C++之RVO返回值优化

Optimization。RVO是一种编译器优化技术,可以把通过函数返回创建的临时对象给”去掉”,然后可以达到少调用拷贝构造的操作目的,
2022年3月21日
其他

NDK编程Java如何保存C或C++对象

前言最近有个想进阶Android,学习NDK编程的小伙伴问我说看了不少网上的视频教程,大多数的主题都是讲JNI的方法签名、JNI线程绑定、JNI调用Java方法等主要的内容。自己在练习的过程中发现如果需要重复利用一个C或者C++的对象时就不知道怎么处理了。其实这就是Java对象如何保存Native对象的一个问题而已。听了这个朋友的疑问,我翻了下网上关于NDK的视频教程,确实是很多教程都没有介绍Java对象如何复用一个Native对象。但是这又是一个在NDK实战中必然会碰到的一个关键点。有道是老师带入门,修行在自身,这句话是很在理的。在这个信息爆炸的年代,你与知识的距离就是一跟网线的距离,那么如何拉开大家的距离呢?或许这个时候就看谁的自学自研能力,甚至是
2021年3月28日
其他

Android使用ffmpeg解码视频为YUV

fwrite(frame->data[1],1,cc_ctx->width/2*cc_ctx->height/2,yuvFile);
2020年2月25日
其他

将ffmpeg引入到Android Studio工程中

NewStringUTF(av_version_info());}通过TextView显示一下获取到的版本号:成功获取到ffmpeg版本号遇到的问题报错ffmpeg的相关库没有找到
2020年2月6日
其他

NDKr20使用clang编译ffmpeg4.2.2

有关ffmpeg的编译资料网上一大推,但是照着资料拷贝的运行进行编译能顺利编译出静态库或静态库产物的寥寥无几。笔者在学习的时候也是踩了很多的坑,确实是每次编译会诞生一个放弃的念头,原因还是自己的基础学得不够扎实。因为ffmpeg和NDK都是在不断进行迭代的,比如说NDK在r18之后之后彻底移除了gcc(包含r18版本),ffmpeg在4.o版本开始也针对Android平台的交叉编译默认使用clang编译,但是网上的很多资料都是使用gcc编译的。所以如果要对照网上资料进行编译的话,保证NDK版本和ffmpeg版本甚至是编译环境工具都和作者的一样,这样会大大提高编译的成功率。在编译成功之后再不断尝试修改参数结合搜索资料尝试,力求弄清楚每个参数的意义,做到触类旁通。本次编译使用的是mac苹果电脑,使用的NDK版本是r20,ffmpeg是从官网下载的最新版4.2.2。编译脚本从ffmpeg官网下载好源码解压后,进入源码目录,新建shell脚本文件,比如build_ffmpeg.sh
2020年2月5日
其他

音视频基础知识-YUV图像

128)YUV420p和YUV420sp具体分类和详情YUV420也是目前最主流的采样方式,因为这样的采样最省空间,而又不会大幅度影响人类肉眼的观赏性。YUV420p:又叫planer平面模式,Y
2020年1月21日