Привет, меня зовут Олег Герасимов, я директор центра компетенций IT-кластера Ростелекома. Наша команда среди многих задач разрабатывает прошивки камер видеонаблюдения для B2B и B2C-сервисов. В предыдущей статье я рассказывал, как мы научились самостоятельно разрабатывать софт и прошивки для IP-камер, в том числе и недорогих, и подключать их к облаку.
За прошедшее время камеры с нашей прошивкой уже появились на рынке, и, судя по данным Яндекс.Маркета, на полках магазинов цены на них начинаются от 1500 рублей. И это уже не дешевый ноунэйм, а качественные камеры ведущих мировых брендов: Hikvision, Dahua и Uniview. На мой взгляд, это отличный результат!
Когда мы начинали работать с прошивками, количество поддерживаемых моделей камер было небольшим. В процессе разработки общих компонентов мы самостоятельно реализовывали поддержку новых моделей камер.
Тогда у нас была возможность самим выбирать, какие модели интегрировать в первую очередь, а какие нет, исходя из технических соображений.
Например, если в камере используется сенсор, под который в SDK процессора нет драйвера, то драйвер сенсора придется разработать самим. Это очень трудоемкий процесс, требующий сложной разработки и отладки. Сенсор технически сложный компонент, и на одно изучение технического описания (Datasheet) сенсора могут уйти недели. Это, на секундочку, сотни страниц с описанием тысяч регистров, влияющих на работу сенсора, и логики взаимодействия с ними.
Первое время мы обходили стороной камеры с незнакомыми сенсорами, чтобы не застрять в деталях настройки конкретного железа, а сосредоточиться на разработке общих компонентов, которые будут использоваться в большинстве камер. Иногда нам удавалось найти уже готовые драйверы сенсора в оригинальной прошивке камеры, но это было скорее счастливым исключением из правил. Работая в таком режиме, мы поддержали около десятка моделей камер на нескольких наиболее популярных чипсетах, делая упор не на количество моделей, а на функциональность.
Следующий этап разработки прошивок для камер совпал с объявлением тендера на закупку камер. Это уже серьезное событие. Ростелеком закупал сотни тысяч камер на открытом тендере, в который могли войти любые вендоры камер, соответствующих по своим ТТХ продуктовым и техническим требованиям.
Одно из ключевых требований к поставщикам предоставление технической информации о схемотехнике камер, например, о GPIO-выводах, к которым подключены светодиоды, кнопки, ИК фильтры и т.д. Кроме этой информации, мы просили вендоров предоставить специфичные для оборудования патчи ядра/загрузчика и исходные тексты драйверов устройств, в первую очередь, сенсоров и WI-FI чипов.
Такой подход существенно облегчил нашу задачу по поддержке новых камер. Вместо данных, добытых реверс-инжинирингом, у нас появились официальные спецификации и исходники драйверов от вендоров.
Однако по-прежнему много времени уходило на подготовку прошивок, даже когда вендоры стали делиться информацией: данные в спецификациях были неточными, драйверы не хотели заводиться на железе, а то и вовсе отказывались собираться.
Самостоятельно найти ошибку в спецификациях или драйверах
получалось не всегда, да и искать ошибки в стороннем коде небыстрое
занятие. Поэтому чаще для решения проблемы приходилось обращаться к
вендорам. Как правило разработчики, которые могут ответить на
вопросы о схемотехнике, найти
и поправить ошибки в драйверах, находятся в Китае. А это сразу
замедляет коммуникацию одна итерация вопрос-ответ может занимать
несколько дней, а исправление ошибок и того дольше.
Пока поток новых камер был небольшим такой режим устраивал, но со
временем запросы от маркетологов выросли. Возникла потребность в
интеграции большего количества линеек: уличные камеры с Wi-Fi,
домашние с PTZ, с сиреной и т.д. Но с другой стороны, по мере
развития облачного видеонаблюдения увеличивалось количество
вендоров, желающих работать с нами.
В этот момент мы поняли, что силами команды с возросшим в разы
количеством новых камер уже не справиться. Всё время разработки
будет занимать исключительно интеграция новых камер, а на
разработку новых фич и улучшения времени не останется. Нужно было
найти новый подход.
Мы начали анализировать узкие места процесса. Они оказались на поверхности: больше всего времени уходило на итерации получения патчей и драйверов, багрепорты в сторону вендоров и ожидание исправлений.
Логичная мысль: дать вендорам возможность самим собирать нашу прошивку с драйверами их оборудования и конфигурациями, проверять результаты и отлаживать работу у себя, не тратя драгоценное время на переписку.
Техническое решение, с одной стороны, очевидное: сделать SDK для сборки нашей прошивки. Но есть ряд требований:
- SDK должен уметь собирать прошивки под все типы поддерживаемых SoC. На сегодня это больше 10 чипсетов от Hisilicon, Ambarella, MStar и Fullhan.
- Нельзя передавать компоненты прошивок от одного вендора другим, потому что это интеллектуальная собственность. Мы подписываем NDA, в котором обязуемся не раскрывать передаваемую информацию.
- Результаты интеграции, полученные от вендора, нужно уметь замерджить в общее дерево исходников прошивки в нашем Git.
- У вендора должна быть возможность вносить патчи и дополнения во все компоненты: ядро, загрузчик, SoC SDK и прочие.
- Нужно иметь гибкую структуру настроек, в которой будут учитываться максимальное количество возможных конфигураций оборудования.
- Для каждой пары вендор-SoC должна собираться универсальная прошивка, поддерживающая все камеры вендора на базе этого процессора.
- Сборка должна работать автономно и не требовать доступа в
Интернет. Да, большинство разработчиков ПО для камер в Китае не
имеют доступа в Интернет на рабочих местах.
Структура системы сборки, в тот момент, была не готова к такому подходу. Например, в некоторых файлах конфигурации были совмещены настройки камер от нескольких вендоров, а для сборки прошивки и загрузки пакетов требовался доступ к нашим внутренним репозиториям. Да и некоторые места системы сборки (чего греха таить) не предполагали такого масштабирования: их разработали в то время, когда поддерживался один тип процессора и две модели камеры...
Другая проблема: под каждый процессор поставляется отдельный SDK от его производителя, с уникальным набором системных компонентов: своя версия и набор патчей ядра, toolchain, uboot, системная библиотека (где-то uclibc, а может быть glibc). Под эти факторы приходится подстраивать систему сборки, а местами и код приложений. Для наглядности масштабов фрагментации вот табличка со списком версий компонентов:
Процессор | Версия Linux | Версия gcc |
---|---|---|
Hisilicon 3516a/d | 3.4.y | gcc 4.9 |
Hisilicon 3518ev100 | 3.0.y | gcc 4.4 |
Hisilicon 3518ev200 | 3.4.y | gcc 4.9 |
Hisilicon 3516cv300 | 3.18.y | gcc 4.9 |
Hisilicon 3518ev300/3516ev200/ev300 | 4.9.y | gcc 6.3 |
Hisilicon 3516cv500/dv300 | 4.9.y | gcc 6.3 |
mStar i3 | 3.18 | gcc 4.8 |
mStar i6 | 4.9 | gcc 8.2 |
Ambarella s2l | 3.10 | gcc 4.9 |
Ambarella s3l | 3.10 | gcc 5.2 |
Fullhan fh8632 | 3.0.y | gcc 4.3 |
Как видно, разброс огромный: от легаси десятилетней давности до относительно свежих ревизий.
С такими вводными нам предстоял рефакторинг системы сборки прошивок: выделить общие патчи и драйвера, которые будут доступны для всех вендоров, повторить это для 10+ поддерживаемых моделей SoC, полностью переосмыслить систему конфигурации наших компонентов. Заодно выпилить специфичные для камер костыли из init-скриптов, сделав общие и универсальные решения.
В результате мы пришли к структуре, в которой все специфичные для конкретных моделей настройки/конфигурации/makefile/патчи собраны в папках, структурированную по иерархии "Вендор SoC Модель камеры". Такая иерархия позволила автоматизировать сборку SDK с разделением сборок по вендорам. Вот пример, драйверы и конфигурации для камер от выдуманного вендора Megatech на чипсете Hisilicon.
Драйверы
drivers + megatech/ -> драйвера и конфиги для вендора 'megatech'| + hi3518ev200/ -> чипсет hisilicon hi3518ev200| | + 1421 -> конфигурации модели камеры с кодом оборудования 1421| | | | + ipcdb.1421.yml -> общая конфигурация| | | | + mpi/entry.1421.yml -> конфигурация видеозахвата| | | | + ptz/entry.1421.yml -> конфигурация PTZ| | + motor -> драйверы моторов управления PTZ| | | + bu24036_motor -> драйвер шагового мотора на чипе bu24036| | | | gpio_motor -> драйвер шагового мотора управляемый GPIO выводами| | + wlan -> драйверы wi-fi чипов | | | + Makefile -> скрипт сборки | | + sensor -> драйверы сенсоров| | | + Makefile -> скрипт сборки
Патчи ядра
kernel+ megatech/| + hi3518ev200/| | + mmc_hotplug.patch| | + kernel-config.patch
Патчи uboot
uboot+ megatech/| + hi3518ev200/| | + uboot-mmc.patch| | + uboot-spi.patch
Все файлы конфигурации камер перевели в формат YAML, как самый удобный для ручного редактирования, и разделили по компонентам:
- Настройки оборудования модели камеры (GPIO, наличие и тип Wi-Fi, сенсора, флаги наличия микрофонов, динамиков, дополнительные скрипты инициализации).
1421: vendor: megatech model: Model A soc: 3518ev2 ethernet: 0 wlan: rtl8188eu sensor: ov9732 leds: ir: gpio: 23 inverse: true red: gpio: 10 power: gpio: 10 green: gpio: 2 net: gpio: 2 keys: wps: gpio: 16 reset: gpio: 16 peri-out: pwdn: gpio: 1 inverse: true ircut.p: gpio: 57 ircut.n: gpio: 60 wifi_pwr: gpio: 7 flash: spi misc: microphone: true speaker: true mic_hpf_level: 3 mic_anr_level: 4 scripts: insert-sns: - himm 0x200f0040 0x2; # I2C0_SCL - himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz init-wlan: - insmod 8188eu.ko
- Настройки видеоприложения для конкретной модели (тип сенсора, поддерживаемые разрешения, режимы синхронизации и видеозахвата, подстройки алгоритмов).
1421: sensor: type: ov9732 lib: libsns_ov9732.so resolutions: - targets: - { width: 1280, height: 720, maxrate: 30 } - { width: 640, height: 480, maxrate: 30 } - { width: 640, height: 360, maxrate: 30 } - { width: 320, height: 240, maxrate: 30 } channels: - main source: { width: 1280, height: 720, rates: [30, 25] } combo_dev_attr: input_mode: CMOS_33V vi_dev_attr: interface_mode: DIGITAL_CAMERA component_mask: [67043328, 0] syn_cfg: vsync: field vsync_neg: high hsync: valid_signal hsync_neg: high vsync_valid: valid_signal vsync_valid_neg: high timing_blank: [ 370, 1280, 0, 6, 720, 6, 0, 0, 0 ] isp_image_attr: bayer_format: BGGR
- Настройки PTZ (тип чипа, тайминги работы шаговых драйверов).
1421: type: pan_controller_and_tilt_gpio_generic interrupt_gpio: 50 absolute: true pan: park_ccw: false continuous: [-20, 20] relative: [-7.9, 7.9] absolute: [0, 355] channel: 0 min_wait: 100 max_step: 140 max_speed: 375 unity: 430 tilt: park_ccw: true continuous: [-20, 20] relative: [-3.5, 3.5] absolute: [0, 90] max_step: 2000 unity: 157
Выбор способа сборки дистрибуции SDK был очевидным. Docker
оказался вне конкуренции, с его помощью можно легко передать
подготовленную среду.
Мы использовали Docker практически с самого начала разработки, как
в CI, так и для локальной отладки на компьютерах разработчиков.
Процесс сборки полностью автоматизирован. Docker-образы с нашим SDK собираются в общем CI под матрицу сочетаний SoC-вендор.
Исходно у нас было два основных репозитория:
- build-tools в нем хранятся Dockerfile, скрипты установки SoC SDK и скрипты сборки общих библиотек для поддерживаемых аппаратных платформ. В CI этого репозитория собираются Docker-образы со всем необходимым для сборки прошивки и софта под целевую платформу.
- vc-firmware здесь хранится система сборки прошивки и компонент. К этому же репозиторию как git-submodule подключены репозитории с исходниками наших компонентов: видеоприложение, облачный агент, модуль обновления). Результатом работы CI в этом репозитории являются сами прошивки камер.
Для нового SDK добавили еще один репозиторий, vc-sdk, к которому подключили vc-firmware и build-tools как git-submodule. В CI этого репозитория сборка разделена на этапы:
- подготовка базового Docker-образа по аналогии с репозиторием build-tools;
- сборка пакетов с компонентами (видеоприложение, облачный агент, модуль обновления);
- загрузка пакетов с общими компонентами (публичные библиотеки, драйверы Wi-Fi и т.д.)
- копирование каталогов с драйверами и патчами, специфичными для вендора
В результате работы CI получается автономный Docker-образ,
рассчитанный на сборку прошивок для камер на выбранном чипе
вендором. Он загружался
в общий registry образов, из которого вендор может скачать свой
образ.
Следующий объемный фронт работ разработка документации. Документацию мы писали поэтапно, собирая обратную связь от вендоров и учитывая замечания. Кстати, для документации использовался наш инструмент Foliant. Про него наши ребята уже рассказывали на митапе Write the Docs Moscow (http://personeltest.ru/aways/habr.com/ru/post/431210/).
Заключение
За этот год уже 8 вендоров освоило использование нашего SDK, с его помощью добавили поддержку работы с видеонаблюдением Ростелекома в нескольких десятков новых моделей камер. Некоторые из этих камер уже продаются.
Важно, что выбранный подход разработка собственной прошивки на базе SDK работает на потребителей: интеграция камер таким способом позволила организовать честную конкуренцию при тендере на закупку камер. Победители выявляются по объективным показателям: качеству оборудования и наименьшей стоимости.
Наконец, если раньше количество поддерживаемых моделей камер было ограничено силами и ресурсами команды, то сегодня эта проблема ушла в прошлое. Теперь вендоры камер могут сами добавлять поддержку новых моделей через облако РТК.