Zachytávání videa II

V předchozím článku jsme si ukázali tu nejjednodušší implementaci programu na zachytávání videa pomocí MCI a „video for windows“. V tomto pokračování si ukážeme, jak umožnit pokročilejší nastavení ovladače, vybrat cílový soubor a podobně.
Výběr ovladače

Nejprve si ukažme jak vůbec získat seznam nainstalovaných příslušných ovladačů, z nichž si pak můžeme vybrat, ke kterému se připojit. V minulém článku jsme použili výchozí ovladač s indexem 0. Vytvořme si tedy nový dialog s jedním list-boxem a proveďme potřebné ve funkci InitDialog:

char szDeviceName[80];
char szDeviceVersion[80];
for ( int i = 0; i < 10; i++)
{
if ( capGetDriverDescription (i,
szDeviceName, sizeof (szDeviceName),
szDeviceVersion, sizeof (szDeviceVersion)))
m_DriversList.AddString(CString(szDeviceName)+
"  "+CString(szDeviceVersion));
}

Položky list boxu představují získané názvy (s připojeným označením verze) jednotlivých ovladačů pro zachytávání videa.

Podle výběru ze seznamu pak připojíme příslušný driver. Do třídy CRPJVideoCapture si přidáme prvek

INT m_DriverIndex;

který nastavíme jako výsledek výše uvedeného dialogu:

void CUkazkaDlg::OnDriversList()
{
m_VideoCapture.m_DriverIndex = m_DriversList.DoModal();
}

přičemž v Dialogu CDriverList musíme upravit funkci OnOk:

void CDriversList::OnOK()
{
m_DriverIndex = m_DriversList.GetCurSel();
EndDialog(m_DriverIndex);
}

Upravená členská funkce, která vytvoří okno pro zachytávání videa a připojí se k vybranému zařízení, bude nyní vypadat takto

BOOL CRPJVideoCapture::Create(HWND hwndParent)
{
if ( IsWindow(m_hWnd) )
return FALSE;
m_hWnd = capCreateCaptureWindow(
(LPSTR)"RPJ Video Capture",
WS_CHILD | WS_VISIBLE,
0, 0, 352, 288,
(HWND)hwndParent,
(int)0);
if ( !IsWindow(m_hWnd) )
return FALSE;
if ( !capDriverConnect(m_hWnd, m_DriverIndex) )
return FALSE;
return TRUE;
}

Nastavení parametrů ovladače

Nyní si ukažme, jak vyvolat dialog pro nastavení parametrů příslušného ovladače. Pro nastavení vlastností zdroje videa vyvoláme dialog s nastavením, které se bude lišit s každým typem ovladače. K tomu použijeme makro capDlgVideoSource:

BOOL capDlgVideoSource(
HWND hwnd
);

Nejdříve bychom si však měli ověřit, zda daný ovladač vůbec umožňuje aplikovat tento systémový dialog, což provedeme pomocí makra capDriverGetCaps:

BOOL capDriverGetCaps(
  hwnd,   
  psCaps, 
  wSize   
);

hwnd je handle okno ovladače, které tedy musíme nejdříve vytvořit (funkcí capCreateCaptureWindow), psCaps je ukazatel na strukturu CAPDRIVERCAPS a wSize je velikost této struktury. Funkce nám pak tuto strukturu naplní požadovanými informacemi.

typedef struct {
UINT  wDeviceIndex;
BOOL  fHasOverlay;
BOOL  fHasDlgVideoSource;
BOOL  fHasDlgVideoFormat;
BOOL  fHasDlgVideoDisplay;
BOOL  fCaptureInitialized;
BOOL  fDriverSuppliesPalettes;
HANDLE hVideoIn;
HANDLE hVideoOut;
HANDLE hVideoExtIn;
HANDLE hVideoExtOut;
} CAPDRIVERCAPS;

  • wDeviceIndex je již zmiňovaný index vybraného zařízení.
  • fHasOverlay je TRUE, pokud zařízení podporuje overlay
  • fHasDlgVideoSource je TRUE, pokud zařízení podporuje dialog pro volbu a ovládání zdroje videa
  • fHasDlgVideoFormat je TRUE, pokud zařízení podporuje dialog pro výběr formátu videa
  • fHasDlgVideoDisplay je TRUE, pokud zařízení podporuje dialog pro ovládání zobrazení zachyceného videa z bufferu
  • fCaptureInitialized je TRUE, pokud ovladač byl bez chyb připojen
  • fDriverSuppliesPalettes je TRUE, pokud zařízení podporuje používání vlastních palet.
Další prvky se již v aplikacích Win32 nepoužívají, jsou zde z důvodů zpětné kompatibility.

