#ifndef __HSS_AUTO_REVISE_AVI_FRAMERATE_HSS__
#define __HSS_AUTO_REVISE_AVI_FRAMERATE_HSS__ /**************************************************************************************************\
* 2012-05-31
关于avi的一些功能。
(1)
由于丢帧等问题,导致录像长度不对,根据录像时间和帧数,修正avi文件中的帧率信息
auto_avi::ReviseAviFrameRate(sec, frame, file);
auto_avi::ReviseAviFrameRate_ms(millsec, frame, file); \**************************************************************************************************/ #include <auto_file.h>
#include <__time.h> class auto_avi
{
public:
auto_avi()
{
}; ~auto_avi()
{
} public:
/**************************************************************************************************\
* static void :
* ReviseAviFrameRate : 修正avi录像的长度(修改文件头里面的信息,把帧率修改为实际的帧率)
* DWORD nSeconds : 录像长度
* DWORD nFrame : 总帧数
* LPCTSTR pszFile :
\**************************************************************************************************/
static void ReviseAviFrameRate(DWORD nSeconds, DWORD nFrame, LPCTSTR pszFile)
{
auto_file f;
if (!f.Open(pszFile, GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING, 0))
return;
SetFilePointer(f.m_hFile, 0x80, 0, FILE_BEGIN);
DWORD scale = 1000;
DWORD rate = nFrame * 1000 / nSeconds;
f.OverWrite((LPBYTE)&scale, 4);
f.OverWrite((LPBYTE)&rate, 4);
} /**************************************************************************************************\
* static void :
* ReviseAviFrameRate_ms : 指定毫秒的版本
* DWORD nMilliSeconds : 录像长度毫秒
* DWORD nFrame : 帧率
* LPCTSTR pszFile : 录像文件
\**************************************************************************************************/
static void ReviseAviFrameRate_ms(DWORD nMilliSeconds, DWORD nFrame, LPCTSTR pszFile)
{
auto_file f;
if (!f.Open(pszFile, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING, 0))
{
return;
} if (nFrame == 0)
{
SetFilePointer(f.m_hFile, 0x8c, 0, FILE_BEGIN);
if (!f.Read((LPBYTE)&nFrame, 4))
return;
} SetFilePointer(f.m_hFile, 0x80, 0, FILE_BEGIN); DWORD scale = 1000; ULONGLONG a = nFrame; a *= 1000000; a /= nMilliSeconds; DWORD rate = (DWORD)a; f.OverWrite((LPBYTE)&scale, 4); f.OverWrite((LPBYTE)&rate, 4);
}
}; #endif
#ifndef __HSS_AUTO_AVI_HSS__
#define __HSS_AUTO_AVI_HSS__ #include <StringN.h>
#include <HBuffer.H> class auto_avi_icc
{
public:
auto_avi_icc()
{
__memzero(m_Com);
__memzero(param):
__memzero(strhdr);
m_pFile = 0;
tStartTime = 0;
psz = 0;
} ~auto_avi_icc()
{
} struct
{
BITMAPINFOHEADER bmi;
BITMAPINFOHEADER bmo;
}param;
private:
BOOL InitCompress()
{
//利用代码选择压缩器
__memzero(m_Com); m_Com.cbSize = sizeof(m_Com);
m_Com.dwFlags = ICMF_COMPVARS_VALID; m_Com.fccType = ICTYPE_VIDEO;
m_Com.lFrame = 0;
m_Com.lKey = 3; //关键帧
m_Com.lKeyCount = 3;
m_Com.lDataRate = 780;
m_Com.lpbiOut = (BITMAPINFO*)&m_OutInfo;
//压缩MPG4格式
//m_Com.hic = ICOpen(ICTYPE_VIDEO, mmioFOURCC('M', 'P', '4', '2'), ICMODE_COMPRESS);
//压缩DIVX
//m_Com.hic = ICOpen(ICTYPE_VIDEO, mmioFOURCC('D', 'I', 'V', 'X'), ICMODE_COMPRESS);
//压缩H264
m_Com.hic = ICOpen(ICTYPE_VIDEO, mmioFOURCC('X', '2', '6', '4'), ICMODE_COMPRESS);
m_Com.cbState = 1180;
//ICCompressorChoose(NULL,ICMF_CHOOSE_ALLCOMPRESSORS ,(LPVOID)&m_InInfo,NULL,&m_Com,"选择压缩类型");
ICCompressGetFormat(m_Com.hic, (LPBITMAPINFO)&param.bmi, (LPBITMAPINFO)&param.bmo);
int ret = ICCompressBegin(m_Com.hic, (LPBITMAPINFO)&param.bmi, (LPBITMAPINFO)&param.bmo); if(ret != ICERR_OK )
{
//MessageBox(NULL, "视频压缩器无法启动!", "系统提示", MB_ICONSTOP);
return FALSE;
} return TRUE;
} BOOL CreateAviFile(LPCTSTR pszFileName, LPBITMAPINFOHEADER pbi, LPBITMAPINFOHEADER pbo)
{
param.bmi = *pbi;
param.bmo = *pbo; m_IndexFrame = 0 ;
//AVI文件初始化
AVIFileInit();
//设置压缩参数
if(!InitCompress())
{
AVIFileExit();
return FALSE;
}
//打开文件
m_pFile = NULL;
HRESULT hr = ::AVIFileOpen(&m_pFile, pszFileName, OF_WRITE|OF_CREATE, NULL);
if(hr != 0)
{
AVIFileExit();
//MessageBox(NULL, "无法创建视频文件!", "系统提示", MB_ICONSTOP);
return 0;
} memset(&strhdr, 0, sizeof(strhdr)) ;
strhdr.fccType = streamtypeVIDEO;// stream type
strhdr.fccHandler = 0;
strhdr.dwScale = 1;
strhdr.dwRate = iLuxFrameRate; // 25 fps
//int WIDTH = (m_InInfo.bmiHeader.biWidth * m_InInfo.bmiHeader.biBitCount + 31) / 32 * 4;
//strhdr.dwSuggestedBufferSize = WIDTH * m_InInfo.bmiHeader.biHeight;
strhdr.dwSuggestedBufferSize = m_InInfo.bmiHeader.biWidth * m_InInfo.bmiHeader.biHeight * 3; SetRect(&strhdr.rcFrame,
0,
0,
m_InInfo.bmiHeader.biWidth,
m_InInfo.bmiHeader.biHeight); hr = AVIFileCreateStream(m_pFile, &ps, &strhdr); if (hr != AVIERR_OK)
{
AVIFileExit();
//MessageBox(NULL, "无法创建视频文件!", "系统提示", MB_ICONSTOP);
return 0;
} tStartTime = GetTickCount(); return true;
} void CloseAviFile()
{
//结束数据压缩
if (m_Com.hic)
{
ICCompressEnd(m_Com.hic); //关闭压缩句柄
ICClose(m_Com.hic); if(ps)
AVIStreamClose(ps); if(m_pFile)
AVIFileClose(m_pFile); AVIFileExit();
}
} BOOL AddFrame(LPBITMAPINFOHEADER pbih, LPBYTE pBits)
{
char* buffer = new char [NWIDTH * NHEIGHT * 3 + 1];
memset(buffer, 0, NWIDTH * NHEIGHT * 3 + 1);
DWORD dwCkID = 0;
DWORD dwCompFlags = 0;
DWORD dwQuality = 100;
iLuxFrameRate = 25;
DWORD m_RealFrame = ((GetTickCount() - tStartTime) * iLuxFrameRate + 500) / 1000;
long cj = m_RealFrame - m_IndexFrame;
for(long i = 0; i < cj + 1; i ++)
{
//视频压缩
memset(buffer, 0, NWIDTH * NHEIGHT * 3 + 1);
if(ICCompress(m_Com.hic, 0, &m_OutInfo.bmiHeader, buffer,
&m_InInfo.bmiHeader, (unsigned char *)pBuffer, &dwCkID, &dwCompFlags, m_IndexFrame ++, 0, dwQuality, NULL, NULL) == ICERR_OK)
{
AVIStreamSetFormat(ps, m_IndexFrame, &m_OutInfo.bmiHeader, sizeof(m_OutInfo.bmiHeader));
VERIFY(0 == AVIStreamWrite(ps, //stream pointer
m_IndexFrame , //time of this frame
1, //number to write
(LPBYTE) buffer, //pBuffer,
m_OutInfo.bmiHeader.biSizeImage, //size of this frame
AVIIF_KEYFRAME, // flags....
NULL,
NULL)); OutputDebugString(".");
}
else
{
VERIFY(0);
}
}
delete []buffer;
} private:
COMPVARS m_Com;
PAVIFILE m_pFile; //AVI文件
AVISTREAMINFO strhdr; //AVI流信息
PAVISTREAM ps; //AVI流指针
DWORD tStartTime;
HBuffer m_BufFrame;
}; #endif
#ifndef __HSS_AVI_STREAM_HSS__
#define __HSS_AVI_STREAM_HSS__ /**************************************************************************************************\
* 2013-09-08
新的监控录像类,自动持续录像,改变录像大小,叠加文字等,但是没有图像缓冲区 auto_avi_stream avi; avi.SetConfigFile avi.Open(... avi.AddFrame avi.Close( \**************************************************************************************************/ #include <auto_x264.h>
#include <rjpeg.h>
#include <auto_IplImage.h>
#include <HBuffer.h>
#include <timemath.h>
#include <overtext.h>
#include <StringN.h> #define FCCX264 (*(DWORD*)"X264") class auto_avi_stream
{
public:
struct
{
}param; struct
{
char szFileName[_MAX_PATH];
DWORD fccHandler;
RJPEG_OPEN Param;
BITMAPINFOHEADER bih; ULONGLONG lTickBegin;
SYSTEMTIME stBegin;
ULONGLONG lFrameIndex; //下一帧的索引
ULONGLONG lFrameCount;
ULONGLONG lTickEnd;
SYSTEMTIME stEnd; BOOL fFirstRun;
}info; auto_x264 m_264; HBuffer m_BufResized; HBuffer m_BufOverlayText; public:
auto_avi_stream()
{
__memzero(param);
__memzero(info);
} ~auto_avi_stream()
{
} /**************************************************************************************************\
* void : 2013年9月8日 设置配置文件,x264会自动把后缀修改为 .x264.cfg
* SetConfigFile :
* LPCTSTR pszFile :
\**************************************************************************************************/
void SetConfigFile(LPCTSTR pszFile)
{
__strcpy(m_264.param.szConfigFile, pszFile);
} /**************************************************************************************************\
* BOOL : 2013年9月8日 是否打开
* IsOpen :
\**************************************************************************************************/
BOOL IsOpen()
{
if (info.fccHandler == FCCX264)
return m_264.IsOpen(); return FALSE;
} /**************************************************************************************************\
* BOOL : 2013年9月8日 打开录像
* Open :
* LPCTSTR pszFile : 文件名(可以是模板)
* DWORD fccHandler : 编码,*(DWORD*)"X264"(FCCX264)
* RJPEG_OPEN* param : 录像参数
* DWORD dwTick = 0 : 开始时刻
* SYSTEMTIME* pst = 0 : 开始时间
\**************************************************************************************************/
BOOL Open(LPCTSTR pszFile, DWORD fccHandler, RJPEG_OPEN* param, DWORD dwTick = 0, SYSTEMTIME* pst = 0)
{
if (param->Format.nFrameRate <= 0)
return FALSE; info.Param = *param;
info.fccHandler = fccHandler;
__strcpy(info.szFileName, pszFile); if (dwTick == 0 || pst == 0)
{
info.lTickBegin = ::GetTickCount();
GetLocalTime(&info.stBegin);
}
else
{
info.lTickBegin = dwTick;
info.stBegin = *pst;
} info.lTickEnd = info.lTickBegin;
info.stEnd = info.stBegin;
info.lFrameCount = 0; BITMAPINFOHEADER bih = {0};
info.bih.biBitCount = 24;
info.bih.biWidth = info.Param.Format.biWidth;
info.bih.biHeight = info.Param.Format.biHeight;
info.bih.biPlanes = 1;
info.bih.biSize = sizeof(info.bih);
info.bih.biSizeImage = (info.bih.biWidth * info.bih.biBitCount + 31) / 32 * 4 * info.bih.biHeight; char szf[_MAX_PATH] = {0}; GetFileName(szf, info.szFileName, &info.stBegin); return Open(szf);
} /**************************************************************************************************\
* BOOL : 2013年9月8日 增加帧
* AddFrame : 会自动停止等
* DWORD dwTick :
* LPBITMAPINFOHEADER pbih :
* LPBYTE pBits :
\**************************************************************************************************/
BOOL AddFrame(DWORD dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits)
{
if (pbih->biBitCount != 24)
return FALSE; ULONGLONG tick = GetTickCount(dwTick); //帧率控制
double sec = (double)(LONGLONG)(tick - info.lTickBegin) / 1000.0; ULONGLONG index = (ULONGLONG)(LONGLONG)(sec * info.Param.Format.nFrameRate + 0.5);
if (index <= info.lFrameIndex && info.lTickEnd != info.lTickBegin)
return TRUE; info.lFrameIndex = index;
info.lTickEnd = tick; SYSTEMTIME stold = info.stEnd;
SYSTEMTIME st = info.stBegin;
SystemTimeAdd(&st, (int)(LONGLONG)(tick - info.lTickBegin));
info.stEnd = st; //先看看是否需要改变大小
if (pbih->biWidth != info.bih.biWidth
|| pbih->biHeight != info.bih.biHeight
)
{
int size = info.bih.biSizeImage; LPBYTE p = m_BufResized.GetBuffer(size);
if (p == 0)
return FALSE; auto_IplImage src(pbih, pBits);
if (!src)
return FALSE; auto_IplImage dst(&info.bih, p);
if (!dst)
return FALSE; cvResize(src, dst, CV_INTER_LINEAR ); pbih = &info.bih;
pBits = p;
} //叠加文字
if (info.Param.oiText[0])
{
//第一步,如果没有改变大小,则要复制一下内存,防止改变了原始内存
if (pBits != m_BufResized.m_pBuffer)
{
int size = info.bih.biSizeImage; LPBYTE p = m_BufResized.GetBuffer(size);
if (p == 0)
return FALSE; ASSERT(info.bih.biSizeImage == pbih->biSizeImage); memcpy(p, pBits, pbih->biSizeImage); pBits = p;
pbih = &info.bih;
} //下面做实际的叠加文字
Overlay(pbih, pBits, info.stEnd, info.lFrameIndex);
} //增加到录像
if (!CompressFrame(tick, pbih, pBits))
return FALSE; info.lFrameCount ++; BOOL bStop = 0; if (info.Param.dwFileEveryMinutes)
{
if (info.Param.dwFileEveryMinutes == 1)
{
if (info.stEnd.wSecond < stold.wSecond)
{
double sec = GetSeconds(); if (sec > 30)
{
bStop = TRUE;
}
}
}
else if ((info.stEnd.wMinute % info.Param.dwFileEveryMinutes) == 0)
{
double sec = GetSeconds(); if (sec > info.Param.dwFileEveryMinutes * 60.0 / 2.0)
{
bStop = TRUE;
}
}
}
else if (info.Param.dwSecondsLimit)
{
double sec = GetSeconds(); if (sec >= info.Param.dwSecondsLimit)
{
bStop = TRUE;
}
} if (bStop)
{
//停止录像,开始新录像
Stop(); char szf[_MAX_PATH] = {0}; if (0 == GetFileName(szf, info.szFileName, &info.stEnd))
{
//非模板,直接关闭
return TRUE;
} info.lTickBegin = tick;
info.lTickEnd = tick;
info.stBegin = info.stEnd; return Open(szf);
} return TRUE;
} /**************************************************************************************************\
* double : 2013年9月8日 录像时间长度
* GetSeconds :
\**************************************************************************************************/
double GetSeconds()
{
double sec = (double)(LONGLONG)(info.lTickEnd - info.lTickBegin) / 1000.0; if (sec < 1.0)
sec = 1.0; return sec;
} /**************************************************************************************************\
* DWORD : 2013年9月8日 录像多少帧
* GetFrames :
\**************************************************************************************************/
DWORD GetFrames()
{
return (DWORD)info.lFrameCount;
} /**************************************************************************************************\
* void : 2013年9月8日 关闭
* Close :
\**************************************************************************************************/
void Close()
{
Stop();
} /**************************************************************************************************\
* void : 2013年9月8日 配置
* Config :
* HWND hwnd :
\**************************************************************************************************/
void Config(HWND hwnd)
{
if (info.fccHandler == FCCX264)
{
m_264.Config(hwnd);
}
} /**************************************************************************************************\
* LPCTSTR : 2013年9月8日 获取文件名
* GetFileName :
\**************************************************************************************************/
LPCTSTR GetFileName()
{
if (info.fccHandler == FCCX264)
{
return m_264.info.szFile;
} return "";
} /**************************************************************************************************\
* double : 2013年9月8日 获取实际的帧率
* GetFrameRate :
\**************************************************************************************************/
double GetFrameRate()
{
return GetFrames() / GetSeconds();
} /**************************************************************************************************\
* void : 2013年9月8日 获取当前录像的信息
* GetInfo :
* char* psz :
* int cb :
* int& n :
\**************************************************************************************************/
void GetInfo(char* psz, int cb, int& n, int mode = 0)
{
double sec = GetSeconds();
LPCTSTR stm = "秒"; if (sec > 3600.0)
{
sec /= 3600.0;
stm = "时";
}
else if (sec > 60.0)
{
sec /= 60.0;
stm = "分";
} if (mode == 0)
{
if (info.fccHandler == FCCX264)
{
__snprintcat2(psz, cb, n), "%.1lf%s, 帧%d, 帧率%.1lf\n#录像文件:%s%s%s",
sec, stm,
GetFrames(),
GetFrameRate(),
GetFileName(),
m_264.info.szAsciiFile[0] ? "\n#临时文件:" : "",
m_264.info.szAsciiFile
);
}
else
{
__snprintcat2(psz, cb, n), "%s, %.1lf%s, 帧%d, 帧率%.1lf",
GetFileName(),
sec, stm,
GetFrames(),
GetFrameRate()
);
}
}
} private: /**************************************************************************************************\
* void : 2013年9月8日 停止
* Stop :
\**************************************************************************************************/
void Stop()
{
if (info.fccHandler == FCCX264)
{
m_264.Close();
}
} /**************************************************************************************************\
* BOOL : 2013年9月8日 压缩一帧
* CompressFrame :
* ULONGLONG dwTick :
* LPBITMAPINFOHEADER pbih :
* LPBYTE pBits :
\**************************************************************************************************/
BOOL CompressFrame(ULONGLONG dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits)
{
BOOL retval = 0; if (info.fccHandler == FCCX264)
{
retval = m_264.AddFrame(dwTick, pbih, pBits);
} return retval;
} /**************************************************************************************************\
* ULONGLONG : 2013年9月8日 防止毫秒时刻转回来
* GetTickCount :
* DWORD dwTick :
\**************************************************************************************************/
ULONGLONG GetTickCount(DWORD dwTick)
{
ULONGLONG t = dwTick;
if (dwTick < info.lTickEnd)
{
t += 0x100000000;
}
return t;
} /**************************************************************************************************\
* BOOL : 2013年9月8日 内部使用打开录像文件
* Open :
* LPCTSTR pszFile :
\**************************************************************************************************/
BOOL Open(LPCTSTR pszFile)
{
if (info.fccHandler == FCCX264)
return m_264.Open(pszFile, &info.bih); return FALSE;
} /**************************************************************************************************\
* int : 2013年9月8日 把文件模板转成真正的文件名
* GetFileName : 返回替换的模板个数
* char* pszFile :
* LPCTSTR pszTemplate :
* SYSTEMTIME* pst :
\**************************************************************************************************/
int GetFileName(char* pszFile, LPCTSTR pszTemplate, SYSTEMTIME* pst)
{
CString szf(pszTemplate); int nr = 0; char szi[8] = {0};
__sprintf(szi), "%04d", pst->wYear);
nr += szf.Replace("{y}", szi); __sprintf(szi), "%02d", pst->wMonth);
nr += szf.Replace("{m}", szi); __sprintf(szi), "%02d", pst->wDay);
nr += szf.Replace("{d}", szi); __sprintf(szi), "%02d", pst->wHour);
nr += szf.Replace("{h}", szi); __sprintf(szi), "%d", pst->wHour);
nr += szf.Replace("{H}", szi); __sprintf(szi), "%02d", pst->wMinute);
nr += szf.Replace("{M}", szi); __sprintf(szi), "%02d", pst->wSecond);
nr += szf.Replace("{s}", szi); __strncpy(pszFile, (LPCTSTR)szf, _MAX_PATH); return nr;
} /**************************************************************************************************\
* LPBYTE : 2013年9月8日 叠加文字
* Overlay :
* LPBITMAPINFOHEADER pdbih :
* LPBYTE pdBits :
* SYSTEMTIME st :
* DWORD lFrameIndex :
\**************************************************************************************************/
LPBYTE Overlay(LPBITMAPINFOHEADER pdbih, LPBYTE pdBits, SYSTEMTIME st, DWORD lFrameIndex)
{
//叠加文字
if (info.Param.oiText[0])
{
//计算时间 //把[T]替换为时间,把[F]替换为帧号[t]为简写时间
char szt[64] = {0};
char szT[64] = {0};
char szm[64] = {0}; __sprintf(szT), "%04d年%02d月%02d日 %02d:%02d:%02d",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); __sprintf(szt), "%04d-%02d-%02d %02d:%02d:%02d",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); __sprintf(szm), "%03d", st.wMilliseconds); char szf[32] = {0};
__sprintf(szf), "%d", lFrameIndex); CString szOverlay(info.Param.oiText);
szOverlay.Replace("[T]", szT);
szOverlay.Replace("[t]", szt);
szOverlay.Replace("[F]", szf);
szOverlay.Replace("[m]", szm);
szOverlay.Replace("[N]", "\r\n"); if (_OT_GetTextBitmap(&m_BufOverlayText, &info.Param.oiFormat.lfFont, szOverlay, pdbih->biWidth))
{
OT_FLAGS of = {0};
of.nPositionType = 0; //0 位置 1 下面水平条
of.nPositionX = info.Param.oiFormat.nPosX; //位置坐标
of.nPositionY = info.Param.oiFormat.nPosY; //位置坐标
of.lfFont.lfFont = info.Param.oiFormat.lfFont; //字体和颜色(前景)
of.lfFont.rgbFont = info.Param.oiFormat.crColor;
of.nBkTransparent = 100 - info.Param.oiFormat.nBackGround * 25;
of.nEdgeWidth = info.Param.oiFormat.nEdgeWidth; //边框宽度(用背景颜色)边框
of.crBackground = RGB(0, 0, 0);
of.nTransparent = 0; //100 全透明 0 背景颜色(背景)
of.bAutoWhiteBlack = info.Param.oiFormat.bAutoWhiteBlack; //2011年11月29日 自动黑白字 _OT_OverTextBitmap4(&m_BufOverlayText, pdbih, pdBits, pdbih->biSizeImage,
FALSE,
0,
0,
&of);
}
} return pdBits;
}
}; #endif
#ifndef __HSS_AVI_ENC_HSS__
#define __HSS_AVI_ENC_HSS__ /**************************************************************************************************\
* 2013-08-31
新的压缩avi类,更简单,并且支持数据流(但是可能不理想,先展示不管了) 关于配置文件的处理:
可以设置配置文件,若没有设置配置文件,则使用缺省的配置,不进行配置的相关处理和调用
因为很多编码器都可以保存配置,保存为缺省
现在必须处理配置,是因为保存的位置可能被写保护,所以必须保存到其他地方 (1) 若指定了配置文件,则自动装载配置文件,并检查配置文件是否匹配,如果匹配则使用,如果不匹配,则不使用
(2) 若没有指定配置文件,则使用缺省
(3) 若指定了配置文件,必须显式调用配置函数,否则不进行自动的配置 配置:
m_enc.param.fccHandler = *(DWORD*)"X264";//"XVID";
m_enc.param.lKey = 3;
m_enc.param.lFrameRate = 12;
m_enc.param.szConfigFile... m_enc.Config(GetSafeHwnd()); 用法:
m_enc.param.fccHandler = *(DWORD*)"X264";//"XVID";
m_enc.param.lKey = 3;
m_enc.param.lFrameRate = 12;
m_enc.Open(pbih);
m_enc.AddFrame(tick, pbih, pbits, &Buf);
if (!Buf.IsEmpty())
{
//写入avi文件
} \**************************************************************************************************/ #include <StringN.h>
#include <auto_file.h>
#include <mmsystem.h>
#include <vfw.h>
#include <__dbg.h>
#include <HBuffer.h>
#include <auto_folder.h>
#include <auto_buffer.h> #pragma comment(lib, "vfw32.lib") typedef struct _AVIENC_CONFIGFILE
{
DWORD mask; //acfg
COMPVARS cv;
}AVIENC_CONFIGFILE; class auto_avienc
{
public:
struct
{
DWORD fccHandler; // handler of chosen compressor or
long lFrameRate; // 帧率
long lKey; // 关键帧数量
long lDataRate; //码率
long lQ; //质量
char szConfigFile[_MAX_PATH]; //文件
DWORD bChooseFccHandler : 1; // 选择压缩编码器
}param; struct
{
ULONGLONG uTickBegin; //开始帧的时刻
ULONGLONG uTickEnd; //最后一帧时刻
LONG lFrameIndex; //最后一帧索引
BITMAPINFO in;
BITMAPINFO out;
}info; auto_buffer m_Buf; //压缩和状态内存, ICINFO, STATE HIC m_hic;
BOOL m_bLoaded; //是否装载过配置
public: auto_avienc()
{
__memzero(param);
__memzero(info); m_hic = 0;
m_bLoaded = 0; param.fccHandler = *(DWORD*)"WMV3";
param.lFrameRate = 15;
param.lKey = 20;
param.lDataRate = 0;
param.bChooseFccHandler = 1;
} ~auto_avienc()
{
Close();
} /**************************************************************************************************\
* BOOL : 2013年9月1日 是否打开
* IsOpen :
\**************************************************************************************************/
BOOL IsOpen()
{
return m_hic != 0;
} /**************************************************************************************************\
* void : 2013年9月1日 是否成功没有关系
* LoadConfig :
\**************************************************************************************************/
void LoadConfig()
{
if (param.szConfigFile[0] == 0 || m_bLoaded)
return; if (!auto_file::Read(param.szConfigFile, &m_Buf))
return; if (m_Buf.m_p == 0 || m_Buf.m_size == 0 || m_Buf.m_size < sizeof(ICINFO))
{
m_Buf.free();
return;
} ICINFO* pi = (ICINFO*)m_Buf.m_p;
if (pi->dwSize != sizeof(ICINFO))
{
m_Buf.free();
return;
} if (param.fccHandler == 0 || param.bChooseFccHandler) //使用保存的编码器类型
{
param.fccHandler = pi->fccHandler; __trace_file "usering %X", param.fccHandler);__trace_end;
} m_bLoaded = TRUE;
} /**************************************************************************************************\
* BOOL : 2013年8月31日 这个检查是否配置正确,如果配置正确,则使用,不正确则不使用
* CheckConfig :
\**************************************************************************************************/
BOOL CheckConfig()
{
if (m_hic == 0)
return FALSE; if (!m_Buf)
return FALSE; ICINFO in = {0}; if (0 == ICGetInfo(m_hic, &in, sizeof(in)))
{
__trace_file "");__trace_end;
return FALSE;
} ICINFO* pi = (ICINFO*)(LPBYTE)m_Buf;
if (memcmp(pi, &in, sizeof(in)) != 0)
{
__trace_file "");__trace_end;
return FALSE;
} DWORD size = ICGetStateSize(m_hic); if (size != m_Buf.m_size - sizeof(ICINFO))
{
__trace_file "");__trace_end;
return FALSE;
} LPBYTE pState = (LPBYTE)(m_Buf.m_p) + sizeof(ICINFO); if (0 == ICSetState(m_hic, pState, size))
{
__trace_file "");__trace_end;
return FALSE;
} __trace_file "");__trace_end; return TRUE;
} /**************************************************************************************************\
* BOOL : 2013年8月31日 配置信息,导入以前保存的配置,如果导入的配置不对,则重新显示对话框配置
* Config :
* HWND hwnd : 2013年9月1日 修改,如果fccHandler是0,则显示配置也选择的对话框。
如果fccHandler指定,则只配置指定的
\**************************************************************************************************/
BOOL Config(HWND hwnd)
{
LoadConfig(); //可能没装载就调用了Config //2013年9月1日
HIC hic = 0;
if (param.fccHandler == 0 || param.bChooseFccHandler)
{
COMPVARS cv = {0};
cv.cbSize = sizeof(cv);
cv.fccType = ICTYPE_VIDEO;
cv.fccHandler = param.fccHandler;
cv.dwFlags = ICMF_COMPVARS_VALID;
if (!ICCompressorChoose(hwnd, ICMF_CHOOSE_ALLCOMPRESSORS|ICMF_CHOOSE_KEYFRAME|ICMF_CHOOSE_DATARATE, 0, 0, &cv, 0))
{
__trace_file "%X", param.fccHandler);__trace_end;
return FALSE;
} hic = cv.hic;
param.fccHandler = cv.fccHandler;
if (cv.lKey)
param.lKey = cv.lKey;
if (cv.lDataRate)
param.lDataRate = cv.lDataRate;
}
else
{
hic = ICOpen(ICTYPE_VIDEO, param.fccHandler, ICMODE_COMPRESS|ICMODE_FASTCOMPRESS); if (hic == 0)
return FALSE; //下面这句话可能不对,因为XVID这个返回没有,但是实际上有对话框
//if (ICERR_OK != ICQueryConfigure(hic))
// goto LABLE_CLOSE_HIC; if (ICERR_OK != ICConfigure(hic, hwnd))
{
ICClose(hic);
return FALSE;
}
} //保存配置,用于下次使用
BOOL bSucc = 0; int size = ICGetStateSize(hic); LPBYTE p = m_Buf.alloc(size + sizeof(ICINFO));
if (p)
{
m_Buf.zero(); if (0 != ICGetInfo(hic, (ICINFO*)p, sizeof(ICINFO)))
{
p += sizeof(ICINFO); if (ICERR_OK == ICGetState(hic, p, size))
{
if (param.szConfigFile[0])
{
auto_folder af(param.szConfigFile); if (auto_file::Write(param.szConfigFile, &m_Buf))
{
bSucc = TRUE;
}
}
else
{
bSucc = TRUE;
}
}
}
} ICClose(hic); if (!bSucc)
{
m_Buf.free();
} return bSucc;
} /**************************************************************************************************\
* BOOL : 2013年8月31日 打开指定格式的录像,准备录像
* Open :
* LPBITMAPINFOHEADER pbih :
\**************************************************************************************************/
BOOL Open(LPBITMAPINFOHEADER pbih)
{
//关闭
Close(); info.in.bmiHeader = *pbih;
info.out.bmiHeader = *pbih; //初始化压缩类型
if (param.fccHandler == 0)
param.fccHandler = *(DWORD*)"XVID"; //装载配置,如果设置了 ,则自动更新为保存中的fccHandler
//LoadConfig(); m_hic = ICOpen(ICTYPE_VIDEO, param.fccHandler, ICMODE_COMPRESS|ICMODE_FASTCOMPRESS); if (m_hic == 0)
return FALSE; __trace_file "fcc = %X", param.fccHandler);__trace_end; CheckConfig(); if (ICERR_OK != ICCompressGetFormat(m_hic, &info.in, &info.out))
return FALSE; if (ICERR_OK != ICCompressBegin(m_hic, &info.in, &info.out))
return FALSE; return TRUE;
} /**************************************************************************************************\
* BOOL : 增添一帧,根据时刻判断帧率,及是否抛弃
* AddFrame :
* DWORD dwTick :
* LPBITMAPINFOHEADER pbih :
* LPBYTE pBits :
* HBuffer* pBufOut :
\**************************************************************************************************/
BOOL AddFrame(DWORD dwTick, LPBITMAPINFOHEADER pbih, LPBYTE pBits, HBuffer* pBufOut)
{
if (m_hic == 0)
return FALSE; if (pbih->biWidth != info.in.bmiHeader.biWidth
|| pbih->biHeight != info.in.bmiHeader.biHeight
|| pbih->biBitCount != info.in.bmiHeader.biBitCount
)
{
return FALSE;
} if (dwTick == 0)
{
if (info.uTickBegin == 0)
{
info.uTickBegin = GetTickCount();
info.uTickEnd = info.uTickBegin;
info.lFrameIndex = 0;
}
else
{
info.lFrameIndex ++;
}
}
else
{
ULONGLONG tick_end = 0;
if (info.uTickBegin == 0)
{
info.uTickBegin = dwTick;
tick_end = dwTick;
}
else if (dwTick < info.uTickEnd)
{
//循环了
tick_end = dwTick + 0x100000000;
}
else
{
tick_end = dwTick;
} int dIndex = (int)(double((LONGLONG)(tick_end - info.uTickBegin)) / 1000.0 * param.lFrameRate + 0.5);
if (dIndex && dIndex <= info.lFrameIndex)
{
return TRUE;
} info.uTickEnd = tick_end;
info.lFrameIndex = dIndex;
} LPBYTE pOut = pBufOut->GetBuffer(__max(info.out.bmiHeader.biSizeImage, info.in.bmiHeader.biSizeImage));
if (pOut == 0)
return FALSE; DWORD dwCkID = 0;
DWORD dwCompFlags = 0;
DWORD dwQuality = 0; if(ICCompress(m_hic,
((info.lFrameIndex % param.lKey) == 0 ? ICCOMPRESS_KEYFRAME : 0),
&info.out.bmiHeader,
pOut,
pbih,
(unsigned char *)pBits,
&dwCkID,
&dwCompFlags,
(LONG)info.lFrameIndex,
0,
dwQuality,
NULL,
NULL
) != ICERR_OK)
{
return FALSE;
} //__trace_file "size=%d\r\n", info.out.bmiHeader.biSizeImage);__trace_end; pBufOut->m_nBuffer = info.out.bmiHeader.biSizeImage; return TRUE;
} /**************************************************************************************************\
* void : 2013年8月31日 关闭
* Close :
\**************************************************************************************************/
void Close()
{
if (m_hic)
{
ICCompressEnd(m_hic); ICClose(m_hic); m_hic = 0;
}
} }; #endif

