音视频格式转换
前一階段,項目中用到無線傳輸視頻文件。視頻采用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
}
?
?
?
?
總結
- 上一篇: 【Hexo搭建个人博客】(八)添加背景效
- 下一篇: H3CNE中静态路由实验