Введение

Приветствую профессиональное сообщество Хабра.

В этой статье описана прошивка IPTV приставки MOTOROLA VIP1003 ARRIS для получения удалённого доступа, а также портирование приложения на целевую архитектуру с целью добавления функционала воспроизведения контента с источников, требующих авторизации.

В заключительной части подведены итоги описанной в статье работы, а также рассмотрена область использования IPTV приставки MOTOROLA VIP1003 ARRIS.

Со всей серьёзностью заявляю, что написание простейшей программы, первой для IPTV приставки MOTOROLA VIP1003 ARRIS, печатающей на экран терминала сообщение “Hello World” является важным моментом, рассматривающим техническую возможность портирования более сложных проектов. Имеются особенности, которые необходимо рассмотреть.

Для конечных пользователей модифицированного устройства приведено Руководство пользователя.

Содержание

  1. Обзор IPTV приставки MOTOROLA VIP1003 ARRIS

  2. Интерфейс UART. Подключение диагностического вывода к терминалу.

  3. Настройки. Перечисление и описание функции настроек приставки в интерактивном конфигурационном меню.

  4. Программное обеспечение. Описание используемого программного обеспечения. Выход в Интернет необходим только в этом разделе.

  5. Подготовка к прошивке. Пошаговое руководство для подготовки к процессу прошивки. Дополнительную информацию можно найти в предыдущих разделах.

  6. Процесс прошивки. Комментарии к сообщениям терминала.

  7. Воспроизведение контента. Здесь описывается функция новой прошивки.

  8. Первая программа для IPTV приставки. Особенности сборки простейшей программы для целевой архитектуры и её запуска на целевой системе. Обман вообщем.

  9. Портирование FFmpeg на архитектуру SuperH SH. Настройка кросс-компиляции популярного проекта FFmpeg и его запуск на целевой системе.

  10. Воспроизведение контента с источника RTSP, требующего basic авторизации. Применение FFmpeg для реализации поддержки функции.

  11. Проблема портирования приложений для архитектуры SuperH SH. Чем ограничено расширение функционала?

  12. Целесообразность модификации приставки. Что за ерундой мы только что занимались?

  13. Руководство пользователя. Инструкция по использованию модифицированной приставки для конечного пользователя.

  14. Резюме.

  15. Источники


Обзор IPTV приставки MOTOROLA VIP1003 ARRIS

Общий вид. [1]
Общий вид. [1]

Управление производится с пульта ДУ. Например от Ростелекома.

Пульт управления [6]
Пульт управления [6]
Вид сзади. [2]
Вид сзади. [2]

Питание 12В/1A. Выход HDMI. Функционал HDCP предоставляется. Композитный видеовыход. Коаксиальный выход S/PDIF интерфейса. Существуют модели, имеющие разьём SCART, вместо композитки. Форма корпуса диктуется, вероятно, вопросами совместимости с разьёмами SCART.

Внутренняя компоновка довольно просторная.

Вид изнутри. [3]
Вид изнутри. [3]

По центру расположен чип, в котором обьединены микропроцессор RISC архитектуры SuperH SH STx7105 и процессорное ядро архитектуры VLIW ST231. На базе ST231 реализован декодер видео H.264. Такая специфика по всей видимости и позволяет устройству работать с большим обьёмом видеоданных без перегрева.

Контактные площадки, которые расположены слева — это интерфейсы UART и EJTAG. Как видите, расположены они обособленно, так что подпаяться к ним можно не испортив другие компоненты. Обратим внимание на UART

[к содержанию]


Интерфейс UART

Оба крайних вывода — GND, средний вывод — питание 3В. Вывод ближе к задней стенке — TX. Интерфейс работает с уровнями TTL — 3В. Для подключения требуется преобразователь TTL/RS232 (или TTL/USB). О выводах RX мне известно лишь то, что он работает не у всех моделей.

Но нам и этого будет достаточно. Информация о ходе процесса перепрошивки выводится в последовательный интерфейс (UART). Параметры передачи: 115 200 бод 8N1 Информацию о любом сбое можно получить исключительно оттуда. Через видеовыход выводится лишь общее сообщение о неудавшейся загрузке ПО.

[к содержанию]


Настройки

Меню конфигурации встроенного программного обеспечения
Меню конфигурации встроенного программного обеспечения

Приставка обладает большим количеством настроек, доступных в меню. В подменю TV доступны настройки видеорежима PAL/NTSC.

Подменю сетевых настроек IP и дополнительных настроек Advanced открываются путём набора на пульте управления последовательности цифр 2357 и 7532 соответственно. В подменю IP настраивается метод получения адреса STATIC/DHCP и стандартные адреса шлюза, подсети, маска, а также разрешается или запрещается загрузка при неудачном получении сетевого адреса. В подменю Advanced настраивается порядок загрузки, адрес загрузки, адрес NFS сервера.

Приставка поддерживает несколько способов загрузки: Multicast, TFTP, HTTP и LS. Загрузка с NFS сервера не поддерживается, настройка предназначена для некоторых типов прошивок, которые используют NFS сервер вместо памяти устройства. Порядок загрузки задаётся настройками Kernel protocol и Splash protocol. Настройка Kernel protocol касается загрузки образа ядра, настройка Splash protocol — экранной заставки. Если в порядке загрузки указать 2 — приставка будет пытаться загрузить образ с TFTP сервера. Если в порядке загрузки указать 6 — приставка будет пытаться загрузить образ с HTTP сервера. Очень много настроек, касающихся загрузки с TFTP сервера. Приставка поддерживает загрузку с пула TFTP серверов 4 (четырёх) нод. Задаётся количество попыток загрузки с одной ноды и количество попыток подключения к пулу, таймаут а также размер блока. Адрес ноды может анонсироваться DHCP сервером и необходимость в указании адреса отпадает. Задать можно имена загружаемых файлов. Если адрес загружаемого файла анонсирует DHCP сервер и в настройках указан метод получения адреса от DHCP сервера, имя файла, указанное в настройках, не будет иметь силы.

Выполненные настройки не сохраняются автоматически. Я намеренно не описал ещё одно подменю. Ниже поймёте почему.

[к содержанию]


Программное обеспечение.

Желательно заранее загрузить и верифицировать программное обеспечение, необходимое для прошивки и программирования устройства.

Ниже приведен список программного обеспечения для загрузки.

  1. kreatv‑kernel‑SMARTLABS.bin — загрузочное ядро.

  2. rt firmvare ver. 5.24246.191016 (legacy) — прошивка (первичная) от Rostelecom.

  3. PHP‑MOTO1003VIP — прошивка с php сервером и telnet. Перед прошивкой на приставке в ОБЯЗАТЕЛЬНОМ порядке должна стоять версия LEGACY 5.24246.191016 (ТОЛЬКО ОНА И НИКАКАЯ ИНАЧЕ).

  4. toolchain_st40_2.5.0.tar.bz2 — утилиты для сборки собственных приложений

  5. FFmpeg - популярный кроссплатформенный проект.

После загрузки проверьте хэши прошивок sha265. Эти прошивки проверить очень важно.

SHA265: 5fae869425b054a34975dd1f62ba99cc40f7e69c98af504301a5f15af7939f6c kreatv‑kernel‑SMARTLABS.bin

SHA265: b5976a0a6a4d023ab9318ff274fa5dec369b2a47014cad682bfe79249f777e8a firmware_vip19×3_5.24246.191016.bin

Опишем каждый компонент подробнее.

Ядро kreatv‑kernel‑SMARTLABS.bin загружается с FTP сервера. При последуюих запусках ядро ищет файл firmware.bin на флеш‑карте или на сетевом ресурсе. Дальнейшей загрузки не происходит. Если прошивка найдена, ядро начинает её запись в память. Если быть точным, то ядро запускает файл, чем бы он ни был. Ядро может запустить подписанный скрипт, и уже этот скрипт записывает прошивку. Содержимое скрипта не проверяется. Технически можно скопировать легитимный скрипт в корень флешки под именем firmware.bin и видоизменить его содержимое под произвольные нужды. Например, для удобства, запуск другого скрипта. Помимо подписи, скрипт должен содержать код для поиска и монтирования флешки Загрузочное ядро содержит утилиту wget, таким образом возможна даже загрузка скрипта из сети. Это можно использовать например для получения информации от утилит dmesg, uname, ps

Прошивка rt firmvare ver. 5.24246.191016 (legacy) содержит SSH сервер, однако доступ невозможно получить так как применяются ассиметричные ключи RSA. Состоит из одного файла firmware.bin. После перепрошивки файл переименуется в firmware_done.bin

Прошивка PHP‑MOTO1003VIP содержит PHP сервер и TELNET. PHP сервер предоставляет веб‑интерфейс, доступ к которому возможен по URL http://[IP]/index.php. Веб интерфейс предоставляет возможность загрузки плейлиста пункты которого затем станут доступны в приложении для их выбора с пульта. Приложение загружается и работает автономно, воспроизведение контента возможно из локальной сети. Логин: root/12341234. Сообщения, которые выводятся в UART, дублируются в файле /var/log/messages.

Состоит прошивка из четырёх файлов

  1. branding.bin (CRC32: 0D A7 4F FB) — фирменное приложение

  2. firmware.bin (CRC32: D8 12 47 D9) — подписанный скрипт

  3. rootfs.bin (CRC32: 7B 74 4E 7F) — загружаемый образ системы

  4. splashimage.bmp (CRC32: AB 3D C3 93) — экранная заставка

Toolchain для сборки приложений располагается внутри архива SDK: kreatv‑kit‑oss_4.2_st40.tgz, который можно загрузить из Интернета. Вы можете выбрать версию SDK для загрузки. Компилятор, входящий в toolchain, поддерживает компиляцию исходного кода на языке C в устаревшем стандарте — c99 Есть стандартная библиотека языка C, реализующая поддержку большинства функций, например printf. Целевая архитектура для компилятора — Renesas / SuperH SH Приложение, собранное для целевой машины, использует динамический линковщик ld‑uClibc.so.0. Все необходимые для запуска приложений библиотеки содержатся в sdk. Разработчик — STMicroelectronics. Версия GCC — 4.6.3 20120313. Версия GNU LD — 2.22.

FFmpeg [5] поддерживает кросс компиляцию.

Коммит id:52c7366c83aba4dc92ceedecbee592d629c98e29 совместим с устаревшим стандартом языка C - с99.

Вот что пишет git про данный коммит.

Author: Martin Storsjö <martin@martin.st>
Date:   Thu Dec 1 11:10:19 2016 +0200

    aarch64: vp9itxfm: Restructure the idct32 store macros
    
    This avoids concatenation, which can't be used if the whole macro
    is wrapped within another macro.
    
    This is also arguably more readable.
    
    This is cherrypicked from libav commit
    58d87e0f49bcbbc6f426328f53b657bae7430cd2.
    
    Signed-off-by: Martin Storsjö <martin@martin.st>

[к содержанию]


Подготовка к прошивке

  1. Поднимаем DHCP (isc‑dhcp‑server) и TFTP (tftpd‑hpa)

    1. В настройках DHCP (/etc/dhcp/dhcpd.conf) указываем файл kreatv‑kernel‑SMARTLABS.bin

    2. В каталог /srv/tftp копируем kreatv‑kernel‑SMARTLABS.bin

  2. Подготавливаем флеш карту

    1. Флеш карту форматируем в ext3

    2. В корень копируем прошивку rt firmvare ver. 5.24246.191016 под именем firmware.bin

    3. Добавляем в корень файл firmware.bin.config с содержимым force=1

    4. В корне создаём каталог PHP‑MOTO1003VIP и копируем туда все четыре файла прошивки

  3. Настраиваем приставку.

    1. Включаем приставку и после включения жмём MENU на пульте

    2. Метод получения сетевого адреса адреса устанавливаем в DHCP

    3. Запрещаем загрузку без получения сетевого адреса

    4. Kernel protocol устанавливаем в 323.

    5. Убеждаемся что Ignore VCI установлен в NO

    6. Стираем старое ПО System → Remove Software.

    7. Сохраняем настройки и отключаем приставку

ВНИМАНИЕ! Прежде чем выполнять пункт 3.6, прочитайте все описания и выполните все рекомендации выше. Лучше отключить приставку и вернуться к настройке позже, когда всё будет подготовлено. Эта функция не скрыта по умолчанию и сделать из устройства нерабочий кирпич очень легко.

[к содержанию]


Процесс прошивки

В процессе прошивки желательно исключить риск пропадания питания. Также заранее подключаем UART, поднимаем Ethernet соединение и подключаем флеш‑карту, поскольку процесс происходит быстрее, чем вы захотите мяукнуть.

Всё подготовлено? Включаем приставку в сеть. Всё внимание на терминал.

System memory: 256 MB
Using Slot 1
Unpacking Image ...Done

Первые «шаги»

TFTP: Server node attempt 2 of 2
Connecting to 192.168.1.100
Sending read request for kreatv-kernel-SMARTLABS.bin

Если сервер действительно работает и указанный файл присутствует, загрузка начинается просто. В терминал выводятся указанный в настройках размер блока, полученный размер файла и таймаут.

Negotiation block size = 512
Negotiation transfer size = 3376610
Negotiation data timeout = 5 seconds
Download completed
Verifying image...

Последние шаги

Image in Local Storage is not up-to-date
Storing kernel image in Local Storage

Это значит, что ядро загрузилось и больше не будет дёргаться с TFTP сервера

Kernel loaded successfully
Starting new kernel
kexec information

Это значит что ядро запустилось. Ловим строчку

KreaTV bootimage is ... Changed, disabling boot until upgrade

Дальнейшая загрузка производиться не будет до тех пор, пока устройство не найдёт прошивку

MASSSTORAGE_DEVICES = /dev/sda 
kjournald starting.  Commit interval 5 seconds
EXT3 FS on sda, internal journal
EXT3-fs: mounted filesystem with ordered data mode.
Successfully mounted /dev/sda to /tmp/sda

Это значит, что флешка примонтировалась.

Upgrade sources:  --url="http://upgrade.riskymeije.ru/vip1963x" --url="file:///tmp/sda/firmware.bin"

Это источники, где приставка будет искать прошивку. Если флешка отсутствует, приставка попытается найти прошивку ещё раз.

Splash message: Successfully flashed new firmware. Rebooting ...

Сообщение после прошивки образа rt firmvare ver. 5.24246.191016 (legacy)

Restarting system.
Watchdog reset!

Приставка перезагрузится. При следующих перезагрузках приставка будет распаковывать образ из локальной памяти.

Loading kernel image
Using Local Storage
LS: Image found
Will not search for new images on the network
Using kernel image in flash
Copying 3392028 bytes...
Verifying image...
Uncompressing image...

Прошивка также подтягивается из локальной памяти

Actual bootimage hash - 3edd21ecd89032b18b51c8472d7c8603
Expected bootimage hash - 3edd21ecd89032b18b51c8472d7c8603
KreaTV bootimage is ... Unchanged.

Выключаем приставку и подготавливаем прошивку PHP‑MOTO1003VIP. Если вы всё сделали так, как написано, достаточно её скопировать из каталога в корень флешки.

Прошиваем с флешки и ожидаем подключения через TELNET

Подготовка прошивки к записи на флеш память
Upgrade sources:  --url="http://upgrade.riskymeije.ru/vip1963x" --url="file:///tmp/sda/firmware.bin"

download/download.c(2580) [   0 s]: Command line arguments values:

download/download.c(2582) [   0 s]:  - vendor: Motorola

download/download.c(2584) [   0 s]:  - device: vip19x3

download/download.c(2586) [   0 s]:  - hw revision: 0

download/download.c(2588) [   0 s]:  - version: 7.41484.230401

download/download.c(2597) [   0 s]:  - localization file: /etc/branding/messages.l10n

download/download.c(2600) [   0 s]:  - certificates dir: /etc/branding/certificates

download/download.c(2602) [   0 s]:  - timeout per retry: 5

download/download.c(2604) [   0 s]:  - max retries: 2

download/source_http.c(0505) [   0 s]: Not a direct firmware URL http://upgrade.riskymeije.ru/vip1963x

download/source_http.c(0173) [   0 s]: Downloading http://upgrade.riskymeije.ru/vip1963x/check_version_ext?output=text&board=vip19x3&mac=00%3A02%3A9B%3AA9%3A99%3AA5&serial=M91443EG0205&current_firmware_version=7%2E41484%2E230401 ...

download/source_file.c(0040) [   0 s]: Config file "/tmp/sda/firmware.bin.config" found

download/source_http.c(0324) [   0 s]: Unexpected wget exit code: 256

download/source_http.c(0173) [   0 s]: Downloading http://upgrade.riskymeije.ru/vip1963x/check_version?output=text&board=vip19x3&mac=00%3A02%3A9B%3AA9%3A99%3AA5&serial=M91443EG0205&current_firmware_version=7%2E41484%2E230401 ...

download/source_http.c(0324) [   0 s]: Unexpected wget exit code: 256

download/download.c(1296) [   0 s]: Discarding unresolved http://upgrade.riskymeije.ru/vip1963x

download/download.c(1438) [   0 s]: Callback failed with code -1

download/download.c(2699) [   0 s]: Firmware candidates:

download/download.c(2709) [   0 s]:  - 5.24246.191016 (hw rev. 0) force : file:///tmp/sda/firmware.bin

download/download.c(2743) [   0 s]: Best URL: file:///tmp/sda/firmware.bin

download/download.c(0526) [   0 s]:  -1% Please wait. Preparing to download firmware ...

download/download.c(2033) [   0 s]: Verifying firmware checksums and RSA signature ...

download/verify.c(0087) [   0 s]: Loading the CA root certificate ...

download/verify.c(0106) [   0 s]: Loading certificates from "/etc/branding/certificates" ...

download/verify.c(0163) [   0 s]: Loading cerificate from file "/etc/branding/certificates/rostelecom-generic-cert.pem" ...

download/download.c(1721) [   0 s]: 	Block 1 (signed) @ addr = 0x0x29558278

download/download.c(1722) [   0 s]: 		data size           : 0x0033c21c (3392028) byte(s)

download/download.c(1723) [   0 s]: 		header size         : 0x00000222 (546) byte(s)

download/download.c(1724) [   0 s]: 		type                : 2 (Linux Kernel Image)

download/download.c(1725) [   0 s]: 		CRC32               : 0x4bcf4722

download/download.c(1728) [   0 s]: 		signature[0] length : 256

download/download.c(1728) [   0 s]: 		signature[1] length : 256

download/download.c(1735) [   0 s]: 		SHA1                : e4644884a8fdde2df91aadf831c41d5c7ba34553

download/download.c(1738) [   0 s]: 		content             : unknown

download/verify.c(0272) [   1 s]: Signature check failed

download/verify.c(0272) [   1 s]: Signature check failed

download/download.c(1721) [   1 s]: 	Block 2 (signed) @ addr = 0x0x298946bc

download/download.c(1722) [   1 s]: 		data size           : 0x02960000 (43384832) byte(s)

download/download.c(1723) [   1 s]: 		header size         : 0x00000222 (546) byte(s)

download/download.c(1724) [   1 s]: 		type                : 3 (Root FS Image)

download/download.c(1725) [   1 s]: 		CRC32               : 0xd8b09ef7

download/download.c(1728) [   1 s]: 		signature[0] length : 256

download/download.c(1728) [   1 s]: 		signature[1] length : 256

download/download.c(1735) [   1 s]: 		SHA1                : 9dd5db805dda709258f90c1402ba1e416048ce68

download/download.c(1738) [   1 s]: 		content             : JFFS2

download/verify.c(0272) [   9 s]: Signature check failed

download/verify.c(0272) [   9 s]: Signature check failed

download/download.c(1721) [   9 s]: 	Block 3 (signed) @ addr = 0x0x2c1f48e4