Funkce (přidáme si ji jako členskou do třídy CRPJVideoCapture pro vyvolání vlastností zdroje videa, pak bude vypadat takto:

void CRPJVideoCapture::DlgVideoSource()
{
CAPDRIVERCAPS CapDriverCaps;
capDriverGetCaps(m_hWnd, &CapDriverCaps, sizeof (CAPDRIVERCAPS));
if (CapDriverCaps.fHasDlgVideoSource)
capDlgVideoSource(m_hWnd);
}

Obdobným způsobem si vytvoříme členskou funkci pro vyvolání dialogu volby zobrazení videa:

void CRPJVideoCapture::DlgVideoDisplay()
{
CAPDRIVERCAPS CapDriverCaps;
capDriverGetCaps(m_hWnd, &CapDriverCaps, sizeof (CAPDRIVERCAPS));
if (CapDriverCaps.fHasDlgVideoDisplay)
capDlgVideoDisplay(m_hWnd);
}

a stejně tak funkci pro zobrazení volby formátu videa, tedy u většiny ovladačů zde bude volba rozlišení (velikost v pixelech), barevná hloubka a případně komprese videa.

void CRPJVideoCapture::DlgVideoFormat()
{
CAPDRIVERCAPS CapDriverCaps;
capDriverGetCaps(m_hWnd, &CapDriverCaps, sizeof (CAPDRIVERCAPS));
if (CapDriverCaps.fHasDlgVideoFormat)
capDlgVideoFormat(m_hWnd);
}

Určení cílového souboru a jeho alokace

Nyní si ukažme, jak určit vlastní cílový soubor pro zachytávání videa. K tomu slouží makro:

BOOL capFileSetCaptureFile(
  hwnd, 
  szName  // jméno cílového souboru
);

můžeme proto přímo v hlavním dialogu zařadit příslušný handler třeba takto:

void CUkazkaDlg::OnSelectFile()
{
CFileDialog saveDialog(FALSE);
if ( saveDialog.DoModal() != IDOK )
return;
capFileSetCaptureFile(m_VideoCapture.m_hWnd,
saveDialog.GetPathName().GetBuffer(_MAX_PATH));
}

Dále máme možnost určit „předalokaci“ cílového souboru. Jde o to, že při zachytávání vysoce kvalitního videa s minimální kompresí je většinou tím nejslabším článkem rychlost zápisu videodat na pevný disk. A tato rychlost by měla být samozřejmě co nejstálejší, tedy bez „mikropřerušení“ způsobených postupnou realokací cílového souboru. Proto máme možnost tento soubor předem naalokovat na velikost, o které předpokládáme, že bude dostatečná pro uložení celé videosekvence. V ideálním případě můžeme před vlastním spuštěním zachytávání tento soubor ještě defragmentovat. K této předalokaci nám slouží makro capFileAlloc:

BOOL capFileAlloc(
HWND hwnd, 
DWORD dwSize
);

Můžeme si tedy vytvořit příslušnou členskou funkci:

BOOL CRPJVideoCapture::Preallocate(DWORD dwSize)
{
if ( !IsWindow(m_hWnd) )
return FALSE;
return capFileAlloc(m_hWnd, dwSize);
}

Formát doprovodného zvuku

Nyní si stručně řekněme o možnosti určit formát zvukového kanálu ve výsledné videosekvenci. K tomu se používá makro capSetAudioFormat:

BOOL capSetAudioFormat(
HWND hwnd,
(LPARAM)(LPWAVEFORMATEX) psAudioFormat,
WPARAM wSize
);

kde psAudioFormat je adresa struktury WAVEFORMATEX nebo PCMWAVEFORMAT.

typedef struct {
WORD  wFormatTag;
WORD  nChannels;
DWORD  nSamplesPerSec;
DWORD  nAvgBytesPerSec;
WORD  nBlockAlign;
WORD  wBitsPerSample;
WORD  cbSize;
} WAVEFORMATEX;

typedef struct {
WAVEFORMAT  wf;
WORD  wBitsPerSample;
} PCMWAVEFORMAT;

typedef struct {
WORD  wFormatTag;
WORD  nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD  nBlockAlign;
} WAVEFORMAT;

Jako příklad si ukažme, jak nastavit zvukový formát například na 11-kHz PCM 8-bitů, stereo:

WAVEFORMATEX wfex;
wfex.wFormatTag = WAVE_FORMAT_PCM;
wfex.nChannels = 2;                // stereo
wfex.nSamplesPerSec = 11025;
wfex.nAvgBytesPerSec = 22050;
wfex.nBlockAlign = 2;
wfex.wBitsPerSample = 8;
wfex.cbSize = 0;
capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));

Získání aktuálního stavu ovladače

Pokud chceme v daném okamžiku získat informace o stavu zařízení pro zachytávání videa, použijeme makro capGetStatus:

