做avcodec_receive_frame和avcodec_send_packet块/如何设计ffmpeg解码循环?

问题描述

我正在考虑如何设计一个循环,该循环从Internet读取帧,馈送到ffmpeg解码器,然后从ffmpeg接收以发送到渲染器。

请考虑以下伪代码循环:

while true {
    auto packet = receive_packet_from_network();
    avcodec_send_packet(packet);
    auto frame = alloc_empty_frame();
    int r = avcodec_receive_frame(&frame);
    if (r==0) {
        send_to_render(frame);
    }
}

avcodec_send_packetavcodec_receive_frame块或ffmpeg是否具有内部线程?我担心这个循环,因为它等待来自网络的数据包,因此有一些延迟。我想改成这样:

//thread 1
while true {
    auto packet = receive_packet_from_network();
    avcodec_send_packet(packet);
}
//thread 2
while true {
    auto frame = alloc_empty_frame();
    int r = avcodec_receive_frame(&frame);
    if (r==0) {
        send_to_render(frame);
    }
}

但是,现在,如果avcodec_receive_frame没有阻塞,则此循环将运行得太快,每秒百万次。

那么,我应该如何以最有效的方式设计ffmpeg中数据包的发送/接收?我不想像在thread2循环中那样花费cpu周期。

解决方法

事件驱动,例如:

while true {
auto packet = receive_packet_from_network();
std::async(std::launch::async,[packet]() {
    avcodec_send_packet(packet);
    auto frame = alloc_empty_frame();
    do{
       int r = avcodec_receive_frame(&frame);
       if (r == 0) {
        send_to_render(frame);
      }
    }while(r == 0)
   
});}