车载USB DVR(行车记录仪)的源码架构浅析(基于AndroiidM)

news/2024/11/29 12:42:47/

基于AndroiidM的USB DVR的源码架构浅析,主要讲述大概流程,以便于分析问题。

APP层

源码路径:

AndroidM/vendor/mediatek/proprietary/packages/apps/DVR

主要 DVR操作的两个类 FrontView.java MainActivity.java

1、 FrontView 继承了 SurfaceView 用于摄像头视频的预览,把 SurfaceView 通过调用 JNI 的 DVR.java 类对象方法 setFrontSurface(SurfaceHolder sh) 传入到底层,交给底层来实现在 SurfaceView 上的视频渲染。FrontView在主布局中被调用。

2、 MainActivity 中通过调用 JNI 的 DVR.java 类对象,实现了众多功能,包括解析度的改变(720p,1080p),录制时长的改变(10mins,5mins,3mins),视频预览的开始与停止,视频的录制,快照的截取,紧急录像,设置摄像头时间、坐标等等。主要在于实例化了一个 JNI 层的 DVR 类对象来调用底层的对于摄像头基本功能的实现。
应用设置 Handler 用来接收 framework 返回的消息,类型是DVRNativeEvent,需 要 注 意 接 收 到 DVRNativeEvent.DVR_UI_MSG_PREVIEW_ERROR等错误时需要做出容错措施。用到的DVR框架的主要方法为:DVR.SetFrontSurfaceDVR.StartRecordDVR.StopRecordDVR.StartPreviewDVR.StopPreview

FrameWork 层

源码路径:

AndroidM/vendor/mediatek/proprietary/frameworks/base/camera/dvr/…

主要的两个类为DVR.javaandroid_media_DVR.cpp

1、DVR.java中加载了drv_jni库,封装了几个关于摄像头属性的类,坐标、时间、VideoInfo、SinkInfo。根据摄像头底层功能函数定义了各个native方法,然后再用 java 方法把这些native方法再次封装起来,提供给上层对DVR类实例化后的调用。
2、android_media_DVR.cpp中定义各个函数用于对底层 dvrav.cpp 中的对于摄像头基本功能函数进行封装,然后将这些封装好的方法和 DVR.java中native方法映射起来。

Hardware层

源码路径:

AndroidM/vendor/mediatek/proprietary/hardware/mtkcam/dvr

主要的三个类为dvrav.cppPreviewRenderer.cppdvr_preview.cpp
1、 dvrav.cpp

该类被 JNI 层调用的方法最终通过 sendMsg 的方式来分别实现各个功能。在这个文件中,相当于底层与 JNI 的接口,所有的最终实现是通过这个文件中的方法分发下去具体各个类的函数中去实现功能函数。例如:start_preview,JNI 调用到 dvrav.cpp 中的 DVR_StartPreview()方法,通过 Msg 中的枚举量找到具体实现的地方,然后再分发下去调用 dvr_preview.cpp中的DVR_Preview_StartPreview(),在此方法中实例化一个结构体中PreviewRenderer对象mRenderer用于对视频的渲染。

2、 PreviewRenderer.cpp 该类主要功能是用MediaCodec对视频流数据进行硬解码操作,并且在SurfaceView上渲染视频。改变视频流格式的解码格式主要通过对MediaCodec进行配置,目前使用的是video/avc"(H.264)格式。

这篇文章有介绍使用MediaCodec硬解码MJPEG格式帧可能会遇到的问题:MediaCodec硬解码

3、dvr_preview.cpp
该类中函数主要功能是操作PreviewRenderer类对象,配置并初始化MediaCodec,对PreviewRenderer类对象中方法的实现与一些功能拓展。围绕创建实例,释放实例,获取预览实例,创建渲染Looper,释放渲染Looper,设置SurfaceView,开始和停止预览这几个功能。

底层实现中还包括了,在dvr_audiorecord.cpp中实现了关于音频记录的功能,在dvr_avimuxer.cpp中实现了音频和视频的整合,在dvr_recorder.cpp中实现了视频的记录和紧急视频的录制,在dvr_snapshot.cpp 实现视频快照的截取并保存等等,DVR中所有的基本都由底层来实现,上层只是调用。

V4L2驱动层

获取 USB 记录仪视频:采用 linux 下的V4L2(video for linux 2)标准接口,dvr_v4l2.hdvr_v4l2.cpp

open 设备节点(/dev/video21)拿的数是 H.264。

