Этот блог посвящен моей работе в VideoLAN Organization.

Ссылка на код: https://code.videolan.org/blurrrb/vlc/tree/gsoc19/modules/js

Что такое GSoC?

Google Summer of Code или сокращенно GSoC - это платформа, предоставляемая Google, чтобы помочь студентам-энтузиастам начать вносить свой вклад в проекты с открытым исходным кодом.

Кто я?

Я Аакаш Сингх, студент Национального технологического института, Карнатака, Индия. Я заядлый читатель и технический энтузиаст. Я люблю исследовать новые технологии.

Как я попал в GSoC?

В моем колледже есть сообщество разработчиков и участников открытого исходного кода, которые помогают новичкам вносить свой вклад в разработку открытого исходного кода. Итак, после участия в одном из их переговоров я просматривал предлагаемые проекты на веб-сайте VLC, мне понравился этот проект, я связался с разработчиками по каналу IRC и начал работать. Когда пришло время, я написал подробное предложение того, чем я хочу заниматься, мои наставники это одобрили, и вот я делаю проект.

Какой у меня проект?

В рамках VLC я работал над «Интеграцией движка JavaScript в VLC». Это не проект JavaScript, он полностью написан на языке C. Этот проект направлен на интеграцию облегченного движка JavaScript в VLC, чтобы включить поддержку сценариев и расширений в JavaScript.

VLC имеет поддержку сценариев и расширения, но на языке Lua, который не известен многим, и, следовательно, ограниченное количество расширений, доступных для VLC. Переход на JS с Lua привлечет на новую платформу намного больше разработчиков.

Что именно я делал в рамках этого проекта?

Работа над этим проектом началась еще до того, как страница GSoC была открыта в этом году (2019). Я начал с чтения документации VLC о том, как VLC работает внутри, о том, как новый код может быть добавлен в VLC, не мешая старому коду? Ответ на все эти вопросы - модули. VLC поддерживает сложный метод загрузки модулей, который позволяет добавлять новый код в базу кода без особых хлопот.

В течение этого времени я также просматривал код Lua, разговаривал с разработчиками из других сообществ, таких как MPV, чтобы понять, как можно интегрировать JS-движок, и тем временем также обсуждал с членами сообщества VLC, какой JS-движок будет лучше всего работать для VLC. вариант использования. Мы составили список доступных JS-движков и обсудили плюсы и минусы для каждого, имея в виду главную цель - низкий объем памяти и кроссплатформенность. После более чем недельного обсуждения мы остановились на MuJS, исключив JerryScript, V8, SpiderMonkey и многие другие.

MuJS - отличное программное обеспечение, созданное группой замечательных людей из MuPDF, которые помогли без промедления разрешить большинство моих запросов. Я изучил API MuJS, который довольно прост, написав несколько игрушечных примеров и, наконец, интерпретатор, который затем интегрировал в VLC для целей тестирования.

Первым шагом этого проекта было предоставление способа установки MuJS и сборки статических и переносимых библиотек MuJS, которые можно скомпилировать и включить в сборку VLC. Это было сделано путем внесения записи о MuJS в файлы VLC. Это упрощает общую установку MuJS до простой команды «make .mujs». Сценарий автоматически загружает библиотеку MuJS, проверяет хэш, устанавливает заголовки в локальный каталог contrib, а затем создает статические библиотеки.

После того, как все вышеперечисленное было сделано, пришло время сообщить системе сборки VLC о новом гостевом MuJS и проверить, правильно ли установлен MuJS. Это было сделано путем записи в файл configure.ac в корневой папке. Это выполнило 2 вещи:

  • включить поддержку флагов ‘- enable-js’ и ‘- disable-js’ в системе сборки, по умолчанию - ‘- enable-js’.
  • проверьте, правильно ли установлена ​​библиотека перед компиляцией, чтобы избежать ошибок во время компиляции.

На данный момент VLC был готов поддерживать любой модуль, требующий поддержки MuJS, но что хорошего может сделать модуль, который не может взаимодействовать с ядром VLC? Итак, следующим шагом было выбрать API, который позволит JS взаимодействовать с VLC. Мы назвали его API vlcjs. Основное внимание было уделено тому, чтобы сделать API похожим на старый Lua API, чтобы старые скрипты можно было легко переносить, а старые разработчики Lua могли легко перейти на новую реализацию.

Были согласованы вызовы API vlcjs, в основном похожие на Lua, отличаясь только реализацией. Старые вызовы API VLC были отброшены в пользу более новых и надежных API, таких как новые API плейлистов и проигрывателей. Реализация вызовов API была огромной задачей, отнимающей много времени. Предстояло реализовать множество вызовов API - строки, видео, аудио, анализатор XML, потоки, файловую систему, ведение журнала и т. Д., Которые охватывали большое количество конечных точек API. Это было особенно необходимо, поскольку все взаимодействия с внешним миром, включая доступ к сети и файлам, необходимо маршрутизировать через ядро ​​VLC. Этот подход имеет несколько преимуществ - безопасность, абстракцию от операционной системы, системные вызовы, а также простую поддержку для добавления новых API vlcjs.

