biohazard

Первый скрин

Получен певый скрин Isotoxin-а под убунтой.




На фоне убунты

Вот тут в большом разрешении. Залил на какой-то хостинг.

Пока это просто то что вывел Isotoxin нативно под никсами. Ни о каком взаимодействии с юзером пока речи не идет. Как видно, даже некоторые элементы отрендерились криво. Вобщем, работы там еще как бы не больше, чем потребовалось, чтобы этот срин получить. Работу очень сильно тормозит тотальная забагованность и ущербность IDE code::blocks. И это один из лучших представителей IDE под никсами... Лано, работаем дальше.

biohazard

Трудности портирования 2

Вот смотрите.

Акт первый.

У меня есть свой супер гипер крутой массив. Ну велосипед, да, но пока что возражения типа "юзал бы std::vector и горя не знал" я не принимаю. Так вот, массив этот много чего умеет и состоит чуть менее чем полностью из шаблонов. Например, он умеет быть массивом указателей, для которых надо вызывать delete. Или не надо. По желанию. Понимает, что некоторые типы могут быть непереносимыми в памяти. С такими типами он работает чуть медленнее, вызывая конструкторы и деструкторы при ресайзе массива. А если тип поддерживает перемещение, то такие объекты переносятся в памяти средствами memcpy, что, разумеется, значительно быстрее. Ну и так далее. Велосипед сей написан давно, оттестирован и нареканий в работе не вызывает.

Акт второй.

Есть такое свойство у классов — копируемость. Обычно все классы обладают этим свойством. Но есть такие, которые не обладают. Их мало, но они очень вредные. Ну, если не знаете, это когда объект данного класса не копируется. Ну т.е., обычно, если поднапрячься, то функцию копирования написать, конечно, можно, но вот не нужно. Классический пример — класс File. Т.е. такой объект будучи созданным однажды, копировать нет никакого смысла, т.к. это бы означало сложную операцию открытия того же файла, позиционирования в этом файле на ту же позицию и может еще какие-то не очень быстрые операции.

Акт третий.

Collapse )
biohazard

Трудности портирования

Привет.
Кажется я забил на этот блог. А может я забил и на Isotoxin?
Пока затрудняюсь ответить. Стал уделять больше времени другим проектам. Несмотря на то, что Isotoxin кишит багами, я решил пока на них не отвелкаться. Худо бедно работает, и хорошо. Сейчас, если я занимаюсь Isotoxin-ном, то это только портирование. Сразу признаюсь, работа идет со скрипом. Здесь я опишу некоторые трудности. Они, вероятно, будут сильно раздуты и вообще являются лишь следствием моей некомпетентности. Но ведь это я портирую Isotoxin, а не вы, не так ли? Так что можете просто считать этот пост нытьём человека, который идет вразрез правилам. Правилам грамотного написания портируемого кода. А такой путь - это путь боли :)
Итак.

Как вы, наверное, знаете Visual Studio - это IDE под windows и только под windows. Isotoxin писался с помощью этой IDE. Под линуксом мне понадобилось выбирать редактор кода, который бы был хотя бы в чем-то близок Visual Studio. Нет нет, никаких vim-ов, что вы. Я старый больной человек, мне поздно переучиваться. Да и смысла нет, т.к. я вовсе не собераюсь приобщаться к светлому миру юникса.
Сначала я попробовал использовать CodeLite. Подкупила близость концепции к Visual Studio. Но, провозившись с ней какое-то время, я отказался. Бесконечные мелкие баги интерфейса еще можно было пережить, но, что меня совершенно выбешивало - это глючный build. Ну вот как с эти можно работать: изменяю что-то в файле, нажимаю на build и... трам пам пам, всё прекрасно, build закончен, ошибок нет. Оно просто не выполняло build после редактирования файла. Сначала я перезапускал эту IDE. Потом случайно обнаружил, что если в папке с проектом выполнить make, то build в IDE снова начинал работать, но до следующего изменнеия исходника. Вобщем, в один прекрасный момент снёс это чудо и забыл как страшный сон.
Потом были QTCreator (не заработал вообще, разбираться особо не стал), еще какие-то IDE-шки, которые мне не подходили, т.к. были завязаны на cmake (мне не нравится идеология cmake, не переубеждайте, бесполезно). Eclipse даже пробовать не стал, наслышан о ее жадности до ресурсов (IDE на java - ну нафик. Мне хватило Android Studio. Жрет память как не всебя.)
Короче, пока остановился на Code::Blocks. Тот еще рассадник багов, но хоть build работает, и дебагер завёлся из коробки. За это и терплю.