download/download.c(1722) [   9 s]: 		data size           : 0x00005000 (20480) byte(s)

download/download.c(1723) [   9 s]: 		header size         : 0x00000222 (546) byte(s)

download/download.c(1724) [   9 s]: 		type                : 5 (Branding Image)

download/download.c(1725) [   9 s]: 		CRC32               : 0x052d237b

download/download.c(1728) [   9 s]: 		signature[0] length : 256

download/download.c(1728) [   9 s]: 		signature[1] length : 256

download/download.c(1735) [   9 s]: 		SHA1                : 0b864ea8110807b5accac300254cf410faa801b6

download/download.c(1738) [   9 s]: 		content             : Cramfs

download/verify.c(0272) [   9 s]: Signature check failed

download/verify.c(0272) [   9 s]: Signature check failed

download/download.c(0526) [   9 s]:  75% Please wait. Flashing firmware ...

download/download.c(1721) [   9 s]: 	Block 1 (signed) @ addr = 0x0x29558278

download/download.c(1722) [   9 s]: 		data size           : 0x0033c21c (3392028) byte(s)

download/download.c(1723) [   9 s]: 		header size         : 0x00000222 (546) byte(s)

download/download.c(1724) [   9 s]: 		type                : 2 (Linux Kernel Image)

download/download.c(1725) [   9 s]: 		CRC32               : 0x4bcf4722

download/download.c(1728) [   9 s]: 		signature[0] length : 256

download/download.c(1728) [   9 s]: 		signature[1] length : 256

download/download.c(1735) [   9 s]: 		SHA1                : e4644884a8fdde2df91aadf831c41d5c7ba34553

download/download.c(1738) [   9 s]: 		content             : unknown

File /flash2/.bootimage is successfully written.

download/download.c(1721) [  10 s]: 	Block 2 (signed) @ addr = 0x0x298946bc

download/download.c(1722) [  10 s]: 		data size           : 0x02960000 (43384832) byte(s)

download/download.c(1723) [  10 s]: 		header size         : 0x00000222 (546) byte(s)

download/download.c(1724) [  10 s]: 		type                : 3 (Root FS Image)

download/download.c(1725) [  10 s]: 		CRC32               : 0xd8b09ef7

download/download.c(1728) [  10 s]: 		signature[0] length : 256

download/download.c(1728) [  10 s]: 		signature[1] length : 256

download/download.c(1735) [  10 s]: 		SHA1                : 9dd5db805dda709258f90c1402ba1e416048ce68

download/download.c(1738) [  10 s]: 		content             : JFFS2

download/download.c(2319) [  10 s]: Preparing to flash block #2 ('rootfs') to '/dev/mtd6' ('rootfs') ...

flash_eraseall(): entering...

В слитой в сеть документации ООО Смартлабс детально описывается структура прошивок для IP приставок

Устанавливаем подключение через TELNET и открываем файл tail -f /var/log/messages. В лог сообщений выводится куча полезной информации.

Поддерживаемые видеорежимы.

Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.135    34 1080p30  16:9              1920x1080p @ 29.97/30Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.136    33 1080p25  16:9              1920x1080p @ 25Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.138    32 1080p24  16:9              1920x1080p @ 23.98/24Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.139    18 576pH    16:9                720x576p @ 50Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.140     3 480pH    16:9                720x480p @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.141    20 1080i25  16:9              1920x1080i @ 50Hz* 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.143     5 1080i    16:9              1920x1080i @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.144    19 720p50   16:9               1280x720p @ 50Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.145     4 720p     16:9               1280x720p @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.146    31 1080p50  16:9              1920x1080p @ 50Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.147     1 DMT0659   4:3                640x480p @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.148    22 576iH    16:9          720(1440)x576i @ 50Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.150    21 576i      4:3          720(1440)x576i @ 50Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.151    17 576p      4:3                720x576p @ 50Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.152     7 480iH    16:9          720(1440)x480i @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.153     6 480i      4:3          720(1440)x480i @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.154     2 480p      4:3                720x480p @ 59.94/60Hz 
Jan  1 00:01:46 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:46.155    16 1080p    16:9              1920x1080p @ 59.94/60Hz 

Поддерживаемые форматы контента.

Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.594 player/info : Supported video codecs: 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.596 player/info :  -  MPEG-2 video 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.598 player/info :  -  H.264/14496-10 video (MPEG-4/AVC) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.599 player/info :  -  14496-2 Visual (MPEG-4 part 2 video, DivX) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.601 player/info :  -  SMPTE 421M video (VC1) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.602 player/info :  -  FLV video 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.603 player/info :  -  VP6 video 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.604 player/info :  -  VP6F video 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.606 player/info :  -  Motion JPEG video 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.633 audio/info : Supported audio codecs: 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.635 audio/info :  -  ISO/IEC 13818-3 audio (MPEG-2) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.636 audio/info :  -  ISO/IEC 13818-7 audio with ADTS transport syntax (AAC) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.637 audio/info :  -  ISO/IEC 14496-3 audio with LATM transport syntax (14496-3/AMD 1) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.639 audio/info :  -  ATSC A/52 audio (AC3) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.640 audio/info :  -  ATSC A/52B audio (EAC3) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.641 audio/info :  -  PCM audio 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.643 audio/info :  -  LPCM audio 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.644 audio/info :  -  WMA 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.645 audio/info :  -  ISO/IEC 11172-3/13818-3 audio (MP3) 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.646 audio/info :  -  FLAC audio 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.648 audio/info :  -  Vorbis audio 
Jan  1 00:01:45 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 10.01.01 00:01:45.649 audio/info :  -  ISO/IEC 11172-3 audio (MPEG-1) 

Прошивка завершена.

[к содержанию]


Воспроизведение контента

Плейлист со ссылкой на произвольный контент можно поместить по пути /mnt/persistent/server/play.m3u8 с содержимым вида

#EXTM3U8,
#EXTINF:-1,Youtube http://127.0.0.1/youtube.m3u8 

Далее плейлист необходимо добавить через веб интерфейс http://IP_адрес_приставки/player.php

Поддерживается воспроизведение по протоколам FTP, HTTP, UDP (Multicast), RTSP (без авторизации). TLS не поддерживается. Поддерживается стандарт сжатия H.264 и не поддерживается H.265.

Выключаем приставку, подключаем видеовыход и Интернет. Приставкой можно пользоваться.

Итоги недели
Итоги недели

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

И вот о чём расскажем далее...

[к содержанию]


Первая программа для IPTV приставки

Напишем исходный код и сохраним в файл main.c с надеждой, что выстрелит.

#include <stdio.h> 
#include <stdlib.h>
int main(void) 
{ 
printf("%s","Hello World\n");
}        

«Ты меня учить будешь? Свободен. Нужно будет — позвоню.»

© К/ф «Бой с тенью»

Людей можно понять. Но для начала скомпилируем код. Для этого распакуем SDK и зададим переменные окружения. Предполагаем, что тулчейн находится в домашнем каталоге.

sh4gcc="~/toolchain/st40/2.5.0/bin/sh4-motorola-linux-uclibc-gcc"
sh4ld="~/toolchain/st40/2.5.0/bin/sh4-motorola-linux-uclibc-ld"
sh4readelf="~/toolchain/st40/2.5.0/bin/sh4-motorola-linux-uclibc-readelf"
sh4nm="~/toolchain/st40/2.5.0/bin/sh4-motorola-linux-uclibc-nm"
sh4strip="~/toolchain/st40/2.5.0/bin/sh4-motorola-linux-uclibc-strip"

Подключим библиотеки

LDFLAGS=~/toolchain/st40/2.5.0/sh4-motorola-linux-uclibc/sys-root/usr/lib/crt1.o -L~/toolchain/st40/2.5.0/lib -L~/toolchain/st40/2.5.0/sh4-motorola-linux-uclibc/sys-root/lib -L~/toolchain/st40/2.5.0/sh4-motorola-linux-uclibc/sys-root/usr/lib -L~/toolchain/st40/2.5.0/sh4-motorola-linux-uclibc/lib -L. -L~/toolchain/st40/2.5.0/lib/gcc/sh4-motorola-linux-uclibc/4.6.3 -lc -lgcc -ldl -lm -lutil -lnsl -lcrypt -lresolv -luargp -lrt -lpthread -rpath . --dynamic-linker ld-uClibc.so.0 

Теперь можно компилировать

sh4gcc -c main.c -o main.o
sh4ld $LDFLAGS main.o -o main.bin

Рассмотрим обьектный файл

Главное. Таблица символов и текстовая секция
architecture: sh4, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000038  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  0000006c  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  0000006c  2**0
                  ALLOC
  3 .rodata       00000034  00000000  00000000  0000006c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .debug_info   0000008c  00000000  00000000  000000a0  2**0
                  CONTENTS, RELOC, READONLY, DEBUGGING
  5 .debug_abbrev 00000041  00000000  00000000  0000012c  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_loc    00000020  00000000  00000000  0000016d  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_aranges 00000020  00000000  00000000  0000018d  2**0
                  CONTENTS, RELOC, READONLY, DEBUGGING
  8 .debug_line   00000074  00000000  00000000  000001ad  2**0
                  CONTENTS, RELOC, READONLY, DEBUGGING
  9 .debug_str    00000115  00000000  00000000  00000221  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .comment      0000002f  00000000  00000000  00000336  2**0
                  CONTENTS, READONLY
 11 .note.GNU-stack 00000000  00000000  00000000  00000365  2**0
                  CONTENTS, READONLY
 12 .debug_frame  00000028  00000000  00000000  00000368  2**2
                  CONTENTS, RELOC, READONLY, DEBUGGING
