【Camera专题】HAL层-实现第三方算法并集成到Android系统

更新时间:2023-05-15 08:08:13 阅读: 评论:0

【Camera专题】HAL层-实现第三⽅算法并集成到Android系统系列⽂章
动⼿⼊门第三⽅算法集成系列:
⼀、前⾔
最近⾃⼰学了⼀下Camera数据流的知识,如何运⽤这些知识呢?
最好的⽅式就是加⼊第三⽅算法。当然,虽然学习都是以HelloWorld的⽅式;
但⾃⼰实现的算法,还是要能看到效果的,也要容易理解。
平台:⾼通8909
版本:HAL1
需要掌握的⼀些知识点
1.熟悉Camera数据流,⾄少知道回调函数在哪⾥
2.了解YUV的相关知识
3.掌握相关的结构体
4.掌握HAL层的⼀些API
5.掌握JNI的知识
6.动⼿实践第三⽅算法,并植⼊系统。
第三⽅算法的集成⽅式
APP集成
这就需要你会java并且懂JNI
Hal层集成
需要你熟悉Camera数据流,YUV的相关知识,HAL层的⼀些API。
本⽂选⽤HAL层的集成⽅式。
第三⽅算法集成推荐博客
这是我同事的博客,以前专门做第三⽅算法移植的,现在做framework层了。
很多知识我也是看他的博客学习的,下⾯的知识点就是参考他的。
然后我加⼊⾃⼰的实践,学以致⽤!固定资产盘点方案>校事
⼆、知识点
1.HAL1-Camera数据流的回调函数
参考我同事写的⽂章
这⾥做⼀些总结:(以下是HAL1的函数)
1.Preview流 回调函数
正常模式下
根据平台不同,会调⽤都下⾯其中⼀个函数。委托协议书
hardware/qcom/camera/QCamera2QCameraHWICallbacks.cpp
1. QCamera2HardwareInterface::preview_stream_cb_routine(...)
2. QCamera2HardwareInterface::synchronous_stream_cb_routine(...)
no-display-mode模式下
no-display-mode是指App打开Camera后, 在startPreview之前设置参数Parameters.t(“no-display-mode”, “1”);,然后可以不设置预览surface进⾏预览拍照(主要⽤于双摄项⽬中, 副摄设置no-display-mode, 对⽤户不可见).
1. QCamera2HardwareInterface::nodisplay_preview_stream_cb_routine(...)
2.Snapshot流 回调函数
⾮ZSL模式
hardware/qcom/camera/QCamera2/QCameraHWICallbacks.cpp
hardware/qcom/camera/QCamera2/QCameraPostProc.cpp
1. QCamera2HardwareInterface::capture_channel_cb_routine(...)
2. QCameraPostProcessor::processPPData(...)
ZSL模式
1. QCamera2HardwareInterface::zsl_channel_cb(...)
2. QCameraPostProcessor::processPPData(...)
⼩技巧:如果希望第三⽅算法对任意拍照模式都⽣效,那就在【processPPData】函数⾥⾯改动!
3.Video流 回调函数
录像预览流数据
hardware/qcom/camera/QCamera2/QCameraHWICallbacks.cpp
1.  QCamera2HardwareInterface::video_stream_cb_routine(...)
录像拍照流数据
1.QCamera2HardwareInterface::snapshot_channel_cb_routine(...)
⼩结:
以上的函数,都可拿到 void* data 类型的YUV数据,本质上就是 unsigned char* 类型的数组
数据范围[0-255]
如果你打印出来,你可以看到 0x00到0xff的数据
2.YUV的⼀些基础知识
关于YUV的知识,可以⾃⾏度娘或者⾕歌学习。
以下总结⼀些我觉得应该知道的:
YUV的含义
YUV也是⼀种颜⾊编码⽅法,主要⽤于电视系统以及模拟视频领域,
它将亮度信息(Y)与⾊彩信息(UV)分离,没有UV信息⼀样可以显⽰完整的图像,
只不过是⿊⽩的,这样的设计很好地解决了彩⾊电视机与⿊⽩电视的兼容问题。
并且,YUV不像RGB那样要求三个独⽴的视频信号同时传输,所以⽤YUV⽅式传送占⽤极少的频宽。
YUV 采样(其中⼀种)
YUV 4:2:0采样,每四个Y共⽤⼀组UV分量⼀个YUV占8+2+2 = 12bits 1.5个字节。
需要占⽤的内存:w * h * 3 / 2=w * h * 1.5
内存则是:yyyyyyyyuuvv
存放⽅式是⼀个⼀维数组,但是你可以根据宽x⾼把他看作⼆维数组来理解,如下图。
YUV420sp格式如下图
分辨率为8X4的YUV图像,它们的格式如下图:
我们经常看到的Android或者IOS摄像头采集到的NV12或者NV21数据,其实本质上是YUV,即YUV420sp。数据存放的格式【YYYYUV】,先放完所有的Y数据,然后在放UV数据。
3.掌握相关的结构体
1. mm_camera_buf_def_t:数据流 帧缓冲区 结构体
hardware/qcom/camera/QCamera2/stack/common/mm_camera_interface.h
typedef  struct  {
uint32_t stream_id ;//标识流对象的id ,跟⼈的⾝份证类似
cam_stream_type_t stream_type ;//数据流类型
uint32_t buf_idx ;//放在内存中的 buf 索引
uint8_t is_uv_subsampled ;
struct  timespec ts ; //时间戳,在调⽤DQBUF 时填充
uint32_t frame_idx ;//帧序列编号,待DQBUF 填充
int8_t num_planes ;//帧缓冲区的平⾯数,在mem 分配期间填充
struct  v4l2_plane planes [VIDEO_MAX_PLANES ];//帧缓冲区的平⾯信息,将在mem 分配期间填充
int  fd ; //帧缓冲区的⽂件描述符
void  *buffer ;//指向帧缓冲区的指针
size_t frame_len ;//帧长度
月饼void  *mem_info ;//指向附加mem 信息的⽤户特定指针
} mm_camera_buf_def_t ;
这个结构体⾥,最重要的信息:
指向帧缓冲区的指针
void* data 类型的YUV数据,本质上就是 unsigned char* 类型的数组
帧长度
最好吃的蛋糕
2. mm_camera_super_buf_t
hardware/qcom/camera/QCamera2/stack/common/mm_camera_interface.h
typedef  struct  {
uint32_t camera_handle ;//唯⼀标识相机对象
uint32_t ch_id ;//通道id
uint32_t num_bufs ;//super buf 中的缓冲区数,不能超过4
mm_camera_buf_def_t * bufs [MAX_STREAM_NUM_IN_BUNDLE ];
//bundle 中的缓冲区数组
} mm_camera_super_buf_t ;
这⾥的super_buf"继承"了⽗类mm_camera_buf_def_t,
(C语⾔的继承就是结构体⾥包含其他结构体)。
加⼊了通道信息ch_id、缓冲区数。
3. cam_frame_len_offt_t 和cam_mp_len_offt_t
hardware/qcom/camera/QCamera2/stack/common/cam_types.h
1.void ∗buffer
2.size _tframe _len
typedef struct{
uint32_t len;
uint32_t offt;
int32_t offt_x;
int32_t offt_y;
int32_t stride;
int32_t scanline;
int32_t width;/* width without padding */
int32_t height;/* height without padding */
} cam_mp_len_offt_t;
typedef struct{
uint32_t num_planes;
union{
cam_sp_len_offt_t sp;
cam_mp_len_offt_t mp[VIDEO_MAX_PLANES];
};
uint32_t frame_len;
} cam_frame_len_offt_t;
⾮对齐(⾮填充)的宽⾼
width
height
对齐(填充)后的宽⾼
int32_t stride;
nt32_t scanline;
4. cam_dimension_t
hardware/qcom/camera/QCamera2/stack/common/cam_types.h
typedef struct{
int32_t width;
int32_t height;
} cam_dimension_t;
图⽚的实际宽⾼
对齐(填充)概念
在⾼通平台, YUV数据⼀般会有对齐, 对齐是指为了处理效率更⾼, 图⽚宽⾼必须是某些数的整数倍(如 32或者64),
当然为什么对齐后处理效率更⾼, 这个好像是由于硬件设计的⼀些特性, 详细就不太清楚了. 如果图⽚宽⾼不是64位倍数, 对齐过后会在原图⽚右侧和下⽅留下⽆效像素, 当然经过JPEG硬件编码过后会被裁剪,
所以App层看到的是正常的, 只不过我们在HAL层获取的YUV数据是有⽆效像素的,
4.HAL层相关的API
如果你看过我之前写的博客,应该知道,数据流都是存放在通道⾥的!
⼀个通道⾥⾯可以有多个数据流。
1.获取 通道[QCameraChannel]
通道类型:
QCAMERA_CH_TYPE_VIDEO(video)
录像预览通道
QCAMERA_CH_TYPE_SNAPSHOT(video snap)
录像拍照通道
QCAMERA_CH_TYPE_ZSL(zsl)
ZSL通道
QCAMERA_CH_TYPE_CAPTURE(capture)
拍照通道
相关API:
凉拌腐竹的做法
⽰例(zsl_channel_cb()中获取channel):
我们的神本为大
QCamera2HardwareInterface *pme =(QCamera2HardwareInterface *)urdata; QCameraChannel *pChannel = pme->m_channels[QCAMERA_CH_TYPE_ZSL];
其他通道类似。
2.获取 数据流
⽅式⼀
mm_camera_buf_def_t* yuvFrame =NULL;//定义数据流缓冲区结构体
QCameraStream* stream =NULL;//数据流
总是干咳
// frame 为 mm_camera_super_buf_t 类型
for(uint32_t i =0; i < frame->num_bufs; i++){
//通过getStreamByHandle找到数据流
stream = pChannel->getStreamByHandle(frame->bufs[i]->stream_id);
if(stream !=NULL){
// 通过isOrignalTypeOf 找到拍照数据等其他数据
if(stream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)){
yuvFrame = frame->bufs[i];
break;
}
}
}
⽅式⼆
preview_stream_cb_routine(mm_camera_super_buf_t *super_frame,
QCameraStream * stream,
void*urdata){
···
mm_camera_buf_def_t *frame = super_frame->bufs[0];
···
}
在我们的回调函数中,通过 mm_camera_buf_def_t *frame = super_frame->bufs[0];就可以拿到mm_camera_buf_def_t 的YUV数据了。
3.获取 数据流⾥⾯的相关信息
1.数据流的地址
mm_camera_buf_def_t *frame;
unsigned char* yuvDta =(unsigned char*)frame->buffer;
2.数据流长度

本文发布于:2023-05-15 08:08:13,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/638363.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   数据流   算法
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图