我编写了一个程序,读取n个视频作为输入,将这些视频绘制到GLFW窗口,最后将其编码为单个视频输出.问题是,每个视频的帧可能不同,这取决于用户的输入.

例如:用户可以放入FPS为30和59的两个视频,并且可能需要23,797个输出.问题是这些视频彼此不同步,因此在输出上我们可以看到输入视频要么更快要么更慢.

每个视频的持续时间也取决于输入.例如,根据前面的示例,第一个输入可能是30秒,第二个可能是13秒,而输出是50秒.

我主要阅读类似于移动的PNG的帧,而不是稳定的视频,因为没有IFRAME和BFRAME.这只是我从GLFW窗口获得的数据.

例如,假设我们给出一个视频作为输入,它的FPS为30,持续时间为30,而我们的输出具有FPS为23.797,持续时间为30.我有2个函数的skip_framewait_frame,它们分别读取一个帧两次,因此我们跳过一个帧,或者不在该迭代中读取该帧.这些函数的使用取决于具体情况,无论是输出输入还是输出输入.

下面是我的代码的大致外观:

while(current_time < output_duration){
   for(auto input_video: all_inputs){
      for(int i = 0; i < amount_to_read_from_input(); i++){
         frame = input_video.read_frame();
      }
   }
   
   GLFW_window.draw_to_screen(frame);

   encoder.encode_one_video_frame(GLFW_window.read_window());
}

基本上,skip_framewait_frame都在amount_to_read_from_input()内,分别返回2或0.

到目前为止,我已经try 将输入和输出的持续时间与fps相乘.然后得到它们的减法结果.从前面的例子来看,我们得到900-714=186. 然后我将结果除以输出fps,如下所示:714/186=3.8.这意味着我必须每3.8次迭代跳过一帧.(我每3次迭代跳过一帧,并将剩余的0.8保存到下一次ITER.)

但它还是落后了一两秒钟.(就像30秒的输出在29秒结束.)并且音频不同步.Ffmpeg处理我的音频,所以这部分没有错误.

我也看到了this question,但我认为我不能在这里使用ffmpeg的函数,因为我从glfw窗口读取数据,它归结为我的算法.

问题是what is the math here

我可以做些什么来确保这些帧稳定在几乎所有的输入/输出组合上?

推荐答案

对于那些在类似情况下苦苦挣扎的人:问题在于我的编码器的时基:我将其作为int而不是格式化的AVRational传递.我的fps变量是一个浮点数,当我将其传递给编码器时,它会将其舍入为最接近的整数.举个例子,我超过了23.797,四舍五入到了23.所以,无论我写什么算法,它总是错误的,因为我的算法被连接到计算23.797,而ffmpeg试图编码23.

time_base = (AVRational){ 1, fps};更改为time_base = av_d2q(1 / STREAM_FRAME_RATE, std::numeric_limits<int>::max());会导致我的所有算法都能按预期工作.

我仍然不确定是否有一个计算这一点的标准,我的计算方法对我来说很好.

C++相关问答推荐

海湾合作委员会是否保证大小匹配的访问?

Pure Win32 C(++)-除了替换控件的窗口程序之外,还有其他方法可以在输入时禁用按钮吗?

在C中将通用字符名称转换为UTF-8

C中的指针增量和减量(*--*++p)

在C语言中,是否可以使枚举数向后计数?

如何在ASM中访问C struct 成员

GTK3按钮信号错误

这个计算C中阶乘的函数正确吗?

在另一个函数中使用realloc和指针指向指针

C:在编译时构建和使用字符串文字的预处理器宏?

如何仅使用软件重新初始化STM32微控制器中的USB枚举?

我不知道为什么它不能正常工作,我用了get()和fget(),结果是一样的

程序对大输入给出错误答案

变量值不正确的问题

我正在使用 klib 库 我可以使用 (khash) KHASH_SET_INIT_INT64() 负值作为键.因为我在头文件中看到它使用 unsigned long int

一元运算符

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

free后内存泄漏?

获取 struct 中匿名 struct 的大小

如何使用 raylib 显示数组中的图像