Как мы прошли путь от разработки прошивок для каждой камеры до создания универсального SDK для вендоров камер

    Привет, меня зовут Олег Герасимов, я директор центра компетенций 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, сенсора, флаги наличия микрофонов, динамиков, дополнительные скрипты инициализации).

    Пример yaml
    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

    • Настройки видеоприложения для конкретной модели (тип сенсора, поддерживаемые разрешения, режимы синхронизации и видеозахвата, подстройки алгоритмов).

    Пример yaml
    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 (тип чипа, тайминги работы шаговых драйверов).

    Пример yaml
    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» (https://habr.com/ru/post/431210/).


    Заключение


    За этот год уже 8 вендоров освоило использование нашего SDK, с его помощью добавили поддержку работы с видеонаблюдением Ростелекома в нескольких десятков новых моделей камер. Некоторые из этих камер уже продаются.


    Важно, что выбранный подход — разработка собственной прошивки на базе SDK — работает на потребителей: интеграция камер таким способом позволила организовать честную конкуренцию при тендере на закупку камер. Победители выявляются по объективным показателям: качеству оборудования и наименьшей стоимости.


    Наконец, если раньше количество поддерживаемых моделей камер было ограничено силами и ресурсами команды, то сегодня эта проблема ушла в прошлое. Теперь вендоры камер могут сами добавлять поддержку новых моделей через облако РТК.

    Ростелеком
    Территория возможностей

    Comments 15

      +2
      от каких объемов китайцы согласны использовать чужой sdk вместо своего?
        +1

        Зависит от размера вендора. В среднем, как правило, на партиях от нескольких тысяч штук.

          +1
          Не понял, зачем делать целый BSP, если вам надо только видеопоток забрать из камеры? Почему бы не послать китайцам ваше приложение, которое они бы просто добавили в свои собственные прошивки и всё?
            +3

            Захват и трансляция видеопотока это далеко не единственная функция прошивки. Софт отвечает за настройку параметров аудио/видео, за обратный канал аудио, за видео- и аудио- аналитики (детекторы событий — например движения и анормального звука), управление PTZ и т.д. и т.п. Кроме этого. нужно реализовать механизм обновления прошивок.
            Подстраиваться под API каждого вендора камер (которых намного больше чем используемыз SoC) никаких ресурсов не хватит. И это не говоря о поддержке и выпуске обновлений.


            А еще во многих случаях китайские прошивки содержат дыры/бэкдоры и много ненужного функционала который с одной стороны снижает информационную безопасность, а с другой стороны увеличивает требования к железу.


            О мотивации было подробнее в предыдущей статье — https://habr.com/ru/post/415841/

              0
              Я читал прошлую статью, там всё было понятно. Когда вы берёте камеры от производителей, которые с вами не сотрудничают, выбора нет.

              Но теперь, производители с вами сотрудничают и даже стараются победить друг друга в тендерах, так почему не сделать приложение, пихнуть туда весь функционал (включая обновления) и предложить (записать в условия тендера) производителям самим сделать всё окружение так, чтобы ваше приложение работало хорошо. Поставить ограничение на минимальную версию ядра и всё такое. Чтобы упростить поддержку разных платформ, приложение можно на lua сделать
                +1

                Мы пробовали делать интеграцию на уровне API с несколькими вендорами — уходит очень много времени на отладку взаимодействия, и на тестирование результирующих прошивок. И более того, каждый апдейт со стороны — все старые проблемы вылезают обратно.


                По опыту дешевле сделать поддержку в приложении работы напрямую с SoC. При наличии уже готового нашего видео-приложения и системы сборки — добавление поддержки нового SoC, быстрее чем тестирование/интеграция в прошивку вендора.

                  0
                  Китайские ODMы ничего не могут сделать с проблемами безопасности, потому что у них нет профильных специалистов, поэтому отдать туда разработку — гарантировать себе наличие проблем безопасности и\или бэкдоров.
                    0
                    в принципе, имея мастер-приложение, эти проблемы можно обойти несколькими способами:
                    1. самое простое: запускать мастер-приложение как init
                    2. устанавливать правила iptables, запрещающие всё, кроме нужного
                    3. убивать всё что открывает сокеты
                      +1
                      Ну вот тут у нас и остается один шаг до собственного SDK, раз уж мы решили так яростно вмешиваться в работу юзерспейса, что запускаемся там init'ом, контролируем сокеты и т.п. «Так долго боролся с драконами, что сам им стал».
                        0
                        один шаг? Приложение, запускаемое в качестве init, это всё ещё обычное приложение. Скрипт для iptables, который закрывает все порты на вход и выход кроме двух, умещается в 10 строчках.
                        SDK, описанное в статье, включает несколько версий ядра, несколько версий gcc, десятки патчей от разных вендоров. Тут очень много шагов от обычного приложения
                          +1

                          Версии gcc/ядра/библиотек идут из SoC SDK, и вне зависимости от подхода надо будет их поддерживать в приложении.
                          У вендоров камер нет технической возможности нормализовать версии gcc/libc.


                          Скрипт для iptables, который закрывает все порты на вход и выход кроме двух, умещается в 10 строчках.

                          А софт вендора раз в 30 секунд будет их обратно открывать (да, это пример из реальной жизни) :)

                            0
                            Версии gcc/ядра/библиотек идут из SoC SDK, и вне зависимости от подхода надо будет их поддерживать в приложении.

                            Слинковать статически и ставить приложение как блоб? Тогда нужны будут только версии под разные архитектуры процессора. Хотя, в вашем случае, большеват блоб, наверное, получится.
                            А софт вендора раз в 30 секунд будет их обратно открывать (да, это пример из реальной жизни) :)

                            сочувствую
              –1

              А вы можете сделать прошивку с минимальными задержками в передаче изображения и с интерфейсом GigE Vision? А также с честным WDR?

                0

                подскажите, как скачать/купить для домашнего использования?

                  0
                  Ваш «ИТ-кластер» — это стыд и позор. Имел «счастье» подключать видеонаблюдение Ростелекома, эпопея тянется две недели.

                  Приходят монтажники, протягивают Ethernet. Договор активировать не могут, т.к. у РТК в этот день ломается маршрутизация. Сайт rt.ru и onlime.ru можно открыть только через VPN в Германии, из России он не открывается. Телефон 8-800 не отвечает — соединение просто не устанавливается.

                  Когда спустя пару часов всё стало подниматься, и личные кабинеты стали открываться, попытка активации камеры завершалась такой вот высокоинформативной ошибкой:

                  image

                  Камера сканирует QR-код, на мгновение появляется в ЛК и пропадает. И всё, хоть ты тресни.

                  А дальше — две недели ада с дозвоном в абонентскую службу, закрытием тикетов с формулировкой «вы пришлите скриншотов пошагово» (уже прислал, Ростелеком их продолбал). Работа IVR — это треш (меня два раза робот спрашивает, из Москвы ли я, или из Подмосковья, я 10 минут выслушиваю про то, как WiFi плохо работает через стены).

                  Плата за камеру и за услугу при этом, конечно же, списывается исправно.

                  В процессе очень хотелось позвонить Диане Самошкиной и рассказать об этом дивном опыте в красках, но сдержался — видимо, зря.

                  P.S. Тикеты INC000012540123 и INC000012568045

                  Only users with full accounts can post comments. Log in, please.