Проигрывание аудио- и видеофайлов в Delphi с использованием VideoLAN  libvlc.dll

            Проигрывание аудио- и видеофайлов стандартными средствами Windows в Delphi – с помощью видеоплейера и  модуля MMSystem, обычно затруднений не вызывает. Однако, если речь идет об использовании видео в свободном формате OGGtheora+vorbis, дело обстоит несколько сложнее. Особенно, когда имеется ввиду воспроизведение в приложении, которое может устанавливаться на машину, на которой соответствующие кодеки отсутствуют.

            Проще всего дело обстоит с воспроизведением звука. Популярные библиотеки fmod и bass имеют поддержку OGG, интегрируются с программами Delphi, и бесплатны для некоммерческого применения. Есть возможность использовать и OpenAL, что, правда, несколько сложнее. Хорошая подборка статей на эту тему (переводов с сайта www.noeska.com) есть тут.

            Хуже дело обстоит с видео в формате OGG-theora. Мне не удалось найти материалов про использование этого кодека в программах на Delphi. Однако в этих поисках я натолкнулся на свободно распространяемый вместе с исходными кодами плейер VideoLAN - VLC media player, который содержит библиотеку, позволяющую воспроизводить аудио- и видеоматериалы в формате OGGtheora+vorbis без использования дополнительных кодеков. И что особенно ценно – эта библиотека (libvlc.dll) очень легко подключается к программам Delphi.

            Я написал небольшой файл-интерфейс к этой библиотеке, который дает доступ к большинству ее функций (кроме потоковых). Ниже я изложу основные сведения, необходимые для использования libvlc.dll и основные «подводные камни», которые я обнаружил.

 

            За и против использования библиотеки от VideoLAN в своих проектах.

            За – бесплатность библиотеки и открытый код. Простота и многофункциональность. Проигрывание множества форматов, в том числе OGGtheora+vorbis, без необходимости отдельной установки кодеков в систему.

            Противнеобходимость установки самого плейера VideoLAN (около 9 Мб для полной инсталляции). В конце статьи я укажу способ, который позволяет этого избежать.

 

            Использование libvlc.dll в программах на Delphi.

            Создадим новый проект, содержащий, как минимум, один стандартный компонент типа TPanel. Этот компонент будет использоваться как экран для вывода видео. В секцию uses включим модуль libvlc.

            В событие OnCreate формы включим следующий код:

var

 err :integer;

 args:array[0..1] of pchar;

 val :TValue;

 

...

err := VLD_LoadLibrary; // загрузка библиотеки

 

// проверка кода ошибки

if err<>VLD_SUCCESS then

begin

        case err of

        VLD_NOLIB   : ShowMessage('OOPS! libvlc.dll 0.8.6 not found!'); // библиотека не найдена

        VLD_NOTFOUND: ShowMessage('libvlc.dll invalide ?!');            // библиотека не может загрузится

        end;

  Application.Terminate;

        exit;

end;

 

// если всё в порядке, идем дальше

     vlc:= VLC_Create; // создаем ссылку к библиотеке и получаем код экземпляра

 

     args[0]:=pchar(VLD_LibPath); // передаем ссылку на путь, к файлу библиотеки. Почему он нужен – а чёрт его знает, но иначе не работает...

     args[1]:=nil;

     VLC_Init(vlc,1,@args[0]);

 

     val.AsInteger:=Panel1.Handle;  // передаем ссылку на Handle компонента, который служит нашим экраном.

     err := VLC_VariableSet(vlc,'drawable',val);

 

 

На этом инициализация библиотеки закончена. Для проигрывания видеофайла, его необходимо включить в список проигрывания, например, так:

 

     if not OpenDialog1.Execute then exit; // Отмечаем файлы для проигрывания.

 

     if VLC_IsPlaying(vlc) then VLC_Stop(vlc); // останавливаем проигрывание, если оно сейчас идет

 

     VLC_PlaylistClear(vlc); // очищаем список проигрывания

 

     for i := 0 to OpenDialog1.Files.Count - 1 do

     begin

          s:=UTF8Encode(OpenDialog1.Files[i]);

          VLC_AddTarget(vlc,PChar(s),nil,0,PLAYLIST_APPEND,PLAYLIST_END); // добавляем пути к файлам в формате UTF8

                                                                          // по очереди, в конец списка проигрывания

     end;

 

Теперь список можно проиграть командой:

 

VLC_Play(vlc);

 