objdump: /home/sandrabullok/motorola_developer/develop/tmp.aWAM.d/tmp.ZBbU.o: not a dynamic object
SYMBOL TABLE:
00000000 l    df *ABS*	00000000 tmp.ZBbU.c
00000000 l    d  .text	00000000 .text
00000000 l    d  .data	00000000 .data
00000000 l    d  .bss	00000000 .bss
00000000 l    d  .rodata	00000000 .rodata
00000000 l    d  .debug_info	00000000 .debug_info
00000000 l    d  .debug_abbrev	00000000 .debug_abbrev
00000000 l    d  .debug_loc	00000000 .debug_loc
00000000 l    d  .debug_aranges	00000000 .debug_aranges
00000000 l    d  .debug_line	00000000 .debug_line
00000000 l    d  .debug_str	00000000 .debug_str
00000000 l    d  .note.GNU-stack	00000000 .note.GNU-stack
00000000 l    d  .debug_frame	00000000 .debug_frame
00000000 l    d  .comment	00000000 .comment
00000000 g     F .text	00000038 main
00000000         *UND*	00000000 printf
00000000         *UND*	00000000 puts


DYNAMIC SYMBOL TABLE:
no symbols



Disassembly of section .text:

00000000 <main>:
#include </home/sandrabullok/motorola_developer/develop/tmp.aWAM.d/tmp.ZBbU.h>
int main(void) 
{ 
   0:	22 4f       	sts.l	pr,@-r15
printf("%s","This is a stub program for ");
   2:	08 d2       	mov.l	24 <main+0x24>,r2	! 0 <main>
   4:	08 d1       	mov.l	28 <main+0x28>,r1	! 4
   6:	23 64       	mov	r2,r4
   8:	13 65       	mov	r1,r5
   a:	08 d1       	mov.l	2c <main+0x2c>,r1	! 0 <main>
   c:	0b 41       	jsr	@r1
   e:	09 00       	nop	
printf("%s","the target machine\n");
  10:	07 d1       	mov.l	30 <main+0x30>,r1	! 20
  12:	13 64       	mov	r1,r4
  14:	07 d1       	mov.l	34 <main+0x34>,r1	! 0 <main>
  16:	0b 41       	jsr	@r1
  18:	09 00       	nop	
  1a:	00 e1       	mov	#0,r1
}                                                                                                                                                                   
  1c:	13 60       	mov	r1,r0
  1e:	26 4f       	lds.l	@r15+,pr
  20:	0b 00       	rts	
  22:	09 00       	nop	
  24:	00 00       	.word 0x0000
			24: R_SH_DIR32	.rodata
  26:	00 00       	.word 0x0000
  28:	04 00       	mov.b	r0,@(r0,r0)
			28: R_SH_DIR32	.rodata
  2a:	00 00       	.word 0x0000
  2c:	00 00       	.word 0x0000
			2c: R_SH_DIR32	printf
  2e:	00 00       	.word 0x0000
  30:	20 00       	.word 0x0020
			30: R_SH_DIR32	.rodata
  32:	00 00       	.word 0x0000
  34:	00 00       	.word 0x0000
			34: R_SH_DIR32	puts
	...

Код на языке Ассемблера

00000000 <main>:
#include </home/sandrabullok/motorola_developer/develop/tmp.aWAM.d/tmp.ZBbU.h>
int main(void) 
{ 
   0:	22 4f       	sts.l	pr,@-r15
printf("%s","This is a stub program for ");
   2:	08 d2       	mov.l	24 <main+0x24>,r2	! 0 <main>
   4:	08 d1       	mov.l	28 <main+0x28>,r1	! 4
   6:	23 64       	mov	r2,r4
   8:	13 65       	mov	r1,r5
   a:	08 d1       	mov.l	2c <main+0x2c>,r1	! 0 <main>
   c:	0b 41       	jsr	@r1
   e:	09 00       	nop	
printf("%s","the target machine\n");
  10:	07 d1       	mov.l	30 <main+0x30>,r1	! 20
  12:	13 64       	mov	r1,r4
  14:	07 d1       	mov.l	34 <main+0x34>,r1	! 0 <main>
  16:	0b 41       	jsr	@r1
  18:	09 00       	nop	
  1a:	00 e1       	mov	#0,r1
}                                                                                                                                                                   
  1c:	13 60       	mov	r1,r0
  1e:	26 4f       	lds.l	@r15+,pr
  20:	0b 00       	rts	
  22:	09 00       	nop	

Как можно увидеть, система команд, применяемая в коде, совершенно специфическая. Это система команд микропроцессора STx7105. Ссылка на документацию [4] к сожалению умерла.

Всего регистров - 16. Обозначаются как rN - где N - номер регистра от 0 до 15. Команда перемещения между регистрами такая же, как в системе команд процессоров Intel - mov. Команды копирования по адресу в памяти слева в регистр справа: mov.l - копирование двойных слов, mov.w - копирование слов, mov.b - копирование байт. Команды sts и lds с аналогичными суффиксами - сохранение и загрузка содержимого регистров.

Переход к подпрограмме - jsr. Возврат из подпрограммы - rts. Передача операндов через регистры.

Рассмотрим исполняемый файл

Код
Disassembly of section .plt:

004002f0 <printf@plt-0x1c>:
  4002f0:	05 d0       	mov.l	400308 <printf@plt-0x4>,r0	! 410544
  4002f2:	02 60       	mov.l	@r0,r0
  4002f4:	06 2f       	mov.l	r0,@-r15
  4002f6:	03 d0       	mov.l	400304 <printf@plt-0x8>,r0	! 410548
  4002f8:	02 60       	mov.l	@r0,r0
  4002fa:	2b 40       	jmp	@r0
  4002fc:	f6 60       	mov.l	@r15+,r0
  4002fe:	09 00       	nop	
  400300:	09 00       	nop	
  400302:	09 00       	nop	
  400304:	48 05       	.word 0x0548
  400306:	41 00       	.word 0x0041
  400308:	44 05       	mov.b	r4,@(r0,r5)
  40030a:	41 00       	.word 0x0041

0040030c <printf@plt>:
  40030c:	04 d0       	mov.l	400320 <printf@plt+0x14>,r0	! 41054c
  40030e:	02 60       	mov.l	@r0,r0
  400310:	02 d1       	mov.l	40031c <printf@plt+0x10>,r1	! 4002f0
  400312:	2b 40       	jmp	@r0
  400314:	13 60       	mov	r1,r0
  400316:	03 d1       	mov.l	400324 <printf@plt+0x18>,r1	! 0
  400318:	2b 40       	jmp	@r0
  40031a:	09 00       	nop	
  40031c:	f0 02       	.word 0x02f0
  40031e:	40 00       	.word 0x0040
  400320:	4c 05       	mov.b	@(r0,r4),r5
  400322:	41 00       	.word 0x0041
  400324:	00 00       	.word 0x0000
	...

00400328 <puts@plt>:
  400328:	04 d0       	mov.l	40033c <puts@plt+0x14>,r0	! 410550
  40032a:	02 60       	mov.l	@r0,r0
  40032c:	02 d1       	mov.l	400338 <puts@plt+0x10>,r1	! 4002f0
  40032e:	2b 40       	jmp	@r0
  400330:	13 60       	mov	r1,r0
  400332:	03 d1       	mov.l	400340 <puts@plt+0x18>,r1	! c
  400334:	2b 40       	jmp	@r0
  400336:	09 00       	nop	
  400338:	f0 02       	.word 0x02f0
  40033a:	40 00       	.word 0x0040
  40033c:	50 05       	.word 0x0550
  40033e:	41 00       	.word 0x0041
  400340:	0c 00       	mov.b	@(r0,r0),r0
	...

00400344 <abort@plt>:
  400344:	04 d0       	mov.l	400358 <abort@plt+0x14>,r0	! 410554
  400346:	02 60       	mov.l	@r0,r0
  400348:	02 d1       	mov.l	400354 <abort@plt+0x10>,r1	! 4002f0
  40034a:	2b 40       	jmp	@r0
  40034c:	13 60       	mov	r1,r0
  40034e:	03 d1       	mov.l	40035c <abort@plt+0x18>,r1	! 18
  400350:	2b 40       	jmp	@r0
  400352:	09 00       	nop	
  400354:	f0 02       	.word 0x02f0
  400356:	40 00       	.word 0x0040
  400358:	54 05       	mov.b	r5,@(r0,r5)
  40035a:	41 00       	.word 0x0041
  40035c:	18 00       	sett	
	...

00400360 <_init@plt>:
  400360:	04 d0       	mov.l	400374 <_init@plt+0x14>,r0	! 410558
  400362:	02 60       	mov.l	@r0,r0
  400364:	02 d1       	mov.l	400370 <_init@plt+0x10>,r1	! 4002f0
  400366:	2b 40       	jmp	@r0
  400368:	13 60       	mov	r1,r0
  40036a:	03 d1       	mov.l	400378 <_init@plt+0x18>,r1	! 24
  40036c:	2b 40       	jmp	@r0
  40036e:	09 00       	nop	
  400370:	f0 02       	.word 0x02f0
  400372:	40 00       	.word 0x0040
  400374:	58 05       	.word 0x0558
  400376:	41 00       	.word 0x0041
  400378:	24 00       	mov.b	r2,@(r0,r0)
	...

0040037c <__uClibc_main@plt>:
  40037c:	04 d0       	mov.l	400390 <__uClibc_main@plt+0x14>,r0	! 41055c
  40037e:	02 60       	mov.l	@r0,r0
  400380:	02 d1       	mov.l	40038c <__uClibc_main@plt+0x10>,r1	! 4002f0
  400382:	2b 40       	jmp	@r0
  400384:	13 60       	mov	r1,r0
  400386:	03 d1       	mov.l	400394 <__uClibc_main@plt+0x18>,r1	! 30
  400388:	2b 40       	jmp	@r0
  40038a:	09 00       	nop	
  40038c:	f0 02       	.word 0x02f0
  40038e:	40 00       	.word 0x0040
  400390:	5c 05       	mov.b	@(r0,r5),r5
  400392:	41 00       	.word 0x0041
  400394:	30 00       	.word 0x0030
	...

