准备资料

一、硬件资源

可以看到x2000是拥有2个ISP模块的。

选择通过ISP模块时,camera 设备节点名为 mscaler。

  • 开启单摄时为 mscaler0 或 mscaler1,对应的是 sensor0 或 sensor1;
  • 开启双摄时为 mscaler0 和 mscaler1,分别对应 sensor0 和 sensor1;
  • 每个mscaler支持3个 channel,故完整的设备名为 mscalerx-chx.

mscaler0-ch0 表示isp0,通道0的设备节点。

从框图看,sensor0和sensor1都有对应的独立ISP,以我的开发板为例,RGB摄像头接的是MIPI-CSI 1,即对应的设备节点为mscaler1,可以利用mscaler1-ch0和mscaler1-ch1实现一个双通道编码应用。

二、编码节点

X2000将vpu分为felix和helix两部分:

  • felix是h264解码,包括:流解析器、运动补偿、反量化、IDCT和De-block engines的功能。
  • helix是h264编码、JPEG压缩和解压缩。

三、设计需求

  • 设计两个通道,分别为主码流和子码流。
  • 主码流参数:1080p@30fps,H264编码,以文件形式保存;
  • 子码流参数:720p@30fps,H264编码,以文件形式保存;

四、设计思路

再回到数据流框图

也就是说,sensor的mipi数据通过,VIC单元控制送如ISP模块,再通过Mscaler节点输出,因此只需要从对应的Mscaler节点拿到sensor数据,然后送给/dev/video1编码器节点进行编码即可。

五、代码实现

参考君正给的SDK内的demo加以修改,路径:ingenic/x2000/libisp/src/demo/

ISP格式配置——

/* isp格式配置 */
static struct frame_image_format output_fmt_main = {.width              = 1920,.height             = 1080,.pixel_format       = CAMERA_PIX_FMT_NV12,.scaler.enable      = 0,.scaler.width       = 0,.scaler.height      = 0,.frame_nums         = 2,
};static struct frame_image_format output_fmt_sub = {.width              = 1280,.height             = 720,.pixel_format       = CAMERA_PIX_FMT_NV12,.scaler.enable      = 0,.scaler.width       = 0,.scaler.height      = 0,.frame_nums         = 2,
};

ISP初始化——

参考这个流程图

static int init_isp_camera(char * isp_cam_path, struct frame_image_format * pformat, struct camera_info * info)
{int ret;int fd;fd = isp_open(isp_cam_path);if (fd < 0) {fprintf(stderr, "isp open failed\n");return -1;}ret = isp_get_sensor_info(fd, info);if (ret < 0) {fprintf(stderr, "isp get sensor info failed\n");goto close_isp;}if (pformat->width != 0 || pformat->height != 0)pformat->scaler.enable = 1;pformat->scaler.width = pformat->width ? pformat->width : info->width;pformat->scaler.height = pformat->height ? pformat->height : info->height;pformat->width = pformat->scaler.width;pformat->height = pformat->scaler.height;ret = isp_set_format(fd, pformat);if (ret < 0) {fprintf(stderr, "isp set format failed\n");goto close_isp;}ret = isp_requset_buffer(fd, pformat);if (ret < 0) {fprintf(stderr, "isp set request buffer failed\n");goto close_isp;}isp_get_info(fd, info);ret = isp_mmap(fd, info);if (ret < 0)goto free_isp_buffer;ret = isp_power_on(fd);if (ret < 0)goto free_isp_buffer;ret = isp_stream_on(fd);if (ret < 0)goto power_off_isp;return fd;power_off_isp:isp_power_off(fd);
free_isp_buffer:isp_free_buffer(fd);
close_isp:isp_close(fd, info);return -1;
}

主码流实现——

void * main_stream_thread(void * arg)
{struct v4l2_h264_encoder_config config;struct frame_info frame_info;int res = 0;int frame_cnt = 0;int output_size = 0;menc_cfg_main.isp_path = malloc(20);menc_cfg_main.output_file_path = malloc(20);menc_cfg_main.encoder_path = malloc(20);memmove(menc_cfg_main.output_file_path, "output00", 9);memmove(menc_cfg_main.isp_path, "/dev/mscaler1-ch0", 18);memmove( menc_cfg_main.encoder_path, "/dev/video1", 12);menc_cfg_main.camera_fd = -1;menc_cfg_main.output_file_fd = -1;memset(&config, 0, sizeof(struct v4l2_h264_encoder_config));menc_cfg_main.camera_fd = init_isp_camera(menc_cfg_main.isp_path, &output_fmt_main, &menc_cfg_main.camera_info);if (menc_cfg_main.camera_fd < 0) {fprintf(stderr, "Init isp camera failed\n");goto exit;}config.video_path = menc_cfg_main.encoder_path;config.width = output_fmt_main.width;config.height = output_fmt_main.height;config.line_length = menc_cfg_main.camera_info.line_length;config.input_fmt = menc_cfg_main.camera_info.data_fmt;config.gop_size = 10;config.bitrate = 400000;menc_cfg_main.encoder = v4l2_h264_encoder_open(&config); if (!menc_cfg_main.encoder) {fprintf(stderr, "Uanble to open v4l2 h264 encoder\n");res = -1;goto close_isp_cam;}menc_cfg_main.output_file_fd = open(menc_cfg_main.output_file_path, O_RDWR | O_CREAT | O_TRUNC);if ( menc_cfg_main.output_file_fd < 0) {fprintf(stderr, "open file %s error.\n", menc_cfg_main.output_file_path);goto close_encoder;}while (1){res = isp_dqbuf_wait(menc_cfg_main.camera_fd, &frame_info);if (res){fprintf(stderr, "isp_dqbuf_waitopen file %s error.\n");goto close_file;}if (frame_cnt == 5){v4l2_h264_encoder_set_keyframe(menc_cfg_main.encoder);}void *mem = v4l2_h264_encoder_work_by_phy_mem(menc_cfg_main.encoder, frame_info.vaddr, frame_info.paddr, &output_size);if (!mem) {fprintf(stderr, "V4l2 h264 encode work failed, ret : %d, %p\n", res, mem);res = -1;goto close_file;}isp_put_frame(menc_cfg_main.camera_fd, frame_info.vaddr);write(menc_cfg_main.output_file_fd, mem, output_size);if (frame_cnt++ >= 120){break;}}fprintf(stderr, "frame_cnt:%d\r\n",frame_cnt);close_file:close(menc_cfg_main.output_file_fd);
close_encoder:v4l2_h264_encoder_close(menc_cfg_main.encoder);
close_isp_cam:deinit_isp_camera(menc_cfg_main.camera_fd, &menc_cfg_main.camera_info);
exit:menc_cfg_main.camera_fd = -1;fprintf(stderr, "main_stream_thread exit\r\n");
}

子码流实现——

void * sub_stream_thread(void * arg)
{struct v4l2_h264_encoder_config config;struct frame_info frame_info;int res = 0;int frame_cnt = 0;int output_size = 0;menc_cfg_sub.isp_path = malloc(20);menc_cfg_sub.output_file_path = malloc(20);menc_cfg_sub.encoder_path = malloc(20);memmove(menc_cfg_sub.output_file_path, "output01", 9);memmove(menc_cfg_sub.isp_path, "/dev/mscaler1-ch1", 18);memmove( menc_cfg_sub.encoder_path, "/dev/video1", 12);menc_cfg_sub.camera_fd = -1;menc_cfg_sub.output_file_fd = -1;memset(&config, 0, sizeof(struct v4l2_h264_encoder_config));menc_cfg_sub.camera_fd = init_isp_camera(menc_cfg_sub.isp_path, &output_fmt_sub, &menc_cfg_sub.camera_info);if (menc_cfg_sub.camera_fd < 0) {fprintf(stderr, "Init isp camera failed\n");goto exit;}config.video_path = menc_cfg_sub.encoder_path;config.width = output_fmt_sub.width;config.height = output_fmt_sub.height;config.line_length = menc_cfg_sub.camera_info.line_length;config.input_fmt = menc_cfg_sub.camera_info.data_fmt;config.gop_size = 10;config.bitrate = 400000;menc_cfg_sub.encoder = v4l2_h264_encoder_open(&config); if (!menc_cfg_sub.encoder) {fprintf(stderr, "Uanble to open v4l2 h264 encoder\n");res = -1;goto close_isp_cam;}menc_cfg_sub.output_file_fd = open(menc_cfg_sub.output_file_path, O_RDWR | O_CREAT | O_TRUNC);if ( menc_cfg_sub.output_file_fd < 0) {fprintf(stderr, "open file %s error.\n", menc_cfg_sub.output_file_path);goto close_encoder;}while (1){res = isp_dqbuf_wait(menc_cfg_sub.camera_fd, &frame_info);if (res){fprintf(stderr, "isp_dqbuf_waitopen file %s error.\n");goto close_file;}if (frame_cnt == 5){v4l2_h264_encoder_set_keyframe(menc_cfg_sub.encoder);}void *mem = v4l2_h264_encoder_work_by_phy_mem(menc_cfg_sub.encoder, frame_info.vaddr, frame_info.paddr, &output_size);if (!mem) {fprintf(stderr, "V4l2 h264 encode work failed, ret : %d, %p\n", res, mem);res = -1;goto close_file;}isp_put_frame(menc_cfg_sub.camera_fd, frame_info.vaddr);write(menc_cfg_sub.output_file_fd, mem, output_size);if (frame_cnt++ >= 120){break;}}fprintf(stderr, "frame_cnt:%d\r\n",frame_cnt);close_file:close(menc_cfg_sub.output_file_fd);
close_encoder:v4l2_h264_encoder_close(menc_cfg_sub.encoder);
close_isp_cam:deinit_isp_camera(menc_cfg_sub.camera_fd, &menc_cfg_sub.camera_info);
exit:menc_cfg_sub.camera_fd = -1;fprintf(stderr, "sub_stream_thread exit\r\n");
}

main函数实现——

