Camera Hal(Hal3)层修改Preview流

问题描述

在Camera的Hal层修改数据流,系统相机应用获取到的数据会改变,除此之外,调用相机服务的第三方应用获取到的数据也会得到改变。比如Oppo手机 ColorOS 12 OMOJI功能:微信视频通话的时候可以使用3D表情功能。

Camera Hal(Hal3)层修改Preview流_第1张图片
如果在相机的Hal层对数据流进行修改,第三方使用相机服务的应用得到的数据也会改变。
具体怎样对Camera Hal层的数据进行修改?

解决问题思路

1.找到Camera Hal层的数据流
2.了解数据流格式,对其进行修改

问题解决

找到Preview数据流:
hardware\qcom\camera\QCamera2\HAL3
QCamera2HardwareInterface::preview_stream_cb_routinemm_camera_super_buf_t *super_frame, QCameraStream * stream, void userdata)
//了解下 mm_camera_super_buf_t数据结构
typedef struct {
uint32_t camera_handle;
uint32_t ch_id;
uint32_t num_bufs;
uint8_t bUnlockAEC;
uint8_t bReadyForPrepareSnapshot;
mm_camera_buf_def_t
bufs[MAX_STREAM_NUM_IN_BUNDLE]; //各种数据流
} mm_camera_super_buf_t;

其中super_frame->bufs[0]的就是Preview流,继续了解mm_camera_buf_def_t的数据结构:
typedef struct mm_camera_buf_def {
uint32_t stream_id;
cam_stream_type_t stream_type;
cam_stream_buf_type buf_type;
uint32_t buf_idx;
uint8_t is_uv_subsampled;
struct timespec ts;
uint32_t frame_idx;
union {
mm_camera_plane_buf_def_t planes_buf;
mm_camera_user_buf_def_t user_buf;
};
int fd;
void *buffer; //真正数据
size_t frame_len;
void *mem_info;
uint32_t flags;
uint32_t cache_flags;
} mm_camera_buf_def_t;

preview流真正的数据:super_frame->bufs[0]->buffer;

数据修改:
preview流的数据是YUV,格式为nv21。
以一个44的小图来解释格式nv21
一共有的数据个数为 4
43/2,其中44是Y(明亮度),44/2为UV(色彩)
Y Y Y Y
Y Y Y Y
Y Y Y Y
Y Y Y Y
V U V U
V U V U
如果我把想把4
4这个小图设置为灰色图,即色彩值为128(色彩黑,色彩值为0;色彩白,色彩值为255;色彩灰,色彩之为128(0x80))
可以写一个灰色滤镜函数:
void GrayFilter(unsigned char* yuvsrc, int width, int height)
{
int Y_len=widthheight;
int VU_len=Y_len/2;
unsigned char
p=yuvsrc+Y_len;
memset(p,0x80,(size_t)VU_len);
}

其中 for(int i=0;i *p=0x80;
代码和 memset(p,0x80,(size_t)VU_len); 实现效果一致,但是使用memset(p,0x80,(size_t)VU_len)效率更高。这句话的含义就是把YUV途中色彩部分(VU_len)赋值为0x80(即十进制的128,灰色)。

在Camera Hal2中进行调用这个函数

voidQCamera2HardwareInterface::preview_stream_cb_routine
(mm_camera_super_buf_t *super_frame, QCameraStream * stream, void userdata)
{
//获取YUV数据地址
++ unsigned char
yuvsrc = (unsigned char *)super_frame->bufs[0]->buffer;

++ cam_frame_len_offset_t offset;
++ stream->getFrameOffset(offset);
//其中offset.mp[0].stride为对齐后的宽
//offset.mp[0].scanline为对齐后的高
//调用灰色滤镜函数
++ GrayFilter(yuvsrc,offset.mp[0].stride,offset.mp[0].scanline);
}

效果

   编译之后,刷机,相机的预览后面相当于加了个灰色滤镜的效果,第三方调用相机服务的预览画面也是加了个灰色滤镜的效果。 
   本来想做个黑白滤镜的效果,即把色彩VU的值都复制为0;但是测试的时候,发现画面都是绿色,不知道是不是相机底层加了颜色纠正的功能,如果有人知道这个问题,不吝赐教~~~

写在最后的话

   今天周日对之前的学习进行了个小总结~~~写了这篇博客,如果觉得这篇文章对你有点帮忙,就点个赞吧~~~~ 

你可能感兴趣的:(c++,android,图像处理)