ffmpeg关于视频前几秒黑屏的问题解决

时间:2022-10-06 01:00:57

关于音频播放器视频前两秒黑屏的解决,及QtAV和ffmpeg的环境搭建(软件包可以找李青璠提供,也可以自己下)

首先我们可以参考下面两个博客进行ffmpeg的搭建,第一个博客的问题可以在第二个博客里寻求方法解决。其中第一个博客ffmpeg的编译命令应该改成./configure --enable-shared --prefix=/usr/local/ffmpeg,如果需要安装yasm,那么编译语句

ffmpeg关于视频前几秒黑屏的问题解决

中的./configure可以改成./configure --prefix=/usr/local/yasm (--prefix的作用是指定路径,而--enable-shared是指定生成动态库)

(1条消息) Ubuntu安装ffmpeg_大笨钟47的博客-CSDN博客_ffmpeg ubuntu安装

(1条消息) linux上如何安装QtAV插件?(环境:ubuntu18.04,qt5.12.3,ffmpeg-4.1.3)_ResttaPersevere的博客-CSDN博客

这里我们安装好了ffmpeg.下面我们进行QtAV的编译安装,可以直接点击下面的网址,Build QtAV · wang-bin/QtAV Wiki · GitHub我按他的推荐选了一种方式,大家可以参考如下;

sudo apt-get install libopenal-dev libpulse-dev libva-dev libxv-dev libass-dev libegl1-mesa-dev

cp -r /usr/local/ffmpeg/include/* /home/liqingfan/Qt5.12.10/5.12.10/gcc_64/include/

cp -r /usr/local/ffmpeg/lib/* /home/liqingfan/Qt5.12.10/5.12.10/gcc_64/lib/

下面就可以使用QtCreator With MSVCQtCreator will detect VC compiler if it is installed. So it's easy to build in QtCreator这样这个环境就搭建完成了。用QtCreator选中QtAV.pro进行编译即可

下面描述一下问题的解决过程和结论,

首先

在编译后的文件目录下会找到:sdk_install.sh

赋予sdk_install.sh 执行权限,命令 chmod 777 sdk_install.sh

安装qtav,命令:./ sdk_install.sh

并且把/home/liqingfan/ffmpegAndQtav/build-QtAV-Desktop_Qt_5_12_10_GCC_64bit-Debug/lib_linux_x86_64/目录下的文件放到/home/liqingfan/ffmpegAndQtav/203ideoclient/libs/下就可以正常的编译这个视频项目啦

后面是关于卡顿问题的分析:

我们随意打开一个视频,可以看到日志有下面几句非常的可疑。

"AVClock started!!!!!!!!"

"no frame could be decompressed: Error number 1390 occurred 0/1390"

"invalid video frame from decoder. undecoded data size: 0"

"no frame could be decompressed: Error number 898 occurred 0/898"

"invalid video frame from decoder. undecoded data size: 0"

"no frame could be decompressed: Error number 490 occurred 0/490"

"invalid video frame from decoder. undecoded data size: 0"

"setInSize => calculating aspect ratio from converted input data(1.777778)"

QtAV::VideoFormat(pixelFormat: 15 "yuvj420p" alpha: false, channels: 3, planes: 3, bpc: 8, bpp: 12/12 -8-8-8)

"pixel format changed: => yuvj420p 15"

material changed: "gl material 16to8bit: 0, planar: 0, has alpha: 0, 2d texture: 0, 2nd plane rg: 0, xyz: 0" => "gl material 16to8bit: 0, planar: 1, has alpha: 0, 2d texture: 1,

可以看出前面几面的视频帧有问题,通过向上去找log,invalid video frame from decoder. undecoded data size: 0"证明了猜想

通过log定位在了解码器。bool VideoDecoderFFmpegBase::decode(const Packet &packet);

这是我们再分析视频合成的视频,这里分析工具用的是

ffmpeg关于视频前几秒黑屏的问题解决

我们把视频拖进去看一下,

ffmpeg关于视频前几秒黑屏的问题解决

明显第一帧和其他是不一项的。从此入手,我的解决方案就是跳过有问题的帧。于是对解码这块的源码做了如下改进。改进的函数是bool VideoDecoderFFmpegBase::decode(const Packet &packet);

bool VideoDecoderFFmpegBase::decode(const Packet &packet)

{

if (!isAvailable())

return false;

DPTR_D(VideoDecoderFFmpegBase);

// some decoders might need other fields like flags&AV_PKT_FLAG_KEY

// const AVPacket*: ffmpeg >= 1.0. no libav

int got_frame_ptr = 0;

int ret = 0;

if (packet.isEOF()) {

AVPacket eofpkt;

av_init_packet(&eofpkt);

eofpkt.data = NULL;

eofpkt.size = 0;

ret = avcodec_decode_video2(d.codec_ctx, d.frame, &got_frame_ptr, &eofpkt);

} else {

ret = avcodec_decode_video2(d.codec_ctx, d.frame, &got_frame_ptr, (AVPacket*)packet.asAVPacket());

}

//qDebug("pic_type=%c", av_get_picture_type_char(d.frame->pict_type));

d.undecoded_size = qMin(packet.data.size() - ret, packet.data.size());

if (ret < 0) {

//qWarning("[VideoDecoderFFmpegBase] %s", av_err2str(ret));

return false;

}

if (!got_frame_ptr) {

//liqingfan add for fix delay:begin

while(!got_frame_ptr){

if (packet.isEOF()) {

AVPacket eofpkt;

av_init_packet(&eofpkt);

eofpkt.data = NULL;

eofpkt.size = 0;

ret = avcodec_decode_video2(d.codec_ctx, d.frame, &got_frame_ptr, &eofpkt);

if (ret < 0) {

//qWarning("[VideoDecoderFFmpegBase] %s", av_err2str(ret));

return false;

}

if(!got_frame_ptr){

return !packet.isEOF();

}

} else {

ret = avcodec_decode_video2(d.codec_ctx, d.frame, &got_frame_ptr, (AVPacket*)packet.asAVPacket());

if (ret < 0) {

//qWarning("[VideoDecoderFFmpegBase] %s", av_err2str(ret));

return false;

}

}

}

//liqingfan add for fix delay:end

qWarning("no frame could be decompressed: %s %d/%d", av_err2str(ret), d.undecoded_size, packet.data.size());

return !packet.isEOF();

}

if (!d.codec_ctx->width || !d.codec_ctx->height)

return false;

//qDebug("codec %dx%d, frame %dx%d", d.codec_ctx->width, d.codec_ctx->height, d.frame->width, d.frame->height);

d.width = d.frame->width; // TODO: remove? used in hwdec

d.height = d.frame->height;

//avcodec_align_dimensions2(d.codec_ctx, &d.width_align, &d.height_align, aligns);

return true;

}