我的视频课程(编码直播推流):《Android视频编码和直播推流》
我的视频课程(C++ OpenGL):《Android C++ OpenGL教程》
通过这段时间的加班,终于把我的FFmpeg开发课程《FFmpeg打造Android万能音频播放器》和《FFmpeg+OpenGL ES+OpenSL ES打造Android视频播放器》录制完成了。在开发过程中涉及到了许多的知识点,其中一个就是C++多线程解码退出问题,今天我们就来讲讲怎样按顺序退出多线程。
一、引出问题
首先我们来看一下FFmpeg解码多线程流程图:
从图中我们看到了至少得用3个线程来解码视频:
第一个是:FFmpeg的解码线程
第二个是:音频播放线程
第三个是:视频播放线程
并且,这3个线程都是在while循环中执行的,因此当我们想停止播放时问题就来了:我们需要分别停止这3个线程并回收线程资源,而这3个线程也有共同的操作对象。当线程还在执行时我们就回收资源的话(因为线程中有sleep操作,不能保证在回收资源钱线程就退出了),就会导致还在执行的线程调用资源时出现错误的地址访问,导致崩溃现象,这是多线程中经常出现的一个问题。
二、解决方案
为了解决上面的问题,我们最理想的就是:在回收资源之前,需要把所有访问资源的线程给停止掉,然后就可以放心的回收资源了。那么解决的办法也有许多:
第一种:就在线程的最后直接回收资源,只要线程结束,就回收资源,如:
第二种:添加变量来判断线程是否退出,回收资源前循环判断此变量,知道线程退出后才回收资源,如:
第三种:使用pthread_join(thread, void**)函数,这个函数会阻塞当前线程,直到目标线程退出后才往下执行。这就是最完美的等待线程退出的方法。
三、实现过程
在回收资源之前,调用pthread_join函数阻塞当前线程,等待目标线程退出后才回收资源,这样就能保证回收的资源时没有被使用的:
这样就能完美的解决多线程退出问题了,我们还可以指定退出顺序,完全按照自己的想法退出,就能很好地解决我们的问题了。
四、实例代码
这里我写了一个模拟多线程解码的demo,详细代码我就不贴出来了,文末有实例下载地址,可以自行下载运行。
4.1 未添加线程控制pthread_join函数时效果:
我们发现,资源已经回收之后,而音频或视频的解码线程还在解码,这样就会导致方法资源地址错误。
4.2 使用线程控制pthread_join函数时效果:
从上面打印日志可以看出,都是先退出线程后回收资源,这样就能保证多线程退出的安全性了。
五、总结
FFmpeg解码音视频算是很复杂的了,里面牵扯太多知识点。但是任何复杂的功能,都是有一个个功能(知识点)组合而来的,只有当我们把这些知识点理解透彻之后,才能写出健壮而复杂的程序出来,最后来一张我视频课程里面的效果图:
好了,就到这里吧,实例下载地址:
GitHub地址:C++多线程退出并释放资源