前言
接上一篇,测试采用POSIX共享内存与信号量测试进程间通信,POSIX共享内存没有进程间同步操作,因此需要信号量实现同步。POSIX信号量作为进程间同步操作时,使用匿名信号量,且匿名信号量必须预先位于共享内存段中。编译POSIX函数时,需要链接 librt.so,因此在链接库文件时需要指定 “-lrt” 参数
需求说明
- 进程A:Gstreamer进程,使用appsrc、vpuenc_h264、appsink三个元件对视频进行H264编码,appsrc通过元件的信号获取NV12格式的图像数据,vpuenc_h264元件进行编码,appsink获取编码后的H264帧、appsink的信号回调函数负责通过共享内存与信号量,将数据传输到进程B
- 进程B:视频推动进程,通过共享内存获取H264视频帧,使用rtmp方式推送到服务端
进程A
共享内存以及信号均由进程B创建并初始化
- 注意共享内存的数据结构ShmVideo360Struct,数据结构内预定义用于进程同步的信号量,由创建共享内存的进程B初始化
- 共享内存文件名标识#define POSIX_SHM “POSIX.shm”,文件名可随意,但是不能存在多重路径,例如:#define POSIX_SHM “/home/root/POSIX.shm”,这样会导致shm_open函数失败,原因是非法参数
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/un.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <ipu.h>
typedef struct _GstDataStruct{
GstElement *pipeline;
GstElement *app_source;
GstElement *video_convert;
GstElement *h264_encoder;
GstElement *app_sink;
guint sourceid; // To control the GSource
guint app_src_index;
guint app_sink_index;
guint bus_watch_id;
GstBus *bus;
GMainLoop *loop; // GLib's Main Loop
int frame_rate;
int gop_size;
int bit_rate;
int quant;
} GstDataStruct;
typedef struct
{
struct fb_var_screeninfo vinfo; // 可变的STOP显示屏幕信息
struct fb_fix_screeninfo finfo;
int width; // width 宽度
int height; // height 高度
int bpp; // bit per pixel 像素的位数
int rowsize; // 屏幕一行所占字节数
int real_len; // 实际显示区域的字节数
int total_len; // 显示区域总字节数,即长度
int offset; // 实际显示位置在总长度中的偏移量
}FbInfoStruct;
#define VIDEO_BUF_SIZE ((128 * 1024 * 1024) - (sizeof(unsigned int)*3) - (sizeof(sem_t)*2))
typedef struct
{
sem_t sem_h264_put;
sem_t sem_h264_get;
unsigned int head;
unsigned int len;
unsigned int index;
unsigned char data[VIDEO_BUF_SIZE];
}ShmVideo360Struct;
static int fb_init(void);
static int gst_pipeline_init(void);
static void new_h264_sample_on_appsink (GstElement *sink, GstDataStruct *pGstData);
static void start_feed (GstElement * pipeline, guint size, GstDataStruct *pGstData);
static void stop_feed (GstElement * pipeline, GstDataStruct *pGstData);
gboolean bus_msg_call(GstBus *bus, GstMessage *msg, GstDataStruct *pGstData);
static void *ipu_thread(void *arg);
struct IPU_PHY_MEM {
char *vaddr;
unsigned int paddr;
unsigned int size;
};
struct ipu_task gtask;
struct IPU_PHY_MEM ipu_pmem;
static GstDataStruct GstData;
static FbInfoStruct FbInfo;
ShmVideo360Struct *shared360 = NULL; //指向shm
int posix_shm_fd;
void* posix_shm;
int fd_fb;
int fd_ipu;
sem_t sem_frame_put;
sem_t sem_frame_get;
#define POSIX_SHM "POSIX.shm"
#define OBJ_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
int main(int argc, char *argv[])
{
int ret = 0;
pthread_t tid;
printf("================ imx60 360 main start =============\n");
memset (&GstData, 0, sizeof (GstDataStruct));
sem_init(&sem_frame_put, 0, 0);
sem_init(&sem_frame_get, 0, 0);
if(argc == 5)
{
GstData.frame_rate = atoi(argv[1]);
GstData.gop_size = atoi(argv[2]);
GstData.bit_rate = atoi(argv[3]);
GstData.quant = atoi(argv[4]);
}
else
{
GstData.frame_rate = 30;
GstData.gop_size = 30;
GstData.bit_rate = 1800;
GstData.quant = 1;
}
printf("frame_rate:%d, gop_size:%d, bit_rate:%d ,quant:%d!\n",
GstData.frame_rate, GstData.gop_size, GstData.bit_rate, GstData.quant);
while(1)
{
posix_shm_fd = shm_open(POSIX_SHM, O_RDWR, 0); //打开已存在的共享内存
if(posix_shm_fd != -1) break;
printf("posix shm open failed, try again, 2 second later!\n");
sleep(2);
}
errno = 0;
posix_shm = mmap(NULL, sizeof(ShmVideo360Struct), PROT_READ | PROT_WRITE, MAP_SHARED, posix_shm_fd, 0);
if (posix_shm == MAP_FAILED)
{
printf("posix mmap failed\n");
printf("errno info: %s\n", strerror(errno));
close(posix_shm_fd);
shm_unlink(POSIX_SHM);
return 0;
}
shared360 = (ShmVideo360Struct*)posix_shm;
fb_init();
ret =