После того, как API vlcjs был завершен, следующей важной задачей было разработать унифицированный механизм, чтобы сообщить среде выполнения MuJS о вызовах API и сделать вызовы API доступными для сценария JS. Это обрабатывается другим API vlcjs, который принимает указатель на состояние js и создает глобальный объект с именем «vlc» внутри среды выполнения js, а затем регистрирует все вызовы API для этого объекта. MuJS предоставляет механизм для перевода объектов JS в примитивы C и наоборот. Он также может обрабатывать вызов функций C из JS. Это делается путем манипулирования стеком JS и последующего помещения возвращаемого значения в стек после завершения выполнения функции C.

Следующим большим шагом была интеграция модуля интерпретатора. Это был первый модуль VLC, который мог запускать JS-код, а также взаимодействовать с VLC и внешним миром с помощью вызовов API vlcjs. Это был простой модуль, который ждал ввода пользователя, после получения он запускал его во время выполнения JS с помощью API MuJS. Этот модуль больше похож на тестовый модуль, позволяющий тестировать другие вызовы API. Позже в этот модуль были добавлены дополнительные функции.

После выполнения вышеуказанных шагов все ингредиенты были доступны для реализации фактических модулей - парсер плейлистов и загрузчик расширений. Синтаксический анализатор плейлистов реализовать было несложно, так как его работа довольно проста. Анализатор списка воспроизведения, когда он вызывается VLC со ссылкой, ищет сценарии в предопределенных папках, создает среду выполнения JS, по одной для каждого сценария, запускает их по одному и ищет правильный сценарий. Ссылка передается в сценарий с использованием механизмов, предоставляемых API MuJS, и сценарий запускает функцию проверки, а затем возвращает истину или ложь в зависимости от того, может ли он обработать ссылку. После нахождения правильного сценария для сценария становится доступным API vlcjs, а затем вызывается функция синтаксического анализа. Эта функция выполняет синтаксический анализ и возвращает список ссылок на видео- и аудиопотоки. Довольно прямолинейно. Я также написал сценарий youtube.js, чтобы продемонстрировать работу этого модуля. Скрипт работает, анализируя HTML-код страницы YouTube с помощью RegEx, чтобы извлечь ссылку на видеопоток. В сценарии есть сложные механизмы для выбора правильного видеопотока в зависимости от доступности и предпочтений пользователя. Текущий скрипт использует последнюю версию Youtube API и отбрасывает старый API, который использовался соответствующим вариантом Lua.

Следующий модуль - загрузчик расширений оказался не таким уж прямолинейным. Это потребовало много извращенного мышления и большого количества кода. Первой проблемой было написать vlcjs API, который может обрабатывать диалоги и создание виджетов, чтобы скрипты могли поддерживать графический интерфейс. Для обработки событий графического интерфейса требуется некоторое количество параллелизма, но однопоточный MuJS его не обеспечивает. Доступ к среде выполнения несколькими потоками одновременно может привести к повреждению стека выполнения. Итак, посоветовавшись с наставниками, я придумал API-интерфейс параллелизма vlcjs, который представляет собой однопоточную систему на основе цикла событий, обеспечивающую поддержку обработки событий в сценариях. Это была одна из самых сложных задач, поскольку она предполагала использование нескольких потоков, мьютексов, условных переменных. После того, как часть кодирования была завершена, следующей частью была ее отладка. Реализация была ошибочной - случайное повреждение памяти, взаимоблокировки и т. Д. После недели интенсивной отладки API был наконец завершен и готов к работе с модулем загрузчика расширений и диалоговым интерфейсом vlcjs API. Я модифицировал модуль интерпретатора для поддержки API параллелизма, а также протестировал его. Фактически это была последняя часть моего проекта и знаменует конец моего проекта GSoC в этом году.

Что я узнал?

Это трехмесячное путешествие было наполнено изучением нового и оттачиванием старых навыков.

  • улучшенные коммуникативные навыки
  • лучшее понимание того, как работают потоки
  • лучшее понимание того, как можно оптимизировать код C
  • научился эффективно использовать RegEx
  • узнал о внутренней работе VLC и других функциях ОС при реализации API vlcjs
  • и многое другое

Какие у меня планы?

Планирую портировать скрипт VLSub с Lua на JS. Это будет служить двум целям - работать как готовый пример для новых разработчиков, а также поможет протестировать новый модуль загрузчика расширений. Я также планирую работать над тем, чтобы сделать модуль загрузчика расширений доступным изнутри интерфейсного модуля VLC GUI.