LINUX qt 用mpp库编写视频采集及保存视频文件
时间: 2024-04-05 16:30:05 浏览: 24
使用MPP库编写视频采集并保存视频文件,可以按照以下步骤进行:
1. 初始化MPP库,包括创建MPP上下文、配置MPP参数等。
2. 创建视频编码器,如H.264或H.265编码器。
3. 配置编码器参数,包括视频分辨率、帧率等。
4. 创建视频采集模块,如V4L2或HDMI采集模块。
5. 启动采集模块,获取视频帧数据。
6. 对采集到的视频帧进行编码,得到编码后的视频数据。
7. 将编码后的视频数据保存到文件中,可以使用FFmpeg等第三方库进行封装。
在Qt中使用MPP库进行视频采集和保存,可以参考以下步骤:
1. 在Qt项目中添加MPP库的头文件和链接库。
2. 创建Qt界面,包括视频预览窗口和控制按钮等。
3. 初始化MPP库,并创建视频编码器和采集模块。
4. 启动视频采集和编码,并将编码后的视频数据保存到文件中。
5. 在Qt界面中显示视频预览,并添加控制按钮实现视频录制、暂停、停止等功能。
需要注意的是,视频采集和编码是比较底层的操作,需要对MPP库和视频编码器有一定的了解。同时,视频采集和编码对硬件性能要求较高,需要在具备足够的硬件资源的情况下进行。
相关问题
LINUX qt 用mpp库编写视频采集及保存视频文件 C++代码
下面是用MPP库编写视频采集和保存视频文件的C++代码示例:
```cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "mpp.h"
#define MPP_ALIGN(x, a) (((x)+(a)-1) & ~((a)-1))
typedef struct {
int width;
int height;
int fps;
int bitrate;
int gop;
int bps;
int qp;
} mpp_cfg_t;
typedef struct {
int fd;
void* addr;
int size;
} mpp_mem_t;
void* mpp_malloc(int size)
{
return malloc(size);
}
void mpp_free(void* ptr)
{
free(ptr);
}
int mpp_open(const char* name, int flag)
{
return open(name, flag);
}
int mpp_close(int fd)
{
return close(fd);
}
void* mpp_mmap(void* addr, int size, int prot, int flags, int fd, int offset)
{
return mmap(addr, size, prot, flags, fd, offset);
}
int mpp_munmap(void* addr, int size)
{
return munmap(addr, size);
}
int mpp_ioctl(int fd, int cmd, void* arg)
{
return ioctl(fd, cmd, arg);
}
int mpp_config(int fd, mpp_cfg_t* cfg)
{
MppApi* mpp = NULL;
MppCtx ctx = NULL;
MppParam param = NULL;
MppCodingType type = MPP_VIDEO_CodingAVC;
MppFrameFormat fmt = MPP_FMT_YUV420SP;
int ret = MPP_OK;
mpp = new MppApi(type);
if (!mpp) {
printf("MPP create failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_OUTPUT_FORMAT, &fmt);
if (ret) {
printf("MPP set output format failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_IDR_FRAME, NULL);
if (ret) {
printf("MPP set IDR frame failed!\n");
return -1;
}
param = mpp->param_new();
if (!param) {
printf("MPP new param failed!\n");
return -1;
}
mpp->param_set_uint32(param, "coding_type", type);
mpp->param_set_uint32(param, "width", cfg->width);
mpp->param_set_uint32(param, "height", cfg->height);
mpp->param_set_uint32(param, "fps_in_num", cfg->fps);
mpp->param_set_uint32(param, "fps_in_denorm", 1);
mpp->param_set_uint32(param, "bps_target", cfg->bitrate);
mpp->param_set_uint32(param, "gop_size", cfg->gop);
mpp->param_set_uint32(param, "bitrate", cfg->bps);
mpp->param_set_uint32(param, "qp_init", cfg->qp);
mpp->param_set_uint32(param, "qp_max", cfg->qp);
mpp->param_set_uint32(param, "qp_min", cfg->qp);
ret = mpp->control(ctx, MPP_SET_OUTPUT_PARAMETER, param);
if (ret) {
printf("MPP set output parameter failed!\n");
return -1;
}
mpp->param_delete(¶m);
delete mpp;
return 0;
}
int mpp_mem_alloc(mpp_mem_t* mem, int size)
{
mem->fd = open("/dev/mem", O_RDWR|O_SYNC);
if (mem->fd < 0) {
printf("Open /dev/mem failed!\n");
return -1;
}
mem->size = MPP_ALIGN(size, 4096);
mem->addr = mmap(NULL, mem->size, PROT_READ | PROT_WRITE, MAP_SHARED, mem->fd, 0);
if (mem->addr == MAP_FAILED) {
printf("Mmap failed!\n");
return -1;
}
return 0;
}
int mpp_mem_free(mpp_mem_t* mem)
{
if (mem->addr) {
munmap(mem->addr, mem->size);
mem->addr = NULL;
}
if (mem->fd >= 0) {
close(mem->fd);
mem->fd = -1;
}
return 0;
}
int mpp_frame_encode(int fd, void* in, int in_size, void* out, int out_size)
{
MppApi* mpp = NULL;
MppCtx ctx = NULL;
MppFrame frame = NULL;
MppPacket packet = NULL;
MppBuffer buffer = NULL;
int ret = MPP_OK;
mpp = new MppApi(MPP_VIDEO_CodingAVC);
if (!mpp) {
printf("MPP create failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_INPUT_TIMEOUT, 5);
if (ret) {
printf("MPP set input timeout failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_OUTPUT_TIMEOUT, 5);
if (ret) {
printf("MPP set output timeout failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_INPUT_SIZE, &in_size);
if (ret) {
printf("MPP set input size failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_OUTPUT_SIZE, &out_size);
if (ret) {
printf("MPP set output size failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_INPUT_PTR, in);
if (ret) {
printf("MPP set input ptr failed!\n");
return -1;
}
ret = mpp->control(ctx, MPP_SET_OUTPUT_PTR, out);
if (ret) {
printf("MPP set output ptr failed!\n");
return -1;
}
frame = mpp->frame_new();
if (!frame) {
printf("MPP new frame failed!\n");
return -1;
}
mpp->frame_set_width(frame, 1920);
mpp->frame_set_height(frame, 1080);
mpp->frame_set_hor_stride(frame, 1920);
mpp->frame_set_ver_stride(frame, 1088);
mpp->frame_set_fmt(frame, MPP_FMT_YUV420SP);
mpp->frame_set_pts(frame, 0);
ret = mpp->control(ctx, MPP_ENC_GET_EXTRA_INFO, &packet);
if (ret) {
printf("MPP get extra info failed!\n");
return -1;
}
ret = mpp->encode_put_frame(ctx, frame);
if (ret) {
printf("MPP put frame failed!\n");
return -1;
}
ret = mpp->encode_get_packet(ctx, &packet);
if (ret) {
printf("MPP get packet failed!\n");
return -1;
}
ret = mpp->packet_write(packet, out, out_size);
if (ret) {
printf("MPP packet write failed!\n");
return -1;
}
mpp->packet_deinit(&packet);
mpp->frame_deinit(&frame);
delete mpp;
return 0;
}
int main(int argc, char* argv[])
{
mpp_cfg_t cfg;
mpp_mem_t input, output;
int fd = -1;
char* addr = NULL;
int size = 0;
int ret = 0;
memset(&cfg, 0, sizeof(cfg));
cfg.width = 1920;
cfg.height = 1080;
cfg.fps = 30;
cfg.bitrate = 4000000;
cfg.gop = 60;
cfg.bps = 2000000;
cfg.qp = 30;
ret = mpp_mem_alloc(&input, cfg.width * cfg.height * 3 / 2);
if (ret) {
printf("Input memory alloc failed!\n");
return -1;
}
ret = mpp_mem_alloc(&output, cfg.width * cfg.height * 3 / 2);
if (ret) {
printf("Output memory alloc failed!\n");
return -1;
}
ret = mpp_config(fd, &cfg);
if (ret) {
printf("MPP config failed!\n");
return -1;
}
fd = mpp_open("/dev/video0", O_RDWR);
if (fd < 0) {
printf("Open /dev/video0 failed!\n");
return -1;
}
while (1) {
addr = (char*)mpp_mmap(NULL, input.size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
printf("Mmap input buffer failed!\n");
break;
}
ret = mpp_frame_encode(fd, addr, input.size, output.addr, output.size);
if (ret) {
printf("MPP encode failed!\n");
break;
}
mpp_munmap(addr, input.size);
}
mpp_mem_free(&input);
mpp_mem_free(&output);
mpp_close(fd);
return 0;
}
```
需要注意的是,上述代码是仅供参考的示例代码,具体实现还需要根据具体的需求进行调整和完善。
rk3588 + ubuntu20.02 用mpp库编写视频采集及保存视频文件 C++代码
以下是一个简单的C++代码示例,用于使用MPP库在RK3588 + Ubuntu20.02上进行视频采集和保存视频文件:
```c++
#include <iostream>
#include <unistd.h>
#include "rockchip/rk_mpi.h"
#include "rockchip/mpp_buffer.h"
#include "rockchip/mpp_frame.h"
#include "rockchip/mpp_packet.h"
#include "rockchip/mpp_video.h"
using namespace std;
#define MAX_BUFFER_NUM 4
int main(int argc, char** argv) {
RK_U32 width = 1920;
RK_U32 height = 1080;
RK_U32 frame_rate = 30;
RK_U32 bit_rate = 2000000;
RK_U32 gop = 30;
RK_U32 fps_in = 30;
RK_U32 fps_out = 30;
RK_U32 rotate = 0;
RK_U32 mirror = 0;
/* 初始化 MPP 库 */
RK_MPI_SYS_Init();
/* 创建视频编码器 */
MPP_ENC_CONFIG enc_config;
memset(&enc_config, 0, sizeof(enc_config));
enc_config.format = MPP_FMT_YUV420SP;
enc_config.width = width;
enc_config.height = height;
enc_config.rc_mode = MPP_ENC_RC_MODE_CBR;
enc_config.bps = bit_rate;
enc_config.fps_in = fps_in;
enc_config.fps_out = fps_out;
enc_config.gop = gop;
enc_config.rotate = rotate;
enc_config.mirror = mirror;
MPP_RET ret;
MppCtx ctx;
ret = mpp_create(&ctx, &enc_config);
if (ret) {
cout << "Failed to create mpp context" << endl;
return 1;
}
/* 初始化编码器 */
ret = mpp_init(ctx);
if (ret) {
cout << "Failed to init mpp context" << endl;
return 1;
}
/* 创建输入帧 */
MppFrame frame_in;
ret = mpp_frame_init(&frame_in);
if (ret) {
cout << "Failed to init input frame" << endl;
return 1;
}
mpp_frame_set_fmt(frame_in, enc_config.format);
mpp_frame_set_width(frame_in, enc_config.width);
mpp_frame_set_height(frame_in, enc_config.height);
/* 创建编码输出帧 */
MppFrame frame_out;
ret = mpp_frame_init(&frame_out);
if (ret) {
cout << "Failed to init output frame" << endl;
return 1;
}
/* 创建编码输出数据包 */
MppPacket packet;
ret = mpp_packet_init(&packet, NULL, 0);
if (ret) {
cout << "Failed to init packet" << endl;
return 1;
}
/* 创建输入缓冲区 */
MppBufferGroup buf_grp_in;
ret = mpp_buffer_group_get_internal(&buf_grp_in, MPP_BUFFER_TYPE_ION);
if (ret) {
cout << "Failed to get input buffer group" << endl;
return 1;
}
ret = mpp_buffer_group_limit_config(buf_grp_in, MAX_BUFFER_NUM, 0);
if (ret) {
cout << "Failed to config input buffer group" << endl;
return 1;
}
/* 创建输出缓冲区 */
MppBufferGroup buf_grp_out;
ret = mpp_buffer_group_get_internal(&buf_grp_out, MPP_BUFFER_TYPE_ION);
if (ret) {
cout << "Failed to get output buffer group" << endl;
return 1;
}
ret = mpp_buffer_group_limit_config(buf_grp_out, MAX_BUFFER_NUM, 0);
if (ret) {
cout << "Failed to config output buffer group" << endl;
return 1;
}
/* 打开输入设备 */
MppCtx input_ctx;
MppParam param = NULL;
ret = mpp_open(&input_ctx, MPP_CTX_DEC, param);
if (ret) {
cout << "Failed to open input device" << endl;
return 1;
}
/* 打开输出设备 */
MppCtx output_ctx;
ret = mpp_open(&output_ctx, MPP_CTX_ENC, param);
if (ret) {
cout << "Failed to open output device" << endl;
return 1;
}
/* 开始采集 */
MppBuffer buffer = NULL;
MppPacket packet_out = NULL;
MppFrame frame = NULL;
while (1) {
/* 从输入设备读取数据 */
ret = mpp_device_poll(input_ctx, MPP_POLL_BLOCK);
if (ret) {
cout << "Failed to poll input device" << endl;
break;
}
ret = mpp_device_dequeue(input_ctx, &frame);
if (ret) {
cout << "Failed to dequeue input frame" << endl;
break;
}
/* 将输入帧存储到输入缓冲区 */
buffer = mpp_buffer_group_get(buf_grp_in);
if (buffer == NULL) {
cout << "Failed to get input buffer" << endl;
break;
}
mpp_frame_set_buffer(frame_in, buffer);
ret = mpp_buffer_write(buffer, 0, mpp_frame_get_ptr(frame), mpp_frame_get_size(frame));
if (ret) {
cout << "Failed to write data to input buffer" << endl;
break;
}
/* 进行视频编码 */
ret = mpp_encode_put_frame(ctx, frame_in);
if (ret) {
cout << "Failed to put input frame to encoder" << endl;
break;
}
ret = mpp_encode_get_packet(ctx, &packet_out);
if (ret) {
cout << "Failed to get output packet" << endl;
break;
}
/* 将编码后的数据存储到输出缓冲区 */
buffer = mpp_buffer_group_get(buf_grp_out);
if (buffer == NULL) {
cout << "Failed to get output buffer" << endl;
break;
}
ret = mpp_packet_write(packet_out, 0, mpp_buffer_get_ptr(buffer), mpp_buffer_get_size(buffer));
if (ret) {
cout << "Failed to write data to output buffer" << endl;
break;
}
/* 将输出缓冲区的数据写入保存的视频文件中 */
// 这里省略了将数据写入文件的代码
/* 释放输入帧和输出数据包 */
mpp_frame_deinit(&frame);
mpp_packet_deinit(&packet_out);
}
/* 关闭输入和输出设备 */
mpp_close(input_ctx);
mpp_close(output_ctx);
/* 销毁 MPP 组件 */
mpp_buffer_group_put(buf_grp_in);
mpp_buffer_group_put(buf_grp_out);
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame_out);
mpp_frame_deinit(&frame_in);
mpp_destroy(ctx);
RK_MPI_SYS_Exit();
return 0;
}
```
请注意,此示例仅用于演示如何使用MPP库进行视频采集和编码,它并没有包含完整的代码,例如文件读写和错误处理等。在实际的应用中,你需要根据自己的需求进行修改和完善。
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)