00400398 <_fini@plt>:
  400398:	04 d0       	mov.l	4003ac <_fini@plt+0x14>,r0	! 410560
  40039a:	02 60       	mov.l	@r0,r0
  40039c:	02 d1       	mov.l	4003a8 <_fini@plt+0x10>,r1	! 4002f0
  40039e:	2b 40       	jmp	@r0
  4003a0:	13 60       	mov	r1,r0
  4003a2:	03 d1       	mov.l	4003b0 <_fini@plt+0x18>,r1	! 3c
  4003a4:	2b 40       	jmp	@r0
  4003a6:	09 00       	nop	
  4003a8:	f0 02       	.word 0x02f0
  4003aa:	40 00       	.word 0x0040
  4003ac:	60 05       	.word 0x0560
  4003ae:	41 00       	.word 0x0041
  4003b0:	3c 00       	mov.b	@(r0,r3),r0
	...

Disassembly of section .text:

004003b4 <_start>:
  4003b4:	00 ee       	mov	#0,r14
  4003b6:	f6 65       	mov.l	@r15+,r5
  4003b8:	f3 66       	mov	r15,r6
  4003ba:	66 2f       	mov.l	r6,@-r15
  4003bc:	46 2f       	mov.l	r4,@-r15
  4003be:	07 d0       	mov.l	4003dc <L_fini>,r0	! 400398 <_fini@plt>
  4003c0:	06 2f       	mov.l	r0,@-r15
  4003c2:	04 d4       	mov.l	4003d4 <L_main>,r4	! 4003e8 <main>
  4003c4:	04 d7       	mov.l	4003d8 <L_init>,r7	! 400360 <_init@plt>
  4003c6:	06 d1       	mov.l	4003e0 <L_uClibc_main>,r1	! 40037c <__uClibc_main@plt>
  4003c8:	0b 41       	jsr	@r1
  4003ca:	09 00       	nop	
  4003cc:	05 d1       	mov.l	4003e4 <L_abort>,r1	! 400344 <abort@plt>
  4003ce:	2b 41       	jmp	@r1
  4003d0:	09 00       	nop	
  4003d2:	09 00       	nop	

004003d4 <L_main>:
  4003d4:	e8 03       	.word 0x03e8
  4003d6:	40 00       	.word 0x0040

004003d8 <L_init>:
  4003d8:	60 03       	.word 0x0360
  4003da:	40 00       	.word 0x0040

004003dc <L_fini>:
  4003dc:	98 03       	.word 0x0398
  4003de:	40 00       	.word 0x0040

004003e0 <L_uClibc_main>:
  4003e0:	7c 03       	mov.b	@(r0,r7),r3
  4003e2:	40 00       	.word 0x0040

004003e4 <L_abort>:
  4003e4:	44 03       	mov.b	r4,@(r0,r3)
  4003e6:	40 00       	.word 0x0040

Символы подпрограмм fini@plt, init@plt экспортируются в подключаемом обьектном файле crt1.o. Подпрограмма _start является точкой входа в программу и помимо вызова main выполняет кучу других вещей.

Полученный исполняемый файл не получится запустить, он предназначается для другой архитектуры. В чём мы сейчас убедимся.

sh-5.1$ $sh4readelf -h main.bin
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Renesas / SuperH SH
  Version:                           0x1
  Entry point address:               0x4003b4
  Start of program headers:          52 (bytes into file)
  Start of section headers:          1536 (bytes into file)
  Flags:                             0x9, sh4
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         6
  Size of section headers:           40 (bytes)
  Number of section headers:         16
  Section header string table index: 13

Копируем исполняемый файл в единый каталог вместе с библиотеками

итого 4236
-rwxrwxr-x 1 sandrabullok sandrabullok    4038 июл 22 13:07 app.bin
-r-xr-xr-x 1 sandrabullok sandrabullok   96925 июл 22 13:07 ld-uClibc.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok   28676 июл 22 13:07 libcrypt.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok 3200747 июл 22 13:07 libc.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok   32815 июл 22 13:07 libdl.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok  160246 июл 22 13:07 libm.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok    6219 июл 22 13:07 libnsl.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok  567364 июл 22 13:07 libpthread.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok    6234 июл 22 13:07 libresolv.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok   96503 июл 22 13:07 librt.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok   96053 июл 22 13:07 libuargp.so.0
-r-xr-xr-x 1 sandrabullok sandrabullok   14626 июл 22 13:07 libutil.so.0

Особенно заостряю ваше внимание на библиотеке ld‑uClibc.so.0. Динамический компоновщик редактирует связи с динамическими библиотеками непосредственно в памяти устройства. Сделано так, возможно, для экономии оперативной памяти: оверлей программы подгружается, когда он необходим, в произвольном порядке и на лету редактируется. Если данную библиотеку не подключить, программа будет вылетать в SEGFAULT, потому что при запуске программа делает первый шаг и делает его в пропасть — в таблицах адресов ничего нет.

Далее начинается то, ради чего полстатьи маялись. Упакуйте в TAR архив и разместите на HTTP сервере. Устанавливаем подключение к приставке через TELNET и скачиваем архив командой wget. Например

wget http://192.168.1.100/$APP_NAME.tar 
tar -xf $APP_NAME.tar 
rm $APP_NAME.tar 
ls - la

Запускаем программу и видим текст

Hello World

Эта программа работает на целевой машине (IPTV приставке MOTOROLA VIP1003)!

А это значит, что технически возможно портировать крупный проект.

[к содержанию]


Портирование FFmpeg на архитектуру SuperH SH

Есть проблема. Приставка не может воспроизвести контент с источника RTSP потока, требующего basic аутентификацию.

Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: OPTIONS rtsp://login:pass@[IP]/path RTSP/1.0
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: User-Agent: Restream/7.999.9999 (vip19x3; Motorola_VIP1003) SmartSDK/1.5.63-rt-38-22-g950636f Qt/4.7.3 API/0.30.0
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: CSeq: 1
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q:  
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 18.09.06 19:50:50.818 rtsp/info : Response Header: 
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: RTSP/1.0 200 OK
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: CSeq: 1
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: Public: OPTIONS, DESCRIBE, PLAY, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A:  
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 18.09.06 19:50:50.823 rtsp/debug : Outgoing RTSP command: 
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: DESCRIBE rtsp://login:pass@[IP]/path RTSP/1.0
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: Accept: application/x-rtsp-mh, application/sdp
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: User-Agent: Restream/7.999.9999 (vip19x3; Motorola_VIP1003) SmartSDK/1.5.63-rt-38-22-g950636f Qt/4.7.3 API/0.30.0
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q: CSeq: 2
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: Q:  
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 18.09.06 19:50:50.833 rtsp/info : Response Header: 
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: RTSP/1.0 401 Unauthorized
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: CSeq: 2
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: WWW-Authenticate: Digest realm="RTSP SERVER", nonce="1b5eff39c311f943304b9c10bc8efba7", stale="FALSE"
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: WWW-Authenticate: Basic realm="RTSP SERVER"
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A: Date: Fri, 03 Jul 2026 18:23:12 GMT
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: A:  
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 18.09.06 19:50:50.836 rtsp/error : invalid response status code 401 from RTSP server. Aborting ... 
Sep  6 16:50:50 vip19x3-00029BA999A5-7_999_9999 local1.debug app: 18.09.06 19:50:50.838 rtsp/error : RTSP protocol failure !!! 

А можно ли добавить в приставку поддержку какого‑нибудь недостающего сетевого протокола, например. Теперь есть полные основания портировать для IPTV приставки серьёзный проект. И таким проектом будет FFmpeg.

Подразумеваем, что исходники подготовлены, далее выполняем сборку проекта. Сборка пока что происходит для компьютера.

Как уже было замечено, коммит древний — 2016 года и поддерживает устаревший стандарт языка C — c99. Новые коммиты будут падать с ошибками компиляции.

Свободной памяти в устройстве немного, так что придётся поторговаться. Отключаем по умолчанию все кодеры, миксеры, поддержку устройств и сетевых протоколов. И выбираем только то что нужно.

# Individual component option
INDIVIDUAL_OPTIONS=""
INDIVIDUAL_OPTIONS+="--disable-encoders "
INDIVIDUAL_OPTIONS+="--disable-decoders "
INDIVIDUAL_OPTIONS+="--disable-muxers "
INDIVIDUAL_OPTIONS+="--disable-demuxers "
INDIVIDUAL_OPTIONS+="--disable-protocols "
INDIVIDUAL_OPTIONS+="--disable-devices "
INDIVIDUAL_OPTIONS+="--enable-protocol=rtp "
INDIVIDUAL_OPTIONS+="--enable-protocol=udp "
INDIVIDUAL_OPTIONS+="--enable-muxer=mpegts "
INDIVIDUAL_OPTIONS+="--enable-demuxer=rtsp "

В расширении флагов компоновки указываем библиотеки с поддержкой целевой архитектуры.

EXTRA_LDFLAGS="-L."
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/sh4-motorola-linux-uclibc/lib "
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/sh4-motorola-linux-uclibc/sys-root/lib "
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/sh4-motorola-linux-uclibc/sys-root/usr/lib "
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/lib/gcc/sh4-motorola-linux-uclibc/4.6.3 "
EXTRA_LDFLAGS+="-lc -lgcc -ldl -lm -lutil -lnsl -lcrypt -lresolv -luargp "
EXTRA_LDFLAGS+="-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample "

Давайте посмотрим сюда.

EXTRA_CXXFLAGS+="-std=c99 "	# Assume that the input sources are for <standard>
EXTRA_CXXFLAGS+="-m4 "	# Generate SH4 code
EXTRA_CXXFLAGS+="-mglibc "	# Use GNU C library
EXTRA_CXXFLAGS+="-pthread "

Флаги -std=c99 и -m4 предписывают системе сборки компилировать код для целевой архитектуры и использовать совместимый стандарт языка C. Чем библиотека glibc лучше или хуже чем libc не понимаю.

Компилироваться будет только ffmpeg

Следующий флажок включает кросс-компиляцию. Также необходимо прописать путь к тулчейну для целевой архитектуры.

--enable-cross-compile
Полный код скрипта настройки сборки.
#!/bin/bash