Пример простейшего плейера находится в файле delphi_vl.zip. Пример видеофайла, сделанного автором статьи - flag10s.zip прилагается. Свобода распространения гарантируется.

Внимание! Для работы этого примера у вас должен быть установлен плейер VideoLAN - VLC media player. Ссылка для скачивания инсталляции - http://www.videolan.org/mirror.php?file=vlc/0.8.6d/win32/vlc-0.8.6d-win32.exe

 

Для быстрой конвертации видеофайлов других форматов в формат OGG удобна маленькая утилита командной строки ffmpeg2theora.

 

 

В данном примере использован так называемый «старый интерфейс», который функционально ограничен. В библиотеке есть набор функций «нового интерфейса», который обеспечивает расширенную функциональность.

 

Предупреждение! Смешивать оба интерфейса нельзя! Надо с самого начала инициализировать библиотеку или командой VLC_Create старого интерфейса, или командой libvlc_new интерфейса нового – возвращаемые ими значения разные!

 

Объяснения команд можно посмотреть в сишных заголовочных файлах libvlc.h и vlc.h исходников или на сайте, на страницах http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc.html и http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__old.html

 

Использование libvlc.dll без установки VLC media player.

Теперь интересный вопрос – как распространять библиотеку совместно со своими программами.

Просто приложить файл libvlc.dll к сожалению недостаточно – требуется регистрация пути к нему в реестре Windows. Но и этого мало – библиотека использует многочисленные дополнения-pluginы, которые находятся в отдельных файлах. Расположены эти pluginы должны быть в подкаталоге с именем plugins в том каталоге, который зарегистрирован в реестре как корневой для библиотеки. Всего в поставку входит этих pluginов целых 210 штук и они составляют основной объем инсталляции. Разумеется, для простого проигрывания нужны они не все, но выяснить, какие именно необходимы – задача не тривиальная.

            Автором экспериментально J был установлен минимальный набор pluginов достаточных для воспроизведения OGGtheora+vorbis аудио-видео через Direct3D. Это

libaccess_file_plugin.dll

libdirect3d_plugin.dll

libogg_plugin.dll

libtheora_plugin.dll

libtrivial_channel_mixer_plugin.dll

libtrivial_mixer_plugin.dll

libtrivial_resampler_plugin.dll

libvorbis_plugin.dll

libwaveout_plugin.dll

libwingdi_plugin.dll

 

Всего около 1,5 Мб. Этот набор содержится в файле vlc.zip. Для использования libvlc.dll на машине, на которой VideoLAN не установлен, надо содержимое этого файла распаковать куда-нибудь, и в программе запустить запись в реестр пути к файлу libvlc.dll командой: VLD_Registry(apath), где  apath – текстовая переменная (string), содержащая этот путь. Делать это, разумеется, надо только в том случае, если функция  VLD_LoadLibrary выдала код ошибки VLD_NOLIB.

 

Дополнение – список некоторых основных функций libvlc и их параметров 

 

«Старый интерфейс»:

 

VLC_Version :function  :pcharверсия библиотеки

VLC_Error :function (id :integer) :pchar – возвращает текстовое сообщение об ошибке с кодом id

VLC_Create :function  :integer; - инициализирует библиотеку и возвращает либо индекс экземпляра библиотеки (положительное значение), либо код ошибки (отрицательное значение)

