基于发布-订阅模型的音视频流分发框架

news/2024/9/17 7:13:33/ 标签: 音视频

有时需要同时网络推流和把流封装为某格式,或做一些其它操作。这就需要一个分发流的机制,把同一路流分发给多个使用者去操作,下面实现了一个简易的线程安全的音视频流分发框架。代码如下:

avStreamHub.h

#ifndef STREAMHUB_H
#define STREAMHUB_H#include <stddef.h>
#include <pthread.h>typedef void (*AVStreamCallback)(void *data, size_t size, void *arg);typedef struct Subscriber
{AVStreamCallback callback;void *arg;
} Subscriber;typedef struct AVStreamHub
{Subscriber *subscribers; // 存储订阅者的数组size_t size;             // 当前订阅者数量size_t capacity;         // 动态数组容量pthread_mutex_t lock;    // 互斥锁
} AVStreamHub;/*** @brief 初始化AVStreamHub* @param hub 指向AVStreamHub结构体的指针* @param initial_capacity 初始分配的订阅者容量* @return 0 成功,-1 失败*/
int avStreamHub_init(AVStreamHub *hub, size_t initial_capacity);/*** @brief 添加订阅者* @param hub 指向AVStreamHub结构体的指针* @param callback 订阅者的回调函数* @param arg 回调携带的参数* @return 0 成功,< 0 失败*/
int avStreamHub_addSub(AVStreamHub *hub, AVStreamCallback callback, void *arg);/*** @brief 删除订阅者* @param hub 指向AVStreamHub结构体的指针* @param callback 要移除的订阅者的回调函数* @return 无*/
void avStreamHub_removeSub(AVStreamHub *hub, AVStreamCallback callback);/*** @brief 将数据流分发给所有已注册的订阅者* @param hub 指向AVStreamHub结构体的指针* @param data 指向要分发的数据的指针* @param size 数据的大小* @return 无*/
void avStreamHub_publish(AVStreamHub *hub, void *data, size_t size);/*** @brief 销毁AVStreamHub* @param hub 指向AVStreamHub结构体的指针* @return 无*/
void avStreamHub_destroy(AVStreamHub *hub);#endif // STREAMHUB_H

avStreamHub.c

#include "avStreamHub.h"
#include <stdlib.h>
#include <string.h>#define INITIAL_CAPACITY 2int avStreamHub_init(AVStreamHub *hub, size_t initial_capacity)
{hub->size = 0;hub->capacity = 0;if (initial_capacity == 0){initial_capacity = INITIAL_CAPACITY;}hub->subscribers = (Subscriber *)malloc(initial_capacity * sizeof(Subscriber));if (!hub->subscribers){return -1;}memset(hub->subscribers, 0, initial_capacity * sizeof(Subscriber));hub->capacity = initial_capacity;pthread_mutex_init(&hub->lock, NULL);return 0;
}// 添加订阅者
int avStreamHub_addSub(AVStreamHub *hub, AVStreamCallback callback, void *arg)
{pthread_mutex_lock(&hub->lock);// 检查该回调是否已存在for (size_t i = 0; i < hub->size; i++){if (hub->subscribers[i].callback == callback){pthread_mutex_unlock(&hub->lock);return -1; // 回调已存在}}// 如果容量不足则扩展容量if (hub->size == hub->capacity){hub->subscribers = (Subscriber *)realloc(hub->subscribers,hub->capacity * 2 * sizeof(Subscriber));if (!hub->subscribers){pthread_mutex_unlock(&hub->lock);return -2;}hub->capacity *= 2;}// 添加新订阅者hub->subscribers[hub->size].callback = callback;hub->subscribers[hub->size].arg = arg;hub->size++;pthread_mutex_unlock(&hub->lock);return 0;
}// 删除订阅者
void avStreamHub_removeSub(AVStreamHub *hub, AVStreamCallback callback)
{pthread_mutex_lock(&hub->lock);for (size_t i = 0; i < hub->size; i++){if (hub->subscribers[i].callback == callback){size_t j = i;for (; j < hub->size - 1; j++){hub->subscribers[j] = hub->subscribers[j + 1];}hub->subscribers[j].callback = NULL;hub->subscribers[j].arg = NULL;hub->size--;break;}}pthread_mutex_unlock(&hub->lock);
}// 分发数据
void avStreamHub_publish(AVStreamHub *hub, void *data, size_t size)
{pthread_mutex_lock(&hub->lock);for (size_t i = 0; i < hub->size; i++){hub->subscribers[i].callback(data, size, hub->subscribers[i].arg);}pthread_mutex_unlock(&hub->lock);
}// 销毁AVStreamHub
void avStreamHub_destroy(AVStreamHub *hub)
{free(hub->subscribers);hub->subscribers = NULL;hub->size = 0;hub->capacity = 0;pthread_mutex_destroy(&hub->lock);
}