# Head #
ARCH=sh
CPU=STx7105
TARGET_OS=linux
TOOLCHAIN_PATH=~/ffmpeg/toolchain/st40/2.5.0           
# $TOOLCHAIN_PATH
CROSS_PREFIX="${TOOLCHAIN_PATH}/bin/sh4-motorola-linux-uclibc-"
CROSS_PREFIX_ENABLED=0
ENABLE_CROSS_COMPILE=1
PROGS_SUFFIX=''
DIST=~/ffmpeg/dist
########

if [ $ENABLE_CROSS_COMPILE -ne 0 ]
then
    LOG=configure_cross.log
else
    LOG=configure_nocross.log
fi

if [ $CROSS_PREFIX_ENABLED -eq 0 ]
then
    ### set use tools from toolchain ###
    NM=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-nm             
#use nm tool NM [nm -g]
    AR=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-ar             
#use archive tool AR [ar]
    AS=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-as             
#use assembler AS []
    #LN_S
    STRIP=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-strip       
#use strip tool STRIP [strip]

    CC=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-gcc            
#use C compiler CC [gcc]
    STDC=c99                                                        
#use C standard STDC [c17]
    CXX=$TOOLCHAIN_PATH/bin/sh4-motorola-uclibc-g++           
#use C compiler CXX [g++]
    STDCXX=c++17                                                    
#use C standard STDCXX [c++17]
    LD=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-ld             
#use linker LD []
    RANLIB=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-ranlib     
#use ranlib RANLIB [ranlib]
    SIZE=$TOOLCHAIN_PATH/bin/sh4-motorola-linux-uclibc-size
    ### set use tools from toolchain ###
fi

#PATH=$PATH:${TOOLCHAIN_PATH}/bin:${DIST}/bin


BSG_SRC=../../.. 
BSG_INCLUDE=${DIST}/st40/include 


# Standard options
STANDARD_OPTIONS=""
#STANDARD_OPTIONS+="--quiet "
STANDARD_OPTIONS+="--logfile=$LOG "

# Program options
PROGRAM_OPTIONS=""

# Documentation options:
DOCUMENTATION_OPTIONS=""
DOCUMENTATION_OPTIONS+="--disable-doc "           
# do not build documentation
DOCUMENTATION_OPTIONS+="--disable-htmlpages "     
# do not build HTML documentation pages
DOCUMENTATION_OPTIONS+="--disable-manpages "      
# do not build man documentation pages
DOCUMENTATION_OPTIONS+="--disable-podpages "      
# do not build POD documentation pages
DOCUMENTATION_OPTIONS+="--disable-txtpages "       
# do not build text documentation pages

# Component options
COMPONENT_OPTIONS=""
COMPONENT_OPTIONS+="--disable-swscale "
COMPONENT_OPTIONS+="--disable-avresample "
COMPONENT_OPTIONS+="--disable-avdevice "
COMPONENT_OPTIONS+="--disable-avfilter "

# Individual component option
INDIVIDUAL_OPTIONS=""
INDIVIDUAL_OPTIONS+="--disable-encoders "
INDIVIDUAL_OPTIONS+="--disable-decoders "
INDIVIDUAL_OPTIONS+="--disable-muxers "
INDIVIDUAL_OPTIONS+="--disable-demuxers "
INDIVIDUAL_OPTIONS+="--disable-protocols "
INDIVIDUAL_OPTIONS+="--disable-devices "
INDIVIDUAL_OPTIONS+="--enable-protocol=rtp "
INDIVIDUAL_OPTIONS+="--enable-protocol=udp "
INDIVIDUAL_OPTIONS+="--enable-muxer=mpegts "
INDIVIDUAL_OPTIONS+="--enable-demuxer=rtsp "

# External library support
ELIBRARY_SUPPORT=""
ELIBRARY_SUPPORT+="--disable-sdl2 "         
# disable sdl2 [autodetect]

# Toolchain options 
TOOLCHAIN_OPTIONS=""

if [ $ENABLE_CROSS_COMPILE -ne 0 ]
then
    echo 'Set flag ENABLE_CROSS_COMPILE'
    TOOLCHAIN_OPTIONS+="--enable-cross-compile "   
#assume a cross-compiler is used
fi
TOOLCHAIN_OPTIONS+="--arch=$ARCH "              
# select architecture []
TOOLCHAIN_OPTIONS+="--cpu=$CPU "                
# select the minimum required CPU (affects
                           
# instruction selection, may crash on older CPUs)
if [ ! $CROSS_PREFIX_ENABLED -eq 0 ] 
then
    echo 'Set flag CROSS_PREFIX_ENABLED'
    TOOLCHAIN_OPTIONS+="--cross-prefix=$CROSS_PREFIX "    
# use PREFIX for compilation tools []
fi
TOOLCHAIN_OPTIONS+="--build-suffix=$PROGS_SUFFIX "    
# program name suffix []
TOOLCHAIN_OPTIONS+="--target-os=$TARGET_OS "           
#compiler targets OS []
#TOOLCHAIN_OPTIONS+="--sysroot=$SYSROOT "           
#root of cross-build tree
#TOOLCHAIN_OPTIONS+="--sysinclude=$SYSINCLUDE "        
#location of cross-build system headers
#TOOLCHAIN_OPTIONS+="--target-exec=$TARGET_EXEC "        
#command to run executables on target
#TOOLCHAIN_OPTIONS+="--target-path=$TARGET_PATH "        
#path to view of build directory on target
#TOOLCHAIN_OPTIONS+="--target-samples=$TARGET_SAMPLES "     
#path to samples directory on target
#TOOLCHAIN_OPTIONS+="--tempprefix=$TEMPPREFIX "        
#force fixed dir/prefix instead of mktemp for checks
#TOOLCHAIN_OPTIONS+="--toolchain=$TOOLCHAIN "         
#set tool defaults according to NAME
                            #(<tool>[-sanitizer[-...]], e.g. clang-asan-ubsan
                            #tools: gcc, clang, llvm, msvc, icl, gcov, llvm-cov,
                            #       valgrind-memcheck, valgrind-massif, hardened
                            #sanitizers: asan, fuzz, lsan, msan, tsan, ubsan)



if [ $CROSS_PREFIX_ENABLED -eq 0 ]
then
    TOOLCHAIN_OPTIONS+="--nm=$NM --ar=$AR --as=$AS --cc=$CC --ld=$LD "          
    #TOOLCHAIN_OPTIONS+="--ln_s=$LN_S "                                 #use symbolic link tool LN_S [ln -s -f]
    #TOOLCHAIN_OPTIONS+="--windres=$WINDRES "                           #use windows resource compiler WINDRES [windres]
    #TOOLCHAIN_OPTIONS+="--x86asmexe=$X86ASMEXE "                       #use nasm-compatible assembler EXE [nasm]
    #TOOLCHAIN_OPTIONS+="--objcc=$OBJCC "                               #use ObjC compiler OCC [gcc]
    #TOOLCHAIN_OPTIONS+="--dep-cc=$DEPCC "                              #use dependency generator DEPCC [gcc]
    #TOOLCHAIN_OPTIONS+="--glslc=$GLSLC "                               #use GLSL compiler GLSLC [glslc]
    #TOOLCHAIN_OPTIONS+="--nvcc=$NVCC "                                 #use Nvidia CUDA compiler NVCC or clang []
    #TOOLCHAIN_OPTIONS+="--metalcc=$METALCC "                           #use metal compiler METALCC [xcrun -sdk macosx metal]
    #TOOLCHAIN_OPTIONS+="--metallib=$METALLIB "                         #use metal linker METALLIB [xcrun -sdk macosx metallib]
    #TOOLCHAIN_OPTIONS+="--pkg-config=$PKGCONFIG "                      #use pkg-config tool PKGCONFIG [pkg-config]
    #TOOLCHAIN_OPTIONS+="--pkg-config-flags=$PKGCONFIG_FLAGS "          #pass additional flags to pkgconf []
    #TOOLCHAIN_OPTIONS+="--doxygen=$DOXYGEN "                           #use DOXYGEN to generate API doc [doxygen]
    #TOOLCHAIN_OPTIONS+="--makeinfo=$MAKEINFO "                         #use MAKEINFO to generate documentation [makeinfo]
    # --strip=$STRIP --cxx=$CXX --stdcxx=$STDCXX --stdc=$STDC --ranlib=$RANLIB 
fi

HOST_CC="gcc"                                                           #use host C compiler HOSTCC
HOST_CFLAGS="-m32"                                                      #use HCFLAGS when compiling for host
HOST_CXX="g++" 
HOST_CPPFLAGS=""                                                        #use HCPPFLAGS when compiling for host    
HOST_LD="ld"                                                            #use host linker HOSTLD
HOST_LDFLAGS="-m32"                                                     #use HLDFLAGS when linking for host
HOST_EXTRALIBS=""                                                       #use libs HLIBS when linking for host
HOST_OS=""                                                              #compiler host OS []

TOOLCHAIN_OPTIONS+="--host-cc=$HOST_CC "                                #use host C compiler HOSTCC
TOOLCHAIN_OPTIONS+="--host-cflags=$HOST_CFLAGS "                        #use HCFLAGS when compiling for host
#TOOLCHAIN_OPTIONS+="--host-cppflags=$HOST_CPPFLAGS "                    #use HCPPFLAGS when compiling for host
TOOLCHAIN_OPTIONS+="--host-ld=$HOST_LD "                                #use host linker HOSTLD
TOOLCHAIN_OPTIONS+="--host-ldflags=$HOST_LDFLAGS "                      #use HLDFLAGS when linking for host
#TOOLCHAIN_OPTIONS+="--host-extralibs=$HOST_EXTRALIBS "                  #use libs HLIBS when linking for host
TOOLCHAIN_OPTIONS+="--host-os=$HOST_OS "                                #compiler host OS []