VLC_Init :function (id,argc :integer; args:ppchar) :integer; - инициализирует служебную структуру библиотеки. id – индекс экземпляра библиотеки (возвращаемый функцией VLC_Create, argc – число передаваемых аргументов, args список аргументов. Возвращает код ошибки.

VLC_AddIntf :function (id:integer; module:pchar; block,play:longbool) :integer; - вызов стандартного интерфейса проигрывателя VLC media player. id – индекс экземпляра библиотеки, module – имя модуля интерфейса (модуль по умолчанию – nil), block – блокировать(True)/разблокировать(False) интерфейс, play – немедленно начать проигрывание списка, после старта. Возвращает код ошибки.  

VLC_Die :function (id :integer) :integer; - подготавливает деинициализацию, но больше ничего не делает. Для того, чтобы деинициализировать библиотеку реально, необходимо вызвать функции VLC_CleanUp и VLC_Destroy. id – индекс экземпляра библиотеки. Возвращает код ошибки.

VLC_CleanUp :function (id :integer) :integer; - очищает все списки, освобождает устройства ввода и вывода. id – индекс экземпляра библиотеки. Возвращает код ошибки.

VLC_Destroy :function (id :integer) :integer; - деинициализирует библиотеку. id – индекс экземпляра библиотеки. Возвращает код ошибки.

 

VLC_VariableSet :function (id :integer; Name :pchar; value :TValue) :integer; - устанавливает значение внутренней переменной (аналогично параметрам командной строки                 VLC media player). id – индекс экземпляра библиотеки. Name – название переменной, value – ёё значение.  Возвращает код ошибки.

VLC_VariableGet :function (id :integer; Name :pchar; var value:TValue):integer; - позволяет прочитать значение внутренней переменной. id – индекс экземпляра библиотеки. Name – название переменной, value – ёё значение.  Возвращает код ошибки.

VLC_VariableType :function (id :integer; Name: pchar; var typeid:integer):integer; - возвращает тип внутренней переменной.

(список параметров командной строки можно прочитать в документации, на сайте http://wiki.videolan.org/Documentation:Play_HowTo/Advanced_Use_of_VLC#Use_the_command_line)

 

VLC_AddTarget :function (id :integer; target :pchar; szoptions :ppchar; options,mode,pos:integer):integer; - добавляет ссылку на медиафайл в список проигрывания. id – индекс экземпляра библиотеки. target – путь к файлу, szoptions – список опций проигрывания, таких, как :input-repeat и т.п. options – число элементов списка, mode – способ вставки (например, PLAYLIST_APPEND), pos – позиция вставки (например, PLAYLIST_END). Возвращает код ошибки.

 

VLC_Play :function (id :integer) :integer; - проигрывает список. id – индекс экземпляра библиотеки. Возвращает код ошибки.

VLC_Pause :function (id :integer) :integer; - приостонавливает проигрывание текущей записи. id – индекс экземпляра библиотеки. Возвращает код ошибки.

VLC_Stop :function (id :integer) :integer; - прекращает проигрывание. id – индекс экземпляра библиотеки. Возвращает код ошибки.

 

VLC_IsPlaying :function (id:integer):longbool; - возвращает True, если идет проигрывание. id – индекс экземпляра библиотеки.

 

VLC_PlaylistIndex :function (id:integer):integer; - возвращает номер текущей записи в списке проигрывания. id – индекс экземпляра библиотеки.

VLC_PlaylistNumberOfItems :function (id:integer):integer; - возвращает число записей в списке проигрывания. id – индекс экземпляра библиотеки.

VLC_PlaylistNext :function (id:integer):integer; - переходит к следующей записи в списке и начинает проигрывание. id – индекс экземпляра библиотеки. Возвращает код ошибки.

VLC_PlaylistPrev :function (id:integer):integer; - переходит к предыдущей записи в списке и начинает проигрывание. id – индекс экземпляра библиотеки. Возвращает код ошибки.

VLC_PlaylistClear :function (id:integer):integer; - очищает список проигрывания. id – индекс экземпляра библиотеки. Возвращает код ошибки.

 

VLC_VolumeGet :function (id:integer):integer; - возвращает уровень громкости звука (в %) – число в интервале 0..200. id – индекс экземпляра библиотеки.  

VLC_VolumeMute :function (id:integer):integer; - работает как триггер, включая/отключая звук. id – индекс экземпляра библиотеки.

VLC_VolumeSet :function (id,volume:integer):integer; - изменяет уровень громкости звука (в %). id – индекс экземпляра библиотеки. volume – число в интервале 0..200.

 

VLC_FullScreen :function (id:integer):integer; - работает как триггер, включая/отключая полноэкранный режим. id – индекс экземпляра библиотеки.

 

 

«Новый интерфейс»:

 

libvlc_new :function (argc:integer; args:ppchar; var exception:libvlc_exception):libvlc_instance; - инициализирует библиотеку. Переменные argc и args имеют тот же смысл, что и для функции VLC_Init. exception – запись об ошибке. Возвращает ссылку на новый экземпляр библиотеки, который будет использоваться во всех остальных функциях.

libvlc_destroy :procedure (vlc:libvlc_instance); - уничтожает экземпляр библиотеки. vlc – ссылка на эту библиотеку.

libvlc_exception_clear :procedure (var exception:libvlc_exception); - очищает запись об ошибке. exception запись об ошибке.

 

libvlc_playlist_play :procedure (vlc:libvlc_instance; index,optCount:integer; opts:ppchar; var exception:libvlc_exception); - аналог VLC_Play. vlc – ссылка на библиотеку. exception – запись об ошибке.

libvlc_playlist_pause :procedure (vlc:libvlc_instance; var exception:libvlc_exception); - аналог VLC_Pause.  

libvlc_playlist_isplaying :function (vlc:libvlc_instance; var exception:libvlc_exception):longbool; - аналог VLC_IsPlaying

libvlc_playlist_items_count :function (vlc:libvlc_instance; var exception:libvlc_exception):integer; - аналог VLC_PlaylistNumberOfItems.

libvlc_playlist_stop :procedure (vlc:libvlc_instance; var exception:libvlc_exception);- аналог VLC_Stop.  

libvlc_playlist_next :procedure (vlc:libvlc_instance; var exception:libvlc_exception); - аналог VLC_PlaylistNext.

libvlc_playlist_prev :procedure (vlc:libvlc_instance; var exception:libvlc_exception); - аналог VLC_PlaylistPrev.

libvlc_playlist_clear :procedure (vlc:libvlc_instance; var exception:libvlc_exception); - аналог VLC_PlaylistClear.

libvlc_playlist_add :function (vlc:libvlc_instance; fileName,name:pchar; var exception:libvlc_exception):integer; - аналог VLC_AddTarget, упрощенный.

libvlc_playlist_add_extended :function (vlc:libvlc_instance; fileName,name:pchar; optCount:integer; opts:ppchar; var exception:libvlc_exception):integer; - аналог VLC_AddTarget.  

libvlc_playlist_delete_item :function (vlc:libvlc_instance; i_id:integer; var exception:libvlc_exception):libvlc_input; - удаляет запись с номером i_id из списка.

 

 

libvlc_playlist_get_input :function (vlc:libvlc_instance; var exception:libvlc_exception):libvlc_input; - проверяет существует ли устройство для вывода видео и возвращает ссылку на него.

 

libvlc_video_set_parent :procedure (input:libvlc_instance; handle:HWND; var exception:libvlc_exception); - назначает для видеоустройства визуальный элемент (форму, панель и т.п.) с дескриптором handle. Здесь и далее input – ссылка на устройство вывода видео, которую возвращает функция libvlc_playlist_get_input.  

libvlc_video_set_size :procedure (input:libvlc_instance; width,height :integer; var exception:libvlc_exception); - изменяет размеры выводимого изображения. Действует не всегда, а только для тех устройств, размеры которых могут свободно изменяться. width,height – ширина и высота изображения, соответственно.

 

libvlc_toggle_fullscreen :procedure (input:libvlc_input; var exception:libvlc_exception); - управление полноэкранным режимом.

libvlc_set_fullscreen :procedure (input:libvlc_input; var exception:libvlc_exception); - устанавливает полноэкранный режим.

libvlc_get_fullscreen :function (input:libvlc_input; var exception:libvlc_exception):longbool; - проверяет текущий режим.

 

libvlc_video_get_width :function (input:libvlc_input; var exception:libvlc_exception):integer; - возвращает текущую ширину изображения.

libvlc_video_get_height :function (input:libvlc_input; var exception:libvlc_exception):integer; - возвращает текущую высоту изображения.  

libvlc_video_get_aspect_ratio :function (input:libvlc_input; var exception:libvlc_exception):pchar; - возвращает текущее соотношение высоты к ширине изображения.  

libvlc_video_set_aspect_ratio :procedure (input:libvlc_input; aspect :pchar; var exception:libvlc_exception); - изменяет текущее соотношение высоты к ширине изображения.  

   

libvlc_video_take_snapshot :procedure (input:libvlc_input; filepath :pchar; var exception:libvlc_exception); - выполняет снимок экрана. Изображение записывается в файл с путем filepath, с именем и расширением по умолчанию.  

  

libvlc_audio_toggle_mute :procedure (vlc:libvlc_instance; var exception:libvlc_exception); - аналог VLC_VolumeMute.

libvlc_audio_get_mute :function (vlc:libvlc_instance; var exception:libvlc_exception):longbool; - проверяет, отключен ли звук.  

libvlc_audio_set_mute :procedure (vlc:libvlc_instance; mute:longbool; var exception:libvlc_exception); - выключает звук.

libvlc_audio_get_volume :function (vlc:libvlc_instance; var exception:libvlc_exception):integer; - аналог VLC_VolumeGet.  

libvlc_audio_set_volume :procedure (vlc:libvlc_instance; volume:integer; var exception:libvlc_exception); - аналог VLC_VolumeSet.

 

 

 

Снег Север.

Декабрь 2007 г.

 

Вернуться к списку статей Вернуться на главную страницу SourceForge.net Logo