📄 api.c
字号:
}
} else if (sInfo.fccType == streamtypeAUDIO) {
ACMFORMATTAGDETAILSW aftd;
ACMFORMATDETAILSW afd;
memset(&aftd, 0, sizeof(aftd));
memset(&afd, 0, sizeof(afd));
aftd.cbStruct = sizeof(aftd);
aftd.dwFormatTag = afd.dwFormatTag =
((PWAVEFORMATEX)lpFormat)->wFormatTag;
aftd.cbFormatSize = afd.cbwfx = size;
afd.cbStruct = sizeof(afd);
afd.pwfx = lpFormat;
if (acmFormatTagDetailsW(NULL, &aftd,
ACM_FORMATTAGDETAILSF_FORMATTAG) == S_OK) {
if (acmFormatDetailsW(NULL,&afd,ACM_FORMATDETAILSF_FORMAT) == S_OK)
wsprintfW(szFormat, szAudioFmt, afd.szFormat, aftd.szFormatTag);
}
}
}
HeapFree(GetProcessHeap(), 0, lpFormat);
}
/* set text for format description */
SetDlgItemTextW(hWnd, IDC_FORMATTEXT, szFormat);
/* Disable option button for unsupported streamtypes */
if (sInfo.fccType == streamtypeVIDEO ||
sInfo.fccType == streamtypeAUDIO)
EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), TRUE);
else
EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), FALSE);
}
}
static INT_PTR CALLBACK AVISaveOptionsDlgProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
DWORD dwInterleave;
BOOL bIsInterleaved;
INT n;
/*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
switch (uMsg) {
case WM_INITDIALOG:
SaveOpts.nCurrent = 0;
if (SaveOpts.nStreams == 1) {
EndDialog(hWnd, AVISaveOptionsFmtChoose(hWnd));
return TRUE;
}
/* add streams */
for (n = 0; n < SaveOpts.nStreams; n++) {
AVISTREAMINFOW sInfo;
AVIStreamInfoW(SaveOpts.ppavis[n], &sInfo, sizeof(sInfo));
SendDlgItemMessageW(hWnd, IDC_STREAM, CB_ADDSTRING,
0L, (LPARAM)sInfo.szName);
}
/* select first stream */
SendDlgItemMessageW(hWnd, IDC_STREAM, CB_SETCURSEL, 0, 0);
SendMessageW(hWnd, WM_COMMAND, MAKELONG(IDC_STREAM, CBN_SELCHANGE), (LPARAM)hWnd);
/* initialize interleave */
if (SaveOpts.ppOptions[0] != NULL &&
(SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_VALID)) {
bIsInterleaved = (SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_INTERLEAVE);
dwInterleave = SaveOpts.ppOptions[0]->dwInterleaveEvery;
} else {
bIsInterleaved = TRUE;
dwInterleave = 0;
}
CheckDlgButton(hWnd, IDC_INTERLEAVE, bIsInterleaved);
SetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, dwInterleave, FALSE);
EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY), bIsInterleaved);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
/* get data from controls and save them */
dwInterleave = GetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, NULL, 0);
bIsInterleaved = IsDlgButtonChecked(hWnd, IDC_INTERLEAVE);
for (n = 0; n < SaveOpts.nStreams; n++) {
if (SaveOpts.ppOptions[n] != NULL) {
if (bIsInterleaved) {
SaveOpts.ppOptions[n]->dwFlags |= AVICOMPRESSF_INTERLEAVE;
SaveOpts.ppOptions[n]->dwInterleaveEvery = dwInterleave;
} else
SaveOpts.ppOptions[n]->dwFlags &= ~AVICOMPRESSF_INTERLEAVE;
}
}
/* fall through */
case IDCANCEL:
EndDialog(hWnd, LOWORD(wParam) == IDOK);
break;
case IDC_INTERLEAVE:
EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY),
IsDlgButtonChecked(hWnd, IDC_INTERLEAVE));
break;
case IDC_STREAM:
if (HIWORD(wParam) == CBN_SELCHANGE) {
/* update control elements */
AVISaveOptionsUpdate(hWnd);
}
break;
case IDC_OPTIONS:
AVISaveOptionsFmtChoose(hWnd);
break;
};
return TRUE;
};
return FALSE;
}
/***********************************************************************
* AVISaveOptions (AVIFIL32.@)
*/
BOOL WINAPI AVISaveOptions(HWND hWnd, UINT uFlags, INT nStreams,
PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *ppOptions)
{
LPAVICOMPRESSOPTIONS pSavedOptions = NULL;
INT ret, n;
TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd, uFlags, nStreams,
ppavi, ppOptions);
/* check parameters */
if (nStreams <= 0 || ppavi == NULL || ppOptions == NULL)
return AVIERR_BADPARAM;
/* save options in case the user presses cancel */
if (ppOptions != NULL && nStreams > 1) {
pSavedOptions = HeapAlloc(GetProcessHeap(), 0, nStreams * sizeof(AVICOMPRESSOPTIONS));
if (pSavedOptions == NULL)
return FALSE;
for (n = 0; n < nStreams; n++) {
if (ppOptions[n] != NULL)
memcpy(pSavedOptions + n, ppOptions[n], sizeof(AVICOMPRESSOPTIONS));
}
}
SaveOpts.uFlags = uFlags;
SaveOpts.nStreams = nStreams;
SaveOpts.ppavis = ppavi;
SaveOpts.ppOptions = ppOptions;
ret = DialogBoxW(AVIFILE_hModule, MAKEINTRESOURCEW(IDD_SAVEOPTIONS),
hWnd, AVISaveOptionsDlgProc);
if (ret == -1)
ret = FALSE;
/* restore options when user pressed cancel */
if (pSavedOptions != NULL) {
if (ret == FALSE) {
for (n = 0; n < nStreams; n++) {
if (ppOptions[n] != NULL)
memcpy(ppOptions[n], pSavedOptions + n, sizeof(AVICOMPRESSOPTIONS));
}
}
HeapFree(GetProcessHeap(), 0, pSavedOptions);
}
return (BOOL)ret;
}
/***********************************************************************
* AVISaveOptionsFree (AVIFIL32.@)
* AVISaveOptionsFree (AVIFILE.124)
*/
HRESULT WINAPI AVISaveOptionsFree(INT nStreams,LPAVICOMPRESSOPTIONS*ppOptions)
{
TRACE("(%d,%p)\n", nStreams, ppOptions);
if (nStreams < 0 || ppOptions == NULL)
return AVIERR_BADPARAM;
for (; nStreams > 0; nStreams--) {
if (ppOptions[nStreams] != NULL) {
ppOptions[nStreams]->dwFlags &= ~AVICOMPRESSF_VALID;
if (ppOptions[nStreams]->lpParms != NULL) {
HeapFree(GetProcessHeap(), 0, ppOptions[nStreams]->lpParms);
ppOptions[nStreams]->lpParms = NULL;
ppOptions[nStreams]->cbParms = 0;
}
if (ppOptions[nStreams]->lpFormat != NULL) {
HeapFree(GetProcessHeap(), 0, ppOptions[nStreams]->lpFormat);
ppOptions[nStreams]->lpFormat = NULL;
ppOptions[nStreams]->cbFormat = 0;
}
}
}
return AVIERR_OK;
}
/***********************************************************************
* AVISaveVA (AVIFIL32.@)
*/
HRESULT WINAPI AVISaveVA(LPCSTR szFile, CLSID *pclsidHandler,
AVISAVECALLBACK lpfnCallback, int nStream,
PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
{
LPWSTR wszFile = NULL;
HRESULT hr;
int len;
TRACE("%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile), pclsidHandler,
lpfnCallback, nStream, ppavi, plpOptions);
if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
return AVIERR_BADPARAM;
/* convert ASCII string to Unicode and call Unicode function */
len = MultiByteToWideChar(CP_ACP, 0, szFile, -1, NULL, 0);
if (len <= 0)
return AVIERR_BADPARAM;
wszFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (wszFile == NULL)
return AVIERR_MEMORY;
MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len);
hr = AVISaveVW(wszFile, pclsidHandler, lpfnCallback,
nStream, ppavi, plpOptions);
HeapFree(GetProcessHeap(), 0, wszFile);
return hr;
}
/***********************************************************************
* AVIFILE_AVISaveDefaultCallback (internal)
*/
static BOOL WINAPI AVIFILE_AVISaveDefaultCallback(INT progress)
{
TRACE("(%d)\n", progress);
return FALSE;
}
/***********************************************************************
* AVISaveVW (AVIFIL32.@)
*/
HRESULT WINAPI AVISaveVW(LPCWSTR szFile, CLSID *pclsidHandler,
AVISAVECALLBACK lpfnCallback, int nStreams,
PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
{
LONG lStart[MAX_AVISTREAMS];
PAVISTREAM pOutStreams[MAX_AVISTREAMS];
PAVISTREAM pInStreams[MAX_AVISTREAMS];
AVIFILEINFOW fInfo;
AVISTREAMINFOW sInfo;
PAVIFILE pfile = NULL; /* the output AVI file */
LONG lFirstVideo = -1;
int curStream;
/* for interleaving ... */
DWORD dwInterleave = 0; /* interleave rate */
DWORD dwFileInitialFrames;
LONG lFileLength;
LONG lSampleInc;
/* for reading/writing the data ... */
LPVOID lpBuffer = NULL;
LONG cbBuffer; /* real size of lpBuffer */
LONG lBufferSize; /* needed bytes for format(s), etc. */
LONG lReadBytes;
LONG lReadSamples;
HRESULT hres;
TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile), pclsidHandler,
lpfnCallback, nStreams, ppavi, plpOptions);
if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
return AVIERR_BADPARAM;
if (nStreams >= MAX_AVISTREAMS) {
WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams, MAX_AVISTREAMS);
return AVIERR_INTERNAL;
}
if (lpfnCallback == NULL)
lpfnCallback = AVIFILE_AVISaveDefaultCallback;
/* clear local variable(s) */
for (curStream = 0; curStream < nStreams; curStream++) {
pInStreams[curStream] = NULL;
pOutStreams[curStream] = NULL;
}
/* open output AVI file (create it if it doesn't exist) */
hres = AVIFileOpenW(&pfile, szFile, OF_CREATE|OF_SHARE_EXCLUSIVE|OF_WRITE,
pclsidHandler);
if (FAILED(hres))
return hres;
AVIFileInfoW(pfile, &fInfo, sizeof(fInfo)); /* for dwCaps */
/* initialize our data structures part 1 */
for (curStream = 0; curStream < nStreams; curStream++) {
PAVISTREAM pCurStream = ppavi[curStream];
hres = AVIStreamInfoW(pCurStream, &sInfo, sizeof(sInfo));
if (FAILED(hres))
goto error;
/* search first video stream and check for interleaving */
if (sInfo.fccType == streamtypeVIDEO) {
/* remember first video stream -- needed for interleaving */
if (lFirstVideo < 0)
lFirstVideo = curStream;
} else if (!dwInterleave && plpOptions != NULL) {
/* check if any non-video stream wants to be interleaved */
WARN("options.flags=0x%X options.dwInterleave=%u\n",plpOptions[curStream]->dwFlags,plpOptions[curStream]->dwInterleaveEvery);
if (plpOptions[curStream] != NULL &&
plpOptions[curStream]->dwFlags & AVICOMPRESSF_INTERLEAVE)
dwInterleave = plpOptions[curStream]->dwInterleaveEvery;
}
/* create de-/compressed stream interface if needed */
pInStreams[curStream] = NULL;
if (plpOptions != NULL && plpOptions[curStream] != NULL) {
if (plpOptions[curStream]->fccHandler ||
plpOptions[curStream]->lpFormat != NULL) {
DWORD dwKeySave = plpOptions[curStream]->dwKeyFrameEvery;
if (fInfo.dwCaps & AVIFILECAPS_ALLKEYFRAMES)
plpOptions[curStream]->dwKeyFrameEvery = 1;
hres = AVIMakeCompressedStream(&pInStreams[curStream], pCurStream,
plpOptions[curStream], NULL);
plpOptions[curStream]->dwKeyFrameEvery = dwKeySave;
if (FAILED(hres) || pInStreams[curStream] == NULL) {
pInStreams[curStream] = NULL;
goto error;
}
/* test stream interface and update stream-info */
hres = AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
if (FAILED(hres))
goto error;
}
}
/* now handle streams which will only be copied */
if (pInStreams[curStream] == NULL) {
pCurStream = pInStreams[curStream] = ppavi[curStream];
AVIStreamAddRef(pCurStream);
} else
pCurStream = pInStreams[curStream];
lStart[curStream] = sInfo.dwStart;
} /* for all streams */
/* check that first video stream is the first stream */
if (lFirstVideo > 0) {
PAVISTREAM pTmp = pInStreams[lFirstVideo];
LONG lTmp = lStart[lFirstVideo];
pInStreams[lFirstVideo] = pInStreams[0];
pInStreams[0] = pTmp;
lStart[lFirstVideo] = lStart[0];
lStart[0] = lTmp;
lFirstVideo = 0;
}
/* allocate buffer for formats, data, etc. of an initial size of 64 kBytes*/
cbBuffer = 0x00010000;
lpBuffer = HeapAlloc(GetProcessHeap(), 0, cbBuffer);
if (lpBuffer == NULL) {
hres = AVIERR_MEMORY;
goto error;
}
AVIStreamInfoW(pInStreams[0], &sInfo, sizeof(sInfo));
lFileLength = sInfo.dwLength;
dwFileInitialFrames = 0;
if (lFirstVideo >= 0) {
/* check for correct version of the format
* -- need at least BITMAPINFOHEADER or newer
*/
lSampleInc = 1;
lBufferSize = cbBuffer;
hres = AVIStreamReadFormat(pInStreams[lFirstVideo], AVIStreamStart(pInStreams[lFirstVideo]), lpBuffer, &lBufferSize);
if (lBufferSize < (LONG)sizeof(BITMAPINFOHEADER))
hres = AVIERR_INTERNAL;
if (FAILED(hres))
goto error;
} else /* use one second blocks for interleaving if no video present */
lSampleInc = AVIStreamTimeToSample(pInStreams[0], 1000000);
/* create output streams */
for (curStream = 0; curStream < nStreams; curStream++) {
AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
sInfo.dwInitialFrames = 0;
if (dwInterleave != 0 && curStream > 0 && sInfo.fccType != streamtypeVIDEO) {
/* 750 ms initial frames for non-video streams */
sInfo.dwInitialFrames = AVIStreamTimeToSample(pInStreams[0], 750);
}
hres = AVIFileCreateStreamW(pfile, &pOutStreams[curStream], &sInfo);
if (pOutStreams[curStream] != NULL && SUCCEEDED(hres)) {
/* copy initial format for this stream */
lBufferSize = cbBuffer;
hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
lpBuffer, &lBufferSize);
if (FAILED(hres))
goto error;
hres = AVIStreamSetFormat(pOutStreams[curStream], 0, lpBuffer, lBufferSize);
if (FAILED(hres))
goto error;
/* try to copy stream handler data */
lBufferSize = cbBuffer;
hres = AVIStreamReadData(pInStreams[curStream], ckidSTREAMHANDLERDATA,
lpBuffer, &lBufferSize);
if (SUCCEEDED(hres) && lBufferSize > 0) {
hres = AVIStreamWriteData(pOutStreams[curStream],ckidSTREAMHANDLERDATA,
lpBuffer, lBufferSize);
if (FAILED(hres))
goto error;
}
if (dwFileInitialFrames < sInfo.dwInitialFrames)
dwFileInitialFrames = sInfo.dwInitialFrames;
lReadBytes =
AVIStreamSampleToSample(pOutStreams[0], pInStreams[curStream],
sInfo.dwLength);
if (lFileLength < lReadBytes)
lFileLength = lReadBytes;
} else {
/* creation of de-/compression stream interface failed */
WARN("creation of (de-)compression stream failed for stream %d\n",curStream);
AVIStreamRelease(pInStreams[curStream]);
if (curStream + 1 >= nStreams) {
/* move the others one up */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -