准备资料

一、硬件资源

可以看到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. 使用ASP.NET Atlas编写显示真实进度的ProgressBar(进度条)控件
  2. Destroy it!
  3. python爬取糗事百科
  4. 【市场调研与分析】Intel发力移动安全领域——By Me at 20140613
  5. 现代软件工程 结对编程 (II) 电梯调度
  6. TikZ绘图示例——尺规作图: 椭圆的近似画法
  7. python set() 和 dict()
  8. 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第2节 TCP协议_2_TCP通信的概述(下)...
  9. 关于PMSM的弱磁与MTPA结合控制超详细分析
  10. C++大小写转换tolower/toupper以及transform函数
  11. 字节跳动布局游戏,打算从腾讯的碗里“抢饭吃”?
  12. wilcoxon rank sum test R代码
  13. 爬取王者荣耀皮肤-点券领取
  14. 华为发布:30岁以下员工仅占28% 你信吗?
  15. Java虚拟机:Java虚拟机结构
  16. 音乐人工智能在国内计算机领域虽然有所进步但发展缓慢
  17. 互联网奠基人:温顿·瑟夫自曝新冠病毒检测呈阳性
  18. Android实战开发——引导页面(ViewPager)篇
  19. eBoostr v4.0 Build 544b中文特别版
  20. php周计划表_PHPOA日程安排系统,建立井然有序的工作计划

热门文章

  1. 数据结构中集合运算(c++类实现class)交集并集差集子集包含判断
  2. 代码-JS之小星星评论效果
  3. 使用canvas绘制路线图
  4. 外汇天眼:外汇占款是什么意思? 与外汇储备之间的差额是由哪些原因造成的?
  5. java不锁屏_如何控制Android不锁屏
  6. C盘满了,清理C盘常用步骤!
  7. 【干货】美团点评架构师私藏的内部Linux运维笔记!
  8. c# 获取端口设备全名
  9. cannot be inherited as a raw type and with generic type arguments
  10. 2017阿里技术论坛 本周起将席卷全球四大顶级名校