### set linked library ###
EXTRA_LDFLAGS="-L."
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/sh4-motorola-linux-uclibc/lib "
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/sh4-motorola-linux-uclibc/sys-root/lib "
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/sh4-motorola-linux-uclibc/sys-root/usr/lib "
EXTRA_LDFLAGS+="-L${TOOLCHAIN_PATH}/lib/gcc/sh4-motorola-linux-uclibc/4.6.3 "
EXTRA_LDFLAGS+="-lc -lgcc -ldl -lm -lutil -lnsl -lcrypt -lresolv -luargp "
EXTRA_LDFLAGS+="-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample "


#EXTRA_LDFLAGS+="-L${DIST}/st40/lib "
#EXTRA_LDFLAGS+="-L${DIST}/st40/3pp/lib "
#EXTRA_LDFLAGS+="-L${DIST}/st40/vip19x3/lib "
#EXTRA_LDFLAGS+="-L${DIST}/st40/3pp/vip19x3/lib " 
### set linked library ###


ENV="LD_LIBRARY_PATH=~/FFmpeg/toolchain/st40/2.5.0/sh4-motorola-linux-uclibc/lib" #; \
#/usr/local/motorola/toolchain/st40/2.5.0/sh4-motorola-linux-uclibc/sys-root/usr/lib; \
#~/FFmpeg/dist/st40/lib; \
#~/FFmpeg/dist/st40/3pp/lib; \
#~/FFmpeg/dist/st40/vip19x3/lib; \
#~/FFmpeg/dist/st40/3pp/vip19x3/lib " 

echo $ENV

EXTRA_CFLAGS=" -I. "
EXTRA_CFLAGS+="-I${DIST}/st40/include "
EXTRA_CFLAGS+="-I${DIST}/st40/3pp/vip19x3/include "
EXTRA_CFLAGS+="-I${DIST}/st40/3pp/vip19x3/linux/include "
EXTRA_CFLAGS+="-I${DIST}/st40/3pp/include "
EXTRA_CFLAGS+="-I${DIST}/stb-noarch/include "
EXTRA_CFLAGS+="-I${DIST}/stb-noarch/3pp/include "
EXTRA_CFLAGS+="-I${DIST}/noarch/include "
EXTRA_CFLAGS+="-I${DIST}/noarch/3pp/include "
EXTRA_CFLAGS+="-g -Os -finline-limit=50 -D__ST40__=1 -D__VIP19X3__=1 " 
EXTRA_CFLAGS+="-O0 "	# Set optimization level to <number>
EXTRA_CFLAGS+="-std=c99 "	# Assume that the input sources are for <standard>
EXTRA_CFLAGS+="-m4 "	# Generate SH4 code
EXTRA_CFLAGS+="-mglibc "	# Use GNU C library
EXTRA_CFLAGS+="-pthread "

EXTRA_CXXFLAGS="-fvisibility-inlines-hidden  -I. "
EXTRA_CXXFLAGS+="-I${DIST}/st40/include "
EXTRA_CXXFLAGS+="-I${DIST}/st40/3pp/vip19x3/include "
EXTRA_CXXFLAGS+="-I${DIST}/st40/3pp/vip19x3/linux/include "
EXTRA_CXXFLAGS+="-I${DIST}/st40/3pp/include "
EXTRA_CXXFLAGS+="-I${DIST}/stb-noarch/include "
EXTRA_CXXFLAGS+="-I${DIST}/stb-noarch/3pp/include "
EXTRA_CXXFLAGS+="-I${DIST}/noarch/include "
EXTRA_CXXFLAGS+="-I${DIST}/noarch/3pp/include "
EXTRA_CXXFLAGS+="-g -Os -finline-limit=50 -D__ST40__=1 -D__VIP19X3__=1 " 
EXTRA_CXXFLAGS+="-g -Os -finline-limit=50 -D__ST40__=1 -D__VIP19X3__=1 " 
EXTRA_CXXFLAGS+="-O0 "	# Set optimization level to <number>
EXTRA_CXXFLAGS+="-std=c99 "	# Assume that the input sources are for <standard>
EXTRA_CXXFLAGS+="-m4 "	# Generate SH4 code
EXTRA_CXXFLAGS+="-mglibc "	# Use GNU C library
EXTRA_CXXFLAGS+="-pthread "

echo "EXTRA_LDFLAGS=$EXTRA_LDFLAGS"
TOOLCHAIN_OPTIONS+="--extra-ldflags=\"$EXTRA_LDFLAGS\" " 
#add ELDFLAGS to LDFLAGS []
echo "EXTRA_CFLAGS=$EXTRA_CFLAGS"
TOOLCHAIN_OPTIONS+="--extra-cflags=\"$EXTRA_CFLAGS\" "   
#add ECFLAGS to CFLAGS []
echo "EXTRA_CXXFLAGS=$EXTRA_CXXFLAGS"
TOOLCHAIN_OPTIONS+="--extra-cxxflags=\"$EXTRA_CXXFLAGS\" " 
#add ECFLAGS to CXXFLAGS []

CPPFLAGS=" -I. "
CPPFLAGS+="-I${DIST}/st40/include "
CPPFLAGS+="-I${DIST}/st40/3pp/vip19x3/include "
CPPFLAGS+="-I${DIST}/st40/3pp/vip19x3/linux/include "
CPPFLAGS+="-I${DIST}/st40/3pp/include "
CPPFLAGS+="-I${DIST}/stb-noarch/include "
CPPFLAGS+="-I${DIST}/stb-noarch/3pp/include "
CPPFLAGS+="-I${DIST}/noarch/include "
CPPFLAGS+="-I${DIST}/noarch/3pp/include" 


#TOOLCHAIN_OPTIONS+="--extra-objcflags=$EXTRA_OBJFLAGS "  
#add FLAGS to OBJCFLAGS []
#TOOLCHAIN_OPTIONS+="--extra-ldexeflags=$EXTRA_LDEXEFLAGS " 
#add ELDFLAGS to LDEXEFLAGS []
#TOOLCHAIN_OPTIONS+="--extra-ldsoflags=$EXTRA_LDSOFLAGS " 
#add ELDFLAGS to LDSOFLAGS []
#TOOLCHAIN_OPTIONS+="--extra-libs=$EXTRA_LIBS "       
#add ELIBS []
#TOOLCHAIN_OPTIONS+="--extra-version=$EXTRA_VERSION "   
#version string suffix []
#TOOLCHAIN_OPTIONS+="--optflags=$OPTFLAGS "      
#override optimization-related compiler flags
#TOOLCHAIN_OPTIONS+="--glslcflags=$GLSLCFLAGS "  
#extra glslc flags []
#TOOLCHAIN_OPTIONS+="--nvccflags=$NVCCFLAGS "    
#override nvcc flags []
#TOOLCHAIN_OPTIONS+="--build-suffix=$BUILD_SUFFIX "    
#library name suffix []
#TOOLCHAIN_OPTIONS+="--enable-pic "             
#build position-independent code
#TOOLCHAIN_OPTIONS+="--enable-thumb "           
#compile for Thumb instruction set
#TOOLCHAIN_OPTIONS+="--enable-lto[=$arg] "       
#use link-time optimization
TOOLCHAIN_OPTIONS+="--env=\"$ENV\" "     
#override the environment variables
#TOOLCHAIN_OPTIONS+="--disable-response-files 
#Don't pass the list of objects to linker in a file [autodetect]

# Optimization options

OPTIMIZATION_OPTIONS=""
OPTIMIZATION_OPTIONS+="--disable-mmx "
OPTIMIZATION_OPTIONS+="--disable-sse "
OPTIMIZATION_OPTIONS+="--disable-sse2 "
OPTIMIZATION_OPTIONS+="--disable-sse3 "
OPTIMIZATION_OPTIONS+="--disable-sse4 "
OPTIMIZATION_OPTIONS+="--disable-avx "
#OPTIMIZATION_OPTIONS+="--disable-avx2 "
#OPTIMIZATION_OPTIONS+="--disable-avx512 " 
#OPTIMIZATION_OPTIONS+="--disable-fma3 "
#OPTIMIZATION_OPTIONS+="--disable-fma4 "

# Other

OTHER=""
OTHER+="--disable-zlib "

# All options

OPTIONS=""
echo "STANDARD_OPTIONS=$STANDARD_OPTIONS"
OPTIONS+=$STANDARD_OPTIONS
echo "PROGRAM_OPTIONS=$PROGRAM_OPTIONS"
OPTIONS+=$PROGRAM_OPTIONS
echo "DOCUMENTATION_OPTIONS=$DOCUMENTATION_OPTIONS"
OPTIONS+=$DOCUMENTATION_OPTIONS
echo "COMPONENT_OPTIONS=$COMPONENT_OPTIONS"
OPTIONS+=$COMPONENT_OPTIONS
echo "INDIVIDUAL_OPTIONS=$INDIVIDUAL_OPTIONS"
#OPTIONS+=$INDIVIDUAL_OPTIONS
echo "ELIBRARY_SUPPORT=$ELIBRARY_SUPPORT"
OPTIONS+=$ELIBRARY_SUPPORT
echo "OTHER=$OTHER"
OPTIONS+=$OTHER
if [ $ENABLE_CROSS_COMPILE -ne 0 ]
then
    echo "TOOLCHAIN_OPTIONS=$TOOLCHAIN_OPTIONS"
    OPTIONS+=$TOOLCHAIN_OPTIONS
fi
echo "OPTIMIZATION_OPTIONS=$OPTIMIZATION_OPTIONS"
OPTIONS+=$OPTIMIZATION_OPTIONS

# Cmdline

echo '*** Cmdline ***'
CMDLINE="./configure $OPTIONS"
echo Usage: $CMDLINE

echo "Log: $LOG"
echo "$(date): Execute configure... "
eval $CMDLINE 1>$LOG 2>$LOG
echo "Exit code (configure): $?"
[ ! $?=0 ] && exit
echo "$(date): Execute make "
#make clean
#make 1>>$LOG 2>>$LOG # -n --recon 
echo "Exit code (make): $?"
echo "$(date): Done "

ENABLE_CROSS_COMPILE=1

