📄 api.c
字号:
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
return 0;
return asiw.dwStart;
}
/***********************************************************************
* AVIStreamLength (AVIFILE.131)
* AVIStreamLength (AVIFIL32.@)
*/
LONG WINAPI AVIStreamLength(PAVISTREAM pstream)
{
AVISTREAMINFOW asiw;
TRACE("(%p)\n", pstream);
if (pstream == NULL)
return 0;
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
return 0;
return asiw.dwLength;
}
/***********************************************************************
* AVIStreamSampleToTime (AVIFILE.133)
* AVIStreamSampleToTime (AVIFIL32.@)
*/
LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pstream, LONG lSample)
{
AVISTREAMINFOW asiw;
LONG time;
TRACE("(%p,%d)\n", pstream, lSample);
if (pstream == NULL)
return -1;
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
return -1;
if (asiw.dwRate == 0)
return -1;
/* limit to stream bounds */
if (lSample < asiw.dwStart)
lSample = asiw.dwStart;
if (lSample > asiw.dwStart + asiw.dwLength)
lSample = asiw.dwStart + asiw.dwLength;
if (asiw.dwRate / asiw.dwScale < 1000)
time = (LONG)(((float)lSample * asiw.dwScale * 1000) / asiw.dwRate);
else
time = (LONG)(((float)lSample * asiw.dwScale * 1000 + (asiw.dwRate - 1)) / asiw.dwRate);
TRACE(" -> %d\n",time);
return time;
}
/***********************************************************************
* AVIStreamTimeToSample (AVIFILE.132)
* AVIStreamTimeToSample (AVIFIL32.@)
*/
LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
{
AVISTREAMINFOW asiw;
ULONG sample;
TRACE("(%p,%d)\n", pstream, lTime);
if (pstream == NULL || lTime < 0)
return -1;
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
return -1;
if (asiw.dwScale == 0)
return -1;
if (asiw.dwRate / asiw.dwScale < 1000)
sample = (LONG)((((float)asiw.dwRate * lTime) / (asiw.dwScale * 1000)));
else
sample = (LONG)(((float)asiw.dwRate * lTime + (asiw.dwScale * 1000 - 1)) / (asiw.dwScale * 1000));
/* limit to stream bounds */
if (sample < asiw.dwStart)
sample = asiw.dwStart;
if (sample > asiw.dwStart + asiw.dwLength)
sample = asiw.dwStart + asiw.dwLength;
TRACE(" -> %d\n", sample);
return sample;
}
/***********************************************************************
* AVIBuildFilter (AVIFIL32.@)
* AVIBuildFilterA (AVIFIL32.@)
* AVIBuildFilter (AVIFILE.123)
*/
HRESULT WINAPI AVIBuildFilterA(LPSTR szFilter, LONG cbFilter, BOOL fSaving)
{
LPWSTR wszFilter;
HRESULT hr;
TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);
/* check parameters */
if (szFilter == NULL)
return AVIERR_BADPARAM;
if (cbFilter < 2)
return AVIERR_BADSIZE;
szFilter[0] = 0;
szFilter[1] = 0;
wszFilter = HeapAlloc(GetProcessHeap(), 0, cbFilter * sizeof(WCHAR));
if (wszFilter == NULL)
return AVIERR_MEMORY;
hr = AVIBuildFilterW(wszFilter, cbFilter, fSaving);
if (SUCCEEDED(hr)) {
WideCharToMultiByte(CP_ACP, 0, wszFilter, cbFilter,
szFilter, cbFilter, NULL, NULL);
}
HeapFree(GetProcessHeap(), 0, wszFilter);
return hr;
}
/***********************************************************************
* AVIBuildFilterW (AVIFIL32.@)
*/
HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving)
{
static const WCHAR szClsid[] = {'C','L','S','I','D',0};
static const WCHAR szExtensionFmt[] = {';','*','.','%','s',0};
static const WCHAR szAVIFileExtensions[] =
{'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};
AVIFilter *lp;
WCHAR szAllFiles[40];
WCHAR szFileExt[10];
WCHAR szValue[128];
HKEY hKey;
DWORD n, i;
LONG size;
DWORD count = 0;
TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);
/* check parameters */
if (szFilter == NULL)
return AVIERR_BADPARAM;
if (cbFilter < 2)
return AVIERR_BADSIZE;
lp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_FILTERS * sizeof(AVIFilter));
if (lp == NULL)
return AVIERR_MEMORY;
/*
* 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
* extensions and CLSID's
* 2. iterate over collected CLSID's and copy its description and its
* extensions to szFilter if it fits
*
* First filter is named "All multimedia files" and its filter is a
* collection of all possible extensions except "*.*".
*/
if (RegOpenKeyW(HKEY_CLASSES_ROOT, szAVIFileExtensions, &hKey) != S_OK) {
HeapFree(GetProcessHeap(), 0, lp);
return AVIERR_ERROR;
}
for (n = 0;RegEnumKeyW(hKey, n, szFileExt, sizeof(szFileExt)) == S_OK;n++) {
/* get CLSID to extension */
size = sizeof(szValue)/sizeof(szValue[0]);
if (RegQueryValueW(hKey, szFileExt, szValue, &size) != S_OK)
break;
/* search if the CLSID is already known */
for (i = 1; i <= count; i++) {
if (lstrcmpW(lp[i].szClsid, szValue) == 0)
break; /* a new one */
}
if (count - i == -1U) {
/* it's a new CLSID */
/* FIXME: How do we get info's about read/write capabilities? */
if (count >= MAX_FILTERS) {
/* try to inform user of our full fixed size table */
ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS);
break;
}
lstrcpyW(lp[i].szClsid, szValue);
count++;
}
/* append extension to the filter */
wsprintfW(szValue, szExtensionFmt, szFileExt);
if (lp[i].szExtensions[0] == 0)
lstrcatW(lp[i].szExtensions, szValue + 1);
else
lstrcatW(lp[i].szExtensions, szValue);
/* also append to the "all multimedia"-filter */
if (lp[0].szExtensions[0] == 0)
lstrcatW(lp[0].szExtensions, szValue + 1);
else
lstrcatW(lp[0].szExtensions, szValue);
}
RegCloseKey(hKey);
/* 2. get descriptions for the CLSIDs and fill out szFilter */
if (RegOpenKeyW(HKEY_CLASSES_ROOT, szClsid, &hKey) != S_OK) {
HeapFree(GetProcessHeap(), 0, lp);
return AVIERR_ERROR;
}
for (n = 0; n <= count; n++) {
/* first the description */
if (n != 0) {
size = sizeof(szValue)/sizeof(szValue[0]);
if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == S_OK) {
size = lstrlenW(szValue);
lstrcpynW(szFilter, szValue, cbFilter);
}
} else
size = LoadStringW(AVIFILE_hModule,IDS_ALLMULTIMEDIA,szFilter,cbFilter);
/* check for enough space */
size++;
if (cbFilter < size + lstrlenW(lp[n].szExtensions) + 2) {
szFilter[0] = 0;
szFilter[1] = 0;
HeapFree(GetProcessHeap(), 0, lp);
RegCloseKey(hKey);
return AVIERR_BUFFERTOOSMALL;
}
cbFilter -= size;
szFilter += size;
/* and then the filter */
lstrcpynW(szFilter, lp[n].szExtensions, cbFilter);
size = lstrlenW(lp[n].szExtensions) + 1;
cbFilter -= size;
szFilter += size;
}
RegCloseKey(hKey);
HeapFree(GetProcessHeap(), 0, lp);
/* add "All files" "*.*" filter if enough space left */
size = LoadStringW(AVIFILE_hModule, IDS_ALLFILES,
szAllFiles, sizeof(szAllFiles)) + 1;
if (cbFilter > size) {
int i;
/* replace '@' with \000 to separate description of filter */
for (i = 0; i < size && szAllFiles[i] != 0; i++) {
if (szAllFiles[i] == '@') {
szAllFiles[i] = 0;
break;
}
}
memcpy(szFilter, szAllFiles, size * sizeof(szAllFiles[0]));
szFilter += size;
szFilter[0] = 0;
return AVIERR_OK;
} else {
szFilter[0] = 0;
return AVIERR_BUFFERTOOSMALL;
}
}
static BOOL AVISaveOptionsFmtChoose(HWND hWnd)
{
LPAVICOMPRESSOPTIONS pOptions = SaveOpts.ppOptions[SaveOpts.nCurrent];
AVISTREAMINFOW sInfo;
TRACE("(%p)\n", hWnd);
if (pOptions == NULL || SaveOpts.ppavis[SaveOpts.nCurrent] == NULL) {
ERR(": bad state!\n");
return FALSE;
}
if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent],
&sInfo, sizeof(sInfo)))) {
ERR(": AVIStreamInfoW failed!\n");
return FALSE;
}
if (sInfo.fccType == streamtypeVIDEO) {
COMPVARS cv;
BOOL ret;
memset(&cv, 0, sizeof(cv));
if ((pOptions->dwFlags & AVICOMPRESSF_VALID) == 0) {
memset(pOptions, 0, sizeof(AVICOMPRESSOPTIONS));
pOptions->fccType = streamtypeVIDEO;
pOptions->fccHandler = comptypeDIB;
pOptions->dwQuality = (DWORD)ICQUALITY_DEFAULT;
}
cv.cbSize = sizeof(cv);
cv.dwFlags = ICMF_COMPVARS_VALID;
/*cv.fccType = pOptions->fccType; */
cv.fccHandler = pOptions->fccHandler;
cv.lQ = pOptions->dwQuality;
cv.lpState = pOptions->lpParms;
cv.cbState = pOptions->cbParms;
if (pOptions->dwFlags & AVICOMPRESSF_KEYFRAMES)
cv.lKey = pOptions->dwKeyFrameEvery;
else
cv.lKey = 0;
if (pOptions->dwFlags & AVICOMPRESSF_DATARATE)
cv.lDataRate = pOptions->dwBytesPerSecond / 1024; /* need kBytes */
else
cv.lDataRate = 0;
ret = ICCompressorChoose(hWnd, SaveOpts.uFlags, NULL,
SaveOpts.ppavis[SaveOpts.nCurrent], &cv, NULL);
if (ret) {
pOptions->fccHandler = cv.fccHandler;
pOptions->lpParms = cv.lpState;
pOptions->cbParms = cv.cbState;
pOptions->dwQuality = cv.lQ;
if (cv.lKey != 0) {
pOptions->dwKeyFrameEvery = cv.lKey;
pOptions->dwFlags |= AVICOMPRESSF_KEYFRAMES;
} else
pOptions->dwFlags &= ~AVICOMPRESSF_KEYFRAMES;
if (cv.lDataRate != 0) {
pOptions->dwBytesPerSecond = cv.lDataRate * 1024; /* need bytes */
pOptions->dwFlags |= AVICOMPRESSF_DATARATE;
} else
pOptions->dwFlags &= ~AVICOMPRESSF_DATARATE;
pOptions->dwFlags |= AVICOMPRESSF_VALID;
}
ICCompressorFree(&cv);
return ret;
} else if (sInfo.fccType == streamtypeAUDIO) {
ACMFORMATCHOOSEW afmtc;
MMRESULT ret;
LONG size;
/* FIXME: check ACM version -- Which version is needed? */
memset(&afmtc, 0, sizeof(afmtc));
afmtc.cbStruct = sizeof(afmtc);
afmtc.fdwStyle = 0;
afmtc.hwndOwner = hWnd;
acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &size);
if ((pOptions->cbFormat == 0 || pOptions->lpFormat == NULL) && size != 0) {
pOptions->lpFormat = HeapAlloc(GetProcessHeap(), 0, size);
pOptions->cbFormat = size;
} else if (pOptions->cbFormat < (DWORD)size) {
pOptions->lpFormat = HeapReAlloc(GetProcessHeap(), 0, pOptions->lpFormat, size);
pOptions->cbFormat = size;
}
if (pOptions->lpFormat == NULL)
return FALSE;
afmtc.pwfx = pOptions->lpFormat;
afmtc.cbwfx = pOptions->cbFormat;
size = 0;
AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],
sInfo.dwStart, &size);
if (size < (LONG)sizeof(PCMWAVEFORMAT))
size = sizeof(PCMWAVEFORMAT);
afmtc.pwfxEnum = HeapAlloc(GetProcessHeap(), 0, size);
if (afmtc.pwfxEnum != NULL) {
AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],
sInfo.dwStart, afmtc.pwfxEnum, &size);
afmtc.fdwEnum = ACM_FORMATENUMF_CONVERT;
}
ret = acmFormatChooseW(&afmtc);
if (ret == S_OK)
pOptions->dwFlags |= AVICOMPRESSF_VALID;
HeapFree(GetProcessHeap(), 0, afmtc.pwfxEnum);
return (ret == S_OK ? TRUE : FALSE);
} else {
ERR(": unknown streamtype 0x%08X\n", sInfo.fccType);
return FALSE;
}
}
static void AVISaveOptionsUpdate(HWND hWnd)
{
static const WCHAR szVideoFmt[]={'%','l','d','x','%','l','d','x','%','d',0};
static const WCHAR szAudioFmt[]={'%','s',' ','%','s',0};
WCHAR szFormat[128];
AVISTREAMINFOW sInfo;
LPVOID lpFormat;
LONG size;
TRACE("(%p)\n", hWnd);
SaveOpts.nCurrent = SendDlgItemMessageW(hWnd,IDC_STREAM,CB_GETCURSEL,0,0);
if (SaveOpts.nCurrent < 0)
return;
if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent], &sInfo, sizeof(sInfo))))
return;
AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,&size);
if (size > 0) {
szFormat[0] = 0;
/* read format to build format description string */
lpFormat = HeapAlloc(GetProcessHeap(), 0, size);
if (lpFormat != NULL) {
if (SUCCEEDED(AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,lpFormat, &size))) {
if (sInfo.fccType == streamtypeVIDEO) {
LPBITMAPINFOHEADER lpbi = lpFormat;
ICINFO icinfo;
wsprintfW(szFormat, szVideoFmt, lpbi->biWidth,
lpbi->biHeight, lpbi->biBitCount);
if (lpbi->biCompression != BI_RGB) {
HIC hic;
hic = ICLocate(ICTYPE_VIDEO, sInfo.fccHandler, lpFormat,
NULL, ICMODE_DECOMPRESS);
if (hic != NULL) {
if (ICGetInfo(hic, &icinfo, sizeof(icinfo)) == S_OK)
lstrcatW(szFormat, icinfo.szDescription);
ICClose(hic);
}
} else {
LoadStringW(AVIFILE_hModule, IDS_UNCOMPRESSED,
icinfo.szDescription, sizeof(icinfo.szDescription));
lstrcatW(szFormat, icinfo.szDescription);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -