x265的编码流程

转自 https://blog.csdn.net/dragon_dy/article/details/52469678

一、X265的编码主函数
int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)
过程为:
1. 先将输入图像x265_picture* pic_in中的数据复制到内部帧结构Frame *inFrame,计算好其它帧信息
2. 调用m_lookahead->addPicture(*inFrame, sliceType)将当前帧送入lookahead队列,唤醒一个工作线程来处理,在lookahead满后,会将处理完的miniGOP放入output队列,等待getDecidedPicture取出。如果输入帧为NULL,结果编码结束了,则通过调用m_lookahead->flush()来让lookahead处理完剩下的帧,输出miniGOP到output队列。
3. 选择当前的并行帧编码单元FrameEncoder,并调用curEncoder->getEncodedPicture(m_nalList)取它已经在编码的帧数据。如果有已经在编码的帧,会等待其编码结束得到数据,再输出编码数据;如果没有在编码的帧,返回NULL
4. 调用frameEnc = m_lookahead->getDecidedPicture()取出下一帧待编码帧。
5. 调用curEncoder->startCompressFrame(frameEnc)让并行编码器进行编码,此函数将帧数据送入FrameEncoder 后就返回到调用者流程,FrameEncoder 的后台线程会负责编码。FrameEncoder 在编码过程中会根据是否使用了WPP来决定是否唤醒工作线程来调用processRow处理一行


二、线程数目

1. FrameEncoder 个数

        if (!p->bEnableWavefront)
            p->frameNumThreads = X265_MIN3(cpuCount, (rows + 1) / 2, X265_MAX_FRAME_THREADS);
        else if (cpuCount >= 32)
            p->frameNumThreads = (p->sourceHeight > 2000) ? 8 : 6; // dual-socket 10-core IvyBridge or higher
        else if (cpuCount >= 16)
            p->frameNumThreads = 5; // 8 HT cores, or dual socket
        else if (cpuCount >= 8)
            p->frameNumThreads = 3; // 4 HT cores
        else if (cpuCount >= 4)
            p->frameNumThreads = 2; // Dual or Quad core
        else
            p->frameNumThreads = 1;

2. ThreadPool个数

    for (int i = 0; i < numNumaNodes + 1; i++)
    {
        if (threadsPerPool[i])
            numPools += (threadsPerPool[i] + MAX_POOL_THREADS - 1) / MAX_POOL_THREADS;
    }//即线程池个数为CPU个数

    if (numPools > p->frameNumThreads)
    { 
        numPools = X265_MAX(p->frameNumThreads / 2, 1);
    }//且最大为FrameEncoder 个数的一半

3. 线程池中的JobProvider个数

  int maxProviders = (p->frameNumThreads + numPools - 1) / numPools + 1; /* +1 is Lookahead, always assigned to threadpool 0 */

因为JobProvider只有两种FrameEncoder(派生自WaveFront )和Lookahead。Lookahead只在Encoder中有一个。

(p->frameNumThreads + numPools - 1) / numPools的意思是将FrameEncoder 平均分到numPools中,平分后的个数(可能某些pool会少1个)

因此,JobProvider个数就是平分的FrameEncoder 个数+Lookahead

4. 线程池中的线程数

int numThreads = X265_MIN(MAX_POOL_THREADS, threadsPerPool[node]);

就是CPU核心数


三、总结:
1. 编码器中有FrameEncoder个数的后台线程在等待并行编码,这些后台线程每次编码一帧。在编码一帧过程中,会根据WPP设置决定是否调用工作线程来一起处理一行。在编码每行过程中,再在不同的环节通过联合任务的方式来使用其它线程一起对帧数据分成并行单元编码。
2. lookahead没有后台线程,encode会随时唤醒工作线程来进行lookahead处理

猜你喜欢

转载自blog.csdn.net/strikedragon/article/details/81541607