万能版本的ffmpeg

最近在搞屏幕录制软件,需要整合声卡,麦克风音频,还有屏幕画面,本想直接用ffmpeg.exe直接跑进程,录屏的进程发现经常退不出,在网上找了ffmpeg的源码编译完成后,直接把ffmpeg源码拷贝进来,修改后,直接命令行参数传进去,然后再子进程中自己控制ffmpeg流程,可以实现命令行下的所有功能。开发环境 vs 2015 Qt5.9.3

 

1 vs 2015 编译ffmpeg源码

vs下源码与依赖,这位老哥都在gittee上给出来了,比github上好多了,下载速度非常快,编译细节也都给出了

https://gitee.com/ztwlla/FFMPEG

需要注意的是,我这边按照上面 方法直接拷贝VSNASM与VSYASM的dll到相关路径并不能编译成功,建议直接运行install_script.bat运行后编译, 我这边在运行安装VSNASM与VSYASM时没有管理员权限导致安装不成功,修改install_script.bat 脚本后再运行,VSNASM安装成功

修改如下(只需要在bat脚本中加入管理员权限即可):

@echo off&color 17
if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0
bcdedit >nul
if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin)
:UACPrompt
%1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit
exit /B
:UACAdmin
cd /d "%~dp0"
echo 当前运行路径是:%CD%
echo 已获取管理员权限

#上面为增加获取管理员权限

@echo OFF
setlocal enabledelayedexpansion

安装成功后再打开工程即可编译通过

 

2 修改ffmpeg 源码 ,并用Qt生成自己工程,

ffmpeg 工程,默认是命令行参数运行,修改后的源码支持子线程命令函参数传递并加入自己的Qt

工程 ;

在修改的过程中主要有以下几点注意

1 ffmpeg.c中exit_program()函数,默认是调用ffmpeg_clean()后然后exit()退出,这样就会导致整个程序进程退出,删掉exit()

2 ffmpeg.c中通过 transcode()中通过  while (!received_sigterm)来编解码操作 ,只需要通过控制received_sigterm变量即可控制线程循环

 

3 在进程不退出的情况下每次重新启动后,需要清理几个变量,否则会崩溃,因为ffmpeg_clean函数在中,虽然将内存释放掉,但是数组值并没有清零,导致下次启动进程时累加,导致数组未初始化,例如下面:虽然input_files数组清零,但是下次线程启动时nb_input_files并不是从0开始,所以在进程输入数据初始化时会产生堆内存未初始化的崩溃0xcdcdcdcd错误,将所有的传输数据都需要重置为0

  for (i = 0; i < nb_input_files; i++) {
        avformat_close_input(&input_files[i]->ctx);
        av_freep(&input_files[i]);
    }
	nb_input_files = 0; //需要设置为零,默认源码没有清零

自己的Qt工程主文件

#include "QtFFMpegDemo.h"
#include <QDesktopWidget>
void StartFFmpegThread()
{
	char temp[200] = { 0 };
	char size[100] = { 0 };

	/*ffmpeg -f dshow -i audio="virtual-audio-capturer" -f dshow -i audio="麦克风 (Realtek High Definition Audio)" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 
		-f gdigrab -i desktop -vcodec h264 -preset ultrafast  -acodec aac -ar 44100 -ac 2 -f mp4 -q:v 30 -r 15 -y d:/test.mp4
	*/

	memcpy(temp,QString::fromLocal8Bit("audio=麦克风 (Realtek High Definition Audio)").toUtf8().data(), QString::fromLocal8Bit("audio=麦克风 (Realtek High Definition Audio)").toUtf8().length());
	QString str = QString("%1x%2").arg(QApplication::desktop()->width()).arg(QApplication::desktop()->height());
	memcpy(size,str.toUtf8().data(),str.toUtf8().length());
	char *argv[] = { "ffmpeg","-f","dshow","-i","audio=virtual-audio-capturer","-f","dshow","-i", temp,\
		"-filter_complex","amix=inputs=2:duration=first:dropout_transition=2","-f","gdigrab","-i","desktop",		\
		"-vcodec","h264","-preset","ultrafast","-acodec","aac","-ar","44100","-ac", "2","-f","mp4","-q:v","30", "-r","15","-y","d:/test.mp4" };
	int argc = 33;
	ffmpeg_start(argc, argv);
	int n = 0;
}

QtFFMpegDemo::QtFFMpegDemo(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	connect(ui.m_pbStart, &QPushButton::clicked, [&]() {StartFfmpeg(); });
	connect(ui.pushButton, &QPushButton::clicked, this, [&]() {StopFFmpeg();});
}

void QtFFMpegDemo::StartFfmpeg()
{
	m_ffmpegThread = std::thread(StartFFmpegThread);
	m_ffmpegThread.detach();
}

void QtFFMpegDemo::FFmpegCallBack(void *p)
{
	QtFFMpegDemo* pThis = static_cast<QtFFMpegDemo*>(p);
	if (pThis)
	{
		pThis->FfmpegStoped();
	}
}

void QtFFMpegDemo::StopFFmpeg()
{
	ffmpeg_stop(FFmpegCallBack,this);
}

//子线程回调,最好通过信号与槽来通知Ui线程
void QtFFMpegDemo::FfmpegStoped()
{
	Q_EMIT SgnFFmpegStoped();
}

想要什么功能,只需要在StartFFmpegThread()中通过参数传进去即可

修改后的源码工程地址  https://download.csdn.net/download/i7891090/12017514 

由于库文件太大,无法上传,可直接从ffmpeg官网下载库文件即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值