Makefile требуется изменить следующим образом.

$(PROGS): %$(PROGSSUF)$(EXESUF): %$(PROGSSUF)_g$(EXESUF)
	$(info file $<)
#	$(CP) $< $@
#	$(STRIP) $@
%$(PROGSSUF)_g$(EXESUF): %.o $(FF_DEP_LIBS)
	$(info Запуск сборки...)
	$(info linker $(LD))
	$(info output $(LD_O))
	$(info objects $(OBJS-$*))
#	instead	$(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(OBJS-$*) $(FF_EXTRALIBS)

Среда сборки вместо линковки выведет необходимую информацию. Линкуем вручную. Там есть какие‑то конфликтующие зависимости, я даже разбираться не стал. Заработало — и всё тут.

После успешной сборки копируем архив с исполняемым файлом и сопутствующими. Запускаем? Или не хочется опять поймать сегфолт какой‑нибудь?

# ./ffmpeg --help
ffmpeg version N-83801-g52c7366c83 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.6.3 (STMicroelectronics Base) 20120313

Огонь! Программа работает даже под нагрузкой, что далее будет подтверждено.

[к содержанию]


Воспроизведение контента с источника RTSP, требующего basic авторизации.

Произведём предварительные настройки сетевых буферов

sudo sysctl -w net.core.wmem_max=10485760
sudo sysctl -w net.core.wmem_default=1048576
sudo sysctl -w net.core.rmem_max=10485760
sudo sysctl -w net.core.rmem_default=1048576

Сейчас приставка сможет воспроизвести контент с источника RTSP, требующего basic авторизации. В прошивке не было такой возможности. Добавляем плейлист.

#EXTM3U8,
#EXTINF:-1,FFmpeg udp://127.0.0.1:1234

и запускаем FFmpeg

/root/ffmpeg/ffmpeg -buffer_size 1M -r 50 -i rtsp://login:password@[IP]/[path] -c copy -f mpegts udp://127.0.0.1:1234?pkt_size=1316 

Логи с сообщениями приложения, к сожалению, не сохранились. Демультиплексированный RTSP поток датаграмм мультиплексируется в UDP поток контейнеров MPEGTS и отдаётся в адрес локальной петли. Перекодирование потока не требуется. Далее поток остаётся выбрать в меню и включить воспроизведение. UDP поток хорош тем, что при сбоях передачи воспроизведение не останавливается. Приложение может отправить поток в петлю в любой момент, и видеосигнал будет восстановлен. Кстати, откуда RTSP поток можно взять, не догадываетесь?

Готовы?
Вывод видеопотока IP камеры через выход HDMI IPTV приставки. Разумеется, снимок согласован и изменен. А так качество первозданное. Фото моё.
Вывод видеопотока IP камеры через выход HDMI IPTV приставки. Разумеется, снимок согласован и изменен. А так качество первозданное. Фото моё.

Разрешение - 1920x1080 (2 мп). Частота кадров - 25 Гц. Прогрессивная развёртка.

Во избежание мерцания кадра, желательно согласовать частоту кадров.

Битрейт потока - 4 Мбит/с. На удивление, узким местом оказались не характеристики микропроцессора, а малые размеры сетевых буферов. Показатель FPS мог упасть до 3 -2.

Автозапуск FFmpeg можно прописать в скрипте. Зачем, думаю не нужно обьяснять. Формат адреса может быть иным в вашем случае.

cat > /root/smapp << EOF
#!/bin/sh
cd /root/ffmpeg
(while [ 1 ]; do sleep 3; sh -c "nohup /root/ffmpeg/ffmpeg -buffer_size 1M -r 50 -i rtsp://admin:password@192.168.1.2/1/1 -c copy -f mpegts udp://127.0.0.1:1234?pkt_size=1316 "; done) &
cd /root
/root/smapp.rt -qws
EOF

Соответственно, для IPTV приставки задаём статические настройки сетевого адреса. Например 192.168.1.1.

[к содержанию]


Проблема портирования приложений для архитектуры SuperH SH

В linux присутствует устройство фреймбуфера /dev/fb0, /dev/fb1. Они предназначены для вывода видео в HD и SD режимах. Настроить режим можно утилитой fbset

Фреймбуферы доступны до запуска приложения.

Некоторые медиаплееры с открытым исходным кодом поддерживают вывод во фреймбуфер. Например:

mplayer -vo fbdev video.avi

Но портировать подобные проекты сложно. Кодовые базы проектов требуют поддержки стандартов c11, c17 от компиляторов для целевой архитектуры.

[к содержанию]


Целесообразность модификации приставки.

Целесообразна ли подобная модификация приставки? Взвесим все за и против.

С учётом технических параметров IPTV приставки MOTOROLA VIP1003 ARRIS, таких как наличие видеовыхода HDMI, физическая компактность в сравнении со специфическими решениями, такими как видеорегистраторы, и автономность работы её ПО, использование её в системах видеонаблюдения выглядит выгодным вариантом. Во что это вырастает? Грубо говоря, если можно приставку поставить на полку под потолком рядом с видеокамерой, а цифровой сигнал с HDMI сконвертировать для дальней передачи по оптоволокну, например, то можно обеспечить большую совместимость и удобство работы (купи и подключи), по сравнению с сетевой техникой. А также избавиться от недостатков сетевой техники, таких как нестабильность выделяемой пропускной способности для передачи данных, таким образом придав системе видеонабюдения надёжность передачи данных за счёт использования оборудования, совместимого с HDMI.

Однако, использование IPTV приставки MOTOROLA VIP1003 ARRIS там, где требуется удобство монтажа, пожарная безопасность, устойчивость к физическим воздействиям и аномалиям питания, ограничено, поскольку приставка разработана для бытового использования. Также, вместе с отказом от сетевой технологии, появляются ограничения, связанные с беспроводной передачей сигнала. Увеличивается задержка сигнала с момента изменения обьекта наблюдения. Разрешение ограничено требованием совместимости с видеорежимами IPTV приставки.

Я описал в красках, но выбор остаётся за вами. Ниже приведено руководство для конечного пользователя.

[к содержанию]


Руководство пользователя

IPTV приставка MOTOROLA VIP1003 ARRIS данной модификации может использоваться в качестве клиента для IP камер в системе видеонаблюдения.

Технические характеристики:

  • Питание - 12V/1A DC

  • Поддерживаемый видеорежим - 1920x1080p @ 25Hz

  • Поддерживаемый видеокодек - H.264/14496-10 video (MPEG-4/AVC)

  • Поддержка BASIC аутентификации.

  • Пропускная способность - 4 Мбит/с.

Порядок первичной настройки.

  1. Задайте параметры аутентификации для вашей камеры видеонаблюдения. Пользователь - admin. Пароль - password.

  2. Задайте статические настройки сетевого адреса для вашей камеры видеонаблюдения Адрес - 192.168.1.2. Маска сети - 255.255.255.0. Шлюз - 192.168.1.1.

  3. Задайте поддерживаемый видеорежим и формат потока для вашей камеры видеонаблюдения.

  4. Задайте битрейт потока - 4 Мбит/c

  5. Подключите камеру видеонаблюдения к порту Ethrenet IPTV приставки.

  6. Подключите видеовыход HDMI к приёмнику сигнала.

Порядок использования.

  1. Включите питание IP камеры и IPTV приставки.

  2. Дождитесь загрузки и появления меню приложения.

  3. Направьте пульт управления к приставке и нажмите кнопку TOGGLE (переключить режим меню/просмотра).

  4. Проверьте наличие видеосигнала.

[к содержанию]


Резюме

Работа завершена. Описание работы получилось обьёмным. Коротко о главном, что и зачем мы делали. С чем столкнулись и что получилось. Какое преимущество и недостаток у того, что получили. Приведём общие положения.

  • Целью работы, описанной в статье, является портирование приложения для IPTV приставки MOTOROLA VIP1003 ARRIS для обеспечения функционала воспроизведения контента, с источников, требующих авторизации, таких как IP камеры.

  • Инструментом для достижения цели работы, описанной в статье, является удалённый доступ к системе, получаемый путём прошивки IPTV приставки MOTOROLA VIP1003 ARRIS программным обеспечением, поддерживающим данный функционал.

  • Выводом из работы, описанной в статье, является необходимость учитывать поддерживаемую версию языка разработки при портировании для IPTV приставки MOTOROLA VIP1003 ARRIS новых проектов.

  • Итогом работы, описанной в статье, является возможность использования IPTV приставки MOTOROLA VIP1003 ARRIS в качестве клиента для IP камер в системе видеонаблюдения.

  • Преимуществом устройства, модифицированного в результате выполнения работы, описанной в статье, является повышение надёжности передачи видеопотока IP камер за счёт использования оборудования, совместимого с HDMI.

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

Спасибо за внимание!

Василий

Специалист

Почта: vasyusha.artemov.95@mail.ru

Пишем первую программу… для IPTV приставки. Хабр.
Пишем первую программу… для IPTV приставки. Хабр.

Вы можете поделиться ссылкой на данную статью с помощью QR кода на вашем экране.

26 Октября 2026 г.


Источники

  1. https://static‑data2.manualslib.com/product‑images/88f/1937905/motorola‑vip-1003.jpg

  2. https://media.au.ru/imgs/0e3866d1ad05d755494a63a07a3f9ae5/

  3. https://forum.cxem.net/uploads/monthly_03_2016/post-199817-0-19591600-1458908238.jpg

  4. 156346062-STi7105.pdf - Yandex Documents

  5. https://github.com/FFmpeg/FFmpeg?ysclid=mrdzje3v5e527735106

  6. https://ya.ru/images/search?search_client=unknown&text=пульт+ростелеком+для+motorola+vip1003&pos=5&rpt=simage&img_url=https%3A%2F%2Fmedia.au.ru%2Fimgs%2F00801e9f5776a1bfd1245887593a16ec%2Fpult-du-rostelekom-sml-282-arris-vip1003g-motorola-1-18604559.jpg&from=tabbar&lr=49

Комментарии (0)