Домашний фотоальбом
11.04.2021
Эта статья практически совсем ни о чём. Ею я просто хочу завершить некий проект, который представляет из себя историю страданий на ровном месте. Но, кажется, всё завершилось успешно и чтобы не влезать больше в такой блудень я просто зафиксирую для себя какие-то факты, которые происходили вокруг этого.
В какой-то момент времени у меня появилась компьютерная "игрушка" (опустим подробности чтобы не сочли рекламой) и видео-проектор Sony VPL PHZ10.
Этот проектор - неплохая вещь. За несколько лет он себя прекрасно показал. Хотя и есть у него некоторые странности. Компания Sony, хотя и встроила в него ethernet-интерфейс – явно не рассчитывала на то, что этим проектором будут управлять в автоматическом режиме по сети. Интерфейс работает исключительно из под Internet Explorer старой версии. Это, конечно, удалось обойти скриптами, но почему было не сделать нормальное API – неясно. Плюс, через какое-то время эксплуатации стало очевидно, что интерфейс всё равно сыроват и раз в два-три месяца сетевой контроллер проектора подвисает до перезагрузки по питанию. Не самая очевидная фантазия для устройства ценой почти в $3000. Но это удалось решить подвесив проектор по управляемой шине питания и в случае подвисания он автоматом перегружается. Короче – отличный проектор, всем рекомендую.
На этом этапе сразу стала очевидной задача – сделать нормальный звук к этой системе. У проектора не оказалось ничего, чтобы мне помогло (встроенные в него колонки были откровенным шлаком, а аудио-выхода у него нет), но современный мир был добр ко мне и за 400 рублей мне достался прекрасный audio extractor, который был подключен к не менее прекрасному усилителю и подогнанными друзьями колонками Radiotehnika S-50.
Но раз уж всё равно пришлось делать под "игрушку" подобие домашнего кинотеатра, то грех было не обвесить всю эту конструкцию какими-то дополнительными функциями.
Для начала захотелось сделать для детей функционал Dancing Mat. Само устройство было куплено несколько раньше, но поскольку дети не понимали, что прыгать на нём нужно нежно и аккуратно, то использовать его в обычном помещении было почти нереально. Когда они на нём прыгали в жилом доме на шестом этаже – жаловались даже с третьего. Когда они прыгали в загородном доме на втором этаже – коты на первом этаже выли от ужаса и забивались в дальние углы. И вот появилось отдельное помещение с прекрасным экраном, где никто никому наконец не мешал.
Но нужно понимать, что это прекрасное китайское устройство никак не хотело подходить к новому прекрасному проектору, поскольку оно имело исключительно RCA-выходы. Ладно, это беду удалось решить с помощью переходничка. Переходник – откровенное барахло. То есть возможно, что он сам и прекрасен, но изображение, которое рассчитано на RCA – ужасно выглядит в full hd качестве. Но всё лучшее детям!!!
И вот незадача…
Получается есть video-выход "игрушки" и есть video-выход этого прекрасного танцевального мата. И как-то между ними нужно переключаться. А оба устройства выглядят сами по себе просто ужасно и оставлять их на виду нельзя ни в коем случае. Поэтому они убраны за ширму, куда никто и никак не имеет доступа. Как же переключать видео-сигналы на проектор?
В целом – у проктора есть несколько видео-входов (даже два HDMI) и можно было бы переключать просто на проекторе, благо технологию его обвеса скриптами я уже освоил. Но почему-то в тот момент это решение было отметено. Не помню уже почему.
Вместо этого был установлен HDMI-переключатель, который умел переключаться на тот видео-вход, который был подключен последним. Элегантное решение. Детям был выдан конец удлинителя (питающий игровую приставку мата), который они включали в розетку и HDMI-переключатель чувствовал это действие и приставка появлялась на экране в приоритетном порядке. Это даже работало нормально какое-то время.
Но мне не нравилось заставлять 4-5 летних детей развлекаться втыканием чего-то в розетку. Это было как-то не в стиле современных IT-технологий. Я искал изящное решение, и оно было найдено.
Это прекрасный HDMI-переключатель. Он крайне удобен тем, что не требует внешнего питания и управляется единственной кнопкой. Причём эта кнопка механическая и имеет два фиксированных положения – on/off. Дальше дело техники – кнопку мы выпаиваем и на её место ставим управляемое реле. Тут подошло стандартное din-реечное реле ABB с двумя парами выходных контактов. И дело в шляпе – мы можем чётко контролировать какой именно видео-сигнал окажется на выходе! Управление я вывел на настенный планшет и всё стало прозрачно. Эпоха включения танцевального мата в розетку ушла.
Но не тут-то было. Оказалось, что детям хочется на большом экране ещё и смотреть кино/мультфильмы. Для того, чтобы это было удобно делать – было принято решение установить TV-приставку. Выбор пал на STB от Xiaomi. Неплохое с точки зрения эргономики решение, но основное его достоинство было в радио-пульте (не инфракрасном!), который не требовал визуального контакта с самой приставкой. Это позволило её убрать за ширму тоже. Как переключать видео-вход – вы видимо уже догадались – ещё больше HDMI-переключателей.
Не подумайте ничего плохого – первая ссылка на OZON была конечно же потому, что решение хотелось получить быстро, а Aliexpress не славится сильной оперативностью. А так – есть огромное количество одинаковых переключателей в брендированных корпусах. И от Vention, Ugreen, noname… Внутри всё равно одна и та же микросхема. При этом на OZON это волшебное устройство стоило в районе около 2600 рублей, а на ali - чуть меньше 600... Зато с OZON она приехала за три дня.
И вся эта прекрасная конструкция в таком виде просуществовала около трёх лет и не знала никаких бед, знаете ли… Не смотря на лютое китайское происхождение – она была собрана с душой и любовью и прекрасно себя чувствовала за ширмой.
И тут к ней пришла беда откуда не ждали…
В оригинально "игрушке", ради которой всё это строилось, между раундами был некий технический баннер, который никогда не вызывал ни у кого никаких эмоций. Ну был он и был. Он показывался в паузе, которая требовалась на загрузку следующего раунда.
И тут компания-разработчик решила внести свои корректировки в порядок мироздания и этот баннер был заменён на рекламный баннер одной российской компании. Это вызывало бурю необоснованных эмоций с моей стороны!
Но, поскольку реклама явно не являлась сильной стороной разработчиков, то убрать новый навязчивый баннер путём минимального вмешательства в файловую систему – не составило никакого труда. От баннера удалось избавиться простым удалением файла с этим баннером. Но появилось другая проблема… Появилось острое желание вместо этого баннера видеть что-то своё. Например тематические фотографии из домашнего фотоальбома. Ну ведь там всё равно же пауза между загрузками раундов? Почему бы не посмотреть в этот момент на знакомые приятные лица?
Осталось только понять, как именно это интегрировать в абсолютно чужую компьютерную систему, которая никак вообще не была рассчитана на такую увлекательную идею.
Сама "игрушка" работала на обычном Win7. И для начала мне показалось, что не будет никаких сложностей просто нарисовать в нужный момент окно поверх существующего изображения. И в этом окне вывести всё, что мне нужно. А потом вовремя его убрать. Это была прекрасная идея, которой было не суждено сбыться, поскольку, когда я её придумывал я даже не подозревал о существовании таких сложных вещей, как полноэкранный DirectX, который не подразумевает даже теоретического рисования поверх себя чего бы то ни было. Как много нам открытий чудных…
Тут я достаточно оперативно дошёл до тупика и понял, что через него мне не прорваться. Я начал изучать теорию каких-то специализированных утилит, которые были изначально предназначены для того, чтобы рисовать что-то поверх подобных программ. Они использовали технологию dll-hook, для того, чтобы встроиться между игрой и DirectX и иметь возможность показывать свои данные поверх рисунка игры. Я здраво оцениваю свои силы и тут было понятно, что за разумный срок сам разработать с нуля подобное решение я не смогу.
Нужно было искать того, кто уже сталкивался с подобными задачами. freelance.ru? Ну я хотя бы попробовал. Кроме каких-то фееричных мошенников, которые развели меня на 1500 рублей, я не встретил никакого желания у людей заниматься этой задачей. Я попробовал поискать разработчиков на разных площадках, и российских и зарубежных. Но, предполагаю, что задача была слишком сложной и люди с достаточной для её решения квалификацией не торчали на этих полу-помойках.
Попутно возникла другая идея… Ведь поскольку простым удалением рекламного баннера из файловой системы удалось добиться его безболезненного исчезновения с экрана – возможно, что замена этого баннера на собственный – вызвала бы показ нужного мне баннера в соответствующий момент времени? Но вот беда была в том, что баннер хранился в непростом формате .dds (DirectDraw Surface). Хотя это была в общем-то так себе беда. Основная беда была в том, что он был зашифрован. Причём каким-то очень простым повторяющимся ключом длиной в 16 байт. Это было очень хорошо видно по hex-дампу удалённого мною баннера… Да и многие другие изображения в этой "игрушке" хранились ровно в таком же формате.
Что же может быть проще! Нужно просто взломать этот код шифрования! Наверняка это банальный XOR!
Эх… Сколько на это было убито времени – страшно сейчас вспомнить. Оставлю здесь эту картинку для будущей ностальгии. Это зашифрованный баннер с подменённым заголовком dds.
Пара пятен на этой картинке полностью совпадали с такими же пятнами на рекламном баннере в момент показа. Это, и только это, давало надежду.
Это был фееричный тупик. Это был не XOR. Это был или Blowfish или AES. Мы толком не смогли даже этого понять. Мы пытались и перебором ломать эту штуку и отладчиком вскрывать код игры, для того, чтобы попытаться найти тот ключ, которым можно было бы вскрыть эту картинку. Были привлечены какие-то хакеры, которые пытались отладчиком достать это чудо. Я в этом непосредственно участвовал и узнал много нового о современных отладчиках... Это заняло просто нереальное количество ресурсов и не привело ни к чему. Мы даже не поняли до конца тип кодирования этого файла. Хотя длина ключа была точно 16 байт.
Попутно нам удалось выяснить, что вся "игрушка" написана на движке CryEngine. Говорят, что в определённых кругах – очень известная вещь. Но все специалисты, которые с ней работали – на предложение сделать что-то, чтобы удалось рисовать поверх нее – посылали нас грубо и достаточно однозначно формулируя направление движения. Похоже, что это был идеологический тупик.
И уже пора было бросать весь этот геморрой, но ведь чем больше уходило на него времени, тем больше было обидно его бросать незаконченным? Нет, если бы у меня было хотя бы предположение о том, сколько ресурсов это сожрёт – я бы проклял эту идею в самом зародыше. Но убив на неё столько времени – было уже нельзя сдаваться.
Это была славная битва…
Она началась в ноябре 2020 и, надеюсь, закончилась в апреле 2021. Это было полгода.
Поняв, что почти все направления, по которым я двигался, вели в тупик - я уже почти сдался. Но в какой-то момент времени меня посетила странная, неожиданная идея… А если попытаться не рисовать что-то поверх самой "игрушки", а просто подменить на нужное мне время видео-поток, который идёт на проектор от системного блока "игрушки" на другой видео-поток? Ведь визуально это будет почти равнозначно. И никакого вмешательства в работу системы не будет нужно вообще?
Эта задача хотя бы потенциально подразумевала наличие решения. Было непонятно во сколько обойдётся это, но вроде бы никакой масштабной беды на горизонте не было.
Начал я с простого – решил попробовать подменять видео-поток просто на самом проекторе, благо там было два HDMI-входа. Это было просто, бесплатно, но достаточно быстро показало свою несостоятельность. Проектор не такой уже и свежий, да и когда его выпускали – явно не ставили подобную задачу приоритетной. Время на переключение между видео-входами у проектора составляло около 3-4 секунд. При этом на это время экран проектора показывал только большое серое пятно. Нужно понимать, что в целом баннер, о подмене которого идёт речь, показывался на экране не так уж и надолго – в среднем где-то от 3 до 10 секунд. Если тратить на переключение туда и обратно по 4 секунды, то ничего, кроме раздражения подобное решение не вызывает. Я попробовал. Это было плохо.
Плюс нестабильность работы самого проектора и его подвисания – тоже не добавляли надежды, поскольку если во время раунда проектор решит не переключаться обратно на нужный видео-поток, то это явно станет проблемой.
Значит нужно было какое-то устройство, которое бы обмануло всех участников и подменило видео-сигнал само. Например, мой любимый переключатель из начала статьи. Благо у меня был небольшой подготовленный запас этих устройств.
Но тут тоже ничего хорошего не вышло – при подобном переключении между видео-сигналами проектор видел ошибку в поступающем HDMI-сигнале и уходил всё в тот же серый экран на 4 секунды. Плюс со стороны системного блока также возникала ошибка – он видел, что от него был отключен монитор/проектор, а значит и видео и аудио-выходы переинициализировались. Это вызывало и временные артефакты на экране и скрип в колонках. Идея явно была плохая.
Начались поиски. Я узнал, что существует технология подмены EDID. Идея в том, что интеллектуальный HDMI-коммутатор самостоятельно представляется в сторону системного блока монитором, а в сторону монитора/проектора – компьютером. При этом с помощью каких-то настроек (например dip-переключателей) можно задать требуемое разрешение экрана и прочие параметры.
Это явно было то, что нужно! И относительно не дорого. Плюс у устройства из коробки заявлялось наличие RS232, что подразумевало элементарное управление без дополнительных внешних реле. Я почувствовал близость победы…
Нет, это был тоже тупик. Какую-то часть проблем данное устройство сняло, но момент переключения видео-сигналов шёл всё равно непрозрачно. Проектору это переключение категорически не нравилось, и я всё ещё наблюдал серый экран. Но хотя бы на стороне системного блока проблемы ушли – там никто беды больше не замечал.
В бумажной документации к этому коммутатору, кстати, достаточно доходчиво описан протокол управления RS232. Всё просто и прозрачно. Но я до него не добрался – мне явно это решение не подошло.
Результаты дальнейших поисков начали меня пугать. Попался мне ролик, в котором всё происходило ровно так, как мне было нужно.
https://www.youtube.com/watch?v=UWKRaNEfQMQ
Там в ролике мужчина нажимает на кнопки, и картинка на экране меняется как по мановению волшебной палочки. Плюс идея того, что подразумевается возможность picture-in-picture – явно внутри стоят какие-то графические процессоры, которые проксируют видео-сигнал.
Я кинулся вводить названия рекламируемых мужчиной устройств в гугл. Но не тут-то было! Это были явно устройства не предназначенные для бытового применения. Ценник был внушительный.
И пару дней я пытался смириться с подобной стоимостью нужного мне переключателя. Но не справился. Это было просто чудовищно. Но я заметил прекрасный термин в описании подобных устройств. Он обязательно присутствовал во всех описаниях и на морде всех устройств. Seamless. Бесшовный. То есть, предположительно, обрыва видеосигнала быть не должно. И проектор должен это пережевать и проглотить.
После изменения критериев поиска – начали попадаться уже какие-то относительно живые варианты.
Решение было достаточно дорогим, но уже более разумным. Я почти решился на него, но споткнулся… У этого устройства не было никакого внешнего управления. Только кнопки на морде, да ещё и не фиксирующиеся. Даже с помощью внешних реле я бы не смог чётко контролировать какой именно видео-поток демонстрируется в текущий момент времени. Нет, это было опять не оно.
Но тут на помощь пришло то название, которое было написано на этом устройстве. Оказалось, что оно и является ключевым. HDMI Multi-Viewer Seamless Switch. Это мне реально помогло в поисках.
4K HDMI 8x1 Quad Multi-viewer Switcher 8 In 1 Out Seamless Switch 4x1 Multi Viewer PIP Picture Display Screen Divider Converter. Вроде бы решение было уже близко! Я даже решил немного переплатить за доставку, чтобы не растягивать удовольствие. И как не странно – не прогадал. Доплатив 1900 рублей за premium-доставку этого устройства - я получил его на руки через 6 дней. Это было крайне неожиданно для службы DPD. Было вот просто чудом. До этого все посылки, которые попадались в цепкие лапы DPD - шли точно не меньше месяца. Бывало и по два…
Переключатель приехал. Упакован он был просто феерично – замотан в полиэтиленовую плёнку. Без коробки, без пенопласта. Как он доехал живым – остаётся большой загадкой. В комплекте был пульт и блок питания.
Не теряя времени, я решил проверить его в бою. И вы знаете – это было то, что нужно. Он действительно осуществлял "бесшовное" переключение, о котором не догадывались устройства по обе стороны HDMI-кабеля. Это была почти победа!
Осталось только настроить RS232. А вот тут всё оказалось странно… Нигде не было никакой документации о том, какой именно протокол используется на этом устройстве. По разъёму даже было непонятно, где находится RX/TX. Да и ответной части этого разъёма в комплекте не было…
Я потратил два дня на возню с этим чудом. Перебором скоростей, чётности и прочего. В какое-то момент мне начало казаться, что эта задача не имеет решения вообще и что китайцы обманули меня и нет там никакого RS232… Разобрав переключатель, отследив дорожки и начитавшись даташитов на микросхемы – удалось идентифицировать контакты разъёма. Они оказались GND-TX-RX. Ответную часть разъёма удалось свинтить в какого-то RS485-конвертера. И в какой-то момент экспериментов что-то изменилось на экране! Вначале оно переключалось в случайном порядке, не туда куда нужно, не удавалось добиться повторяемости… Но оно явно пыталось работать.
Но потом, после правильно выставленной скорости – всё встало на свои места. Оказалось, что переключатель хочет самые стандартные 9600 8N1 и переключение осуществляется отправкой ему бинарных кодов с номером порта. Предельно просто и прозрачно.
А ещё через день ответил продавец и просто прислал полную документацию на RS232-протокол. Два дня потраченных на него было очень жаль!
Но он заработал!!!
Ну а дальше…
Что дальше…
Дальше всё было просто.
Autohotkey следит за экраном "игрушки" на предмет появления/исчезновения баннера. В случае его появления отправляет информацию о событии в центр управления.
Отдельно установленная RPi показывает с помощью feh картинку из фотоальбома, которую ей выдаёт по HTTP соответствующий сервис.
Отдельной любопытной идеей оказалось то, что экран "игрушки" имеет нестандартное соотношение сторон. Раньше я не замечал этого, поскольку никаких правильных фигур на экране не отображалось. А вот при появлении фотографий выяснилось, что лица на этих фото прилично вытянуты... Вместо 16:9 было 16:13. Пришлось пережимать весь фотоальбом с учётом рассчитанного коэффициента.
Обычный ImageMagiсk справился и с формированием корректного фона для фотографий и с добавлением информации о дате съёмки.
Всё встало на свои места.
Ну и конечно же в новый HDMI Seamless коммутатор были переключены танцевальный мат и Xiaomi STB. С ними всё было просто и прозрачно. А с прекрасными HDMI-переключателями управляемыми внешними реле пришлось расстаться за ненадобностью. Схема включения стала аккуратной и понятной, без лишних проводов и каскадов устройств.
Надеюсь, что получившася конструкция прослужит мне верой и правдой какое-то время. И оправдает затраченные силы посредством прекрасных эмоций...
UPD, 2021-04-16: Оказалось, что показывать фотографии из альбома в случайном порядке – не самая лучшая идея. Мне об этом сразу сказали друзья, но я не очень поверил. Но оказалось, что я не прав… Из-за того, что некоторые фотографии присутствуют в альбоме в большом количестве очень похожих экземпляров (серийная съёмка), то достаточно часто генератор случайных чисел вытягивает подряд почти одинаковые кадры. И возникает впечатление, что фотография вообще не обновилась. Получилось не очень аккуратно. Пришлось переписывать систему выбора фотографий с анализом информации о последних 50 показанных снимках и исключением тех дат, на которые уже было отображение. Стало сильно лучше.
UPD, 2021-04-23: Обнаружилась небольшая проблема в видео-коммутатором. В целом она была предсказуема, если бы немного подумать. Но до этого, конечно, не дошло. Протокол управления подразумевает отправку одного единственного байта, в котором задаются все параметры его текущей работы. При этом ему не нужно ни контрольных сумм, ни символов подтверждения (типа возврата каретки после введённой команды). Получается, что любая наводка на rs232-кабель может дать иллюзию введённого управляющего байта и коммутатор переключится в случайный режим работы. Собственно, это и случилось. При очередном включении системы на экране обнаружился видео-поток с танцевального мата, а аудио-поток с канала "игрушки". Кстати, интересная идея на будущее – то есть коммутатор без проблем может миксовать аудио/видео с разных каналов. Поставил в качестве заплатки навязчивую отправку сигнала переключения коммутатора на правильный порт в момент включения видео-системы. Посмотрим, как пойдёт дальше.