http://www.ppmy.cn/news/1522243.html

相关文章

算法专题一: 双指针

目录 前言1. 移动零&#xff08;easy&#xff09;2. 复写零&#xff08;easy&#xff09;3. 快乐数&#xff08;medium&#xff09;4. 盛水最多的容器&#xff08;medium&#xff09;5. 有效三角形的个数&#xff08;medium&#xff09;6. 和为 s 的两个数字&#xff08;easy&a…

Docker 进阶构建:镜像、网络与仓库管理

目录 三. docker镜像构建 1. docker镜像结构 2. 镜像运行的基本原理 3. 镜像获得方式 4. 镜像构建 5. Dockerfile实例 6. 镜像优化方案 6.1. 镜像优化策略 6.2. 镜像优化示例:缩减镜像层 6.3. 镜像优化示例:多阶段构建 6.4. 镜像优化示例:使用最精简镜像 四. docke…

网络安全服务基础Windows--第15节-CA与HTTPS理论

公钥基础设施&#xff08;Public Key Infrastructure&#xff0c;简称 PKI&#xff09;是指⼀套由硬件、软件、⼈员、策略和程序组成的系统&#xff0c;⽤于创建、管理、分发、使⽤、存储和撤销数字证书。PKI 的核⼼⽬的是通过使⽤公钥加密技术来确保电⼦通信的安全性。PKI 为数…

八月二十九日(day 39)docker6

1.前端&#xff08;nginx&#xff09; [rootlocalhost ~]# docker pull nginx //拉取nginx镜像 [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 5ef79149e0ec 2 we…

