1 搭建 ffmpeg 环境(windows下)
1 下载
点击这里下载FFMPEG的库,里面包含:
- Static :静态库版本
- Shared:动态库版本
- Dev:提供给开发者用的lib文件
如果只要ffmpeg的库就只需要下载 Shared 和 Dev(使用方法见下一步)
如果想在终端命令下执行ffmpeg就下载 Static(下载完毕后值需要将该目录加入环境变量即可使用 ffmpeg 终端命令);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XROq9KOr-1609573256270)(http://www.tamray.cn/wp-content/uploads/2020/05/wp_editor_md_e8205364e111efa8c7696f864d1505d9.jpg)]
2 测试(windows Qt环境)
-
解压下载的文件
-
将 Shared/bin 文件夹中的 dll 文件,复制到当前qt工程debug文件中(或者将dll所在目录添加至环境变量,重启生效)
# 该目录下的dll文件 E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-shared\bin
-
创建Qt的.pro文件中链接库文件(在 Dev/lib 文件夹下)
INCLUDEPATH += E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\include LIBS += E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avcodec.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avdevice.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avfilter.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avformat.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\avutil.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\postproc.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\swresample.lib \ E:\.ffmpeg\ffmpeg-20200515-b18fd2b-win64-dev\lib\swscale.lib
-
测试代码
// 由于 FFMPEG 是 C库,但编译的时候使用的C++的编译器编译, // 因此这里需要加上extern "C",否则会提示各种未定义 extern "C" { #include "libavdevice/avdevice.h" #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> #include <libavutil/imgutils.h> #include <libavutil/opt.h> #include <libavutil/mathematics.h> #include <libavutil/samplefmt.h> } int main() { std::cout << "Test FFmpeg!" << std::endl; av_register_all(); unsigned version = avcodec_version(); std::cout << "version :" << version << std::endl; }
2 搭建 ffmpeg 环境(unbutu16.04下)
2.1 编译
-
先安装相关工具
sudo apt-get install -y autoconf automake build-essential git libass-dev libfreetype6-dev libsdl2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev sudo apt-get install -y nasam yasm cmake mercurial
-
下载 ffmpeg
-
解压下载文件
tar jxvf ffmpeg-4.2.tar.bz2
-
进入解压目录并执行:
cd ffmpeg-4.2/ ./configure --enable-shared --prefix=/usr/local/ffmpeg
注:选项
--prefix
是安装目录,这里是安装到/usr/local/ffmpeg;--enable-shared
是指定生成动态库,默认是静态库,静态库不方便后续开发; -
编译安装
sudo make -j8 sudo make install
-
添加环境变量
在~/.bashrc
文件中添加以下内容,执行source ~/.bashrc
生效:export FFMPEG_HOME=/usr/local/ffmpeg export PATH=$FFMPEG_HOME/bin:$PATH
如果没有安装pkgconfig先自行安装,然后添加环境比变量
PKG_CONFIG_PATH
:export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/ffmpeg/lib/pkgconfig:/usr/loal/lib
-
添加ffmpeg库的链接
在 /etc/ld.so.conf 中 末尾添加/usr/local/ffmpeg/lib
即可,执行:sudo ldconfig
2.2 测试(在 Qt 中测试播放视频)
-
在 .pro 添加库路径:
INCLUDEPATH += /usr/local/ffmpeg/include LIBS += -L /usr/local/ffmpeg/lib -lswscale -lswresample -lavformat -lavdevice -lavcodec -lavutil -lavfilter -lm
-
添加头文件:
// 源代码是由 C 编写的 extern "C"{ #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/avutil.h> #include <libswresample/swresample.h> #include <libavutil/opt.h> #include <libswscale/swscale.h> #include <libavutil/imgutils.h> }
-
创建两个控件:
label
- QLabelpushButton
- QPushButton其中,label 用于显示,pushButton 用于点击开始;
-
c 代码
:::details
void Delay(int msec) // 延时函数
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
void MainWindow::on_pushButton_clicked() // 按键的槽函数
{
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameRGB;
unsigned char *out_buffer;
AVPacket *packet;
int ret, got_picture;
struct SwsContext *img_convert_ctx;
// char filepath[] = "E:\\media\\1.avi";
char filepath[] = "/home/tianru/video/2020-4-10/3.mp4";
//初始化编解码库
av_register_all();//创建AVFormatContext对象,与码流相关的结构。
pFormatCtx = avformat_alloc_context();
//初始化pFormatCtx结构
if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0){
printf("Couldn't open input stream.\n");
return ;
}
//获取音视频流数据信息
if (avformat_find_stream_info(pFormatCtx, NULL) < 0){
printf("Couldn't find stream information.\n");
return ;
}
videoindex = -1;
//nb_streams视音频流的个数,这里当查找到视频流时就中断了。
for (i = 0; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
videoindex = i;
break;
}
if (videoindex == -1){
printf("Didn't find a video stream.\n");
return ;
}
//获取视频流编码结构
pCodecCtx = pFormatCtx->streams[videoindex]->codec;
//查找解码器
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL){
printf("Codec not found.\n");
return ;
}
//用于初始化pCodecCtx结构
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
printf("Could not open codec.\n");
return ;
}
//创建帧结构,此函数仅分配基本结构空间,图像数据空间需通过av_malloc分配
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
//创建动态内存,创建存储图像数据的空间
//av_image_get_buffer_size获取一帧图像需要的大小
out_buffer = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1));
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer,
AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1);
packet = (AVPacket *)av_malloc(sizeof(AVPacket));
//Output Info-----------------------------
printf("--------------- File Information ----------------\n");
//此函数打印输入或输出的详细信息
av_dump_format(pFormatCtx, 0, filepath, 0);
printf("-------------------------------------------------\n");
//初始化img_convert_ctx结构
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
//av_read_frame读取一帧未解码的数据
while (av_read_frame(pFormatCtx, packet) >= 0){
//如果是视频数据
if (packet->stream_index == videoindex){
//解码一帧视频数据
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0){
printf("Decode Error.\n");
return ;
}
if (got_picture){
sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameRGB->data, pFrameRGB->linesize);
QImage img((uchar*)pFrameRGB->data[0],pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
ui->label->setPixmap(QPixmap::fromImage(img));
Delay(10);
}
}
av_free_packet(packet);
}
sws_freeContext(img_convert_ctx);
av_frame_free(&pFrameRGB);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
}
:::