|
一、前言 在前几篇文章当中,有提到过用源码去搭建ffmpeg的命令环境开发,为啥要这样去搭建环境,为什么不用直接用下面这个命令在ubuntu下安装多快,简单又方便: sudo apt install ffmpeg今天分享ffmepg第五弹:ffmpeg+qt+SDL的真正开发环境,就要用源码安装的方式去在qt里面调用ffmpeg相关的库;还记得之前源码搭建创建的三个文件夹不: bin ffmpeg_sources ffmpeg_buildbin文件夹下是编译得到的二进制文件 txp@txp-virtual-machine:~/bin$ lsffmpeg ffplay ffprobe lame nasm ndisasm x264 ffmpeg_sources文件下是下载的各种库的源码: txp@txp-virtual-machine:~/ffmpeg_sources$ lsfdk-aac lame-3.100.tar.gz SDL2-2.0.14.tar.gz ffmpeg libvpx SVT-AV1 ffmpeg-4.2.1 nasm-2.14.02 x264 ffmpeg-4.2.1.tar.bz2 nasm-2.14.02.tar.bz2 x265_git ffmpeg-snapshot.tar.bz2 opus lame-3.100 SDL2-2.0.14 ffmpeg_build文件夹主要是ffmpeg的一些库文件,等下下面演示的模板就要调用ffmpeg相关的库: txp@txp-virtual-machine:~/ffmpeg_build/lib$ lscmake libmp3lame.a libSDL2.la libswscale.a libavcodec.a libmp3lame.la libSDL2main.a libvpx.a libavdevice.a libopus.a libSDL2main.la libx264.a libavfilter.a libopus.la libSDL2.so libx265.a libavformat.a libpostproc.a libSDL2_test.a pkgconfig libavutil.a libSDL2-2.0.so.0 libSDL2_test.la libfdk-aac.a libSDL2-2.0.so.0.14.0 libSvtAv1Enc.a libfdk-aac.la libSDL2.a libswresample.a 因为我已经搭建好了开发环境,从现在来看的话,如果你直接用命令去安装ffmpeg的话,到时候我们在qt的环境中去调用ffmpeg的库,至少到目前为止我暂时不知道去如何配置相关路径来调用ffmpeg的库;所以我们明白了这点,那么就撸起袖子肝就是。 二、 qt环境搭建玩过qt的朋友,对于这块应该比我熟悉多了;不过有可能有一些朋友可能没有接触过qt的话,为此我还是简单演示一下qt的安装步骤:
https://download.qt.io/archive/qt/5.12/5.12.10/
这里我直接把qt的源码包下载到samba服务共享文件下,当然你也可以直接在ubuntu下载:
然后我在share目录创建一个qt文件夹,用存放qt安装的地方,然后直接运行这个源码文件:
接着就会出现qt的安装界面:
最终qt就安装完成了,但是如果你运行qt执行失败的话(注意qtcreator的所放在的路线): txp@txp-virtual-machine:~/share/qt/Qt5.12.10/Tools/QtCreator/bin$ sudo ./qtcreatorGot keys from plugin meta data ("xcb") QFactoryLoader: FactoryLoader() checking directory path "/home/txp/share/qt/Qt5.12.10/Tools/QtCreator/bin/platforms" ...loaded library "/home/txp/share/qt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/libqxcb.so" loaded library "Xcursor" Segmentation fault (core dumped)
在这个脚本里面添加一句话:
然后接着再安装相关插件: sudo apt install --reinstall libxcb-xinerama0然后我们执行一下,就可以成功打开qt了:
还有一种方法直接打开qt,因为按照上面的这种方式打开的话,每次都要跑到这个目录去执行这条语句才行: txp@txp-virtual-machine:~/share/qt/Qt5.12.10/Tools/QtCreator/bin$sudo ./qtcreator 现在我们只要执行下面这条语句就不用这么麻烦了: sudo chown -R txp:txp ~/.config/然后你就可以像在windows环境下去直接打开这个软件就行:
现在我们打开刚才安装好的qt软件,来创建一个工程:
最终一个工程项目就建立好了:
我们可以看到两个文件,一个是以.pro结尾的qt工程管理配置文件,一个主源码文件,现在我们就简单使用ffmpeg库来打印ffmpeg的版本号:
CONFIG += console CONFIG -= app_bundle CONFIG -= qt SOURCES += \ main.c 现在我们要加入ffmpeg_build目录下的ffmpeg库文件: TEMPLATE = appCONFIG += console CONFIG -= app_bundle CONFIG -= qt SOURCES += \ main.c INCLUDEPATH += /home/txp/ffmpeg_build/include #LIBS += /home/txp/ffmpeg_build/lib/libSDL2.so LIBS += /home/txp/ffmpeg_build/lib/libavcodec.a \ /home/txp/ffmpeg_build/lib/libavdevice.a \ /home/txp/ffmpeg_build/lib/libavfilter.a \ /home/txp/ffmpeg_build/lib/libavformat.a \ /home/txp/ffmpeg_build/lib/libavutil.a \ /home/txp/ffmpeg_build/lib/libswresample.a \ /home/txp/ffmpeg_build/lib/libswscale.a
//包含ffmpeg头⽂件 #include "libavutil/avutil.h" int main() { printf("Hello FFMPEG, version is %s\n", av_version_info()); return 0; } 最终结果,显示ffmpeg的版本为 4.2.1: 20:01:19: Starting /home/txp/share/qt/workspace/build-linux_1-ffmpeg-Desktop_Qt_5_12_10_GCC_64bit-Debug/linux_1-ffmpeg ...Hello FFMPEG, version is 4.2.1 20:01:19: /home/txp/share/qt/workspace/build-linux_1-ffmpeg-Desktop_Qt_5_12_10_GCC_64bit-Debug/linux_1-ffmpeg exited with code 0 注意:我们的ubuntu运行环境一定要是64位的,不然安装不了这个版本的qt;还有一点,其实我们在.pro文件里面,按键盘上的ctrl键然后把鼠标放到库文件路径上,是可以打开里面的:
关于什么是SDL,这里我就不造轮子了,可以参考雷神的文章介绍: https://blog.csdn.net/leixiaohua1020/article/details/11954039
下面我们去SDL的官网下源码包就行安装: https://www.libsdl.org/download-2.0.php
txp@txp-virtual-machine:~/ffmpeg_sources$ ls fdk-aac lame-3.100.tar.gz SDL2-2.0.14.tar.gz ffmpeg libvpx SVT-AV1 ffmpeg-4.2.1 nasm-2.14.02 x264 ffmpeg-4.2.1.tar.bz2 nasm-2.14.02.tar.bz2 x265_git ffmpeg-snapshot.tar.bz2 opus lame-3.100 SDL2-2.0.14 然后执行: txp@txp-virtual-machine:~/ffmpeg_sources/SDL2-2.0.14$ ./autogen.shGenerating build information using autoconf This may take a while ... Now you are ready to run ./configure 这里提示了你直接运行 ./configure: ./configure --prefix=/home/txp/ffmpeg_build --bindir=/home/txp/bin
make -j4
sudo make install 下面我再创建一个工程,具体过程我就再写了,和第一个工程创建是一样的:这里我的main.c文件里面的源代码,大家先不用管代码具体啥意思: #include <stdio.h>#include <string.h> #include "SDL2/SDL.h"//包含SDL动态库文件 //自定义消息类型 #define REFRESH_EVENT (SDL_USEREVENT + 1) // 请求画面刷新事件 #define QUIT_EVENT (SDL_USEREVENT + 2) // 退出事件 //定义分辨率 // YUV像素分辨率 #define YUV_WIDTH 320 #define YUV_HEIGHT 240 //定义YUV格式 #define YUV_FORMAT SDL_PIXELFORMAT_IYUV int s_thread_exit = 0; // 退出标志 = 1则退出 int refresh_video_timer(void *data) { while (!s_thread_exit) { SDL_Event event; event.type = REFRESH_EVENT; SDL_PushEvent(&event); SDL_Delay(40); } s_thread_exit = 0; //push quit event SDL_Event event; event.type = QUIT_EVENT; SDL_PushEvent(&event); return 0; } #undef main int main(int argc, char* argv[]) { //初始化 SDL if(SDL_Init(SDL_INIT_VIDEO)) { fprintf( stderr, "Could not initialize SDL - %s\n", SDL_GetError()); return -1; } // SDL SDL_Event event; // 事件 SDL_Rect rect; // 矩形 SDL_Window *window = NULL; // 窗口 SDL_Renderer *renderer = NULL; // 渲染 SDL_Texture *texture = NULL; // 纹理 SDL_Thread *timer_thread = NULL; // 请求刷新线程 uint32_t pixformat = YUV_FORMAT; // YUV420P,即是SDL_PIXELFORMAT_IYUV // 分辨率 // 1. YUV的分辨率 int video_width = YUV_WIDTH; int video_height = YUV_HEIGHT; // 2.显示窗口的分辨率 int win_width = YUV_WIDTH; int win_height = YUV_WIDTH; // YUV文件句柄 FILE *video_fd = NULL; const char *yuv_path = "yuv420p_320x240.yuv"; size_t video_buff_len = 0; uint8_t *video_buf = NULL; //读取数据后先把放到buffer里面 // 我们测试的文件是YUV420P格式 uint32_t y_frame_len = video_width * video_height; uint32_t u_frame_len = video_width * video_height / 4; uint32_t v_frame_len = video_width * video_height / 4; uint32_t yuv_frame_len = y_frame_len + u_frame_len + v_frame_len; //创建窗口 window = SDL_CreateWindow("Simplest YUV Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, video_width, video_height, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); if(!window) { fprintf(stderr, "SDL: could not create window, err:%s\n",SDL_GetError()); goto _FAIL; } // 基于窗口创建渲染器 renderer = SDL_CreateRenderer(window, -1, 0); // 基于渲染器创建纹理 texture = SDL_CreateTexture(renderer, pixformat, SDL_TEXTUREACCESS_STREAMING, video_width, video_height); // 分配空间 video_buf = (uint8_t*)malloc(yuv_frame_len); if(!video_buf) { fprintf(stderr, "Failed to alloce yuv frame space!\n"); goto _FAIL; } // 打开YUV文件 video_fd = fopen(yuv_path, "rb"); if( !video_fd ) { fprintf(stderr, "Failed to open yuv file\n"); goto _FAIL; } // 创建请求刷新线程 timer_thread = SDL_CreateThread(refresh_video_timer, NULL, NULL); while (1) { // 收取SDL系统里面的事件 SDL_WaitEvent(&event); if(event.type == REFRESH_EVENT) // 画面刷新事件 { video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd); if(video_buff_len <= 0) { fprintf(stderr, "Failed to read data from yuv file!\n"); goto _FAIL; } // 设置纹理的数据 video_width = 320, plane SDL_UpdateTexture(texture, NULL, video_buf, video_width); // 显示区域,可以通过修改w和h进行缩放 rect.x = 0; rect.y = 0; float w_ratio = win_width * 1.0 /video_width; float h_ratio = win_height * 1.0 /video_height; // 320x240 怎么保持原视频的宽高比例 rect.w = video_width * w_ratio; rect.h = video_height * h_ratio; // rect.w = video_width * 0.5; // rect.h = video_height * 0.5; // 清除当前显示 SDL_RenderClear(renderer); // 将纹理的数据拷贝给渲染器 SDL_RenderCopy(renderer, texture, NULL, &rect); // 显示 SDL_RenderPresent(renderer); } else if(event.type == SDL_WINDOWEVENT) { //If Resize SDL_GetWindowSize(window, &win_width, &win_height); printf("SDL_WINDOWEVENT win_width:%d, win_height:%d\n",win_width, win_height ); } else if(event.type == SDL_QUIT) //退出事件 { s_thread_exit = 1; } else if(event.type == QUIT_EVENT) { break; } } _FAIL: s_thread_exit = 1; // 保证线程能够退出 // 释放资源 if(timer_thread) SDL_WaitThread(timer_thread, NULL); // 等待线程退出 if(video_buf) free(video_buf); if(video_fd) fclose(video_fd); if(texture) SDL_DestroyTexture(texture); if(renderer) SDL_DestroyRenderer(renderer); if(window) SDL_DestroyWindow(window); SDL_Quit(); return 0; } .pro文件配置成: TEMPLATE = appCONFIG += console CONFIG -= app_bundle CONFIG -= qt SOURCES += \ main.c INCLUDEPATH += /home/txp/ffmpeg_build/include LIBS += /home/txp/ffmpeg_build/lib/libSDL2.so 最终运行结果就可以看到在播放一个yuv格式的视频文件了:
注:这里的播放yuv格式的视频文件,我是事先已经准备好的:
同时要注意我们要把播放的视频文件放到工程目录下,不然播放是不会成功的:
现在ffmpeg真正的开发环境已经搭建完了,其实上面搭建环境蛮折腾人的,特别是源码安装ffmpeg。好了今天的文章就分享到这里了,如果你在看完文章后,有不懂的地方可以后台私聊我。 |
微信公众号
手机版