BOOL capGetStatus(
HWND  hwnd,
(LPARAM)LPCAPSTATUS  s,
WPARAM  wSize
);

kde wSize je velikost struktury, na niž odkazuje parametr s, což je adresa struktury CAPSTATUS:

typedef struct {
UINT    uiImageWidth;
UINT    uiImageHeight;
BOOL    fLiveWindow;
BOOL    fOverlayWindow;
BOOL    fScale;
POINT    ptScroll;
BOOL    fUsingDefaultPalette;
BOOL    fAudioHardware;
BOOL    fCapFileExists;
DWORD    dwCurrentVideoFrame;
DWORD    dwCurrentVideoFramesDropped;
DWORD    dwCurrentWaveSamples;
DWORD    dwCurrentTimeElapsedMS;
HPALETTE hPalCurrent;
BOOL    fCapturingNow;
DWORD    dwReturn;
UINT    wNumVideoAllocated;
UINT    wNumAudioAllocated;
} CAPSTATUS;

Úplný popis jednotlivých prvků struktury naleznete v dokumentaci (MSDN), a proto zde nebudu vše rozepisovat.

Zjištění a nastavení formátu videa

Chceme-li zjistit nebo nastavit formát videa jako datovou strukturu BITMAPINFO, použijeme pro získání informace makro capGetVideoFormat:

DWORD capGetVideoFormat(
HWND  hwnd,
(LPARAM)(BITMAPINFO>  psVideoFormat,
WPARAM  wSize
);

a pro nastavení formátu makro capSetVideoFormat:

BOOL capSetVideoFormat(
HWND  hwnd,
(LPARAM)(BITMAPINFO>  psVideoFormat,
WPARAM  wSize
);

Protože BITMAPINFO je struktura proměnné délky, musíme ji alokovat dynamicky s tím, že její „správnou“ velikost zjistíme pomocí makra capGetVideoFormatSize. Uveďme si příklad:

LPBITMAPINFO lpbi;
DWORD dwSize;

dwSize = capGetVideoFormatSize(hWnd);
lpbi = (LPBITMAPINFO)malloc(dwSize);
capGetVideoFormat(hWnd, lpbi, dwSize);
// .. zde máme přístup k prvkům struktury BITMAPINFO naplněné
// .. informacemi o formátu videa
free(lpbi);

Tím jsme dokončili přehled toho základního, co patří k zachytávání videa pomocí MCI zařízení. Pokud máte zájem o hlubší průnik do této problematiky, bohatým zdrojem informací je (jako vždy) MSDN, kde jsou podrobně rozepsány všechny zde uvedené funkce a jejich parametry.

Zde si můžete stáhnout ukázkový projekt, kde jsou ukázány některé možnosti nastavení ovladačem, jak jsme je probrali v tomto článku: video_capture_II.zip.

Váš názor Další článek: Chystá se Service Pack 3 pro Windows 2000?

Témata článku: Video, Software, Windows, Programování, Cílové zařízení, Dialog, Struktura, Vybraný formát, Code, Word, Zobrazený prvek, DWS, Vid, Makro, Záchyt


Určitě si přečtěte

Nejlepší notebooky do 10 000 korun: Co má ještě smysl kupovat. A co ne?

Nejlepší notebooky do 10 000 korun: Co má ještě smysl kupovat. A co ne?

** Notebooky s cenou do deseti tisíc korun jsou plné kompromisů ** Existuje několik modelů dobře použitelných pro nenáročné použití ** Vhodnou alternativou jsou tablety nebo repasované počítače

David Polesný | 94

David Polesný
Jak vybrat notebookNotebooky
Vybrali jsme 12 programovatelných hraček a stavebnic pro děti a jejich rodiče

Vybrali jsme 12 programovatelných hraček a stavebnic pro děti a jejich rodiče

** Získejte děti pro matematiku a základy techniky ** Kupte jim hračku nebo stavebnici, které vdechnou vlastní život ** Vybrali jsme stavebnice pro malé caparty i budoucí experty

Jakub Čížek | 10

Jakub Čížek
Stavebnice
Co je to UWB? Nová technologie zastoupí Wi-Fi, Bluetooth i NFC a slibuje velké věci

Co je to UWB? Nová technologie zastoupí Wi-Fi, Bluetooth i NFC a slibuje velké věci

** V nových mobilech se začíná objevovat tajemná zkratka UWB ** Jde o další technologii, jak navzájem propojit různá zařízení ** Oproti Wi-Fi a Bluetooth má řadu výhod

Lukáš Václavík | 36

Lukáš Václavík
UWBIoTTechnologie

Aktuální číslo časopisu Computer

Jak prodloužit výdrž notebooku

Velké testy: gamepady a inkoustové tiskárny

Důkladný test Sony Playstation 5