LINUX qt 用mpp库编写视频采集及保存视频文件 C++代码
时间: 2024-03-20 09:38:49 浏览: 18
下面是用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;
}
```
需要注意的是,上述代码是仅供参考的示例代码,具体实现还需要根据具体的需求进行调整和完善。