ffmpeg多线程解码

时间:2024-03-19 22:17:47

一。ffmpeg中使用到的多线程的概念:
   2.共享变量的互斥
       互斥锁(mutex-lock)是一种信号量,用来防止两个线程在同一时刻访问相同的共享资源,它有锁定状态和非锁定状态,在任意时刻,一个线程要想存取共享数据,线程必须首先获得mutex-lock,当此线程释放此共享数据的时候必须对mutex-lock解锁,在一个任意的时间内,只有一个线程能锁定互斥锁,通过函数pthread_mutex_lock上锁,通过函数pthread_mutex_unlock解锁。
  3.同步条件变量
       条件变量用来提供另一种线程同步的方法,其基于实际的变量值来实现线程的同步操作,设置了条件变量的情况下,线程就不需要通过不停的轮询来查询条件是否满足,也不需要不停的忙等,从而能够节省很多系统资源。一个条件变量总是和一个mutex-lock对应,系统通过pthread_cond_await函数来阻塞调用的线程,一直到条件变量得到满足。当这个线程阻塞的时候对应的mutex-lock会自动解锁,但当该线程运行的时候,其对应的mutex-lock会被加锁。使用函数pthread_cond_signal来唤醒等待在条件变量的另一个线程,当用来唤醒多个处于阻塞状态线程时通过pthread_cond_broadcast函数来完成。

ffmpeg中的多线程解码主要分为片Slice级别的多线程解码和帧Frame级别的多线程解码:
       Slice级的解码效率比Frame级的解码效率要低,故,本文先考虑Frame级的多线程解码。通过查看ffmpeg源码,了解到Frame级的多线程解码流程大致如下:
      ffmpeg多线程解码

 其中右侧的frame_worker_thread为解码线程,在open解码器时就已经创建,随后阻塞在pthread_cond_wait(&p->input_cond, &p->mutex)函数。等待被主线程唤醒。
ffmpeg多线程解码

当主线程运行到ff_thread_decode_frame函数时,会调用submit_packet函数,这个函数的目的就是将packet包交给解码线程。submit_packet函数会调用pthread_cond_signal(&p->input_cond)函数,这个函数就是为唤醒刚才阻塞的解码线程。当主线程唤醒解码线程后,其pthread_cond_wait(&p->output_cond, &p->progress_mutex)函数会进入阻塞状态,等待解码线程唤醒。

1.如果Codec未实现update_thread_context()和线程安全的get_buffer(),则必须在解码完成后才能将状态转换为STATUS_SETUP_FINISHED,意味着下一个线程只能在当前线程解码完成后才能开始解码。当解码线程解码完成后,会用pthread_cond_signal(&p->output_cond)将主线程唤醒,其中会通过回调函数将解码线程解码出来的frame获取,从而输出。
ffmpeg多线程解码

2.如果Codec实现update_thread_context()和线程安全的get_buffer(),线程状态可以在解码开始之前转换为STATUS_SETUP_FINISHED,这样,主线程就能够被唤醒,就能够去读包进行下一个包的解码,因此下一个线程就可能与当前线程并行。
ffmpeg多线程解码