FFMPEG挂在缓冲区填充C 上

FFmpeg hangs on buffer fill c++

本文关键字:填充 缓冲区 FFMPEG      更新时间:2023-10-16

我正在使用FFMPEG从RTSP流中处理一堆帧。我最终在这些框架上进行了很多处理,这意味着我并不总是在实时实时拉动。如果缓冲区满足,则过程将悬挂。我想知道以下解决方案之一是否可行/解决了问题,如果是这样,我将如何使用FFMPEG库实施它:

1)如果我到达悬挂的点,是否有办法清除缓冲区?(我可以确定何时悬挂,我只是不知道该怎么做)。

2)有没有办法使缓冲区覆盖旧数据,并且始终读取最新数据?如果我失去框架对我来说没关系。

3)我已经发现我可以使用以下方式使缓冲区较大:av_dict_set(&avd, "buffer_size", "655360", 0);。这可能是一个解决方案,但我不知道它需要多大/小,因为我不知道该流将发布视频的时间多长时间?

4)这只是我需要与ffmpeg人一起提出的错误吗?

5)我没有考虑过的其他东西?

while(av_read_frame(context, &(packet)) >= 0 && fcount < fps*SECONDS) {
    clock_t start, end;
    int ret = avcodec_send_packet(codec_context, packet);
    if(!(packet->stream_index == video_stream_index)) {
      continue;
    }
    if (ret == AVERROR(EAGAIN) || ret == AVERROR(EINVAL)) {
      continue;
    } else if (ret < 0) {
      cerr << "Error while decoding frame " << fcount << endl;
      exit(1);
    }
    ret = avcodec_receive_frame(codec_context, frame);
    if (ret == AVERROR(EAGAIN) || ret == AVERROR(EINVAL)) {
      continue;
    } else if (ret < 0) {
      cerr << "Error while decoding frame " << fcount << endl;
      exit(1);
    }
    sws_scale(img_convert_ctx, frame->data, frame->linesize, 0,
              codec_context->height, picture_rgb->data, picture_rgb->linesize);
    if(!frame) {
      cerr << "Could not allocate video frame" << endl;
      exit(1);
    }
    if(codec_context == NULL) {
      cerr << "Cannot initialize the conversion context!" << endl;
      exit(1);
    }
    // Do something with the frame here
    fcount++;
    av_packet_unref(&(packet));
}

我添加了导致程序悬挂的代码。

您可以尝试进行多线程。每个帧都通过单独的线程处理(使用线程池)。

如果您需要顺序完成顺序,则必须使用一些结构(队列?)来在无序的线程完成时间内订单。

缓冲区的大小是套接字选项,如果缓冲区已满,则在引擎盖下方的ffmpeg下方可能会阻止其套接字RECV调用。查看了FFMPEG代码后,似乎在纯UDP流上有圆形缓冲区的FIFO尺寸选项,但对于RTP流而言,这是禁用的。

为了确保缓冲区永不完整,我将在一个线程中运行所有PKT RECV和框架解码操作,然后将其馈送到我自己的线程安全的圆形缓冲区。RASPI应该能够跟上解码的步伐,但是如果没有,我会研究硬件辅助解码。关键是,确保您的委托和解码保持实时速度。您可以在其他线程中处理所有调整大小,处理和框架写作,并相应地设置圆形缓冲区大小以处理溢出。

看来您正在尝试实时编写原始框架,因此一个警告:显然,FPS和框架尺寸在所有速度的速度中都起着作用,但是我怀疑您会看到很多掉落的帧。

这应该是解决问题的直接解决方案。使用FFMPEG

将流转换为帧时进行缓冲

您应该尝试的是记录流并将其缓存到存储中,然后将其转换。您还可以尝试的是将缓冲区缓存到磁盘上并重新填充FFMPEG过程。

一个黑客解决方案是将RTSP流转换为UDP,实际上很容易AF,然后使用ffmpeg内部缓冲区选项,可用于UDP,该选项可用于RTSP