📄 amcap.cpp
字号:
//------------------------------------------------------------------------------
// File: AMCap.cpp
//
// Desc: Audio/Video Capture sample for DirectShow
//
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include "stdafx.h"
#include <dbt.h>
#include <mmreg.h>
#include <msacm.h>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <commdlg.h>
#include <strsafe.h>
#include "stdafx.h"
#include "amcap.h"
#include "status.h"
#include "crossbar.h"
#include "SampleCGB.h"
#include "..\\..\\Common\\dshowutil.cpp" // Helper functions
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
#define ABS(x) (((x) > 0) ? (x) : -(x))
// An application can advertise the existence of its filter graph
// by registering the graph with a global Running Object Table (ROT).
// The GraphEdit application can detect and remotely view the running
// filter graph, allowing you to 'spy' on the graph with GraphEdit.
//
// To enable registration in this sample, define REGISTER_FILTERGRAPH.
//
#ifdef DEBUG
#define REGISTER_FILTERGRAPH
#endif
//------------------------------------------------------------------------------
// Global data
//------------------------------------------------------------------------------
HINSTANCE ghInstApp=0;
HACCEL ghAccel=0;
HFONT ghfontApp=0;
TEXTMETRIC gtm={0};
TCHAR gszAppName[]=TEXT("AMCAP");
HWND ghwndApp=0, ghwndStatus=0;
HDEVNOTIFY ghDevNotify=0;
PUnregisterDeviceNotification gpUnregisterDeviceNotification=0;
PRegisterDeviceNotification gpRegisterDeviceNotification=0;
DWORD g_dwGraphRegister=0;
struct _capstuff
{
WCHAR wszCaptureFile[_MAX_PATH];
WORD wCapFileSize; // size in Meg
ISampleCaptureGraphBuilder *pBuilder;
IVideoWindow *pVW;
IMediaEventEx *pME;
IAMDroppedFrames *pDF;
IAMVideoCompression *pVC;
IAMVfwCaptureDialogs *pDlg;
IAMStreamConfig *pASC; // for audio cap
IAMStreamConfig *pVSC; // for video cap
IBaseFilter *pRender;
IBaseFilter *pVCap, *pACap;
IGraphBuilder *pFg;
IFileSinkFilter *pSink;
IConfigAviMux *pConfigAviMux;
int iMasterStream;
BOOL fCaptureGraphBuilt;
BOOL fPreviewGraphBuilt;
BOOL fCapturing;
BOOL fPreviewing;
BOOL fMPEG2;
BOOL fCapAudio;
BOOL fCapCC;
BOOL fCCAvail;
BOOL fCapAudioIsRelevant;
bool fDeviceMenuPopulated;
IMoniker *rgpmVideoMenu[10];
IMoniker *rgpmAudioMenu[10];
IMoniker *pmVideo;
IMoniker *pmAudio;
double FrameRate;
BOOL fWantPreview;
long lCapStartTime;
long lCapStopTime;
WCHAR wachFriendlyName[120];
BOOL fUseTimeLimit;
BOOL fUseFrameRate;
DWORD dwTimeLimit;
int iFormatDialogPos;
int iSourceDialogPos;
int iDisplayDialogPos;
int iVCapDialogPos;
int iVCrossbarDialogPos;
int iTVTunerDialogPos;
int iACapDialogPos;
int iACrossbarDialogPos;
int iTVAudioDialogPos;
int iVCapCapturePinDialogPos;
int iVCapPreviewPinDialogPos;
int iACapCapturePinDialogPos;
long lDroppedBase;
long lNotBase;
BOOL fPreviewFaked;
CCrossbar *pCrossbar;
int iVideoInputMenuPos;
LONG NumberOfVideoInputs;
HMENU hMenuPopup;
int iNumVCapDevices;
} gcap;
// implements IAMCopyCaptureFileProgress
//
class CProgress : public IAMCopyCaptureFileProgress
{
public:
CProgress()
{
};
~CProgress()
{
};
STDMETHODIMP_(ULONG) AddRef()
{
return 1;
};
STDMETHODIMP_(ULONG) Release()
{
return 0;
};
STDMETHODIMP QueryInterface(REFIID iid, void **p)
{
if (p == NULL)
{
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*p = reinterpret_cast<IUnknown*>(this);
AddRef();
return S_OK;
}
else if (iid == IID_IAMCopyCaptureFileProgress)
{
*p = reinterpret_cast<IAMCopyCaptureFileProgress*>(this);
AddRef();
return S_OK;
}
else
{
return E_NOINTERFACE;
}
};
STDMETHODIMP Progress(int i)
{
TCHAR tach[80];
HRESULT hr = StringCchPrintf(tach, 80, TEXT("Save File Progress: %d%%\0"), i);
statusUpdateStatus(ghwndStatus, tach);
return S_OK;
};
};
//------------------------------------------------------------------------------
// Function Prototypes
//------------------------------------------------------------------------------
typedef LONG(PASCAL *LPWNDPROC)(HWND, UINT, WPARAM, LPARAM); // pointer to a window procedure
LONG WINAPI AppWndProc(HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam);
LONG PASCAL AppCommand(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void ErrMsg(LPTSTR sz,...);
BOOL SetCaptureFile(HWND hWnd);
BOOL SaveCaptureFile(HWND hWnd);
BOOL AllocCaptureFile(HWND hWnd);
int DoDialog(HWND hwndParent, int DialogID, DLGPROC fnDialog, long lParam);
int FAR PASCAL AllocCapFileProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
int FAR PASCAL FrameRateProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
int FAR PASCAL TimeLimitProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
int FAR PASCAL PressAKeyProc(HWND hDlg, UINT Message, UINT wParam, LONG lParam);
void TearDownGraph(void);
BOOL BuildCaptureGraph();
BOOL BuildPreviewGraph();
void UpdateStatus(BOOL fAllStats);
void AddDevicesToMenu();
void ChooseDevices(TCHAR *szVideo, TCHAR *szAudio);
void ChooseDevices(IMoniker *pmVideo, IMoniker *pmAudio);
void ChooseFrameRate();
BOOL InitCapFilters();
void FreeCapFilters();
BOOL StopPreview();
BOOL StartPreview();
BOOL StopCapture();
DWORDLONG GetSize(LPCTSTR tach);
void MakeMenuOptions();
void OnClose();
//------------------------------------------------------------------------------
// Name: SetAppCaption()
// Desc: Set the caption to be the application name followed by the capture file
//------------------------------------------------------------------------------
void SetAppCaption()
{
TCHAR tach[_MAX_PATH + 80];
StringCchCopy(tach, NUMELMS(tach), gszAppName);
if(gcap.wszCaptureFile[0] != 0)
{
HRESULT hr = StringCchCat(tach, _MAX_PATH + 80, TEXT(" - "));
hr = StringCchCat(tach, _MAX_PATH + 80, gcap.wszCaptureFile);
}
SetWindowText(ghwndApp, tach);
}
/*----------------------------------------------------------------------------*\
| AppInit( hInst, hPrev) |
| |
| Description: |
| This is called when the application is first loaded into |
| memory. It performs all initialization that doesn't need to be done |
| once per instance. |
| |
| Arguments: |
| hInstance instance handle of current instance |
| hPrev instance handle of previous instance |
| |
| Returns: |
| TRUE if successful, FALSE if not |
| |
\*----------------------------------------------------------------------------*/
BOOL AppInit(HINSTANCE hInst, HINSTANCE hPrev, int sw)
{
WNDCLASS cls;
HDC hdc;
const DWORD dwExStyle = 0;
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
/* Save instance handle for DialogBoxs */
ghInstApp = hInst;
ghAccel = LoadAccelerators(hInst, MAKEINTATOM(ID_APP));
if(!hPrev)
{
/*
* Register a class for the main application window
*/
cls.hCursor = LoadCursor(NULL,IDC_ARROW);
cls.hIcon = LoadIcon(hInst, TEXT("AMCapIcon"));
cls.lpszMenuName = MAKEINTATOM(ID_APP);
cls.lpszClassName = MAKEINTATOM(ID_APP);
cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
cls.hInstance = hInst;
cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
cls.lpfnWndProc = (WNDPROC) AppWndProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
if(!RegisterClass(&cls))
return FALSE;
}
// Is this necessary?
ghfontApp = (HFONT)GetStockObject(ANSI_VAR_FONT);
hdc = GetDC(NULL);
SelectObject(hdc, ghfontApp);
GetTextMetrics(hdc, >m);
ReleaseDC(NULL, hdc);
ghwndApp=CreateWindowEx(dwExStyle,
MAKEINTATOM(ID_APP), // Class name
gszAppName, // Caption
// Style bits
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, 0, // Position
320,300, // Size
(HWND)NULL, // Parent window (no parent)
(HMENU)NULL, // use class menu
hInst, // handle to window instance
(LPSTR)NULL // no params to pass on
);
// create the status bar
statusInit(hInst, hPrev);
ghwndStatus = CreateWindowEx(0,
szStatusClass,
NULL,
WS_CHILD|WS_BORDER|WS_VISIBLE|WS_CLIPSIBLINGS,
0, 0,
0, 0,
ghwndApp,
NULL,
hInst,
NULL);
if(ghwndStatus == NULL)
return(FALSE);
ShowWindow(ghwndApp,sw);
// Read the capture file name from win.ini
GetProfileString(TEXT("annie"), TEXT("CaptureFile"), TEXT(""),
gcap.wszCaptureFile,
NUMELMS(gcap.wszCaptureFile));
// Read the list of devices to use from win.ini
ZeroMemory(gcap.rgpmAudioMenu, sizeof(gcap.rgpmAudioMenu));
ZeroMemory(gcap.rgpmVideoMenu, sizeof(gcap.rgpmVideoMenu));
gcap.pmVideo = 0;
gcap.pmAudio = 0;
gcap.fMPEG2 = FALSE;
TCHAR szVideoDisplayName[1024], szAudioDisplayName[1024];
*szAudioDisplayName = *szVideoDisplayName = 0; // null terminate
GetProfileString(TEXT("annie"), TEXT("VideoDevice2"), TEXT(""),
szVideoDisplayName, NUMELMS(szVideoDisplayName));
GetProfileString(TEXT("annie"), TEXT("AudioDevice2"), TEXT(""),
szAudioDisplayName, NUMELMS(szAudioDisplayName));
gcap.fDeviceMenuPopulated = false;
AddDevicesToMenu();
// do we want audio?
gcap.fCapAudio = GetProfileInt(TEXT("annie"), TEXT("CaptureAudio"), TRUE);
gcap.fCapCC = GetProfileInt(TEXT("annie"), TEXT("CaptureCC"), FALSE);
// do we want preview?
gcap.fWantPreview = GetProfileInt(TEXT("annie"), TEXT("WantPreview"), FALSE);
// which stream should be the master? NONE(-1) means nothing special happens
// AUDIO(1) means the video frame rate is changed before written out to keep
// the movie in sync when the audio and video capture crystals are not the
// same (and therefore drift out of sync after a few minutes). VIDEO(0)
// means the audio sample rate is changed before written out
gcap.iMasterStream = GetProfileInt(TEXT("annie"), TEXT("MasterStream"), 1);
// get the frame rate from win.ini before making the graph
gcap.fUseFrameRate = GetProfileInt(TEXT("annie"), TEXT("UseFrameRate"), 1);
int units_per_frame = GetProfileInt(TEXT("annie"), TEXT("FrameRate"), 666667); // 15fps
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -