LiteCoding

Заметки о программировании

Архив по тэгу ‘программирование’

Domination под микроскопом

без комментариев

В этой статье пойдет речь о видеосервере Domination. Не так давно была одна интересная задача, связанная с написанием клиента, способным принимать с него поток видеоданных. Было довольно интересно разбираться с ним, а по итогам этого исследования родилась мысль написать статью. Итак, приступим.
Читать далее »

Written by Дмитрий Воробьев

Январь 14th, 2013 at 06:21

libav: как хранится YUV420 в AVFrame

без комментариев

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

У меня появилась задача декодировать кадр из видеопотока и сохранить его в оперативной памяти в YUV 4:2:0 (PixelFormat.PIX_FMT_YUV420P, как он поименован в libav). И если вопрос декодирования решается довольно быстро и легко (тут есть очень неплохой учебник по написанию видеоплеера с использованием libav, а тут — обновленные примеры из этого учебника для последней версии библиотеки), то попытки разобраться, как данные хранятся в AVFrame, долгое время не давали результата.

Нас интересуют прежде всего поля AVFrame.data и AVFrame.linesize. Первое — массив указателей на участки памяти с данными, а второе — массив с длинами строки данных. Последнее нужно пояснить отдельно — памяти выделяется больше, чем нужно для хранения данных, т.к. она может использоваться кодеком для более эффективного кодирования/декодирования. Т.е. AVFrame.data содержит как полезные данные, так и мусор (в лучшем случае — лишние нулевые байты). При этом данные разделены по каналам: Y-компоненты хранятся в памяти, на которую указывает data[0], U- и V-компоненты — в памяти по data[1] и data[2] соответственно. В моем случае для кадра 704×288 AVFrame.linesize был следующим: {736, 368, 368, 0, 0, 0, 0, 0}.

С Y-каналом никаких проблем возникнуть не могло: там находились 288 (height) строк длиной по 704 (width) байта, и каждая строка была выровнена по границе 736 байт (AVFrame.linesize[0]). А вот попытки прочитать подобным образом U- и V-каналы приводили к выходу за пределы массива данных. Как оказалось, в data[1] и data[2] данные хранятся следующим образом: 144 (height / 2) строки длиной по 352 байта (width / 2), выровненные по границе 368 байт (AVFrame.linesize[1] и AVFrame.linesize[2]).

И, наконец, алгоритм чтения на псевдокоде:

AVFrame frame;
/*...*/
for(int i = 0; i < frame.height; i++) {
    readY(frame.data[0], i * frame.linesize[0], frame.width);	
}
		
for(int i = 0; i < frame.height / 2; i++) {
    readU(frame.data[1], i * frame.linesize[1], frame.width / 2);
    readV(frame.data[2], i * frame.linesize[2], frame.width / 2);
}

И в итоге получаем YUV 4:2:0 фрейм, записанный в непрерывный участок памяти.

Written by Дмитрий Воробьев

Август 3rd, 2012 at 11:22

Как бороться с INSTALL_PARSE_FAILED_NO_CERTIFICATES

без комментариев

Вот, предположим, собираете вы приложение с помощью ant, все прописано как надо, все ПО, участвующее в процессе сборки приложения последних версий, в т.ч. и JDK7. Все проходит успешно, на выходе получаете apk-файл, а приложение не устанавливается. При попытке установить через ADB появляется «информативное» сообщение INSTALL_PARSE_FAILED_NO_CERTIFICATES. Что делать? На самом деле, тут виноват именно JDK7, который по умолчанию использует SHA-256 вместо SHA-1 в утилите jarsigner. Решить эту проблему очень просто. Т.к. задание signjar в ant не поддерживает перегрузку алгоритма для генерации подписи, то вам придется установить JDK6 (вместе с JDK7 они отлично уживаются) и изменить значение переменной окружения JAVA_HOME на каталог bin установленного JDK6. После этого процесс сборки заработает как надо.

Written by Дмитрий Воробьев

Апрель 16th, 2012 at 14:54

Получение списка зависимостей классов в Java

без комментариев

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

Все уже изобретено. А то, что не изобретено, на самом деле изобретено и основательно позабыто. Поэтому я хочу обратить ваше внимание на CDA (Class Dependency Analyzer), инструмент статического анализа классов Java. Сразу огорчу сторонников open source, вы не сможете найти исходный код данного инструмента в открытом доступе. Зато он freeware’ный, т.е. по-настоящему бесплатный. Никакой рекламы, ограничений функциональности и прочих трюков, заставляющих купить полную (full, pro, ultimate) версию продукта. Его GUI построен с помощью JGoodies, поэтому особых красивостей ожидать не стоит. Но зачем нам молоток с уникальным дизайном, если нужно просто вбить гвоздь? Главное, чтобы его рукоятка удобно лежала в руке, его баланс не напрягал, и чтобы он не рассыпался от первого серьезного удара. CDA именно такой инструмент — простой и надежный. У него есть единственный недостаток — не «понимает» рефлексию, но это беда всех статических анализаторов. В остальном этот инструмент полностью оправдывает ожидания.

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

Итак, если у вас есть подобная задача, попробуйте CDA для ее решения. Удачи!

Written by Дмитрий Воробьев

Апрель 16th, 2012 at 13:15

Нестандартный ListView своими руками

без комментариев

Честно говоря, я немного покривил душой, когда придумывал название статьи. Речь сейчас пойдет не столько о нестандартном списке, сколько о нестандартно выглядящих элементах списка. Сам по себе Android API предоставляет очень удобный инструмент для создания списков с нестандартными элементами. Иногда этих возможностей достаточно, тогда с помощью класса SimpleAdapter и несложных манипуляций можно получить требуемый результат (подробности можно посмотреть, например, в одной из статей блога Sai Geetha). Но когда требуется изменить отображение элемента в соответствии с состоянием объекта, приходится садиться за собственную реализацию.

И вот, появляется задача изменить цвет фона элементов на четных позициях, отображать те или иные вложенные элементы в зависимости от флагов и значений. Добро пожаловать в мир настоящих списков с нестандартными элементами.
Читать далее »

Written by Дмитрий Воробьев

Январь 14th, 2012 at 15:11

repo, Python и Cygwin — скачиваем исходники Android на машину с Windows

без комментариев

Если возникла задача скачать все дерево репозиториев Android, без утилиты repo не обойтись. Что это такое, и как ей пользоваться, можно прочитать здесь. Но основная проблема заключается, что после в cygwin’е она не запускается, вываливаясь с ошибкой конвертации UnicodeDecodeError и текстом «‘ascii’ codec can’t decode…» в функции _SetupGnuPG(). С этим бороться довольно просто: открываем repo в текстовом редакторе, находим серию импортов, и копируем после последнего следующий код.

import locale
locale.setlocale(locale.LC_ALL,"")
reload(sys)
sys.setdefaultencoding('utf-8')

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

Written by Дмитрий Воробьев

Июль 11th, 2011 at 19:10

Развертывание заранее созданной БД в приложении для Android

без комментариев

Как я уже неоднократно тут писал, задачи бывают разные. В этот раз мы будем говорить о случае, когда приложение поставляется с контентом «на борту». Согласитесь что, неразумно заставлять пользователя дожидаться окончания загрузки каталога книг, когда можно включить его в приложение, а затем при необходимости накатить обновления. Итак, что же нужно сделать, если перед вами возникла задача развернуть базу данных из ресурсов приложения на клиентском устройстве.
Читать далее »

Written by Дмитрий Воробьев

Июнь 21st, 2011 at 00:20

Использование aParse 2.0 для генерации парсера по ABNF-грамматике

без комментариев

Когда возникает задача что-то быстро распарсить, как правило, берется либо уже готовый парсер, либо пишется что-то свое, которое работает только с исходными данными определенного вида и постоянно требует контроля и ручной корректировки. Но есть еще один вариант — сгенерировать парсер по описанию грамматики входного языка и дальше иметь дело только с его лексическими единицами. Очень часто для таких целей используется Yacc или Bison. Однако, в этой статье речь пойдет о маленькой свободно распространяемой (freeware) утилите aParse.
Читать далее »

Written by Дмитрий Воробьев

Май 31st, 2011 at 15:41

Ant и Eclipse против присутствия .svn в bin

без комментариев

Присутствие файлов Subversion в каталоге, содержащем скомпилированные классы, очень раздражает. А если у вас установлен TortoiseSVN, то это откровенно бесит. Тем не менее, избавиться от нежелательных каталогом .svn весьма несложно. В этом поможет простой ant-скрипт.

<?xml version="1.0" encoding="UTF-8"?>
<project default="purgesvn">
	<target name="purgesvn">
		<echo>PurgeSVN ant script:</echo>
		<delete includeEmptyDirs="true" verbose="true">
			<fileset dir="bin" defaultexcludes="false">
				<include name="**/.svn/**" />
			</fileset>
		</delete>
	</target>
</project>

Его необходимо добавить в проект, создать ему конфигурацию запуска по умолчанию (это проще всего делается запуском самого скрипта), а затем в Project > Configuration > Builders импортировать созданную конфигурацию запуска и поместить ее сразу после Java Builder.

Written by Дмитрий Воробьев

Апрель 13th, 2011 at 18:29

FDB — JDBC с человеческим лицом

5 комментариев

Тот, кто имел дело с JDBC, наверное, согласится, что работать с этим API не так уж и просто. Поэтому его изучение, как правило, сводится к постижению азов и поиску решения, которое возьмет на себя большую часть рутинной работы. Есть ORM-решения, которые позволяют забыть про SQL, и работать непосредственно с сущностями системы. Яркий пример такого фреймворка — hibernate. Есть решения, берущие на себя только заботу об открытии/закрытии соединений, управлении ресурсами, например, jdbcTemplates.

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

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

Использовать эту библиотеку просто:
Читать далее »

Written by Дмитрий Воробьев

Март 3rd, 2011 at 14:10