使用FFmpeg库模拟消息传递的C程序。它创建了一个消息队列以及多个发送者和接收者线程,这些线程在队列中推送和弹出消息。
程序的主要功能包括:
定义了发送者和接收者数据的结构,以及消息的结构。
free_frame函数用于释放消息帧的内存。
sender_thread和receiver_thread函数分别模拟发送者和接收者线程的行为。发送者创建带有帧的消息并将其推送到队列中,而接收者从队列中弹出消息,处理其帧并释放消息。
get_workload函数生成发送者和接收者线程的随机工作负载。
在main函数中,程序从命令行参数中获取配置参数(例如队列大小、发送者/接收者数量、工作负载范围)。
为发送者和接收者数据数组分配内存并初始化消息队列。
程序使用pthread_create函数创建发送者和接收者线程。
在创建所有线程后,程序使用pthread_join函数等待它们完成。
最后,程序释放了分配的资源并检查是否有任何错误。
// 结构体:发送者数据
struct sender_data {
int id; // 发送者的标识符
pthread_t tid; // 发送者线程的标识符
int workload; // 发送者的工作负载,即需要处理的消息数量
AVThreadMessageQueue *queue;// 指向消息队列的指针,发送者通过该队列发送消息
};
// 结构体:接收者数据
// 为了测试目的,将 sender_data 的成员顺序打乱
struct receiver_data {
pthread_t tid; // 接收者线程的标识符
int workload; // 接收者的工作负载,即需要处理的消息数量
int id; // 接收者的标识符
AVThreadMessageQueue *queue;// 指向消息队列的指针,接收者通过该队列接收消息
};
// 结构体:消息
struct message {
AVFrame *frame; // 指向帧数据的指针,用于存储消息的帧数据
int magic; // 用于添加垃圾数据以确保消息大小大于 sizeof(void*)
};
// 宏定义:MAGIC
#define MAGIC 0xdeadc0de // 用于表示消息中垃圾数据的值
sender_thread
// 函数:发送者线程函数
static void *sender_thread(void *arg)
{
int i, ret = 0;
struct sender_data *wd = arg; // 获取发送者数据结构体指针
// 打印发送者的工作负载信息
av_log(NULL, AV_LOG_INFO, "sender #%d: workload=%d\n", wd->id, wd->workload);
// 循环发送消息,模拟发送者的工作
for (i = 0; i < wd->workload; i++) {
// 随机决定是否清空消息队列
if (rand() % wd->workload < wd->workload / 10) {
av_log(NULL, AV_LOG_INFO, "sender #%d: flushing the queue\n", wd->id);
av_thread_message_flush(wd->queue); // 清空消息队列
} else {
char *val;
AVDictionary *meta = NULL;
struct message msg = {
.magic = MAGIC,
.frame = av_frame_alloc(), // 为消息分配帧数据内存
};
if (!msg.frame) {
ret = AVERROR(ENOMEM); // 内存分配失败