202 lines
5.5 KiB
C
202 lines
5.5 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* capframe.c
|
||
|
*
|
||
|
* Single frame capture
|
||
|
*
|
||
|
* Microsoft Video for Windows Sample Capture Class
|
||
|
*
|
||
|
* Copyright (c) 1992, 1993 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* You have a royalty-free right to use, modify, reproduce and
|
||
|
* distribute the Sample Files (and/or any modified version) in
|
||
|
* any way you find useful, provided that you agree that
|
||
|
* Microsoft has no warranty obligations or liability for any
|
||
|
* Sample Application Files which are modified.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#define INC_OLE2
|
||
|
#pragma warning(disable:4103)
|
||
|
#include <windows.h>
|
||
|
#include <windowsx.h>
|
||
|
#include <win32.h>
|
||
|
#include <mmsystem.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <ctype.h>
|
||
|
#include <string.h>
|
||
|
#include <vfw.h>
|
||
|
#include <mmddk.h>
|
||
|
|
||
|
#include "ivideo32.h"
|
||
|
#include "avicapi.h"
|
||
|
|
||
|
#include "mmdebug.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define DSTATUS(lpcs, sz) statusUpdateStatus(lpcs, IDS_CAP_INFO, (LPTSTR) TEXT(sz))
|
||
|
#else
|
||
|
#define DSTATUS(lpcs, sz)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* SingleFrameCaptureOpen
|
||
|
*
|
||
|
*/
|
||
|
BOOL FAR PASCAL SingleFrameCaptureOpen (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
UINT err;
|
||
|
if ((lpcs->fCaptureFlags & CAP_fCapturingNow) || (lpcs->fCaptureFlags & CAP_fFrameCapturingNow)) {
|
||
|
err = IDS_CAP_FILE_OPEN_ERROR;
|
||
|
goto EarlyExit;
|
||
|
}
|
||
|
|
||
|
#ifdef NEW_COMPMAN
|
||
|
/* Warm up the compressor function */
|
||
|
if (lpcs->CompVars.hic) {
|
||
|
if (ICSeqCompressFrameStart(&lpcs->CompVars, lpcs->lpBitsInfo) == FALSE) {
|
||
|
err = IDS_CAP_COMPRESSOR_ERROR;
|
||
|
goto EarlyExit;
|
||
|
}
|
||
|
// Kludge, offset the lpBitsOut ptr
|
||
|
// Compman allocates the compress buffer too large by
|
||
|
// 2048 + 16 so we will still have room
|
||
|
((LPBYTE) lpcs->CompVars.lpBitsOut) += 8;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (!CapFileInit(lpcs)) {
|
||
|
err = IDS_CAP_FILE_OPEN_ERROR;
|
||
|
goto EarlyExit;
|
||
|
}
|
||
|
|
||
|
lpcs->fCaptureFlags |= (CAP_fCapturingNow | CAP_fFrameCapturingNow);
|
||
|
lpcs->dwReturn = DV_ERR_OK;
|
||
|
|
||
|
statusUpdateStatus(lpcs, IDS_CAP_BEGIN); // Always the first message
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
EarlyExit:
|
||
|
errorUpdateError(lpcs, (UINT) err);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* SingleFrameCaptureClose
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
BOOL FAR PASCAL SingleFrameCaptureClose (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
|
||
|
if ((!(lpcs->fCaptureFlags & CAP_fCapturingNow)) && (!(lpcs->fCaptureFlags & CAP_fFrameCapturingNow))) {
|
||
|
errorUpdateError(lpcs, IDS_CAP_FILE_OPEN_ERROR);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
AVIFileFini(lpcs, TRUE /* fWroteJunkChunks */, FALSE /* fAbort */);
|
||
|
|
||
|
#ifdef NEW_COMPMAN
|
||
|
if (lpcs->CompVars.hic) {
|
||
|
// Kludge, offset the lpBitsOut ptr
|
||
|
if (lpcs->CompVars.lpBitsOut)
|
||
|
((LPBYTE) lpcs->CompVars.lpBitsOut) -= 8;
|
||
|
ICSeqCompressFrameEnd(&lpcs->CompVars);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
lpcs->fCapFileExists = (lpcs->dwReturn == DV_ERR_OK);
|
||
|
lpcs->fCaptureFlags &= ~(CAP_fCapturingNow | CAP_fFrameCapturingNow);
|
||
|
|
||
|
statusUpdateStatus(lpcs, IDS_CAP_END); // Always the last message
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* SingleFrameCapture
|
||
|
*
|
||
|
* Append to the open single frame capture file.
|
||
|
*/
|
||
|
BOOL FAR PASCAL SingleFrameCapture (LPCAPSTREAM lpcs)
|
||
|
{
|
||
|
LPVIDEOHDR lpVidHdr = &lpcs->VidHdr;
|
||
|
BOOL fOK = FALSE;
|
||
|
DWORD dwBytesUsed;
|
||
|
BOOL fKeyFrame;
|
||
|
LPSTR lpData;
|
||
|
|
||
|
if ((!(lpcs->fCaptureFlags & CAP_fCapturingNow)) ||
|
||
|
(!((lpcs->fCaptureFlags & CAP_fStepCapturingNow) || (lpcs->fCaptureFlags & CAP_fFrameCapturingNow)))
|
||
|
) {
|
||
|
errorUpdateError(lpcs, IDS_CAP_FILE_OPEN_ERROR);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
videoFrame (lpcs->hVideoIn, &lpcs->VidHdr);
|
||
|
InvalidateRect (lpcs->hwnd, NULL, TRUE);
|
||
|
|
||
|
if (lpVidHdr->dwBytesUsed) {
|
||
|
UINT wError;
|
||
|
BOOL bPending = FALSE;
|
||
|
|
||
|
if (lpcs->CallbackOnVideoFrame)
|
||
|
lpcs->CallbackOnVideoFrame (lpcs->hwnd, lpVidHdr);
|
||
|
|
||
|
// Prepend a RIFF chunk
|
||
|
((LPRIFF)lpVidHdr->lpData)[-1].dwType = MAKEAVICKID(cktypeDIBbits, 0);
|
||
|
((LPRIFF)lpVidHdr->lpData)[-1].dwSize = lpcs->VidHdr.dwBytesUsed;
|
||
|
|
||
|
#ifdef NEW_COMPMAN
|
||
|
//
|
||
|
// We are automatically compressing during capture, so
|
||
|
// compress the frame before we pass it on to be written
|
||
|
//
|
||
|
if (lpcs->CompVars.hic)
|
||
|
{
|
||
|
LPRIFF priff;
|
||
|
|
||
|
dwBytesUsed = 0;
|
||
|
lpData = ICSeqCompressFrame(&lpcs->CompVars, 0,
|
||
|
lpVidHdr->lpData,
|
||
|
&fKeyFrame,
|
||
|
&dwBytesUsed);
|
||
|
|
||
|
priff = ((LPRIFF)lpData) -1;
|
||
|
priff->dwType = MAKEAVICKID(cktypeDIBbits, 0);
|
||
|
priff->dwSize = dwBytesUsed;
|
||
|
}
|
||
|
else {
|
||
|
lpData = lpVidHdr->lpData;
|
||
|
dwBytesUsed = lpVidHdr->dwBytesUsed;
|
||
|
fKeyFrame = lpVidHdr->dwFlags & VHDR_KEYFRAME;
|
||
|
}
|
||
|
#endif // NEW_COMPMAN
|
||
|
|
||
|
// AVIWriteVideoFrame can compress while writing,
|
||
|
// in this case, the dwBytesUsed and KeyFrame settings
|
||
|
// may be modified, so pick these up after the write is finished
|
||
|
|
||
|
AVIWriteVideoFrame (lpcs,
|
||
|
lpData,
|
||
|
dwBytesUsed,
|
||
|
fKeyFrame,
|
||
|
(UINT)-1, 0, &wError, &bPending);
|
||
|
if (wError) {
|
||
|
errorUpdateError(lpcs, wError);
|
||
|
}
|
||
|
else {
|
||
|
fOK = TRUE;
|
||
|
statusUpdateStatus (lpcs, IDS_CAP_STAT_CAP_L_FRAMES,
|
||
|
lpcs->dwVideoChunkCount);
|
||
|
}
|
||
|
} // if the frame is done
|
||
|
else
|
||
|
errorUpdateError (lpcs, IDS_CAP_RECORDING_ERROR2);
|
||
|
|
||
|
return fOK;
|
||
|
}
|