君正x2000音视频多路编码实现
准备资料
一、硬件资源
可以看到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音视频多路编码实现相关推荐
- 君正X2000多核理器数据手册
X2000是君正面向商业市场推出的新一代多核异构跨界处理器产品.其CPU内核采用独特的双XBurst®2+ XBurst®0的三核结构.产品兼有应用处理器的出色算力和微控制器的实时控制.低功耗的特点. ...
- 君正x2000开发板usb口读取文件
## 标题君正x2000开发板USB口读取文件 (由于word文档无法上传,只复制了文字,操作过程中的图片就不做展示) 开发要求 1.外设的tf卡存储录像抓图文件需要通过USB口在电脑上进行查看.拷贝 ...
- 君正X2000/X1500主控CPU芯片应用场景推荐
近期推出了多款搭载君正X2000.x1500芯片的应用案例,如二维码门禁.手持式有害气体检测仪.智能门锁.支付条码二维码等方案. 1,基于君正X2000二维码门禁方案 随着门禁行业的逐渐成熟发展,作为 ...
- 君正X2000/X2000E芯片性能和处理器介绍
简介: X2000是一款低功耗,高性能和高集成度的处理器,专注于IoT设备,同时也可以满足许多其他嵌入式设备的需求.X2000也是第一颗基于XBurst2架构的芯片,运算能力相对于之前的芯片有大幅度提 ...
- 三核异构,跨界处理新引擎—君正X2000 的跨界能力
一. 概述 X2000 是北京君正公司推出的新一代 SoC 产品.该产品有诸多亮点,比如XBurst®2 的首次亮相.双 XBurst®2+ XBurst®0 的三核异构布局.符合IEEE1588-2 ...
- 常见音视频的编码方式和封装格式
视频格式标准http://jingyan.baidu.com/article/fc07f98905797d12ffe519d6.html 视频编码标准只有 h.26x和mpegx.大多听书格式都是对他 ...
- 君正X2000开发板开箱测试
一 上电开机 使用附赠的电源线连接5V电源头和开发板DC电源口,即可开机. 注意:开发板输入电压为5V,切勿输入12V电源 二 连接串口终端 使用附赠的USB Type C接口连接开发板的调试接口 ...
- java 使用mediainfo_音视频文件编码分析软件MediaInfo使用简介
MediaInfo用来分析视频和音频文件的编码和属性内容信息,是一款是自由软件 (免费使用.免费获得源代码).他除了提供DLL之外,本身也提供GUI工具用于查看视频信息.新版本的MediaInfo还支 ...
- 君正主控CPU芯片,X2000多场景应用案例
针对智能设备市场,雷龙发展近期推出基于多核异构跨界处理器X2000芯片的多场景应用案例.如智能门锁.激光打印机.扫译笔及显控板方案. [案例一]智能门锁:低功耗.响应速度快.防伪性能高 芯片:君正X2 ...
最新文章
- php 5/0,PHP 5.5.0 released.该怎么解决
- 灰度图像阈值化分割常见方法总结及VC实现
- 使用PaddleFluid和TensorFlow训练RNN语言模型
- target tile component.js load logic
- leetcode 129. 求根到叶子节点数字之和(先序遍历)
- linux 目录定义,linux根目录定义
- 还在为xmind发愁,赶紧试试xmind移动版、绿色版
- Oracle sql给一列赋值,简单的Oracle变量SQL赋值
- java 正则 html 标签_Java正则 HTML 标签 得到 纯文本
- mongoVue的使用
- 【Unity插件001】VRTK3.3.0的使用
- 一个接近90岁的维族老大爷用酒把我撂倒了
- 论文编写工具使用(1)latex软件
- 阿里巴巴JAVA代码规范二【Major】
- 画廊效果的ViewPager实现(附带无限自动轮播)
- 罗克韦尔AB PLC RSLogix5000中定时器指令使用方法介绍
- 深访杨超越杯编程大赛发起人 还原硬核粉丝追星全过程
- 现实迷途 第十三章 三兵一帅
- 超级强大的SVG SMIL animation动画详解
- VSCode Clang代码自动格式化