视频处理模块优化
上一版的不足
上一版的不足在于其拓展性弱(只支持一路输入源),参数配置麻烦(需要通过宏定义修改)。新版将不再采用宏定义方式进行配置,而是新增一个配置结构体,用户可以在该结构体里面配置信息构建自定义管道,且支持任意数量的输入源同时工作。
0. 配置参数
这一版将配置参数通过enum和union进行统一管理
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
|
typedef enum { SOURCE_TYPE_V4L2, SOURCE_TYPE_UDP, SOURCE_TYPE_TEST, } SOURCE_TYPE;
typedef enum { QUEUE_MODE_FORCE, QUEUE_MODE_PASS, } QUEUE_MODE;
typedef enum { CODER_SOFT, CODER_MPP, } CODER;
#define EINPUT 1 #define EALLOC 2 #define ELINK 3 #define ESIG 4 #define EPUSH 5 #define EPOP 6
typedef enum { VIDEO_FORMAT_RGB, VIDEO_FORMAT_NV12, } VIDEO_FORMAT;
typedef union { int port; const char *dev; } SOURCE_ID;
|
1. GstConfig配置结构体
通过一个配置结构体管理一个视频管道的配置信息,可以在程序中自定义管道。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| typedef struct { uint8_t USE_RGA; uint8_t USE_RECORD; uint8_t USE_SHOW; int max_queue_length; guint sourceid; long frame_count; int video_width; int video_height; int video_fps; VIDEO_FORMAT video_format; SOURCE_TYPE source_type; SOURCE_ID source_id; QUEUE_MODE queue_mode; CODER encode_type; CODER decode_type;
} GstConfig;
|
2. GstApiData结构体
这个结构体的作用相当于Linux驱动中的cdev, 其中的gst_file_operations相当于cdev的file_operations,其中包含read和write函数需要用户实现或使用系统默认。该结构体的功能包括
- 负责管理所需Gstreamer组件的初始化以及管道的搭建和运行
- 用户程序通过该结构体访问视频数据
与上一般的不同在于,GstElement不再根据宏定义配置定义该结构体属性,而是通过GstConfig的配置在初始化函数中构造pipeline中的元素,这些元素直接添加到pipeline和record_pipeline中被其自动管理。此外GstApiData里面多了一个MemoryPool,这样可以实现每一路输入源都有一个内存池来管理内存分配。
1 2 3 4 5 6 7 8 9
| typedef struct { GstConfig* cfg; gst_file_operations *fops; GstElement *pipeline, *record_pipeline; FrameQueue *fqueue, *rqueue; GstBus *bus, *record_bus; MemoryPool* mem_pool; GMainLoop *main_loop; } GstApiData;
|
使用流程
这里演示一下如何构建V4L2和TEST两路管道,使用户可以读取两路的图像数据并将图像保存为MP4。
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
| GstApiData *data[2];
GstConfig cfg = { .USE_RGA=0, .USE_RECORD=0, .USE_SHOW=0, .max_queue_length=16, .video_width=1280, .video_height=720, .video_fps=120, .video_format=VIDEO_FORMAT_RGB, .source_type=SOURCE_TYPE_TEST, .queue_mode=QUEUE_MODE_FORCE, .encode_type=CODER_SOFT, .decode_type=CODER_SOFT, };
GstConfig cfg2 = { .USE_RGA=0, .USE_RECORD=1, .USE_SHOW=0, .max_queue_length=16, .video_width=1920, .video_height=1080, .video_fps=30, .video_format=VIDEO_FORMAT_RGB, .source_type=SOURCE_TYPE_V4L2, .source_id={ .dev="/dev/video0" }, .queue_mode=QUEUE_MODE_FORCE, .encode_type=CODER_SOFT, .decode_type=CODER_SOFT, };
ret = gst_api_init(&data[0], &cfg, &std_fops); ret = gst_api_init(&data[1], &cfg2, &std_fops);
gst_print_informations(data[0]); gst_print_informations(data[1]);
gst_api_try_play(gdata, 2);
|