Gstreamer学习与POSIX共享内存实例

前言

接上一篇,测试采用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 = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值