int main(void)
{int res = 0;signal(SIGINT, signal_handler);res = pthread_create(&main_stream_thread_id, NULL, main_stream_thread, NULL);if(res != 0){printf("main stream pthread create failed.\r\n");}res = pthread_create(&sub_stream_thread_id, NULL, sub_stream_thread, NULL);if(res != 0){printf("sub stream pthread create failed.\r\n");}while (1){sleep(1);}fprintf(stderr, "exit.\n");return 0;
}

板端执行——

输出名为output00和output01的两个h264文件

君正x2000音视频多路编码实现相关推荐

  1. 君正X2000多核理器数据手册

    X2000是君正面向商业市场推出的新一代多核异构跨界处理器产品.其CPU内核采用独特的双XBurst®2+ XBurst®0的三核结构.产品兼有应用处理器的出色算力和微控制器的实时控制.低功耗的特点. ...

  2. 君正x2000开发板usb口读取文件

    ## 标题君正x2000开发板USB口读取文件 (由于word文档无法上传,只复制了文字,操作过程中的图片就不做展示) 开发要求 1.外设的tf卡存储录像抓图文件需要通过USB口在电脑上进行查看.拷贝 ...

  3. 君正X2000/X1500主控CPU芯片应用场景推荐

    近期推出了多款搭载君正X2000.x1500芯片的应用案例,如二维码门禁.手持式有害气体检测仪.智能门锁.支付条码二维码等方案. 1,基于君正X2000二维码门禁方案 随着门禁行业的逐渐成熟发展,作为 ...

  4. 君正X2000/X2000E芯片性能和处理器介绍

    简介: X2000是一款低功耗,高性能和高集成度的处理器,专注于IoT设备,同时也可以满足许多其他嵌入式设备的需求.X2000也是第一颗基于XBurst2架构的芯片,运算能力相对于之前的芯片有大幅度提 ...

  5. 三核异构,跨界处理新引擎—君正X2000 的跨界能力

    一. 概述 X2000 是北京君正公司推出的新一代 SoC 产品.该产品有诸多亮点,比如XBurst®2 的首次亮相.双 XBurst®2+ XBurst®0 的三核异构布局.符合IEEE1588-2 ...

  6. 常见音视频的编码方式和封装格式

    视频格式标准http://jingyan.baidu.com/article/fc07f98905797d12ffe519d6.html 视频编码标准只有 h.26x和mpegx.大多听书格式都是对他 ...

  7. 君正X2000开发板开箱测试

    一  上电开机 使用附赠的电源线连接5V电源头和开发板DC电源口,即可开机. 注意:开发板输入电压为5V,切勿输入12V电源 二  连接串口终端 使用附赠的USB Type C接口连接开发板的调试接口 ...

  8. java 使用mediainfo_音视频文件编码分析软件MediaInfo使用简介

    MediaInfo用来分析视频和音频文件的编码和属性内容信息,是一款是自由软件 (免费使用.免费获得源代码).他除了提供DLL之外,本身也提供GUI工具用于查看视频信息.新版本的MediaInfo还支 ...

  9. 君正主控CPU芯片,X2000多场景应用案例

    针对智能设备市场,雷龙发展近期推出基于多核异构跨界处理器X2000芯片的多场景应用案例.如智能门锁.激光打印机.扫译笔及显控板方案. [案例一]智能门锁:低功耗.响应速度快.防伪性能高 芯片:君正X2 ...

最新文章

  1. php 5/0,PHP 5.5.0 released.该怎么解决
  2. 灰度图像阈值化分割常见方法总结及VC实现
  3. 使用PaddleFluid和TensorFlow训练RNN语言模型
  4. target tile component.js load logic
  5. leetcode 129. 求根到叶子节点数字之和(先序遍历)
  6. linux 目录定义,linux根目录定义
  7. 还在为xmind发愁,赶紧试试xmind移动版、绿色版
  8. Oracle sql给一列赋值,简单的Oracle变量SQL赋值
  9. java 正则 html 标签_Java正则 HTML 标签 得到 纯文本
  10. mongoVue的使用
  11. 【Unity插件001】VRTK3.3.0的使用
  12. 一个接近90岁的维族老大爷用酒把我撂倒了
  13. 论文编写工具使用(1)latex软件
  14. 阿里巴巴JAVA代码规范二【Major】
  15. 画廊效果的ViewPager实现(附带无限自动轮播)
  16. 罗克韦尔AB PLC RSLogix5000中定时器指令使用方法介绍
  17. 深访杨超越杯编程大赛发起人 还原硬核粉丝追星全过程
  18. 现实迷途 第十三章 三兵一帅
  19. 超级强大的SVG SMIL animation动画详解
  20. VSCode Clang代码自动格式化

热门文章

  1. Nuxt3第二篇【路由】
  2. 解析法多元线性回归的实现
  3. web前端面试题(附答案)
  4. 给家庭组小朋友的分享和建议
  5. string LPCTSTR
  6. Qt QString转lpctstr
  7. 快手二季度收入同比增长13.4%;四季酒店集团发布2024年全新私人飞机行程 | 美通企业日报...
  8. Cadence和Synopsys工具介绍
  9. 阿里内网精选:Java微服务实战笔记,共140个案例
  10. 为什么全世界都要鼓励青少儿学习编程?