核心思想
滤镜的预览image处理是基于GPU的,需要openGL环境。核心思想就是预览架构,目前的实现方案是使用GLSurfaceView绑定openGL环境。
预览架构
- 使用GLSurfaceView接相机的预览数据
- 处理相机预览数据的方向,Matrix变换
- 把接的预览数据画到屏上
- 使用fbo快速抓取预览数据
- 对预览数据做二次处理
流程图:
预览架构.png滤镜
- 预览处理接口
- 拍照处理接口
- 设置接口
- 滤镜ui与动画
- postView处理
- 文件结构
- Android.mk模式化编译
预览接口
public interface IPreviewCallbacker {
boolean draw(SurfaceTexture surfaceTexture, int oesTextureId, int surfaceWidth, int surfaceHeight);
boolean drawOffScreen(SurfaceTexture surfaceTexture, int oesTextureId, int width, int height,int fboId);
void modeInitCallback();
void modeUninitCallback();
void surfaceCreatedCallback(SurfaceTexture texture);
void surfaceDestroyCallback(SurfaceTexture texture);
void loadGLResourceCallback(int resId);
void loadGLResourcesCallback(int [] resIds);
}
拍照处理和设置接口
这是常规接口,底层支持多少种类的滤镜,选中的哪种滤镜。只需要和底层协商和联调即可,代码的添加全是机械式的。
滤镜的ui与动画
现有的UIManager不满足要求,需要实现一个FilterUIManager,管理滤镜ui,主要的难点是ArcFilterSwitcher,这个是自定义的,需要自定义View的一些知识,后面会做一次有关自定义View的培训。还有一个难点,是和TopBar和BottomBar的交互。需要拿到要交互的View的句柄和自定义ArcFilterTopItemUI。
postView和mode处理
底层一直说滤镜postView比较难实现,为了能顺便发专项,滤镜的postView是上层实现的,主要接口如下:
public interface IModeCallback {
void init(Context context, ISettingManager.SettingController settingController,
IAppUI appUI, CameraDeviceControl cameraDeviceControl,
String cameraId, IApp.IIntentAction action)
void unInit();
boolean onPostViewData(int yuvWidth, int yuvHeight, int orientation,boolean isMirror);
boolean onShutterClick();
}
这个接口主要绑定mode,目前滤镜内置PhotoMode中的。
文件结构
参数目前的架框,把自己实现的代码放在一起,异于管理。方便模块化。
UI目录.png
Android.mk模式化编译
引子
刚接触p相机新架构,build.gradle有如下写法:
dependencies {
api project(':Feature:setting:Flash')
api project(':Feature:setting:PictureSize')
api project(':Feature:setting:HDR'
......................
}
infinix {
def infinixSrcFolder = [
app_ui_folder + 'Infinix/src',
setting_ui_folder + 'Infinix/Flash/src',
setting_ui_folder + 'Infinix/Focus/src',
setting_ui_folder + 'Infinix/Exposure/src',
]
def infinixResFolder = [
app_ui_folder + 'Infinix/res',
app_ui_folder + 'Infinix/res_overlay',
setting_ui_folder + 'Infinix/Flash/res',
setting_ui_folder + 'Infinix/Focus/res',
setting_ui_folder + 'Infinix/Exposure/res',
]
显然setting是可以模式化的,便是其它的不是,这和模块化开发思想不符合,后来问张超,主要的原因是setting没有资源,像mode是有资源的。如果使用api project的方式,android studio编译是没有问题的,但Android.mk不支持编译成aar包,为了统一处理,才这样的做的。
后在研究,Android.mk是不支持编译成aar包,但是滤镜已开发成了一个模块。如果回到统一处理,引用的资源的java文件要全部把资源包,从import com.transsion.camera.feature.arcfilter.R;换成 import com.transsion.camera.R;
这个比较麻烦,也是最后的选择。
实现思想
Android.mk不支持编译aar选项,如果把滤镜直接编译成apk,是可以带资源的,但是我们Camera的宿主架构不支持动态加载插件。这个思想只能选择放弃。可以选择的也就只能把java文件编译成.jar了,资源文件编译到宿主Camera中,但是资源R文件要是com.transsion.camera.feature.arcfilter.R,还不是宿主的com.transsion.camera.R。aapt是android的资源打包工具,只能研究它了,看有没有方法支持。
appt LOCAL_AAPT_FLAGS += --extra-packages com.transsion.camera.feature.arcfilter
可以满足需求。就是给资源起一个别名。
LOCAL_RESOURCE_DIR += $(LOCAL_PATH)../../../Feature/module/ArcFilter/res
LOCAL_REQUIRED_MODULES := libArcFilter
LOCAL_JNI_SHARED_LIBARARIES := libArcFilter
LOCAL_AAPT_FLAGS += --extra-packages com.transsion.camera.feature.arcfilter
LOCAL_STATIC_JAVA_LIBRARIES += com.transsion.camera.feature.arcfilter
网友评论