rv1126+opencv多线程同时对视频进行膨胀和腐蚀
一.实现流程与代码的讲解
我们之前进行的单独的视频膨胀与腐蚀操作,现在我们用一个工程同时对视频流进行膨胀与腐蚀的操作 。思路流程如下图:
我们看到,进行膨胀与腐蚀的线程都是从VI模块获取数据,将处理后的数据发送到VENC模块,者就涉及到多线程使用共享资源,这会有资源争夺问题,为了解决这个问题我们就需要使用到互斥锁,即一个线程在获取共享资源的时候对齐进行加锁,使得资源无法被其他线程使用,使用完之后进行解锁。这一加解锁就解决了一个线程在使用共享资源的时候别其他线程打断导致数据不完整的问题。
接下来介绍一下互斥锁
1.互斥锁
1.互斥锁基本概念
在多线程编程中,互斥锁(Mutex)是一种用于保护共享资源的同步机制。当多个线程同时访问共享资源时,互斥锁可以确保在同一时间只有一个线程能够访问该资源,从而避免数据竞争和不一致问题。
2.PTHREAD_MUTEX_INITIALIZER 的作用
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
这行代码用于初始化一个互斥锁变量。
PTHREAD_MUTEX_INITIALIZER 是什么:
它是一个 POSIX 标准定义的宏,用于静态初始化互斥锁
本质上是一个结构体常量,包含了互斥锁的初始状态信息
作用:为互斥锁变量g_mutex
提供初始值
完成互斥锁的基本配置,
使其处于可用状态相当于执行了pthread_mutex_init(&g_mutex, NULL)
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;//创建互斥锁并初始化
为什么要这样做:这是初始化互斥锁的一种便捷方式,确保互斥锁在使用前处于已知的初始状态,避免未初始化的互斥锁导致的不确定行为
3.代码中多次加锁解锁,为什么要这样子做呢?
多次加锁的可能原因:
1.减少锁的持有时间:长时间持有锁会降低并发性,可能导致其他线程长时间等待
2.分段保护不同资源:不同操作可能涉及不同的共享资源,需要分别保护
3.避免死锁风险:在复杂场景中,分段加锁可以降低死锁发生的可能性
4.代码结构清晰化:将不同功能模块的锁操作分开,提高代码可读性
二.代码实战讲解
我们上面说到使用同一个VENC会有资源竞争问题,所以我们代码就是初始化一个VNEC模块的两个不同通道来使用如下
线程获取失败的问题我们使用continue函数解决,当一个资源别一个线程占用导致另一个线程获取失败的时候,我们不直接退出线程操作而是跳过接下来的操作回到循环开始重新获取资源。这其实也就是等待另一个线程释放资源的过程
结果如下
腐蚀 膨胀
三.总结
实现同一功能的代码方式有很多种,我们可以多进行尝试。本次介绍的是一个VENC两个通道的方法来实现。我们也可以是创建两个不同的VENC来处理数据。同时我们还可以用同一个VNEC同一个通道+互斥锁的方法来实现。方法是很多的,实现功能都是可以实现的,但是我们需要找出最优方案,这个就是需要我们多实践的。目前我觉得是一个VENC两个通道的方法来实现这种最优,如有更好的方案可以与我分享。