之前的方案都是用海思的安防芯片,新产品原本也准备使用新的海思安防芯片,驱动同事都准备释放版本了。但是由于美帝制裁华为,你懂的。(在此问候川普几千遍)。
小组全部切换到全志T7的方案,T7的视频采集框架基本都是原生的v4l2框架,不像海思封装了一个中间层,应用开发直接调用海思API就可以。所以记录一下v4l2框架笔记,v4l2基本概念请查看这个博客:https://blog.csdn.net/u013904227/article/details/80718831
本章记录一下ffmpeg项目v4l2.c v4l2_read到底做了什么事情。如下图所示,需要关注v4l2_get_device_list,v4l2_read_header ,v4l2_read_packet这个三个方法。
AVInputFormat ff_v4l2_demuxer = {
.name = "video4linux2,v4l2",
.long_name = NULL_IF_CONFIG_SMALL("Video4Linux2 device grab"),
.priv_data_size = sizeof(struct video_data),
.read_probe = v4l2_read_probe,
.read_header = v4l2_read_header,
.read_packet = v4l2_read_packet,
.read_close = v4l2_read_close,
.get_device_list = v4l2_get_device_list,
.flags = AVFMT_NOFILE,
.priv_class = &v4l2_class,
};
v4l2_get_device_list:
static int v4l2_is_v4l_dev(const char *name)
{
//找到一个驱动释放给到用户空间的设备节点/dev/video
return !strncmp(name, "video", 5) ||
!strncmp(name, "radio", 5) ||
!strncmp(name, "vbi", 3) ||
!strncmp(name, "v4l-subdev", 10);
}
static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_list)
{
struct video_data *s = ctx->priv_data;
DIR *dir;
struct dirent *entry;
AVDeviceInfo *device = NULL;
struct v4l2_capability cap;
int ret = 0;
if (!device_list)
return AVERROR(EINVAL);
dir = opendir("/dev");
if (!dir) {
ret = AVERROR(errno);
av_log(ctx, AV_LOG_ERROR, "Couldn't open the directory: %s\n", av_err2str(ret));
return ret;
}
while ((entry = readdir(dir))) {
char device_name[256];
if (!v4l2_is_v4l_dev(entry->d_name))
continue;
snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name);
if ((s->fd = device_open(ctx, device_name)) < 0)
continue;
if (v4l2_ioctl(s->fd, VIDIOC_QUERYCAP, &cap) < 0) {
ret = AVERROR(errno);
av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", av_err2str(ret));
goto fail;
}
device = av_mallocz(sizeof(AVDeviceInfo));
if (!device) {
ret = AVERROR(ENOMEM);
goto fail;
}
device->device_name = av_strdup(device_name);
device->device_description = av_strdup(cap.card);
if (!device->device_name || !device->device_description) {
ret = AVERROR(ENOMEM);
goto fail;
}
if ((ret = av_dynar