int cameraFd;
cameraFd = open("/dev/video0", O_RDWR, 0);```

打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:

extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;

__request:具体的命令标志符。

在进行V4L2开发中,一般会用到以下的命令标志符:

VIDIOC_REQBUFS:分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
VIDIOC_S_FMT:设置当前驱动的频捕获格式
VIDIOC_G_FMT:读取当前驱动的频捕获格式
VIDIOC_TRY_FMT:验证当前驱动的显示格式
VIDIOC_CROPCAP:查询驱动的修剪能力
VIDIOC_S_CROP:设置视频信号的边框
VIDIOC_G_CROP:读取视频信号的边框
VIDIOC_QBUF:把数据从缓存中读取出来
VIDIOC_DQBUF:把数据放回缓存队列
VIDIOC_STREAMON:开始视频显示函数
VIDIOC_STREAMOFF:结束视频显示函数
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。

检查当前视频设备支持的标准,使用VIDIOC_QUERYSTD来检测:

v4l2_std_id std;
do {ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {case V4L2_STD_NTSC://……case V4L2_STD_PAL://……case V4L2_STD_AHD://……
}

设置视频捕获格式:

struct v4l2_format    fmt;
memset ( &fmt, 0, sizeof(fmt) );
fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width       = 720;
fmt.fmt.pix.height      = 576;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {return -1;
}v4l2_format结构体定义如下:struct v4l2_format
{enum v4l2_buf_type type;    // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTUREunion{struct v4l2_pix_format    pix; struct v4l2_window        win; struct v4l2_vbi_format    vbi; __u8    raw_data[200];         } fmt;
};
struct v4l2_pix_format
{__u32                   width;         // 宽,必须是16的倍数__u32                   height;        // 高,必须是16的倍数__u32                   pixelformat;   // 视频数据存储类型,例如是YUV4:2:2还是RGBenum v4l2_field         field;__u32                   bytesperline;   __u32                   sizeimage;enum v4l2_colorspace    colorspace;__u32                   priv;      
};

获取并记录缓存的物理空间

typedef struct VideoBuffer {void   *start;size_t  length;
} VideoBuffer;VideoBuffer*          buffers = calloc( req.count, sizeof(*buffers) );
struct v4l2_buffer    buf;for (numBufs = 0; numBufs < req.count; numBufs++) {memset( &buf, 0, sizeof(buf) );buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory = V4L2_MEMORY_MMAP;buf.index = numBufs;// 读取缓存if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {return -1;}buffers[numBufs].length = buf.length;// 转换成相对地址buffers[numBufs].start = mmap(NULL, buf.length,PROT_READ | PROT_WRITE,MAP_SHARED,fd, buf.m.offset);if (buffers[numBufs].start == MAP_FAILED) {return -1;}// 放入缓存队列if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {return -1;}
}

处理采集数据

struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=0;//读取缓存
if (ioctl(cameraFd, VIDIOC_DQBUF, &buf) == -1)
{return -1;
}
//…………视频处理算法
//重新放入缓存队列
if (ioctl(cameraFd, VIDIOC_QBUF, &buf) == -1) {return -1;
}

更多V4L2介绍参考下面的博文:

v4l2的学习建议和流程解析

V4L2视频采集的基本流程


http://www.ppmy.cn/news/155586.html

相关文章

破旧手机改造系列:最牛逼的行车记录仪

又是一篇废旧手机改造系列&#xff01;最近刚提新车&#xff0c;所以这次我准备把一台不用的手机改造成一台功能超级强大的行车记录仪。你肯定会说&#xff0c;“简单&#xff01;手机本身就有录像功能&#xff0c;直接打开就是喽“。这样也太low了&#xff0c;而且几乎不具备实…

车载、行车记录仪产品知识汇集

[DESCRIPTION] 经常碰到蓝牙耳机和蓝牙车载(Carkit)问题&#xff0c;蓝牙车载和蓝牙耳机有什么区别&#xff1f; [SOLUTION] 蓝牙耳机&#xff1a;市面上&#xff0c;双声道蓝牙耳机大多数支持HFP(手机音频) 和 A2dp(媒体音频) 和AVRCP(音/视频控制)这三个Profile&#xff1b; …

行车记录仪数据删除如何恢复?

10月&#xff0c;公安部交通管理局权威发布&#xff0c;截至2018年9月&#xff0c;全国机动车保有量达3.22亿辆&#xff1b;机动车驾驶人达4.03亿人。随着机动车和驾驶人数量的增加&#xff0c;交通事故和机动车交通事故责任纠纷案件也在逐年上涨。 部分案件常常因没有目击证人…

画质超清晰的行车记录仪,配置确实很强,盯盯拍Z50上手

行车记录仪是很多车友的必需品&#xff0c;不过和爱车不同&#xff0c;行车记录仪的升级速度很快&#xff0c;早期只要有480P的分辨率就算高清了&#xff0c;如今已经很容易找到有着4K分辨率&#xff0c;还支持语音操作的行车记录仪了&#xff0c;像是我上周新装的这款盯盯拍Z5…

最全行车记录仪方案+主控芯片介绍!

最近在关注行车记录仪&#xff0c;了解了之后 写此文章想让车友们知道什么是行车记录仪的高端标准&#xff0c;什么是好货&#xff0c;因为大部分人都不知道。 看到很多朋友在问&#xff0c;什么是行车记录仪的方案&#xff0c;行车记录仪的主控究竟有什么区别&#xff0c;我该…

汽车行驶记录仪

汽车行驶记录仪(zz) shepherd 发表于 2005-1-7 9:02:00 发信人: sataco (贞 Ashes of Time), 信区: AutoTech标 题: 汽车行驶记录仪(zz)发信站: BBS 水木清华站 (Fri Dec 24 20:18:52 2004), 站内汽车行驶记录仪中国汽车技术研究中心 杜启峰 龚进峰--------------------------…

行车记录仪流量卡你了解吗?

随着人们的生活水平逐渐提高&#xff0c;有车一族也越来越多&#xff0c;而交通安全、碰瓷党也屡见不鲜&#xff0c;如果每辆车都安装行车记录仪&#xff0c;能够记录汽车行驶全过程的视频图像和声音&#xff0c;可为交通事故提供证据&#xff0c;行车记录仪就尤为重要。而记录…

行车记录仪格式化了还能恢复吗?

行车记录仪这时我们每一辆车都必备的存储设备&#xff0c;而行车记录仪自动清理内存&#xff0c;也就是行车记录仪的循环记录模式。当然有不少小伙伴们&#xff0c;喜欢看完在进行删除&#xff0c;或者直接格式化了。才发现有一些在行驶过程中的视频和声音&#xff0c;需要用到…