rk3399平台使用mpp压缩图像数据为mjpeg并保存为图像的示例
时间: 2024-03-24 12:37:02 浏览: 212
jpeg图像压缩实例代码
4星 · 用户满意度95%
以下是在RK3399平台上使用mpp压缩图像数据为mjpeg并保存为图像的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <rockchip/mpp.h>
#define DEV_NAME "/dev/video0"
#define IMAGE_WIDTH 640
#define IMAGE_HEIGHT 480
#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT * 2)
int main(int argc, char **argv)
{
int fd_cam, fd_mpp;
struct v4l2_capability cap;
struct v4l2_format fmt;
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buf;
uint8_t *buf_mmap;
MppCtx ctx;
MppApi *mpi;
MppBuffer mpp_buf_in, mpp_buf_out;
MppPacket packet_out;
uint8_t *data_in, *data_out;
uint32_t size_in, size_out, packet_size_out;
FILE *fp;
int i, ret;
fd_cam = open(DEV_NAME, O_RDWR);
if (fd_cam < 0) {
printf("Open camera device error\n");
return -1;
}
ret = ioctl(fd_cam, VIDIOC_QUERYCAP, &cap);
if (ret < 0) {
printf("Query camera device capability error\n");
goto exit_cam;
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
printf("Camera device does not support video capture\n");
goto exit_cam;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
printf("Camera device does not support streaming I/O\n");
goto exit_cam;
}
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = IMAGE_WIDTH;
fmt.fmt.pix.height = IMAGE_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
ret = ioctl(fd_cam, VIDIOC_S_FMT, &fmt);
if (ret < 0) {
printf("Set camera device format error\n");
goto exit_cam;
}
memset(&reqbuf, 0, sizeof(reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 4;
ret = ioctl(fd_cam, VIDIOC_REQBUFS, &reqbuf);
if (ret < 0) {
printf("Request camera device buffers error\n");
goto exit_cam;
}
buf_mmap = malloc(reqbuf.count * IMAGE_SIZE);
memset(buf_mmap, 0, reqbuf.count * IMAGE_SIZE);
for (i = 0; i < reqbuf.count; i++) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ret = ioctl(fd_cam, VIDIOC_QUERYBUF, &buf);
if (ret < 0) {
printf("Query camera device buffer error\n");
goto exit_cam;
}
buf_mmap[i * IMAGE_SIZE] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd_cam, buf.m.offset);
if (buf_mmap[i * IMAGE_SIZE] == MAP_FAILED) {
printf("Map camera device buffer error\n");
goto exit_cam;
}
ret = ioctl(fd_cam, VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("Queue camera device buffer error\n");
goto exit_cam;
}
}
ret = ioctl(fd_cam, VIDIOC_STREAMON, &fmt.type);
if (ret < 0) {
printf("Start camera device streaming error\n");
goto exit_cam;
}
mpp_env_init();
ret = mpp_create(&ctx, &mpi);
if (ret) {
printf("Create mpp context error\n");
goto exit_mpp;
}
ret = mpp_init(ctx, MPP_CTX_ENC, MPP_VIDEO_CodingMJPEG);
if (ret) {
printf("Init mpp context error\n");
goto exit_mpp;
}
ret = mpp_buffer_get(ctx, &mpp_buf_in, IMAGE_SIZE);
if (ret) {
printf("Get mpp input buffer error\n");
goto exit_mpp;
}
ret = mpp_buffer_get(ctx, &mpp_buf_out, IMAGE_SIZE);
if (ret) {
printf("Get mpp output buffer error\n");
goto exit_mpp;
}
data_in = mpp_buffer_get_ptr(mpp_buf_in);
data_out = mpp_buffer_get_ptr(mpp_buf_out);
fp = fopen("image.jpg", "wb");
for (i = 0; i < 10; i++) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd_cam, VIDIOC_DQBUF, &buf);
if (ret < 0) {
printf("Dequeue camera device buffer error\n");
goto exit_cam;
}
memcpy(data_in, buf_mmap + buf.index * IMAGE_SIZE, IMAGE_SIZE);
ret = mpp_frame_init(&packet_out);
if (ret) {
printf("Init mpp output packet error\n");
goto exit_cam;
}
ret = mpi->encode_put_frame(ctx, mpp_buf_in, NULL);
if (ret) {
printf("Put mpp input frame error\n");
goto exit_cam;
}
ret = mpi->encode_get_packet(ctx, &packet_out);
if (ret) {
printf("Get mpp output packet error\n");
goto exit_cam;
}
size_out = mpp_packet_get_length(packet_out);
packet_size_out = size_out;
memcpy(data_out, mpp_packet_get_pos(packet_out), size_out);
fwrite(data_out, size_out, 1, fp);
ret = mpp_packet_deinit(&packet_out);
if (ret) {
printf("Deinit mpp output packet error\n");
goto exit_cam;
}
ret = ioctl(fd_cam, VIDIOC_QBUF, &buf);
if (ret < 0) {
printf("Queue camera device buffer error\n");
goto exit_cam;
}
}
fclose(fp);
exit_mpp:
mpp_buffer_put(mpp_buf_in);
mpp_buffer_put(mpp_buf_out);
mpp_destroy(ctx);
mpp_env_deinit();
exit_cam:
ioctl(fd_cam, VIDIOC_STREAMOFF, &fmt.type);
for (i = 0; i < reqbuf.count; i++) {
munmap(buf_mmap[i * IMAGE_SIZE], IMAGE_SIZE);
}
free(buf_mmap);
close(fd_cam);
return 0;
}
```
这段代码首先通过V4L2接口配置摄像头的格式和缓冲区,并启动摄像头的数据流。然后使用mpp接口初始化编码器上下文,并获取输入和输出缓冲区。在获取每一帧摄像头数据后,将数据拷贝到mpp输入缓冲区中,并调用mpp接口进行编码。编码完成后将输出的mjpeg数据保存到文件中。最后关闭所有资源并退出程序。
阅读全文