首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FFMPEG解码太慢(avcodec_send_packet() / avcodec_receive_frame())

FFMPEG解码太慢(avcodec_send_packet() / avcodec_receive_frame())
EN

Stack Overflow用户
提问于 2017-07-28 01:42:37
回答 2查看 3.6K关注 0票数 8

我使用ffmpeg库在MPEG传输流中解码、缩放和重新编码视频。我刚刚从源代码重新编译到v3.3.2,并从旧的avcodec_decode_video2() API更改为新的发送/接收API。

新旧API对视频的解码速度都非常慢。

25 fps视频=每40毫秒一帧。然而,我看到每帧70到120毫秒的解码。这是一个文件翻译器,所以需要它运行比实时更快。

代码大纲如下。有人对如何提高解码速度有什么想法吗?还有其他关于不推荐的avcodec_decode_video2()速度慢的帖子;这些都没有得到解决。新API不能运行得更快..。

代码语言:javascript
复制
gettimeofday(&tv1, NULL);
int rc = av_read_frame(pFormatContext, pESPacket);
gettimeofday(&tv2, NULL);

int ret = avcodec_send_packet(pDecoderContext, pESPacket);
if (ret < 0)
    continue;

ret = avcodec_receive_frame(pDecoderContext, pFrameDec);
if (ret != 0)
{
    printf("avcodec_receive_frame error: %d\n", ret);
    continue;
}
gettimeofday(&tv3, 0);

u_long twoMinusOne   = (tv2.tv_sec - tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec;
u_long threeMinusTwo = (tv3.tv_sec - tv2.tv_sec) * 1000000 + tv3.tv_usec - tv2.tv_usec;

size_t pktSize = mPacketQueue.getTsPktListSize();
printf("  DECODE ReadFrame %lu usec, DecodeVideo %lu usec. mTsPacketList %u items\n", twoMinusOne, threeMinusTwo, pktSize);

transcodeFrame(pFrameDec);

// Scale and re-encode //
-- call avscale to downsample
-- call avcodec_encode_video2() to encode

一些输出

代码语言:javascript
复制
DECODE ReadFrame 6 usec, DecodeVideo 154273 usec.
Dump mpFrameEnc with DateTime: 
  AVFrame Info frame 720 X 406. PTS = 305700353  PKT_PTS = 305700353 Linesize[0]=720. Linesize[1]=360. Linesize[2]=360.   
Time taken to ENCODE video frame = 3685 usec. Scaling time 4 usec

DECODE ReadFrame 8 usec, DecodeVideo 128203 usec.
Time taken to ENCODE video frame = 3724 usec. Scaling time 3 usec

DECODE ReadFrame 8 usec, DecodeVideo 69321 usec.
Time taken to ENCODE video frame = 3577 usec. Scaling time 3 usec

FFMPEG版本

运行在core2 Duo3.2 GHz,32位Centos 6上的测试.

代码语言:javascript
复制
bin/ffmpeg
ffmpeg version 3.3.2 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-11)
  configuration: --prefix=/mnt/swdevel/DVStor/source_build/ext/ffmpeg-build --libdir=/mnt/swdevel/DVStor/source_build/ext/ffmpeg-build/lib3p_build --shlibdir=/mnt/swdevel/DVStor/source_build/ext/ffmpeg-build/lib3p_build --disable-static --enable-shared --disable-cuda --disable-cuvid --disable-nvenc --enable-libx264 --enable-gpl --extra-cflags=-I/usr/local/include/libx264
  libavutil      55. 58.100 / 55. 58.100
  libavcodec     57. 89.100 / 57. 89.100
  libavformat    57. 71.100 / 57. 71.100
  libavdevice    57.  6.100 / 57.  6.100
  libavfilter     6. 82.100 /  6. 82.100
  libswscale      4.  6.100 /  4.  6.100
  libswresample   2.  7.100 /  2.  7.100
  libpostproc    54.  5.100 / 54.  5.100
Hyper fast Audio and Video encoder
EN

回答 2

Stack Overflow用户

发布于 2021-09-02 07:22:44

供今后参考的一种可能的解决办法如下:

为解码器启用多线程。默认情况下,解码器只使用一个线程,根据解码器的不同,多线程可以大大加快解码速度。

假设您有AVFormatContext *format_ctx,一个匹配的编解码器AVCodec* codecAVCodecContext* codec_ctx (使用avcodec_alloc_context3分配)。

打开编解码器上下文之前(使用avcodec_open2),您可以配置多线程。检查编解码器的能力,以决定可以使用哪种多线程:

代码语言:javascript
复制
// set codec to automatically determine how many threads suits best for the decoding job
codec_ctx->thread_count = 0;

if (codec->capabilities | AV_CODEC_CAP_FRAME_THREADS)
   codec_ctx->thread_type = FF_THREAD_FRAME;
else if (codec->capabilities | AV_CODEC_CAP_SLICE_THREADS)
   codec_ctx->thread_type = FF_THREAD_SLICE;
else
   codec_ctx->thread_count = 1; //don't use multithreading
票数 4
EN

Stack Overflow用户

发布于 2018-01-09 10:35:09

以防你还在寻求帮助。

根据视频的像素格式,VLC可以使用GPU对其进行解码。为了确保您使用GPU(只在windows中工作,也有类似的Linux工具)来测量视频负载引擎。如果是这样的话,您可能需要检查您的libs是否支持GPU编码/解码。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45363566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档