萬能版本的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官網下載庫文件即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章