Как я работаю. Создаю проект, добавляю файлы, настраиваю опции сборки, нажимаю build. Ессесно получаю вагон ошибок, правлю (если это всего-лишь недопонимание со стороны gcc) или пишу новый код, если старый windows-only. Такая себе рутина. Вот только пишу и правлю код я на старой доброй Visual Studio. Но не умеет Code::Blocks того что мне надо! И нет никакой возможности её этому научить. А если и есть, то это сакральное знание нет никакого желания постигать. Все таки я дитя прогресса. Обработка напильником - это для истиных адептов юникс-мира. Не моё это.
Из неудобств: при сохранении убивает кодировку, меняет права доступа к файлу, так, что по самбе они переходят в разряд read-only. Бесит жутко. Нет поиска символов. Нет быстрой навигации по методам в пределах одной единицы трансляции. Переход к определению работает меньше чем в половине случаев. Определение того, будет этот кусок кода компиляться, или будет отброшен из-за #ifdef/#endif - глючит. Приходится добавлять левый символ и пробовать собрать. Поиск медленный и глючный. Доходит до того, что плюю и начинаю искать far-ом по папке, расшаренной в самбе. Это пипец, товарищи. Автоформатирование чудовищное. Логика табов с файлами, если и есть, то я ее не уловил. Табы постоянно меняет свой порядок и постоянно пропадают. А после перезапуска IDE вообще не понятно по какому принципу восстанавливаются. Каша какая-то. Также не сохраняются брейкпоинты. При попытке прервать дебагинг, стоя на брейпоинте, частенько зависает. Если изменить файл и нажать на build, нормальная IDE этот файл сохранит перед сборкой. Но не Code::blocks. Но это еще ладно. Гораздо серьезнее, это то, что IDE не вкурсе, что при изменении файла, требуется пересборка и для всех файлов, которые включают в себя измененный. Приходится делать полный rebuild. Дебажить более одного процесса одновременно нельзя.
Я давно подозревал, что под линуксом софт такой глючный, потому что люди работают в нечеловеческих условиях. Теперь я в этом убедился :) Это фраза не для холивара. Это просто моё скромное мнение.
Сижу и думаю: а оно мне надо?
Шучу. Надо. Из принципа.
biohazard

Обновление групчатов

Я сделал это. Сделал постоянные групчаты в tox-е.
Суть проблемы всем известна - групчаты в токсе умирают сразу после дисконнекта. Отвалилась связь? Заходи в групчат по новой. Перезапустил клиент - заходи в групчат по новой. Чтобы хоть как-то снизить градус нелепости происходящего, были придуманы групботы. Групбот - это такой друг (в терминах tox-а - friend), которы online 24/7 и который без вопросов соглашается на приглашение в друзья от любого, кто это приглашение ему пошлет. Этот групбот сидит в неком групчате (или сразу в нескольких) и таким образом оберегает групчат от исчезновения. За одно этот групбот понимает простые команды, типа invite или info. По команде invite, групбот приглашает вас в свою группу, в которой сидит сам. Есть и продвинуая версия групбота, российская Kalina, которая приглашает вас сразу, как только вы появляетесь в онлайне. Если кому интересно, можете добавить Калину себе в друзья и сразу попадете в чат, в котором обитает и ваш покорный слуга. Адрес Калины: kalina@toxme.io

А теперь пойдет злобный текст.
Как оказалось, такое свойство групчатов tox не потому что невозможно сделать иначе (я слышал фразы типа: "ну это же p2p, там все не так просто"), а потому что irungentoo, тот самый чувак, который и сотворил весь tox (за что ему, конечно, спасибо) забил на разработку. При чем забил, толком не доведя tox до ума. И, как показали дальнейшие события, это был единственный человек, который хоть что-то мог сделать. Все остальные из команды Tox Foundation, просто какие-то импотенты (Ребята, если вам кто-то переведет этот текст, можете меня возненавидеть. Вы реально нихера не умеете. А лучше не рефлексуйте, а идите и работайте). Кстати, существует реализация т.н. "новых" групчатов (тут). Но эту реализацию делали какие-то студенты по программе GSoC, и никто из Tox Foundation не знает как она работает. А она и не работает :) Поэтому воз и ныне там.

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

В результате на свет появилось обновление к текущим групчатам, выраженное вот в этом PR-е. Как вы можете видеть, PR не принят. Я думаю, он не будет принят никогда. А всё потому что ребятки заигрались в крутую команду разработки, сами при этом нихрена не умеючи. Вобщем, они хотят двух вещей, на которые сами не способны: 1. Понять, как это всё работает. 2. Тесты. Я, тесты, понятное дело, писать не буду, т.к. хватит и того, что Isotoxin с этим обновлением вышел и работает. С первым пунктом, похоже вообще беда.

А между тем у обновы следующие свойства:

  • практически полная совместимость с текущим протоколом

  • исправление некоторых багов (например, некоторые клиенты иногда перестают видеть свои же собственные сообщения)

  • минимальное изменение в API

  • восстановление групчата даже если ваш друг (через которого и происходит восстановление) имеет старую версию групчатов


Что не сделано и, скорее всего, никогда не будет сделано, т.к. я, вероятно, буду писать новую реализацию групчатов.

  • восстановление через не-друзей (это возможно, но в рамках существующего протокола - сомнительное удовольствие)

  • публичные чаты. Это вообще за гранью. Не в текущем протоколе, однозначно.

  • синхронизация сообщений

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


Что в итоге. В итоге Isotoxin умеет обновленные групчаты. Вы можете создать с друзьями групчат и он никуда от вас не денется. Вряд-ли вы увидите эту функциональность в других клиентах. Почему? Потому что ленивые жопы, вот почему. Ну или криворукие, если это вам ближе.
Хорошая новость в том, что я плотно засел за linux порт Isotoxin-а. Прямо очень плотно. Намереваюсь во что бы то ни стало, довести это дело до релиза. Плохая новость в том, что мне никто не помогает. С другой стороны, я делаю то что мне нравится, и это хорошая новость :) На этом пока всё.
biohazard

Автоскрываемая панель задач

Ох уж эта винда...
Вобщем, есть в винде возможность сделать таскбар автоскрываемым. Я с самого начала времен решил, что это фишка неудобная, и благополучно забыл о ней. Но, оказывается, есть люди, которые этой фишкой пользуются. Казалось бы, при чем тут Isotoxin? А дело тут вот в чем. Если вкратце, то имеет место баг: если Isotoxin раскрыть на весь экран, то скрытый таскбар не вызывается. Баг есть, надо лечить. Для начала, надо разобраться в сути вопроса.
Как оказалось, таскбар, будучи скрытым, торчит кромкой шириной в 2 пикселя из-за границы экрана поверх всех окон. Когда пользователь подводит туда мышкой, таскбар на это безобразие реагирует появлением. Ну и в чем тут засада? А засада тут в двух моментах:
1. Эти 2 торчащих пикселя не вычитаются из полного экрана, как это происходит, когда таскбар не скрыт.
2. Режим "поверх всех окон" сделан не с помощью стиля TOPMOST, а немного иначе (что, на самом деле правильно).

Что это означает: во первых, программа, запрашивая у системы размер максимальной рабочей области, не видит этих двух пикселей. Система о них не сообщает, фактически. Во вторых, это окно таскбара вообще не поверх всех окон. При раскрытии во весь экран, система просто подрезает максимальное окно на эти 2 пикселя.

Что получается. Поскольку Isotoxin отрабатывает манипуляции над своим окном самостоятельно, то при максимизации отрабатывает не ShowWindow(hwnd, SW_MAXIMIZE), как это обычно бывает, а просто окну выдается размер рабочей области текущего монитора. И, в согласии с особенностями реализации скрытого таскбара (пункты 1 и 2), оный оказывается под распахнутым на весь экран окном Isotoxin'а. Всё. Сообщения от системы о движении мыши таскбару не доходят и он не появляется.

Если честно, то я не знаю как правильно решить эту проблему. Можно было бы сделать окна Isotoxin'а более стандартными, т.е. делегировать все функции по ресайзу системе. Но делать это я не буду. Не хочется переписывать архитектуру движка интерфейса. Так что фикс немного хинтовый. Просто Isotoxin теперь самостоятельно определяет факт нахождения курсора над областью таскбара и сам сообщает ему, что неплохо бы и появиться. Вот такой вот грязный хак.

UPD:
Все же у этого хака есть недостаток: таскбар остается активным, пока явно не будет активировано другое окно.
Все таки немного изменил решение. Просто теперь размеры полного экрана учитывают торчащие 2 пикселя таскбара. Это пришлось сделать вручную, т.к. системные функции получения размера экрана не видят этих 2-х пикселей.
biohazard

Jabber

Решил подтвердить слово "мультипротокольный" в словосочетании "мультипротокольный клиент", когда это словосочетание применяется к Isotoxin'у. Ну да, формально, там сейчас два протокола: Tox и Lan. Но Lan, несмотря на то, что это вполне рабочий протокол, является всего-лишь протоколом, созданным мной для отладочных целей, в том числе и для отладки мультипротокольной архитектуры Isotoxin'а. Просто, некий бонус, необязательный к использованию, хотя и потенциально полезный.
Вобщем, мне нужно срочно добавить поддержку еще одного протокола, желательно распространенного. Сначала я хотел добавить Telegram, но пока решил повременить. Почему? Ну у меня сложилось впечатление, что г-ну Дурову вовсе не интересны сторонние клиенты. Да, протокол открыт. Но! Но не существует официально поддерживаемой библиотеки, поддерживающей этот протокол. Неофициальные - да, такие есть. Но что будет, если в протокол внесут изменения, а разработчик неофициальной библиотеки отошел от дел? Вот именно. Ничего не будет... работать. Поэтому, единственная для меня возможность сделать поддержку телеграма - это использовать официальные исходники Telegram Desktop. Но это не так то просто. Там всё слишком завязано на Qt. Не то, чтобы я был против этой замечательной библиотеки, но тянуть в проект Qt ради кода, который всё что делает, так только соединяется с чем-то в сети, (т.е. никакого GUI), считаю слишком накладным.
Что еще у нас открытого и распространенного? Да собственно, только Jabber, он же XMPP. Решено, делаю поддержку Jabber'а.

После беглого ознакомления со спецификацией, я понял, что этого монстра с нуля мне не осилить. Во всяком случае, за вменяемое время. Поиск библиотек, реализующих хотя бы часть спецификаций (или расширений, в терминах XMPP, т.н. XEP-ов), привел меня к библиотеке gloox. Подкупило, что эта либа написана на C++ (голый C, конечно, хороший язык, но его ограничения вгоняют меня в тоску), а также неплохая документированность. К плюсам библиотеки также можно отнести ее расширяемость: если какой-то XEP не поддерживается непосредственно библиотекой, довольно просто написать необходимую обвязку самостоятельно.
На момент написания этого поста, работы по внедрению поддержки Jabber'а уже близки к завершению. Осталось прикрутить передачу файлов, поддержку групповых чатов и подгрузку offline сообщений сервера. Хотя, как сказать. Возможно на эти три фичи я потрачу времени больше, чем на то что уже сделал (т.е. всё остальное).

Ну и под конец поста немного критики.
Вы, возможно, помните времена бума Jabber'а лет 10 назад. Поддержка крупными компаниями, типа гугла. Светлое будущее, аська должна умереть, что такое скайп и т.п. радостные возгласы. Казалось бы, вот он идеальный протокол обмена мгновенными сообщениями. Как бы не так.
Jabber - это перегруженный фичами монстр, в котором одно и тоже может быть сделано 5-ю разными способами, при этом первый способ устарел, второй поддерживается всем клиентами, но половиной клиентов неправильно, третий способ поддерживается только двумя клиентами, четвертый - только двумя серверами, а пятый еще в разработке и меняется каждый день. Утрирую, конечно. Но, по моему скромному мнению, jabber разваливается под собственным весом. Одних только способов передачи файлов есть как минимум 3 способа. Издевательство какое-то.
Вот такой вот он, jabber, великий и неподъемный. Вот вам маленький такой списочек XEP'ов. По каждому XEP-у многостраничный документ. Да в гробу я видал этот ваш XMPP.
Шучу. Скоро будет.
biohazard

64 бит

При портировании на линукс во всей красе встала необходимость собирать весь код под 64 бита. Вариант 32 битной сборки под линукс, хоть и осуществимый, но нелепый, с точки зрения здравого смысла. Вобщем, 64 бита...
Решено, сначала сделаю 64-биную версию под Windows, а там продолжу портировать под линукс.
Какие проблемы? Ну, особых проблем с C/C++ кодом нет. Включи сборку под 64 бита и компилятор все сделает. При условии, что код специально не затачивался под 32 бита, типа какой-нибудь хитрой арифметики на указателях. Ну я таким не злоупотреблял, поэтому тут все ok. Пришлось, правда, немного поиграться с типами данных, чтобы убрать тонны новых предупреждений на тему "ой, а вот тут у вас size_t в int преобразуется, битики теряются".
Самое веселье началось с _asm вставками. Как известно, в 64-битном режиме _asm вставки теперь вне закона. Сначала я негодовал по этому поводу, но позже понял, что побудило microsoft пойти на такой шаг. Дело в том, что т.н. AMD64, т.е. 64-битная архитектура, которую изначально придумала AMD, а Intel несколько позднее лицензировала, т.е. та самая 64 битная архитектура, которая ныне присутствует в подавляющем большинстве desktop компьютеров, обратно совместима со старым добрым x86. Т.е. код на ассемблере под x86, совершенно валиден для AMD64. Если бы microsoft своим волевым решением не поставила _asm вставки вне закона, то компилятор бы не имел возможности отличить x86 ассемблер от AMD64. Понятно, к чему бы это привело. Да. Старый код с _asm вставками просто приводил бы к неработоспособности только что собранного исполняемого файла.
Впрочем, если бы microsoft ввели ключевое слово, типа _asm64, то было бы намного лучше, чем вообще ничего.

И знаете что? Мне пришло понимание того, что далеко не всякая 64-битная версия какой либо программы, такая же быстрая, как 32-битная. В общем и целом, сборка под 64 бита быстрее - сказывается наличие 8 дополнительных регистров, да и некоторые алгоритмы на 64 бита ложатся лучше. Но есть большое НО. Это старый 32-битный код на ассемблере. Если в программе такого кода много, то разработчик, скорее всего, не будет писать такие же быстрые функции на 64 битном ассемблере (во всяком случае, не сразу), а оставит реализацию на языке высокого уровня. В большинстве случаев, разницы в скорости никто не заметит, но есть случаи, когда разница есть, и она ощутима.
Я говорю об оптимизации работы с графикой на SSE. В коде Isotoxin'а многие тяжелые операции оптимизированы на ассемблере с SSE, и вот сейчас встал вопрос о переписывании этого кода так, чтобы он заработал на 64 битах. Это и оказалось самым сложным в портировании на 64 бита.
Вобщем, решил я попробовать SSE интринсики. Это отдельные SSE команды, которые выглядят как функции. Попробовал и остался доволен результатом. Очень доволен. Как оказалось, если готовую реализацию на ассемблере перевести в код на интринсиках как есть, то скорость работы такого кода иногда даже выше, чем оригинального asm кода! Чудо! Разработчики оптимизаторов - мое почтение!
biohazard

gcc vs msvc

Потихоньку портирую на линукс. Естественно, возникла необходимость собирать код с помощью gcc. Как оказалось, gcc невероятно параноидален в плане соблюдения стандарта. Нет, я не против привести свой код в соответствие, так сказать. Но, местами, откровенно бесит. Вот взять, к примеру, разбор шаблонов. Тут gcc пытается сразу разобрать шаблон по косточкам и убедиться, что там всё верно. Казалось бы, благая цель. Но не все так просто. msvc не пытается найти в шаблонах ошибки. Нет, он находит проблемы в синтаксисе, не без этого. Но вот, если я обращусь к переменной, которой не существует, msvc ничего не скажет. Почему? Ну потому что, когда я проинстанцирую шаблон, возможно эта переменная появится, и ругаться на этапе парсинга шаблона действительно не стОило. К чему это приводит? К тому, что там где msvc спокойно собирает код, gcc спотыкается, требуя подсказок. Вот пример кода, на котором gcc споткнется, а msvc проглотит не икнув:

template<typename T> struct foo {
    T bar;

    void do_something() {
        bar.func<int>( 123 );
    }
};

Видите? Я вызываю шаблонный метод func класса T. gcc не понимает, что я от него хочу. Исправлю код:

template<typename T> struct foo {
    T bar;

    void do_something() {
        bar.template func<int>( 123 );
    }
};