springboot数据库连接由localhost改成IP以后访问报错500(2024/9/7

步骤很详细&#xff0c;直接上教程 情景复现 一.没改为IP之前正常 二.改完之后报错 问题分析 SQL没开启远程连接权限 解决方法 命令行登入数据库 mysql -u root -p切换到对应数据库 use mysql;设置root用户的连接权限允许其他IP连接数据库 update user set host % whe…

前端技术(六)—— AJAX详解

一、原生 AJAX 1. AJAX 简介 AJAX 全称为 Asynchronous JavaScript And XML&#xff0c;就是异步的 JS 和 XML。 通过 AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据。 AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准组…

C语言程序设计(初识C语言后部分)

留一片空白&#xff0c;随时浓墨重彩。 二十&#xff0c;结构体 结构体类型的声明 结构体初始化 结构体成员访问 结构体传参 1.结构体的声明 1&#xff09;结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 2&…

上海网站设计-网站手机端制作

随着移动互联网的迅猛发展&#xff0c;越来越多的人通过手机上网&#xff0c;这使得网站手机端的设计和制作变得尤为重要。在这种背景下&#xff0c;上海的网站设计行业迎来了新的机遇与挑战。 首先&#xff0c;网站手机端制作的必要性不容忽视。根据统计数据显示&#xff0c;手…

Flask框架 完整实战案例 附代码解读 【3】

Flask 是一个轻量级的可定制框架&#xff0c;使用Python语言编写&#xff0c;较其他同类型框架更为灵活、轻便、安全且容易上手。 前面已经写过项目从新建运行安装到测试部署的全流程&#xff0c;其中有写Flask框架从新建到部署全流程&#xff0c;但是只有部分代码。本篇主要是…

微软发布Phi-3.5 SLM,附免费申请试用

Phi-3 模型系列是Microsoft 小型语言模型 (SLM) 系列中的最新产品。 它们旨在具有高性能和高性价比&#xff0c;在语言、推理、编码和数学等各种基准测试中的表现均优于同类和更大规模的模型。Phi-3 模型的推出扩大了 Azure 客户的高质量模型选择范围&#xff0c;为他们编写和…

通信工程学习:什么是FEC前向纠错

FEC&#xff1a;前向纠错 FEC&#xff08;Forward Error Correction&#xff0c;前向纠错&#xff09;是一种增加数据通信可信度的技术&#xff0c;广泛应用于计算机网络、无线通信、卫星通信等多种数据传输场景中。其基本原理和特点可以归纳如下&#xff1a; 一、FEC前向纠错…

ArcGIS出图格网小数位数设置

1、比如要去掉格网后面的小数点&#xff0c;如何设置呢&#xff1f; 2、如下图设置。

linux 下一跳缓存,early demux(‌早期解复用)‌介绍

3.6版本以后的下一跳缓存 3.6版本移除了FIB查找前的路由缓存。这意味着每一个接收发送的skb现在都必须要进行FIB查找了。这样的好处是现在查找路由的代价变得稳定(consistent)了。3.6版本实际上是将FIB查找缓存到了下一跳(fib_nh)结构上&#xff0c;也就是下一跳缓存下一跳缓存…

Flink SQL 中常见的数据类型

Flink SQL 中常见的数据类型 目标 通过了解Flink SQL 中常见的数据类型,掌握正确编写Flink SQL 语句背景 Apache Flink 支持多种数据类型,这些数据类型被用于 Flink SQL 表达式、Table API 以及 DataStream API 中。以下是 Flink SQL 中常见的数据类型: 基本数据类型 Boo…

初识Linux · 进度条

目录 前言&#xff1a; 1 缓冲区和回车换行 2 进度条 前言&#xff1a; 我们目前学习了些许知识&#xff0c;已经足够支持我们写一个非常非常小的项目了&#xff0c;即进度条&#xff0c;相信大家都有过下载游戏&#xff0c;等待游戏更新完成的时候&#xff0c;那么此时就有…

数据结构---单向链表

单向链表 //链表的创建 Link_t *create_link() {Link_t *plink malloc(sizeof(Link_t));if(NULL plink){perror("fail plink");return NULL;}plink->phead NULL;plink->clen 0;return plink; } //头插 int push_link_head(Link_t *plink, DataType data…

一台Linux服务器最多可以支撑多少个TCP连接

一台Linux服务器最多可以支撑多少个TCP连接&#xff1f; 1.端口号资源 在确定最大连接数之前&#xff0c;先来看看系统如何标识一个TCP连接。系统用一个4四元组来唯一标识一个TCP连接【源IP、源端口、目标IP、目标端口】 以Nginx为例&#xff0c;端口是固定使用80&#xff0…

pytorch torch.norm函数介绍

torch.norm 函数用于计算张量的范数(norm),可以理解为张量的“长度”或“大小”。根据范数的不同类型,它可以衡量不同的张量性质。该函数可以计算 向量 和 矩阵 的多种范数,如 L1范数、L2范数、无穷范数 等。 1. 函数签名 torch.norm(input, p=fro, dim=None, keepdim=F…

LabVIEW环境中等待FPGA模块初始化完成

这个程序使用的是LabVIEW环境中的FPGA模块和I/O模块初始化功能&#xff0c;主要实现等待FAM&#xff08;Field-Programmable Gate Array Module&#xff0c;FPGA模块&#xff09;的初始化完成&#xff0c;并处理初始化过程中的错误。让我们逐步分析各部分的功能&#xff1a; 1.…

电脑点击关机之后,又自动重启开机了。根本就关不了?

前言 有个小姐姐说&#xff0c;她家的电脑好生奇怪&#xff1a;点击【关机】按钮之后&#xff0c;电脑提示【正在关机】&#xff0c;过了几秒&#xff0c;电脑又自动开机了…… 好家伙&#xff01;也就是说关机和重启根本就没区别&#xff0c;电脑完全无法断电。 最后忍无可…