前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Twitch如何实现转码比FFmpeg性能提升65%?(下)

Twitch如何实现转码比FFmpeg性能提升65%?(下)

作者头像
LiveVideoStack
发布2021-09-02 12:10:45
1.3K0
发布2021-09-02 12:10:45
举报
文章被收录于专栏:音视频技术

文 / Jeff Gong, Sahil Dhanju, Chih-Chiang Lu, Yueshi Shen

编者按:超过220万创作者在Twitch发布海量的视频,这对实时转码业务造成了巨大压力,Twitch团队通过优化多线程的转码服务以及Intel QuickSync的支持,实现了比FFmepg性能提升65%,并降低80%总体拥有成本。Twitch团队通过博客介绍了这一实现,LiveVideoStack对本文进行了摘译,点击『阅读原文』访问英文博客。同时,Yueshi Shen将在12月8-9日的ArchSummit 2017北京大会上详细介绍实现过程。

FFmpeg的1-in-N-out流水线。为什么它无法处理前面讨论的技术问题?

FFmpeg如何以编程方式处理需要单个输入来生成多个转码和(或)转封装输出的实例? 我们可以通过直接剖析FFmpeg最新3.3版的源代码,来了解其线程模型和转码流水线。

在顶层ffmpeg.c文件中,transcode()函数(第4544行)不断循环并重复调用transcode_step()函数(第4478行),直到其输入信息被完全处理,或用户中断执行为止。Transcode_step()函数封装了主要的流水线,并在许多其他即时步骤之间编排诸如文件I / O、过滤、解码和编码等动作。

在初始设置阶段,init_input_threads()(第4020行)函数被调用,并将根据输入文件的数量,产生一些新的线程来处理这些输入。

代码语言:javascript
复制
if (nb_input_files == 1) {
  return 0;
}
for (i = 0; i < nb_input_files; i++) {
  ...
  ret = av_thread_message_queue_alloc(&f->in_thread_queue, f->thread_queue_size, sizeof(AVPacket));    // line 4033
}

在第4033行中(如上所示),我们看到产生的线程数量完全由输入的数量决定。也就是说,这意味着FFmpeg将只使用一个线程来处理1-in-N-out的场景。

在get_input_packet()函数(第4055行)中,只有当输入文件的数量大于1时,才会调用多线程伴随函数get_input_packet_mt()(第4047行)。get_input_packet_mt()函数可以以非阻塞的方式从消息队列中读取输入帧。否则的话,我们需要使用av_read_frame()(第4072行)来每次读取并处理一个帧。

代码语言:javascript
复制
#if HAVE_PTHREADS
  if (nb_input_files > 1) {
     get_input_packet_mt(f, pkt);
  }
#endif
  return av_read_frame(f->ctx, pkt);

如果我们跟踪帧数据一直到流水线结束,我们发现它进入到process_input_packet()函数(行2591)中,该函数对帧数据进行解码并通过所有适用的过滤器进行处理。时间戳校准和字幕处理的工作也在这个函数中进行。最后,在函数返回之前,已解码的帧被复制到每个相关的输出流。

代码语言:javascript
复制
for (i = 0; pkt && i < nb_output_streams; i++) {
  ...  // check constraints
  do_streamcopy(ist, ost, pkt);    // line 2756
}

最后,transcode_step()函数调用reap_filters()函数(第1424行)来循环遍历每个输出流。reap_filters()函数的for循环负责收集缓冲区中待处理的帧,并将这些帧进行解码,然后封装到一个输出文件中。

代码语言:javascript
复制
// reap_filters line 1423
for (i = 0; i < nb_output_streams; i++) { // loop through all output streams
  ...  // initialize contexts and files
  OutputStream *ost = output_streams[i];
  AVFilterContext *filter = ost->filter->filter;
  AVFrame filtered_frame = ost->filtered_frame;
  while (1) { // process the video/audio frame for one output stream
     ...  // frame is not already complete
     ret = av_buffersink_get_frame_flags(filter, filtered_frame, …);
     if (ret < 0) {
        ...  // handle errors and logs
        break;
     }
     switch (av_buffersink_get_type(filter)) {
     case AVMEDIA_TYPE_VIDEO:
        do_video_out(of, ost, filtered_frame, float_pts);
     case AVMEDIA_TYPE_AUDIO:
        do_audio_out(of, ost, filtered_frame);
     }
     ...
}

通过跟踪这条流水线,我们知道这些帧是如何通过单个线程的上下文顺序进行处理的,从中我们能看到一些冗余。我们可以得出结论,既然1-in-N-out的转码流模型对我们来说是最有价值的,那么FFmpeg仅使用单线程来输出结果则可能并不理想。FFmpeg文档也建议我们在实际用例中,并行地启动多个FFmpeg实例或将更有意义。在这里,我们关键的一点认识是,既然此工具(FFmpeg)没有提供多线程功能,它就无法满足Twitch流媒体服务的严格需求,那么我们就无法随心所欲地使用它。

基准测试

TwitchTranscoder是我们为解决前面讨论的技术问题而开发的内部软件。它已被广泛运用于我们的生产中,每天24小时地处理数万个并发直播流。

为了确定TwitchTranscoder每天在转码任务上的表现是否会优于FFmpeg,我们进行了一系列基本的基准测试。在我们的测试中,我们对两个工具使用相同的Twitch直播流以及有相同预设、配置文件、比特率和其他标志的1080p60视频文件。每个视频源都被转码成我们通常使用的典型的720p60,720p30,480p30,360p30和160p30。

我们的假设是,FFmpeg对于输入文件的转码速度比TwitchTranscoder要慢,甚至可能无法跟上直播的速度。

图9,10和11中的结果比较了TwitchTranscoder与FFmpeg的执行时间。实验表明,即使在我们处理相同及更多(除了上面指定的栈之外,还提供仅音频转码,缩略图生成等等)任务的情况下,我们的转码器对于离线转码一直有绝对优势。

对于输出单个版本的720p60,FFmpeg稍快,这是因为TwitchTranscoder要处理如上所述的更多任务。当版本的数量增加时,TwitchTranscoder的多线程模型表现出更大的优势,这些优势帮助它超越了FFmpeg。观察Twitch完整的ABR梯度,与FFmpeg相比,TwitchTranscoder节省了65%的执行时间。

图9:TwitchTranscoder与FFmpeg转码时间比较,实验1

图10:TwitchTranscoder与FFmpeg转码时间比较,实验2

图11:TwitchTranscoder与FFmpeg转码时间比较,实验2

我们通过比较在出问题前,一台机器上最多能够运行多少个FFmpeg的并行实例来进行实时流转码测试。这里可能发生的问题包括帧丢失、视频伪影等。在我们的生产服务器中,我们能够支持多个通道同时进行转码,同时,更多的通道被转封装。不幸的是,运行多个FFmpeg实例会导致一系列影响转码输出的错误,并且需要更高的CPU利用率(请参见图12中的屏幕截图)。

图12:FFmpeg运行多个实例时的错误消息

结论

在本文中,我们将FFmpeg作为实时流RTMP- to-HLS的转码器进行了研究,并提供了有关如何操作该工具的信息。该解决方案部署起来很简单,但有一些技术问题值得注意,比如段错位、不必要的性能损失,以及缺乏支持我们产品功能的灵活性等。因此,我们实现了自己内部的转码器软件栈TwitchTranscoder,它运行在一个定制的线程模型中,并可以在一个进程中输出N个处理版本。

LiveVideoStack招募全职技术编辑和社区编辑

LiveVideoStack是专注在音视频、多媒体开发的技术社区,通过传播最新技术探索与应用实践,帮助技术人员成长,解决企业应用场景中的技术难题。如果你有意为音视频、多媒体开发领域发展做出贡献,欢迎成为LiveVideoStack社区编辑的一员。你可以翻译、投稿、采访、提供内容线索等。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 LiveVideoStack 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云直播
云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档