1

不需要编写代码

在buildroot中配置,编译;或者下载源码进行编译,移植到开发板

MJPG-streamer方案的实现

2

编译安装MJPG-streamer使用Buildroot编译

执行命令:mjpg_streamer -i “/usr/lib/mjpg-streamer/input_uvc.so -d /dev/video1 -f 30 -q 90 -n” -o “/usr/lib/mjpg-streamer/output_http.so -w /usr/share/mjpg-streamer/www”

确保PC或手机,跟开发板处于同一个局域网 假设开发板IP为:192.168.1.6在chrome浏览器中打开:192.168.1.6:8080/stream.html就可以看见视频了

流媒体方案的实现之ffmpeg,Nginx

3

下载源码,手工编译使用Buildroot

或配置选择ffmpeg,直接编译生成映象文件

执行命令:ffmpeg -f v4l2 -framerate 10 -i /dev/video1 -q 10 my.mp4

它会把摄像头的数据录制为my.mp4

下载源码,手工编译使用Buildroot

或配置选择Nginx,直接编译生成映象文件

推流

ffmpeg -f v4l2 -framerate 10 -i /dev/video1 -q 10 -f flv rtmp://127.0.0.1/live/wei

拉流

在PC上安装VLC播放器:

使用RTMP协议拉流:VLC播放器中点击“媒体”->“打开网络串流”,输入:rtmp://192.168.1.6/live/wei ,就可以播放了

使用HTTPFLV协议拉流:VLC播放器中点击“媒体”->“打开网络串流”,输入:192.168.1.6/test?app=live&stream=wei ,就可以播放了

2

编写代码

V4L2摄像头应用编程

lsusb查找摄像头ID

打开内核源码drivers/media/usb/uvc/uvc_driver.c
找到结构体uvc_ids(滑到文件最后再往上一点)
仿照其他摄像头的代码,添加摄像头的PID和VID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
static int v4l2_dev_init(const char *device)//初始化
static void v4l2_enum_formats(void)//支持格式
static void v4l2_print_formats(void)//打印支持格式
static int v4l2_set_format(void)//设置格式(摄像头必须支持此格式)
static int v4l2_init_buffer(void)
static int v4l2_stream_on(void)


int main(int argc, char *argv[])
{
if (2 != argc) {
fprintf(stderr, "Usage: %s <video_dev>\n", argv[0]);
exit(EXIT_FAILURE);
}

/* 初始化摄像头 */
if (v4l2_dev_init(argv[1]))
exit(EXIT_FAILURE);

/* 枚举所有格式并打印摄像头支持的分辨率及帧率 */
v4l2_enum_formats();
v4l2_print_formats();

/* 设置格式 */
if (v4l2_set_format())
exit(EXIT_FAILURE);

/* 初始化帧缓冲:申请、内存映射、入队 */
if (v4l2_init_buffer())
exit(EXIT_FAILURE);

/* 开启视频采集 */
if (v4l2_stream_on())
exit(EXIT_FAILURE);

/* 读取数据:出队 */
v4l2_read_data(); //在函数内循环采集数据、实现各种要求

exit(EXIT_SUCCESS);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
static void v4l2_read_data(void)
{
int sockfd, connfd; // Socket文件描述符
struct sockaddr_in server_addr, client_addr; // 服务器和客户端地址结构体
socklen_t client_len; // 客户端地址结构体长度
char buffer[BUFFER_SIZE]; // 缓冲区
int bytes_read, bytes_written; // 读取和写入的字节数

char *message = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html> <body><h1>Hello, world!</h1></body></html>"; // 响应消息


struct v4l2_buffer buf = {0};
unsigned short *base;
unsigned short *start;

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
for ( ; ; ) {

for(buf.index = 0; buf.index < FRAMEBUFFER_COUNT; buf.index++) {

ioctl(v4l2_fd, VIDIOC_DQBUF, &buf); //出队

char *image_buffer = (char *)buf_infos[buf.index].start;
// 创建Socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("Failed to create socket");
exit(EXIT_FAILURE);
}
printf("Socket created\n");

// 设置服务器地址结构体
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;

// 绑定Socket到服务器地址
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
printf("Bind completed\n");

// 监听Socket,等待客户端连接请求
if (listen(sockfd, 5) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
printf("Listening on port %d\n", SERVER_PORT);

while (1) {
// 等待客户端连接请求并接受连接请求
client_len = sizeof(client_addr);
connfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
if (connfd < 0) {
perror("Accept failed");
continue;
}
printf("Client connected: %s\n", inet_ntoa(client_addr.sin_addr));

// 发送响应消息给客户端
bytes_written = write(connfd, message, strlen(message));
if (bytes_written < 0) {
perror("Write failed");
} else {
printf("Response sent to client\n");
}
bytes_written = write(connfd, image_buffer, strlen(image_buffer));
// 关闭连接并继续等待客户端连接请求
close(connfd);
printf("Waiting for next client...\n");

free (image_buffer) ; // 释放内存
close(sockfd); // 关闭新的套接字并等待下一个连接请求

// 数据处理完之后、再入队、往复
ioctl(v4l2_fd, VIDIOC_QBUF, &buf);
}
}
}
}

交叉编译,生成32位可执行程序

4

执行./video /dev/video

5

摄像头打开,绑定socket服务器,将数据发送给客户端。

以下是一个使用JavaScript的WebSocket API来创建一个简单的Socket客户端的例子。这段代码将连接到指定的WebSocket服务器,并打印从服务器接收到的所有消息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 创建WebSocket连接
var socket = new WebSocket('ws://your-server-address:port');

// 监听连接建立事件
socket.onopen = function(event) {
console.log('WebSocket connected');
};

// 监听接收到消息事件
socket.onmessage = function(event) {
console.log('Received message: ' + event.data);
// 在这里可以处理接收到的消息
};

// 监听连接关闭事件
socket.onclose = function(event) {
console.log('WebSocket disconnected');
};

// 监听错误事件
socket.onerror = function(error) {
console.error('WebSocket error: ' + error);
};

这段代码需要运行在支持WebSocket的浏览器环境中。同时,你需要将'ws://your-server-address:port'替换为实际的WebSocket服务器地址和端口。当WebSocket连接建立后,它将开始接收来自服务器的数据,并在控制台中打印出来。你可以根据需要添加更多的逻辑来处理接收到的数据。