|
|
|||||||||||||||||||||||||||||
|
IMediaDet - интерфейс для захвата видео и аудио информацииИсточник: delphikingdom Александр Бусаров
Автор: Александр Бусаров, Королевство DelphiВ данной статье я хочу рассмотреть интерфейс IMediaDet, который нам любезно предоставил DirectShow. Интерфейс специально разработан для того, чтобы захватить часть видео или аудио информации. Тема небольшая, да и напишу я немного, но думаю, что информация полезная, потому что лично я сталкивался с такой проблемой раньше и не один раз. Выкручивался как всегда какими-нибудь модулями, которые поддерживали от силы 2-3 формата сжатия. Причем один из них позволял сделать одно, скажем, вытащить картинку, другой - сделать видеосэмпл, третий - аудио. Прежде чем работать с интерфейсом, нужно подключить заголовочный модуль DirectShow (см. файлы к статье). Еще нужно подключить модуль ActiveX. Он идет "в комплекте" с Delphi. Итак, прежде всего этот интерфейс нужно создать. Создается он с нуля, т.е. не методом какого либо объекта, а прямо с помощью CoCreateInstance. Объявляем переменную: Detector:IMediaDet; И создаем ее: CoCreateInstance (CLSID_MediaDet,nil, CLSCTX_INPROC_SERVER, IID_IMediaDet, Detector); После того как детектор создан, мы должны открыть какие то данные. Детектор позволяет нам открывать файлы. Открываем файл методом put_Filename(name: PWideChar) заметьте, что передается юникод-строка. Получить имя открытого файла можно похожим способом: get_Filename Далее нам нужно получить информацию о видеофайле. Для этого у нашего детектора есть метод get_StreamMediaType. Вызывается он всего лишь c одним аргументом типа _AMMediaType. В него он возвращает значение. Тип _AMMediaType объеденил в себе ниформацию об аудио- и видео-данных. Для того, чтобы получить информацию о видеофайле можно просто использовать приведение типов. Вот пример для наглядности: var info:_AMMediaType; height, width:word; Begin Detector.get_StreamMediaType(info); Width:=VIDEOINFOHEADER(info.pbFormat^).bmiHeader.biWidth; Height:=VIDEOINFOHEADER(info.pbFormat^).bmiHeader.biHeight; End; Тип VIDEOINFOHEADER предоставляет нам очень много различной информации. И размер изображения, и сжатие, и много еще всего, но он не предоставляет нам длительность ролика. Поэтому используем метод get_StreamLength(out length:double); Здесь длина представлена в секундах, что очень удобно. Итак, мы подготовились к получению скриншотов нашего видеофайла. Получить скриншот мы можем 2-мя способами. Используем метод (опять юникод в параметрах) WriteBitmapBits(time:double; width, height:integer; FIleName:WideString) Просто передаем этому методу время в секундах, высоту, ширину, полученную, когда мы вызывали get_StreamMediaType, и имя файла, куда все это добро напишется. Понятно, что все это запишется сразу же в файл, а вот как получить скриншот сразу в память? Делается это с помощью метода GetBitmapBits (time:Double; buffersize:PLongint; buffer:PByte; width, height:integer);
ВНИМАНИЕ! Вызвать метод нужно 2 раза. 1-ый, чтобы определить размер буфера, второй - чтобы записать в него данные. Определять размер можно 1 раз сразу после получения информации по файлу. (Это для оптимизации), так же можно сразу выделять память в буфере под скриншот. Метод GetBitmapBits для определения размеров буфера нужно вызывать передавая ему параметр nil в качестве buffer. Тогда в переменную buffersize поместится размер буфера. После этого можно выделять память под buffer, и вызывать второй раз метод GetBitmapBits, теперь уже передавая ему в качестве buffer-а наш буфер. (при этом в параметр buffersize передаем nil. Работает вроде даже если передавать не nil, но так советует Microsoft). Height и width передаем все те же, какие были получены через get_StreamMediaType. Итак, все, в буфере у нас содержится наш рисунок. Осталось только понять как с ним работать, т.е. в каком формате он там хранится. Это формат BITMAPINFOHEADER, который объявлен в Windows.pas. Битовая информация о каждом пикселе содержится по адресу: bitinfo:=Pointer(integer(buffer)+SizeOf(BITMAPINFOHEADER)); Так же можно создать HBitmap с нашего buffer используя CreateDIBitmap из Windows.pas В общем, теперь мы с этой памятью можем делать, что захотим. IMediaDet так же нам предоставляет возможность работать с отрывком (сэмплом) видеофайла. Для этого у него есть метод GetSampleGrabber(grabber: ISampleGrabber). Скажу лишь, что вызывая этот метод, мы создаем объект интерфейса ISampleGrabber. Ну а поскольку это уже другой интерфейс, то о нем я расскажу в другой статье. И напоследок. Удалять указатель на наш IMediaDet нужно, вызвав метод _Release, который есть у всех интерфейсных объектов. К материалу прилагаются файлы:
Ссылки по теме
Файлы для загрузки
|
|