前一階段,項目中用到無線傳輸視頻文件。視頻採用h264格式。但是由於無線傳輸,我們在保證視頻的質量情況下降低幀率和碼流。但處理後的視頻還是是很大。
想到的方案有兩種:
1、h264再次壓縮(低碼流)。由於太專業。往往花錢購買。
2、視頻格式轉碼。網上有許多視頻壓縮轉碼軟件。
經過考慮決定採用第二中方案。但是由於第三方的軟件部提供api接口。我們怎麼才能調用呢?這個是個問題。
腦袋一熱 想模擬鼠標點擊第三方軟件。如果這樣做,一旦轉換失敗或軟件異常都無法控制。
下載了很多軟件終於找到一個可以控制的軟件-----格式工廠
格式工廠安裝後發現安裝目錄
D:\Program Files\FreeTime\FormatFactory\FFModules
有幾個可執行程序
1、RMEncoder.exe
2、mencoder.exe
3、ffmpeg.exe
經過測試發現 這幾個是格式轉碼用的
那我們怎麼找到他們的調用方式呢?
我們首先寫過exe程序 如 A.exe
代碼如下:
int main(int argc, _TCHAR* argv[])
{
//打印輸入的參數
for(int i = 0; i< argc; i++)
{
char szMsg[500] = {0};
printf("para i= %d value = %s\n",i,(char*)argv[i]);
sprintf(szMsg,"para i= %d value = %s\n",i,(char*)argv[i]);
::OutputDebugString(szMsg);
}
return 0;
}
你可能已經明白了,沒錯。就是偷樑換柱。把A.exe 替換成上面幾個程序(RMEncoder.exe、mencoder.exe、ffmpeg.exe) 把debugveiw啓動。
然後再把格式工廠打開,很選擇你要轉換的視頻文件。
如 我是壓縮成avi
/*
00000029 11:58:14.875 [7660] para i= 0 value =
00000030 11:58:14.875 [7660] para i= 1 value = C:\Documents and Settings\Administrator\桌面\1234.avi
00000031 11:58:14.875 [7660] para i= 2 value = -o
00000032 11:58:14.875 [7660] para i= 3 value = E:\FFOutput\1234.avi
00000033 11:58:14.875 [7660] para i= 4 value = -vf
00000034 11:58:14.875 [7660] para i= 5 value = scale=704:576,harddup
00000035 11:58:14.875 [7660] para i= 6 value = -ofps
00000036 11:58:14.875 [7660] para i= 7 value = 12
00000037 11:58:14.875 [7660] para i= 8 value = -nosound
00000038 11:58:14.875 [7660] para i= 9 value = -ovc
00000039 11:58:14.875 [7660] para i= 10 value = x264
00000040 11:58:14.875 [7660] para i= 11 value = -ffourcc
00000041 11:58:14.875 [7660] para i= 12 value = avc1
00000042 11:58:14.875 [7660] para i= 13 value = -x264encopts
00000043 11:58:14.875 [7660] para i= 14 value = bitrate=512:me=hex:level_idc=13:keyint=250:frameref=1:bframes=0:nocabac:threads=auto
00000044 11:58:14.875 [7660] para i= 15 value = -aspect
00000045 11:58:14.875 [7660] para i= 16 value = 1.222
00000046 11:58:14.875 [7660] para i= 17 value = -mc
00000047 11:58:14.875 [7660] para i= 18 value = 1
*/
得到參數後我們就可以自己調用那些轉碼程序了。
但是問題我們怎麼找到轉了多少呢(進度百分比)?
於是我寫了批處理 a.bat
d:\Jerry_work\上海\GPSServer\Testline\Debug\AviLib/mencoder.exe C:\DOCUME~1\ADMINI~1\桌面\1234.avi -o c:/1234.avi -vf scale=704:576,hardup -ofps 12 -nosound -ovc x264 -ffourcc avc1 -x264encopts bitrate=512:me=hex:level_idc=13:keyint=250:frameref=1:bframes=0:nocabac:threads=auto
-aspect 1.222000 -mc 1"
pause
發現在界面中有進度百分比信息,狂歡。。。
如下:
//Pos: 0.8s 10f ( 0%) 0.00fps Trem: 0min 0mb A-V:0.000 [0:0]
//Pos: 77.3s 1159f (99%) 40.02fps Trem: 0min 4mb A-V:0.000 [516:0]
原來主程序和轉碼程序通過管道方式調用。
剩下我想你應該明白了。
下面是我寫的。我把它封裝在dll中了
// CompressAvi.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
//#include <windows.h>
//#include <WinUser.h>
#include "CompressAvi.h"
#include <vfw.h>
char szMsg[2048] ={0};
int g_nScore = 0;
BOOL GetAVIInfo(const char* strFileName,int *nW,int *nH)
{
*nW = 0;
*nH = 0;
HRESULT hr;
PAVIFILE pAVIFile=NULL;
AVIFileInit();
hr=AVIFileOpen(&pAVIFile,strFileName,OF_READ,NULL);
if(FAILED(hr))
{
OutputDebugString("AVIFileOpen failed!");
return FALSE;
}
AVIFILEINFO fileinfo;
ZeroMemory(&fileinfo,sizeof(AVIFILEINFO));
hr=AVIFileInfo(pAVIFile,&fileinfo,sizeof(AVIFILEINFO));
if(FAILED(hr))
{
OutputDebugString("AVIFileInfo failed!");
return FALSE;
}
*nW = fileinfo.dwWidth;
*nH = fileinfo.dwHeight;
AVIFileRelease(pAVIFile);
AVIFileExit();
pAVIFile=NULL;
return TRUE;
}
int HPExecCmd(IN const char* pszCmd)
{
//return 0;
SECURITY_ATTRIBUTES sa;
HANDLE hRead, hWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;//使用系統默認的安全描述符
sa.bInheritHandle = TRUE;//創建的進程繼承句柄
if(!CreatePipe(&hRead, &hWrite, &sa, 0))//創建匿名管道
return -1;
STARTUPINFO si;
PROCESS_INFORMATION pi;
RtlZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;//新創建進程的標準輸出連在寫管道的一端
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
if(!CreateProcess(NULL, (char*)pszCmd, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))//創建子進程
return -1;
CloseHandle(hWrite);
while(TRUE)
{
DWORD dwRead;
char pszBuff[1024] = {0};
if(ReadFile(hRead, pszBuff, 1024, &dwRead, NULL) == NULL)//讀取管道
break;
strcpy(szMsg,pszBuff);
//strcat(pszResult, pszBuff);
//::OutputDebugString(pszBuff);
//::OutputDebugString("\n");
//FirsStatus();
//Sleep(1000);
}
CloseHandle(hRead);
hRead = NULL;
g_nScore = 0;
::TerminateProcess(pi.hProcess,0);
return 0;
}
//Progress 3
COMPRESSAVI_API BOOL FirsPressAvi(const char *pSrc, const char *pDst,int nFps, int nBitRate, int nLevel_idc)
{
g_nScore = 0;
char szTemp[MAX_PATH] = {0};
::GetModuleFileName(NULL, szTemp, sizeof(szTemp)-1);
int iLen = (int)strlen(szTemp);
for(int i = iLen - 1; i >= 0; i--)
{
if (szTemp[i] == '\\')
{
break;
}
else
{
szTemp[i] = 0;
}
}
int nW = 704;
int nH = 576;
float rate = 1.222;
int tmpW = 0,tmpH = 0;
BOOL bRet = GetAVIInfo(pSrc,&tmpW,&tmpH);
if (bRet)
{
nW = tmpW;
nH = tmpH;
rate = tmpW/tmpH;
}
//HPExecCmd()
char szPara[512]={0};
sprintf(szPara,"%sAviLib/mencoder.exe %s -o %s -vf scale=%d:%d,harddup -ofps %d -nosound -ovc x264 -ffourcc avc1 -x264encopts bitrate=%d:me=hex:level_idc=%d:keyint=250:frameref=1:bframes=0:nocabac:threads=auto -aspect %f -mc 1",szTemp,pSrc,pDst,nW,nH,nFps,nBitRate,
nLevel_idc,rate);
HPExecCmd(szPara);
return TRUE;
}
COMPRESSAVI_API int FirsStatus()
{
//Pos: 0.8s 10f ( 0%) 0.00fps Trem: 0min 0mb A-V:0.000 [0:0]
//Pos: 77.3s 1159f (99%) 40.02fps Trem: 0min 4mb A-V:0.000 [516:0]
//Flushing video frames.
char *p1 = strstr(szMsg,"(");
if (NULL != p1)
{
p1 ++;
char *p2 = strstr(p1,"%");
if (p2 != NULL)
{
*p2 = 0;
g_nScore = atoi(p1);
}
}
return g_nScore;
//Progress 3
//Finish
//g_nScore
}