IMediaDet – інтерфейс для захоплення відео і аудіо інформації

Автор: Олександр Бусарєв, Королівство 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);


УВАГА!
DirectShow повертає картинку завжди в 24-бітному форматі кольору. За байту на кожен канал RGB.

Викликати метод потрібно 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, який є у всіх інтерфейсних об'єктів.


До матеріалу додаються файли:

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*