您的位置:首页 > 其它

通过信号量和共享内存实现h264码流在不同进程间传输

2017-03-07 19:02 447 查看
读写这两个进程需要共享的内存,在头文件中定义,

#define DZY_FRAME_SIZE 300000
#define DZY_FRAME_COUNT 10
typedef struct single_frame
{
int length;
char frame[DZY_FRAME_SIZE];
}single_frame;
typedef struct mul_frame
{
int count;
int readIdx;
int writeIdx;
single_frame frame[DZY_FRAME_COUNT];
}mul_frame;


其中single_frame,存放单个视频帧,mul
4000
_frame存放多帧的队列,其中count用来记录帧的数量,readIdx和writeIdx用来记录读帧和写帧的游标,通过结构体实现内存共享,便于操作。

写入进程的共享内存初始化代码

#include <sys/shm.h>
#include <semaphore.h>
int shmid;
mul_frame *shared;//指向shm
sem_t* sem;
void *shm = NULL;//分配的共享内存的原始首地址
shmid = shmget((key_t)1234, sizeof(mul_frame), 0666|IPC_CREAT);
shm = shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
fprintf(stderr, "shmat failed\n");
}
printf("\nMemory attached at %X\n", (int)shm);
shared = (mul_frame*)shm;
shared->readIdx = 0;
shared->writeIdx = 0;
shared->count = 0;

for(int i =0;i<DZY_FRAME_COUNT;i++)
{
shared->frame[i].length=0;
}
sem = sem_open("mysem", O_CREAT | O_RDWR , 0666, 1);
if (sem == SEM_FAILED)
{
printf("errno open sem\n");
}


其中共享内存的keyid为1234,用于不同进程间设置同一的keyid,共享内存的大小为sizeof(mul_frame),可以自定义,这在linux上优于命名管道(fifo),因为命名管道

只能缓冲65536bytes,但是命名管道自带同步机制,而共享内存没有,所以需要定义信

号量sem_t* sem,其中mysem为信号量的keyid,同样用于不同进程间共享。

下面是写入进程的共享内存析构代码

//把共享内存从当前进程中分离
if(shmdt((void*)shared) == -1)
{
fprintf(stderr, "shmdt failed\n");
}
//删除共享内存
if(shmctl(shmid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "shmctl(IPC_RMID) failed\n");
}
sem_destroy(sem);


读取共享内存的初始化的代码

int shmid;
mul_frame *shared;//指向shm
void *shm = NULL;//分配的共享内存的原始首地址
shmid = shmget((key_t)1234, sizeof(mul_frame), 0666|IPC_CREAT);
if(shmid == -1)
{
fprintf(stderr, "shmget failed\n");
}
//将共享内存连接到当前进程的地址空间
shm = shmat(shmid, 0, 0);
if(shm == (void*)-1)
{
fprintf(stderr, "shmat failed\n");
}
printf("\nMemory attached at %X\n", (int)shm);
shared = (mul_frame*)shm;
sem_t* sem;
sem = sem_open("mysem", O_CREAT | O_RDWR , 0666, 0);
if (sem == SEM_FAILED)
{
printf("errno open sem\n");
}


读取共享内存的代码与写共享内存的代码基本一致,其中sem_open不同,写入的代码中最后一个参数是1,而读取的代码中,最后一个参数是0。

读取共享内存的析构代码,暂略。

下面是写入共享内存的代码

//sem_wait(sem);
//printf("shared->count:%d\n",shared->count);
if(shared->count < DZY_FRAME_COUNT)
{
shared->frame[shared->readIdx].length = _rxH264Frame->GetFrameSize() - bytesUsed;
memcpy(shared->frame[shared->readIdx].frame,_rxH264Frame->GetFramePtr() + bytesUsed,shared->frame[shared->readIdx].length);
shared->readIdx = (shared->readIdx+1)%DZY_FRAME_COUNT;
shared->count++;
}else
{
printf("error, shared->count:%d\n",shared->count);
}
sem_post(sem);


下面是读取共享内存的代码

sem_wait(sem);
//printf("shared->count:%d\n",shared->count);
if(shared->count > 0)
{
*len = shared->frame[shared->writeIdx].length;
memcpy(buf,shared->frame[shared->writeIdx].frame,*len);
shared->writeIdx = (shared->writeIdx+1)%DZY_FRAME_COUNT;
shared->count--;
}else
{
printf("error, shared->count:%d\n",shared->count);
}
//sem_post(sem);


由于写入共享内存时,是通过网络接收,而读取共享内存是直接保存文件,网络接收的速度明显慢于保存文件,所以只需要在读取的时候加sem_wait,用来等待写入。

另外,通过%DZY_FRAME_COUNT,来实现环形缓冲区的效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: