LiteCoding

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

Архив за Август, 2012

USB CDC ACM

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

Просматривая поисковые запросы, увидел, что немало посетителей приходят сюда за CDC (Communications Device Class) ACM (Abstract Control Model). Очень странно, учитывая, что я об этом никогда в этом блоге не писал. Тем не менее, ответ есть. Описание того, что это такое, а также ссылку на документацию (внизу страницы) можно найти тут.

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

Август 9th, 2012 at 00:31

Posted in Заметки

Tagged with , ,

Августовские обновления

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

Дорогие (не)многочисленные читатели этого блога,

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

1. Andor’s Trail Editor
Пару месяцев назад написал редактор сэйвов для Andor’s Trail и сегодня выложил первую альфу, которая все это время пылилась у меня на винчестере. Этот редактор пока может и умеет не так уж и много: читать, писать и редактировать количество уже имеющегося в инвентаре предмета. Но это только начало. Вся беда в том, что рисовать я не умею совсем, поэтому если у вас есть желание помочь этому опенсорсному проекту, то я буду рад скетчам GUI, иконкам для классов предметов и т.д. Естественно, каждый соавтор будет упомянут на странице проекта и в разделе «О приложении» (когда он появится).
Скачать apk и исходные коды можно с google code.

2. Smali2Java
Вернулся к своему долгострою, который «подвис» из-за возникших проблем с алгоритмизацией казалось бы простых действий. На данном этапе (pre-Alpha) он уверенно разбирает шапку smali-класса, импорты, поля и прототипы методов. Надеюсь, в ближайшем будущем он уже сможет осилить восстановление конструкторов и геттеров/сеттеров. Этому проекту также требуется помощь: ссылки на описание работы алгоритмов восстановления исходного кода, советы, патчи, запросы новых и баг-репорты по заявленным функциям.

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

Ваш блогмастер LiteCoding.

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

Август 8th, 2012 at 14:44

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