君正T40输出bt656视频流代码
时间: 2023-07-02 16:08:52 浏览: 120
以下是君正T40输出BT656视频流的示例代码:
```c
#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "fcntl.h"
#include "sys/mman.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "linux/fb.h"
#include "linux/videodev2.h"
#define WIDTH 640
#define HEIGHT 480
#define FRAME_SIZE (WIDTH * HEIGHT * 2)
int main(int argc, char **argv) {
int fb_fd = open("/dev/fb0", O_RDWR);
if (fb_fd < 0) {
perror("Failed to open /dev/fb0");
return -1;
}
struct fb_var_screeninfo vinfo;
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
perror("Failed to get variable screen info");
close(fb_fd);
return -1;
}
vinfo.xres = WIDTH;
vinfo.yres = HEIGHT;
vinfo.width = WIDTH;
vinfo.height = HEIGHT;
vinfo.bits_per_pixel = 16;
if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
perror("Failed to set variable screen info");
close(fb_fd);
return -1;
}
uint16_t *fb_map = mmap(NULL, WIDTH * HEIGHT * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
if (fb_map == MAP_FAILED) {
perror("Failed to mmap framebuffer");
close(fb_fd);
return -1;
}
int v4l_fd = open("/dev/video0", O_RDWR);
if (v4l_fd < 0) {
perror("Failed to open /dev/video0");
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
struct v4l2_capability cap;
if (ioctl(v4l_fd, VIDIOC_QUERYCAP, &cap) < 0) {
perror("Failed to query V4L2 capability");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
perror("Device does not support video capture");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
perror("Device does not support streaming I/O");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
struct v4l2_format fmt = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.fmt.pix = {
.width = WIDTH,
.height = HEIGHT,
.field = V4L2_FIELD_ANY,
.pixelformat = V4L2_PIX_FMT_YUYV,
.bytesperline = WIDTH * 2,
.sizeimage = FRAME_SIZE,
},
};
if (ioctl(v4l_fd, VIDIOC_S_FMT, &fmt) < 0) {
perror("Failed to set video format");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
struct v4l2_requestbuffers reqbuf = {
.count = 1,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.memory = V4L2_MEMORY_MMAP,
};
if (ioctl(v4l_fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
perror("Failed to request buffers");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
struct v4l2_buffer buf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.memory = V4L2_MEMORY_MMAP,
.index = 0,
};
if (ioctl(v4l_fd, VIDIOC_QUERYBUF, &buf) < 0) {
perror("Failed to query buffer");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
void *buf_map = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, v4l_fd, buf.m.offset);
if (buf_map == MAP_FAILED) {
perror("Failed to mmap buffer");
close(v4l_fd);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
if (ioctl(v4l_fd, VIDIOC_STREAMON, &buf.type) < 0) {
perror("Failed to start streaming");
close(v4l_fd);
munmap(buf_map, buf.length);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(fb_fd);
return -1;
}
while (1) {
if (ioctl(v4l_fd, VIDIOC_QBUF, &buf) < 0) {
perror("Failed to queue buffer");
break;
}
if (ioctl(v4l_fd, VIDIOC_DQBUF, &buf) < 0) {
perror("Failed to dequeue buffer");
break;
}
uint8_t *yuyv_frame = (uint8_t *)buf_map;
for (int i = 0; i < FRAME_SIZE; i += 4) {
uint8_t y0 = yuyv_frame[i + 0];
uint8_t u = yuyv_frame[i + 1];
uint8_t y1 = yuyv_frame[i + 2];
uint8_t v = yuyv_frame[i + 3];
int r = (298 * (y0 - 16) + 409 * (v - 128) + 128) >> 8;
int g = (298 * (y0 - 16) - 100 * (u - 128) - 208 * (v - 128) + 128) >> 8;
int b = (298 * (y0 - 16) + 516 * (u - 128) + 128) >> 8;
r = r < 0 ? 0 : r > 255 ? 255 : r;
g = g < 0 ? 0 : g > 255 ? 255 : g;
b = b < 0 ? 0 : b > 255 ? 255 : b;
fb_map[(i / 2) + 0] = ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);
r = (298 * (y1 - 16) + 409 * (v - 128) + 128) >> 8;
g = (298 * (y1 - 16) - 100 * (u - 128) - 208 * (v - 128) + 128) >> 8;
b = (298 * (y1 - 16) + 516 * (u - 128) + 128) >> 8;
r = r < 0 ? 0 : r > 255 ? 255 : r;
g = g < 0 ? 0 : g > 255 ? 255 : g;
b = b < 0 ? 0 : b > 255 ? 255 : b;
fb_map[(i / 2) + 1] = ((r >> 3) << 11) | ((g >> 2) << 5) | ((b >> 3) << 0);
}
}
if (ioctl(v4l_fd, VIDIOC_STREAMOFF, &buf.type) < 0) {
perror("Failed to stop streaming");
}
munmap(buf_map, buf.length);
munmap(fb_map, WIDTH * HEIGHT * 2);
close(v4l_fd);
close(fb_fd);
return 0;
}
```
这个示例代码使用了 Linux 内核提供的 framebuffer 和 V4L2 驱动来实现将 BT656 视频流输出到屏幕上。它首先打开 `/dev/fb0` 设备文件,设置分辨率和色深,并通过 `mmap()` 系统调用映射屏幕缓冲区到用户空间。然后打开 `/dev/video0` 设备文件,查询 V4L2 设备能力,设置视频格式并请求视频缓冲区。接下来,它循环从 V4L2 缓冲队列中取出视频帧,将 YUYV 格式转换为 RGB565 格式,并将转换后的像素数据写入屏幕缓冲区。最后,它停止视频流并释放资源。
阅读全文