最新文章

  1. webpack 打包一个简单react组件
  2. 第二篇:Retrofit调用流程图和使用到的设计模式
  3. TextEdit 回车事件
  4. YARN内存使用优化配置
  5. Codeforce Gym 100015I Identity Checker 暴力
  6. Android开发时提示Your project contains error(s),please fix them be
  7. 题目1433:FatMouse (未解决)
  8. Poj 3683-Priest John&#39;s Busiest Day 2-sat,拓扑排序
  9. photoshopcs5 win7安装报错的解决
  10. sql语句实现随机取n条数据(转)
  11. 新技术探究之 GraphQL
  12. mybatis的逆向工程——命令行方式
  13. 【Unity与23种设计模式】代理模式(Proxy)
  14. c语言博客作业-指针
  15. swiper常见问题
  16. spring cloud_1_mm_eureka
  17. Oracle数据库---用户与角色
  18. PHP开发web应用安全总结
  19. C_求质数
  20. Luogu P3959 宝藏

热门文章

  1. 搭建LNAMP环境(七)- PHP7源码安装Memcached和Memcache拓展
  2. WCF学习之旅—实现支持REST客户端应用(二十四)
  3. meta标签
  4. golang 使用 iota
  5. Http协议相关内容
  6. ASP.NET 截获服务器生成的将要发送到客户端的html的方法
  7. 求解第N个素数
  8. 本博客现已迁移到chuxiuhong.com
  9. java设计模式之简单工厂模式
  10. JavaScript弹窗