音視頻格式轉換

前一階段,項目中用到無線傳輸視頻文件。視頻採用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
}

 

 

 

 

發佈了22 篇原創文章 · 獲贊 18 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章