Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Прикладное программирование на CC++ с нуля до мультимедийных и сетевых приложений

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Программируем сжатие аудио информации 161
void __fastcall TForm1::Button4Click(TObject *Sender) {
Close();
} //—————————————————————————————————————-
void __fastcall TForm1::Button5Click(TObject *Sender) {
SrcFmt.wFormatTag = WAVE_FORMAT_PCM;
SrcFmt.nChannels = (WORD)kanal;
SrcFmt.wBitsPerSample = (WORD)razrad;
SrcFmt.nBlockAlign = (WORD)(kanal * (razrad/8));
SrcFmt.nSamplesPerSec = diskret;
SrcFmt.nAvgBytesPerSec = SrcFmt.nSamplesPerSec * SrcFmt.nBlockAlign;
memcpy (&DstFmt, &SrcFmt, min (sizeof (SrcFmt), sizeof (DstFmt)));
ACMFORMATCHOOSE FC;
memset (&FC, 0, sizeof (FC));
FC.cbStruct = sizeof (FC);
FC.fdwStyle = ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
FC.hwndOwner = NULL;
FC.pwfx = &DstFmt;
FC.cbwfx = sizeof (DstFmt);
FC.pwfxEnum = &DstFmt;
FC.pszTitle = "AUAE?AE OIEUEI ?NI e MPEG Layer-3";
FC.pszName = NULL;
FC.fdwEnum = ACM_FORMATENUMF_CONVERT;
acmFormatChoose (&FC);
acmStreamOpen(&Stream, NULL,&SrcFmt, &DstFmt, NULL, 0, 0, 0);
AH.cbStruct = sizeof (AH);
AH.fdwStatus = 0;
AH.pbSrc = lpHdr->lpData;
AH.cbSrcLength = lpHdr->dwBytesRecorded;
AH.cbSrcLengthUsed = lpHdr->dwBytesRecorded;
acmStreamSize(Stream,AH.cbSrcLength,(DWORD *)&DstBufferSize,
ACM_STREAMSIZEF_SOURCE); DstBuffer = (BYTE *)GlobalAlloc (GMEM_FIXED, DstBufferSize); AH.pbDst = DstBuffer; AH.cbDstLength = DstBufferSize; AH.cbDstLengthUsed = DstBufferSize; acmStreamPrepareHeader (Stream, &AH, 0); acmStreamConvert (Stream, &AH, ConvertFlags); acmStreamUnprepareHeader (Stream, &AH, 0); acmStreamClose(&Stream,NULL);
}
//—————————————————————————————————————-
void __fastcall TForm1::Button7Click(TObject *Sender) {
if((DstFmt.wFormatTag !=1)&&(DstFmt.wFormatTag !=85)) { ShowMessage("Конвертировать только в PCM или MPEG Layer-3");
exit(1); }
if (DstFmt.wFormatTag == WAVE_FORMAT_PCM) {
162 Глава 4. Запись, обработка и воспроизведение звука
MMCKINFO ck; // Структура RIFF-файла char szfmt[] = "fmt "; char szdata[] = "data"; DWORD dwFmtSize = 16; // Размер базовой структуры File = mmioOpen("444.wav", NULL, MMIO_CREATE | MMIO_READWRITE); ck.ckid = MMIO_CREATERIFF; ck.cksize = *DstBuffer+ sizeof(PCMWAVEFORMAT) + 20; ck.fccType = mmioFOURCC('W', 'A', 'V', 'E'); mmioCreateChunk(File, (LPMMCKINFO)&ck,MMIO_CREATERIFF); mmioWrite(File, (HPSTR)szfmt, 4); mmioWrite(File, (HPSTR)&dwFmtSize, sizeof(DWORD)); mmioWrite(File, (HPSTR)&DstFmt,16);//sizeof(WAVEFORMAT)); mmioWrite(File, (HPSTR)szdata, 4); mmioWrite(File, (HPSTR)&DstBufferSize, sizeof(DWORD)); mmioWrite(File, (HPSTR)AH.pbDst, AH.cbDstLengthUsed);
mmioClose(File, 0); } else { ACMFORMATTAGDETAILS TagDet;
//Это информационная структура типа формата
memset (&TagDet, 0, sizeof (TagDet)); TagDet.cbStruct = sizeof (TagDet); TagDet.dwFormatTag = DstFmt.wFormatTag; // Это код типа формата acmFormatTagDtails(NULL,&TagDet,
ACM_FORMATTAGDETAILSF_FORMATTAG); File = mmioOpen("1234.mp3",NULL,MMIO_CREATE| MMIO_READWRITE|MMIO_ALLOCBUF|MMIO_DENYWRITE); MMCKINFO FmtChunk; memset (&RiffChunk, 0, sizeof (RiffChunk)); memset (&FmtChunk, 0, sizeof (FmtChunk)); memset (&FactChunk, 0, sizeof (FactChunk)); memset (&DataChunk, 0, sizeof (DataChunk)); RiffChunk.fccType = mmioFOURCC ('W', 'A', 'V', 'E'); mmioCreateChunk (File, &RiffChunk, MMIO_CREATERIFF); FmtChunk.ckid = mmioFOURCC ('f', 'm', 't', ' '); FmtChunk.cksize = TagDet.cbFormatSize;
// Максимальный размер описателя формата mmioCreateChunk (File, &FmtChunk, 0); mmioWrite (File, (char *)&DstFmt, FmtChunk.cksize); FactChunk.ckid = mmioFOURCC ('f', 'a', 'c', 't'); FactChunk.cksize = 4; mmioCreateChunk (File, &FactChunk, 0); mmioWrite (File, (char *)&ConvertedSamples, 4); DataChunk.ckid = mmioFOURCC ('d', 'a', 't', 'a'); DataChunk.cksize = 0; mmioCreateChunk (File, &DataChunk, 0); mmioSeek (File, FactChunk.dwDataOffset, SEEK_SET); mmioWrite (File, (char *)&ConvertedSamples, 4); mmioWrite (File,(char *)&AH.cbDstLengthUsed, sizeof(DWORD)); mmioWrite (File, (char *)AH.pbDst, AH.cbDstLengthUsed); mmioClose (File, 0);
} } //—————————————————————————————————————-
Программируем сжатие аудио информации 163
Важнейшим новшеством здесь является вызов функции acmFormatChoose. Функция инициирует открытие окна стандартного диалога системы ÀÑÌ. Это окно представлено на следующем рисунке. Окно представляет собой стан­дартный диалог Windows, который открывается, например, из стандартной программы звукозаписи (рис. 4.11).
Ðèñ. 4.11
В данном диалоге система предлагает выбрать формат результирующего файла и характеристики звука в нем. Подчеркнем, что ÀÑÌ автоматически определяет наличие программных средств преобразования на компьютере и в соответствии с результатами анализа оформляет предлагаемые варианты фор­матов и атрибутов. Отметим также, что возможности выбора определяются и параметрами исходного звука.
Аргументом функции acmFormatChoose является адрес структуры ACMFORMATCHOOSE FC. Структура содержит некоторые параметры диало­гового окна, в частности заголовок окна, который мы изменили относительно стандартного — смотрите рисунок. Главным объектом структуры FC является, в свою очередь, структура DstFmt. Первоначально она содержит параметры входного звука (формат и атрибуты), которые берутся из блока в оперативной памяти. После окончания работы функции acmFormatChoose â DstFmt будут уже параметры конвертированного звука, которые выберет пользователь. А далее, как и в предыдущем варианте, срабатывают функции acmStreamOpen, acmStreamConvert и все их вспомогательные процедуры. В результате звук, па­раметры которого описывались в SrcFmt, конвертируется в звук с параметра­ми из DstFmt. Результирующие данные хранятся в блоке оперативной памяти с описанием всех атрибутов. Размещение блока и атрибуты находятся в соот­ветствующих полях структуры ÀÍ.
Обработчик нажатия кнопки SAVE выполняет сохранение записи в дис­ковый файл. В поле wFormatTag структуры DstFmt находится имя формата конвертированного звука. Для формата ÐÑÌ числовой эквивалент этого име­ни равен 1, а для формата MPEG Layer-3 числовое значение составляет 85. В первую очередь функция проверяет, какой из этих форматов выбран, и если оказалось, что ни тот, ни другой, программа завершается, выдав предвари­тельно соответствующее уведомление.
164 Глава 4. Запись, обработка и воспроизведение звука
Далее в условной конструкции if ... else реализованы две ветви записи в файл для каждого из возможных форматов. В первом случае процедура созда­ния файла и записи в него информации нам уже знакома из раздела о записи звука. Ничего нового здесь нет. Необходимо только подчеркнуть, что мы на­звали создаваемый файл 444.wav. Вариант формирования файла в формате MPEG Layer-3 с именем 1234.mp3 несколько сложнее. Дело в том, что для файлов, отличных от типа РСМ, более сложно выглядит сама структура раз­мещения данных. В частности, наряду с фрагментами 'fmt ' è 'data' здесь могут присутствовать и другие (например, 'fact'). Формирование заголовков здесь связано со сдвигом данных в файле и другими не совсем тривиальными опе­рациями. В этой связи мы не будем описывать эту ветвь в функции-обработ­чике, а представим ее так (с некоторыми упрощениями), как это сделано в свободно распространяемом исходном тексте программы RTCompress. Изучая этот текст, мы, собственно, и осваивали на работающем примере методику компрессии звука, за что искренне благодарим разработчика.
Итак, приложение готово! Можно его опробовать и констатировать, что у нас в руках разработанный своими силами вполне работоспособный аудиоре­кордер, который способен записывать входной звук с заданными атрибутами и сохранять его в файле с теми же или другими атрибутами в несжатом фор­мате .wav или, что, наверное, самое ценное — в хорошо сжатом виде .mp3. Полученные файлы могут быть воспроизведены большинством современных цифровых плееров, в частности, программой WinAmp или стандартным Windows-проигрывателем. Оставшаяся же, возможно, у читателя некоторая неудовлетворенность слишком беглым описанием разработки должна послу­жить стимулом к дальнейшему самостоятельному изучению.
В ряде случаев предложенная только что организация сжатия звуковой информации может оказаться неудобной. Действительно, вызов стандартного диалогового окна выбора формата конечного файла далеко не всегда целесо­образен. В частности, в программах работы с мультимедиа реального времени, где все операции должны быть максимально автоматизированы и оптимизи­рованы по быстродействию, необходимо, чтобы сжатие производилось в зара­нее определенный формат без всякого общения с пользователем. В этой связи представим приложение, которое записывает звук и сразу конвертирует его в файл .mp3. Поскольку за основу взята предыдущая программа, ограничимся только небольшими комментариями к новому продукту. Листинг приложения представлен ниже.
//—————————————————————————————————————-
#include <VCL.h>
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <MMREG.H>
#include "msacm.h"
#include "Unit1.h"
#pragma resource "*.dfm"
#define min(a, b) (((a) < (b)) ? (a) : (b))
Программируем сжатие аудио информации 165
TForm1 *Form1;
struct WaveFormat : public tWAVEFORMATEX {
BYTE Ext [128]; }; ACMFORMATTAGDETAILS TagDet; int tau,
diskret = 11025,diskret1, razrad=16,
kanal=1; long buf; HWAVEIN hWaveIn; HWAVEOUT hWaveOut; DWORD DstBufferSize; HACMSTREAM Stream; WAVEFORMATEX SrcFmt; WaveFormat DstFmt; HMMIO File; DWORD ConvertFlags; BYTE *DstBuffer; MMCKINFO RiffChunk; MMCKINFO FactChunk; MMCKINFO DataChunk; UINT ConvertedSamples; ACMSTREAMHEADER AH; WAVEFORMATEX wfx; LPWAVEHDR lpHdr = new WAVEHDR;
//————————————————————————————­__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//Задаем исходный формат
SrcFmt.nChannels=kanal; SrcFmt.nSamplesPerSec=diskret; SrcFmt.wBitsPerSample=razrad; SrcFmt.wFormatTag=WAVE_FORMAT_PCM; SrcFmt.nBlockAlign=SrcFmt.nChannels*SrcFmt.wBitsPerSample/8; SrcFmt.nAvgBytesPerSec=SrcFmt.nBlockAlign*SrcFmt.nSamplesPerSec;
//Конечный формат MP3
DstFmt.wFormatTag=85; } //—————————————————————————————————————-
void __fastcall TForm1::Button1Click(TObject *Sender) {
tau = StrToInt(Edit1->Text); buf = SrcFmt.nAvgBytesPerSec*tau; lpHdr->lpData = (HPSTR)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, buf);
wfx.wFormatTag = WAVE_FORMAT_PCM;
int nC = wfx.nChannels = kanal; int BPS = wfx.wBitsPerSample = razrad; int nSPS = wfx.nSamplesPerSec = diskret;
166 Глава 4. Запись, обработка и воспроизведение звука
int nBA = wfx.nBlockAlign = nC*BPS/8; wfx.nAvgBytesPerSec = nSPS*nBA; lpHdr->dwBufferLength = buf; waveInOpen(&hWaveIn, WAVE_MAPPER,&wfx,0L, 0L, 0L); waveInPrepareHeader(hWaveIn, lpHdr,sizeof(WAVEHDR)); waveInAddBuffer(hWaveIn, lpHdr,sizeof(WAVEHDR)); waveInStart(hWaveIn);
}
//—————————————————————————————————————-
void __fastcall TForm1::Button2Click(TObject *Sender) {
waveInReset(hWaveIn); waveInClose(hWaveIn); waveInUnprepareHeader(hWaveIn, lpHdr,sizeof(WAVEHDR)); lpHdr->dwBufferLength = lpHdr->dwBytesRecorded;
}
//—————————————————————————————————————-
void __fastcall TForm1::Button5Click(TObject *Sender) {
acmFormatSuggest(NULL,&SrcFmt,&DstFmt,sizeof(DstFmt),
ACM_FORMATSUGGESTF_WFORMATTAG);
acmStreamOpen(&Stream, NULL,&SrcFmt, &DstFmt, NULL, 0, 0, 0); AH.cbStruct = sizeof (AH); AH.fdwStatus = 0; AH.pbSrc = lpHdr->lpData; AH.cbSrcLength = lpHdr->dwBytesRecorded; AH.cbSrcLengthUsed = lpHdr->dwBytesRecorded; acmStreamSize(Stream,AH.cbSrcLength,(DWORD *)&DstBufferSize,
ACM_STREAMSIZEF_SOURCE);
DstBuffer = (BYTE *)GlobalAlloc (GMEM_FIXED, DstBufferSize); AH.pbDst = DstBuffer; AH.cbDstLength = DstBufferSize; AH.cbDstLengthUsed = DstBufferSize; acmStreamPrepareHeader (Stream, &AH, 0); acmStreamConvert (Stream, &AH, ConvertFlags); acmStreamUnprepareHeader (Stream, &AH, 0); acmStreamClose(Stream,0);
}
//—————————————————————————————————————-
void __fastcall TForm1::Button7Click(TObject *Sender) {
memset (&TagDet, 0, sizeof (TagDet)); TagDet.cbStruct = sizeof (TagDet); TagDet.dwFormatTag = DstFmt.wFormatTag; acmFormatTagDetails(NULL,&TagDet,
ACM_FORMATTAGDETAILSF_FORMATTAG); File = mmioOpen("1234.mp3",NULL,MMIO_CREATE| MMIO_READWRITE|MMIO_ALLOCBUF|MMIO_DENYWRITE);
Программируем сжатие аудио информации 167
MMCKINFO FmtChunk; memset (&RiffChunk, 0, sizeof (RiffChunk)); memset (&FmtChunk, 0, sizeof (FmtChunk)); memset (&FactChunk, 0, sizeof (FactChunk)); memset (&DataChunk, 0, sizeof (DataChunk)); RiffChunk.fccType = mmioFOURCC ('W', 'A', 'V', 'E'); mmioCreateChunk (File, &RiffChunk, MMIO_CREATERIFF); FmtChunk.ckid = mmioFOURCC ('f', 'm', 't', ' '); FmtChunk.cksize = TagDet.cbFormatSize; mmioCreateChunk (File, &FmtChunk, 0); mmioWrite (File, (char *)&DstFmt, FmtChunk.cksize); FactChunk.ckid = mmioFOURCC ('f', 'a', 'c', 't'); FactChunk.cksize = 4; mmioCreateChunk (File, &FactChunk, 0); mmioWrite (File, (char *)&ConvertedSamples, 4); DataChunk.ckid = mmioFOURCC ('d', 'a', 't', 'a'); DataChunk.cksize = 0; mmioCreateChunk (File, &DataChunk, 0); mmioSeek (File, FactChunk.dwDataOffset, SEEK_SET); mmioWrite (File, (char *)&ConvertedSamples, 4); mmioWrite (File,(char *)&AH.cbDstLengthUsed, sizeof(DWORD)); mmioWrite (File, (char *)AH.pbDst, AH.cbDstLengthUsed); mmioClose (File, 0); Close();
} //—————————————————————————————————————-
По сути дела, здесь из предыдущей программы удалено все лишнее и, прежде всего, диалог выбора формата и параметров конвертирования файлов. Новым же является использование функции acmFormatSugest(NULL,&SrcFmt, &DstFmt,sizeof(DstFmt), ACM_FORMATSUGGESTF_WFORMATTAG);.
Полную информацию о функции можно, как всегда, получить в справке по Windows API непосредственно в Builder'е. Важно то, что мы напрямую зада­ем формат исходной информации в структуре SrcFmt и формат сжатой ин­формации в структуре DstFmt. А далее все происходит так, как и при «руч­ном» выборе форматов в диалоге. Необходимо только напомнить, что воз­можности преобразования зависят от программного оснащения вашего компьютера. В частности, конвертирование в формат mp3 будет возможно только при наличии соответствующего кодека или кодеков. При установке на машину операционной системы Windows 98 èëè Windows 2000 эти кодеки ав­томатически не инсталлируются. Их необходимо приобрести и установить до­полнительно. Возможно, наиболее простым способом здесь будет установка последних версий проигрывателя Windows Media Player, где нужный кодек ус­танавливается в систему.
Глава 5
ПРОГРАММИРОВАНИЕ
РАБОТЫ С ВИДЕО
Ввод и вывод изображения
По большому счету, идея записи и воспроизведения подвижного изобра­жения не претерпела серьезных изменений со времен братьев Люмьер, впер­вые запечатлевших на кинопленку первый в истории фильм. Как в те време­на, так и сейчас живое изображение представляется последовательностью от­дельных кадров, на которых зафиксированы последовательные моменты времени. Такой синтез подвижного из неподвижного возможен благодаря тому, что человеческий глаз перестает различать отдельные «картинки», если они сменяются во времени достаточно быстро. Иллюзия непрерывного изме­нения возникает при смене отдельных фаз движения, начиная, примерно, с 20 раз в секунду, то есть при частоте кадров 20 Герц. Точно таким же образом из отдельных кадров формируется изображение и на вашем мониторе, хотя частота смены кадров здесь выше.
А вот технология формирования отдельной картинки, отдельного кадра изменилась неузнаваемо. Изображение на экране монитора состоит из отдель­ных светящихся точек, называемых пикселями, в чем нетрудно убедиться, рассмотрев участок экрана через обычную лупу. Плотность размещения точек является одной из важнейших характеристик качества компьютерного изобра­жения. Эта характеристика называется разрешающей способностью (или про­сто разрешением) экрана. Так, разрешение экрана 800 × 600 означает, что эк­ран состоит из «матрицы» пикселей, содержащих 800 столбцов и 600 строк.
Более детальное рассмотрение отдельного пикселя привело бы нас к вы­воду о том, что он состоит из трех отдельных компонентов. Здесь использует­ся то, что любой цветовой оттенок можно получить комбинацией (наложени­ем) трех фиксированных цветов варьируемой яркости. Этими цветами могут быть, в частности, и, как правило, красный, зеленый и синий. В этом случае говорят, что цвет компонуется из RGB-компонентов, от английского RED, GREEN, BLUE. При цифровом представлении видеоинформации интенсив­ности компонентов могут меняться не непрерывно, а дискретно. Вот тут мы подошли ко второй важнейшей характеристике качества изображения. На ка­ждый пиксель отводится некоторый объем специальной памяти (видеопамя ти). Этот объем определяет глубину цвета, которая измеряется в количестве
-
Ввод и вывод изображения 169
различных отображаемых оттенков. Так, в старых DOS-овских графических системах глубина могла составлять 16 цветов. Открыв свойства экрана в на­стройках Windows на вашем компьютере, вы можете обнаружить у себя глуби­ну цвета, называемую True Color (32 bit). Это означает, что каждый пиксель может быть раскрашен в один из2в32степени оттенков, что, конечно, очень и очень неплохо.
Всеми этими видеобитами и видеобайтами распоряжается специальное устройство, называемое видеоадаптером, видеокартой или видеоплатой. В от­личие от звуковой карты видеоадаптер является совершенно необходимым уз­лом компьютера, поскольку работу на компьютере без монитора представить себе затруднительно. В то же время конструктивно видеокарта является обыч­ным блоком, подключаемым к компьютеру через стандартный или специали­зированный слот расширения материнской платы или же непосредственно интегрированный в материнскую плату. Таким образом, видеоплату без про­блем можно заменять при выходе из строя или обновлять на более совершен­ную модель.
Основное назначение видеоадаптера заключается в управлении монито­ром, то есть формировании цифрового изображения и вывода его на экран. Выход видеокарты подключается к монитору. Некоторые карты имеют и вы­ход для телевизионного сигнала, с использованием которого можно приме­нять в качестве монитора обычный телевизор. А вот входа, как такового, ви­деоадаптер не имеет. Дело в том, что видеоплата работает с изображением, формируемым не внешними источниками, а внутри компьютера, то есть про­граммно.
Качество и стоимость видеоадаптера определяется объемом видеопамяти, установленной на плате. Эта та самая память, которая управляет максималь­ной разрешающей способностью экрана и наилучшей глубиной цвета. Разу­меется, чем больше памяти в распоряжении видеоплаты, тем лучше. Немало­важной характеристикой является и быстродействие карты. Следует отметить, что большинство обычных приложений Windows не предъявляют особо высо­ких требований к быстродействию видеосистемы. Проблемы со скоростью могут возникать при запуске современных компьютерных игр. Для любителей такого досуга можно порекомендовать приобрести видеокарту с так называе­мым графическим акселератором — AGP. Для карт с AGP на материнской плате должен существовать специальный слот.
В контексте этой книги нас в большей степени интересует работа не с изо­бражениями, формируемыми «внутри» компьютера, а с видеоинформацией, поступающей извне. Естественно, для этого компьютер должен быть снабжен аппаратными средствами, принимающими изображения от внешних источни­ков. Существует несколько типов таких устройств. С помощью так называе­мых TV-тюнеров монитор вашего компьютера превращается в экран телевизо­ра. Ценность такого «изобретения» спорна, хотя следует отметить, что телеви­зионное изображение на мониторе более высококачественное по сравнению с изображением на телевизионном экране. Конструктивно TV-тюнер представ­ляет собой схему, подключаемую к стандартному слоту материнской платы. Аналогично к компьютеру могут быть подключены устройства видеоввода.
170 Глава 5. Программирование работы с видео
С их помощью производится оцифровка аналоговых видеосигналов с выходов бытовой (или профессиональной) видеотехники: видеокамер, видеомагнито­фонов. Оцифрованное изображение можно просто просматривать на экране монитора либо создавать и редактировать файлы статических картинок или видеоклипов. Современные цифровые камеры, которые тоже, разумеется, яв­ляются внешними источниками, могут подключаться к компьютеру напрямую. В частности, подключение может быть выполнено через разъем шины USB. Важным приложением компьютерных видеотехнологий является получение и обработка изображений со сканеров.
Наибольший интерес для нас представляет источник видео, называемый web-камерой. Это очень простая и не очень притязательная цифровая камера, специально разработанная для ввода в компьютер изображения. Впрочем, не­которые модели с успехом могут использоваться в качестве цифрового фото­аппарата. Такие модели снабжаются автономным источником питания (бата­рейкой) и внутренней памятью, в которой хранятся отснятые кадры. После заполнения памяти отснятый материал «сбрасывается» в компьютер в виде графических файлов.
Большинство моделей web-камер подключаются к компьютеру через разъ­ем USB. Конструкция камеры зависит от модели. Мы рассмотрим работу с устройством, производимым компанией Creative и поставляемым на рынок под названием Creative Video blaster WebCam Go mini. Внешний вид камеры показан на рис. 5.1.
Ðèñ. 5.1
Эта камера имеет небольшую память для хранения 15 отснятых кадров, так что может использоваться в качестве автономной цифровой камеры.