2017-07-28 2112 views
3

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

旧的和新的API都非常缓慢地解码视频。

25 fps视频=每40ms 1帧。但是,我看到每帧需要70至120毫秒才能解码。这是一个文件翻译器,因此需要它比实时更快地运行

代码大纲如下。任何人有关于如何提高解码速度的任何想法?还有一些关于已弃用的avcodec_decode_video2()缓慢的帖子;这些都没有解决。新的API不跑得更快......

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 

一些输出上酷睿双核运行3.2 GHz的32位元的CentOS

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版本

测试6.

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 
+0

你是否在同一个线程上抓包,解码帧,缩放和编码? – WLGfx

+0

一个线程用TS数据包填充一个队列,这在代码中没有显示。第二个线程使用AVIO提供read_frame,读取帧,解码并编码。但真正的问题在于,当一帧画面时,解码器需要很长时间。 – Danny

+0

你好,丹尼!现在我面临着解码ffmpeg缓慢的问题。我很好奇你是否找到了解决方案?如果是这样,请让我知道。谢谢 –

回答

-1

我发现迄今为止最好的解决方案是回到avcodec_decode_video2()并购买更好的硬件...

+0

谢谢,但它没有任何意义。 CPU足够快 - 可以使用VLC(使用ffmpeg解码器,对吧?)以全帧速播放视频。所以这是我*配置或使用解码器的一些问题...... – Danny

0

如果您仍在寻求帮助。

根据视频的像素格式,VLC可以使用GPU对其进行解码。为了确保您使用GPU-Z(仅适用于Windows,有类似的Linux工具)来测量视频加载引擎。 如果是这样,您可能需要检查您的库是否支持GPU编码/解码。