"Другое дело" - говорит gcc и работает дальше.
Вот и сижу, подсовываю костылики бедненькому gcc, а то не справляется. Но это ладно. Добавить ключевое слово - не великА беда. Гораздо сложнее приходится в том случае, когда чего-то вообще нет в стандарте, но есть в msvc. Я может и был не прав, что использовал эти возможности, но ведь эти возможности не случайно появились в msvc. msvc создавался не ради стандарта, а как рабочий инструмент огромной корпорации, а, значит, старался упрощать жизнь программистам в некоторых областях. Так, msvc поддерживает частичную специализацию функций. Да, в стандарте этого нет. Да, в большинстве случаев, можно обойтись перегрузкой. Но есть ситуации, где перегрузка не спасает и приходится городить кучу вспомогательных шаблонов, просто чтобы уложиться в стандарт. А msvc позволяет сделать красиво и аккуратно. Еще, из-за отсутствия __if_exist, мне добавилось много работы по сопровождению старого кода. Там где __if_exist обеспечивал мне функциональность по умолчанию, теперь нужно сообщать компилятору об этой функциональности явно, что не добавляет коду легкости. Ну да ладно. Хорошо, хоть разработчики gcc перенимают иногда хорошие вещи у msvc (например #pragma once).
Вобщем, работа потихоньку движется.
biohazard

hunspell - кошмар перфекциониста

hunspell - это библиотека проверки орфографии. Используется во многих крупных проектах. Из известных: mozilla firefox, google chrome, open office. Можно сказать, основная библиотека для проверки орфографии. Существует много словарей.
Когда я выбирал библиотеку для проверки орфографии в Isotoxin'а, особо много не думал. Самое популярное, да в таких проектах - конечно надо брать.

Сейчас я расскажу, что предстало моим глазам. Если вкратце - я очень расстроен. Такого унылого кода я давно не видел. Понятно, всё работает. Работает - не трогай. Но, хочется взять и всё переписать.
1. Библиотека не умеет загружать словари из буфера в памяти. Это, товарищи, просто п#$ец. Я это ограничение обошел, но, как говорится, не повторяйте это дома.
2. Библиотека не позволяет проверять на одном словаре сразу несколько слов, используя разные потоки. Можете себе представить, на дворе век многоядерных машин, а кто-то до сих пор пишет код, который не дружит с параллельностью. А проверка одного слова, кстати, не очень то быстрая.
3. Библиотека написана изначально но C, а позже ее частично переписали на C++. Вобщем самые худшие техники обоих языков переплелись воедино. Взгляните на этот код:

std::string tword(appnd);
tword.append(word + strip.size());
return mystrdup(tword.c_str());

Что мы тут видим? Создается std::string строка на стеке, к ней добавляется подстрока (word - это указатель на строку), а затем создается копия строки, которая возвращается. Я не знаю, видите ли вы тут п#$дец настолько отчетливо, насколько его вижу я... Просто поверьте - это говнокод. Особая, ядреная квинтэссенция говнокода, которую только можно написать на обоих языках.

У меня уже третью неделю чешутся руки переписать весь hunspell на c++ по человечески. Останавливают меня только два момента - это моя лень и необходимость последующего вливания обновлений вручную из оригинального репозитория.
biohazard

Попытка улучшить качество видео

Выпустил версию 0.3.424. В ней, среди прочего, реализовал свой собственный способ передачи видео. Как я уже писал, ядро передает все видеоданные в режиме lossy, т.е. с потерями. Я сделал передачу видео без потери. Алгоритм очень простой: кадр ставится в очередь на отправку, и пока весь кадр не будет передан другой стороне, все вновь поступающие кадры с камеры просто отбрасываются. Таким образом я получаю гарантированно целую картинку, но, возможно, с низким fps. Сначала отбрасывал неключевые кадры, т.е. новый кадр отправлялся на сжатие, и если кодек выдавал неключевой кадр, то этот кадр мог быть отброшен, если поступил новый кадр, а ключевой еще не был передан. Однако такая стратегия сразу приводила к порче картинки. То ли vp8 кодек очень чувствителен к потери неключевых кадров, то ли я чего-то в нем не докрутил, но выкидывать из очереди неключевые кадры без ущерба для качества нельзя. Тогда я просто стал выкидывать кадры до отправки их в кодек, а то что успело сжаться, отправлялось безусловно.
Результаты:
Во первых качество передачи видео заметно возросло. Картинка больше не рассыпается на цифровой шум при малейшей возможности. В локальной сети передача full-hd идет без проблем. Победа? Не совсем. Во всей красе всплыл баг toxcore, который частенько проявлял себя при передаче больших файлов: разрыв соединения. Увы, это болячка ядра все еще не исправлена. Видимо, скоро мне придется заняться этой проблемой. Другой момент - низкий fps хорош при передачи изображения с рабочего стола, а вот с камеры - это плохо. С камеры надо снижать битрейт, чтобы fps оставался высоким. Займусь этим вскоре.
Новый способ передачи видео работает только при соединениях Isotoxin-Isotoxin, что очевидно. В продвинутых настройках видеозвонков можно выключить это поведение и видео будет предаваться как и раньше, встроенными средствами toxcore. Там же, в расширенных настройках можно включить кодек vp9. Честно сказать, смысла в этом никакого. По качеству разницы почти не видно, зато vp9 оооочень медленно сжимает. Буквально мой 4-х ядерный i5 загружается на 80%, при том что vp8 на том же видеопотоке едва грузит на 3%. Не исключаю, что я что-то опять напутал в настройках кодека. Займусь этим позже.
Кстати, vp9 еще достаточно сырой кодек, несмотря на то, что гугл уже пилит vp10. Я словил неприятность в виде подвисания декодера. Ну то есть, в какой-то момент декодер vp9 просто натурально зависает. Немного покопавшись, я нашел причину. В процессе работы vp9 использует все доступные буфера кадров, коих он выделяет что-то порядка десятка (точнее смотреть лень) и в этот момент, из за бага в коде, указатель позиции чтения кадра остается в нулевом значении и кодек снова и снова пытается обработать один и тот же кадр и тем самым виснет. В своей сборке кодека я исправил этот баг. Хотел было сделать pull request с исправлением в основной репозиторий кодека, но, как оказалось, зеркало на гитхабе пул реквесты не принимает, а разбираться с тем, как сделать пул реквест в основной репозиторий, мне просто не хочется.
Вобщем, еще есть над чем работать в плане передачи видео. До скайпа пока не дотягиваем, увы.