repstosw 18 17 апреля, 2022 Опубликовано 17 апреля, 2022 · Жалоба 13 hours ago, mantech said: Зачем это вообще? Разрядность и тип, ИМХО должна выставляться только в ините памяти и больше нигде... Согласен. Но не я делал этот движок, поэтому вопрос не по адресу. 13 hours ago, mantech said: Ну если это не для MJPEG, то нафига вообще лезть в дебри этих корок, которые абсолютно недокументированы... Разве, что только ради спортивного интереса. Еще и с учетом того, что эти корки конвертируют только в тейловые форматы, с которыми у вас, судя по пред. посту, как то не очень... Вот именно для спортивного интереса, не более. А YUV в RGB можно и софтово перегнать, в своём софтовом плеере видео MJPEG так и делал. 13 hours ago, mantech said: Скорее всего из-за трансляции виртуальных адресов. Так судя из описания регистры требуют физический, а не виртуальный адрес. Значит начало DDR будет по адресу 0x40000000, что не вяжется с тем куском кода в исходнике. Просмотрел некоторые Allwinner'ы - у них у всех старт DDR с одного и того же адреса. Нет таких камней Allwinner с внешней памятью, лежащей по адресам ниже 256 МБ. Разве что можно подсунуть SRAM, адреса которой лежат от 0, но её катастрофически мало на нужды JPEG (если картинка больших размеров). Глянул JPEG-кодек у STM32 - там всё более прозрачнее и понятнее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ozelot 7 17 апреля, 2022 Опубликовано 17 апреля, 2022 · Жалоба Игрался с аппаратным кодированием/декодированием jpeg на F1C100S. Все заработало. Были нюансы. Основной: в sram нужно разрешить аппаратное использование памяти соответствующими модулями (SRAM Controller Register Guide). typedef struct { __IO u32 CTRL[16]; // 0x00 SRAM Control registers } SYS_T; #define SYS ((SYS_T*)0x01C00000) ....... SYS->CTRL[0] &= 0x80000000; SYS->CTRL[0] |= 0x7fffffff; SYS->CTRL[1] &= 0xefffffff; Кстати, если у кого-то есть инфа по аппаратному модулю деинтерлейса в F1C100S, буду очень признателен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 17 апреля, 2022 Опубликовано 17 апреля, 2022 · Жалоба 2 hours ago, Ozelot said: Игрался с аппаратным кодированием/декодированием jpeg на F1C100S. Все заработало. Были нюансы. Основной: в sram нужно разрешить аппаратное использование памяти соответствующими модулями (SRAM Controller Register Guide). Спасибо, попробую разобраться. Вы можете дать ссылку на гитхаб какой именно пример с кодированием-декодированием JPEG у вас заработал? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 20 апреля, 2022 Опубликовано 20 апреля, 2022 (изменено) · Жалоба Удалось запустить "Кедр" в режиме кодирования JPEG на доске с Allwinner A13. Было несколько граблей, одна из них связана с безалаберным оформлением даташита на A13, другая - с безалаберным написанием кода, взятого с github. Первая грабля - не расписаны биты делителя для PLL4 (VE_PLL). В V3s расписано, в исходниках Линукса этот делитель установлен. Если 16-бит оставить равным 0, то "Кедр" будет работать неправильно: каждый раз длина и содержимое сжатого кадра будут разными. За такие грабли в документации, я считаю, нужно руки отрывать! Вторая грабля - здесь при создании бинарного файла нужно было написать "wb", а не "w". Иначе jpeg-файл выходит битым. Заметил не сразу, потратил на это несколько часов, прежде чем понял, что грешит не кодек, а запись данных в файл. В целом всё работает. Правда, этот кодек не умеет создавать заголовки JPEG и создавать вспомогательные таблицы (Хаффман?). Приходится использовать тяжеловесную библиотеку LIBJPEG. В принципе, для картинок фиксированного размера, заголовки можно просчитать на ПК заранее, а на Allwinner уже использовать готовый: дописывать сжатый буфер данных. On 4/17/2022 at 6:04 PM, Ozelot said: Были нюансы. Основной: в sram нужно разрешить аппаратное использование памяти соответствующими модулями (SRAM Controller Register Guide). В случае A13 этот регион по умолчанию разрешён для "Кедра" - эти манипуляции не нужны. On 4/17/2022 at 10:29 AM, repstosw said: On 4/16/2022 at 9:06 PM, mantech said: Зачем это вообще? Разрядность и тип, ИМХО должна выставляться только в ините памяти и больше нигде... Согласен. Но не я делал этот движок, поэтому вопрос не по адресу. Как оказалось, кодеку пофиг на это: указывал 0x3 - DDR3 32 bit, 0x2 - DDR3 16 bit - оба варианта конфигурации работают. У меня DDR3 16 бит. И самое важное - без нужных гейтов и клоков "Кедр "не заработает. Нужно было сделать это: #define PLL4_CFG_REG (*(IO u32*)0x01C20018) #define AHB_GATING_REG1 (*(IO u32*)0x01C20064) #define VE_CFG_REG (*(IO u32*)0x01C2013C) #define DRAM_SCLK_CFG_REG (*(IO u32*)0x01C20100) PLL4_CFG_REG|=(1UL<<31); //enable PLL4 AHB_GATING_REG1|=1; //enable ahb for VE VE_CFG_REG|=(1UL<<31)|(1<<16)|1; //clock on PLL4 and disable reset => 1<<16 - обязательно! DRAM_SCLK_CFG_REG|=1; //enable DRAM for VE Изменено 20 апреля, 2022 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 20 апреля, 2022 Опубликовано 20 апреля, 2022 (изменено) · Жалоба 3 часа назад, repstosw сказал: Правда, этот кодек не умеет создавать заголовки JPEG Дак вроде аппаратные корки этим и не занимались никогда, что кодеры, что декодеры, они работали только с чистыми данными пакетов. ЗЫ. Честно говоря, эти корки мне интересны только с т.з. декодирования видео... Изменено 20 апреля, 2022 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ozelot 7 20 апреля, 2022 Опубликовано 20 апреля, 2022 · Жалоба Вот простой проект jpeg-декодера для f1c100s. Можно запускать на Lichee Nano. Аппаратное декодирование занимает 3-4mS, потом программное преобразование YUV->RGB 60mS (это можно сделать быстрее аппаратно). Исходник: jpgdec.7z Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 20 апреля, 2022 Опубликовано 20 апреля, 2022 · Жалоба С декодером JPEG тоже разобрался - ничего сложного: 1 hour ago, mantech said: Дак вроде аппаратные корки этим и не занимались никогда, что кодеры, что декодеры, они работали только с чистыми данными пакетов. ЗЫ. Честно говоря, эти корки мне интересны только с т.з. декодирования видео... Видео-формат MJPEG: каждый кадр - JPEG. Моя камера как раз в нём выдаёт видео. Понятно дело, что сжатие хуже, чем у H264. "Кедр" может и H264 кодировать/декодировать. 30 minutes ago, Ozelot said: Вот простой проект jpeg-декодера для f1c100s. Можно запускать на Lichee Nano. Аппаратное декодирование занимает 3-4mS, потом программное преобразование YUV->RGB 60mS (это можно сделать быстрее аппаратно). Спасибо, глянем! В моём варианте тоже идёт программное преобразование YUV в RGB: void output_ppm(struct jpeg_t *jpeg, uint8_t *luma_buffer, uint8_t *chroma_buffer,u32 x0,u32 y0) { int x, y, i = 0; for (y = 0; y < jpeg->height; y++) { for (x = 0; x < jpeg->width; x++) { // reordering and colorspace conversion should be done by Display Engine Frontend (DEFE) int cy = y / jpeg->comp[0].samp_v; float Y = *((uint8_t *)(luma_buffer + (x / 32) * 1024 + (x % 32) + (( y % 32) * 32) + (( y / 32) * (((jpeg->width + 31) / 32) * 1024)))) ; float Cb = *((uint8_t *)(chroma_buffer + (x / 32) * 1024 + ((x % 32) / 2 * 2 ) + ((cy % 32) * 32) + ((cy / 32) * (((jpeg->width + 31) / 32) * 1024)))) - 128.0; float Cr = *((uint8_t *)(chroma_buffer + (x / 32) * 1024 + ((x % 32) / 2 * 2 + 1) + ((cy % 32) * 32) + ((cy / 32) * (((jpeg->width + 31) / 32) * 1024)))) - 128.0; float R = Y + 1.402 * Cr; float G = Y - 0.344136 * Cb - 0.714136 * Cr; float B = Y + 1.772 * Cb; if (R > 255.0) R = 255.0; else if (R < 0.0) R = 0.0; if (G > 255.0) G = 255.0; else if (G < 0.0) G = 0.0; if (B > 255.0) B = 255.0; else if (B < 0.0) B = 0.0; *(u16*)(BG_LFB_BASE+(((400*(y+y0))+(x+x0))*2))=((((uint16_t)R)>>3)<<11)|((((uint16_t)G)>>2)<<5)|(((uint16_t)B)>>3); //RGB 5:6:5 //fprintf(file, "%3u %3u %3u %c", (uint8_t)R, (uint8_t)G, (uint8_t)B, (++i % 5) ? ' ' : '\n'); } } } За основу брал вот этот проект: https://github.com/mosterta/libcedarjpeg Очистил его от Линухоедной шелухи... Декодеру на это оказалось фиолетово: он игнорирует 4 старшие бита адреса - можно задать адрес двумя способами: //так: ((u32)input_buffer) | 0x70000000 //или так: #define VE_MPEG_VLD_ADDR_VAL(x) (((x) & 0x0ffffff0) | ((x) >> 28) | (0x7 << 28)) VE_MPEG_VLD_ADDR_VAL((u32)input_buffer) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 20 апреля, 2022 Опубликовано 20 апреля, 2022 · Жалоба 2 часа назад, repstosw сказал: "Кедр" может и H264 кодировать/декодировать. Это уже интереснее)) Если получится - отпишитесь... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 21 апреля, 2022 Опубликовано 21 апреля, 2022 (изменено) · Жалоба 14 hours ago, mantech said: Это уже интереснее)) Если получится - отпишитесь... С h264 я знаком давно, делал софтовый плеер для его воспроизведения. Получится ли запустить "Кедр" в режиме декодирования h264 - пока неизвестно. Обнаружил ещё одну интересную деталь с декодированием JPEG. Сделал видео в формате MJPEG из 900 фреймов (которые представляют собой обычные JPEG, склеенные между собой). При воспроизведении получившегося MJPEG на ПК всё идёт нормально. Но если этот MJPEG воспроизводится на "Кедр" A13, то 5 фреймов декодируются с ошибкой (бит 1 в регистре статуса =1) и выглядят как артефакт в виде вспышки. Выходит, что "Кедр" ещё не каждый JPEG понимает, нужны какие-то определённые условия при кодировании. Если создавать JPEG с помощью программы irfanview, то из 900 фреймов - постоянно одни и те же 5 оказываются с ошибкой. Если же создавать с помощью ffmpeg, то каждый кадр страшно артeфачит - в квадратах и раскрашен не теми цветами. Цепочка создания MJPEG из видео: rem исходное видео пилится на PNG размером 128x128 ffmpeg -i video.AVI -s 128x128 -r 30 -y frame%%03d.png rem PNG преобразуем в JPEG с качеством 90% for /r %%i in (*.png ) do ( C:\IrfanViewPortable\IrfanViewPortable.exe %%i /jpgq=90 /convert=%%~ni.jpg ) rem получаем список всех JPG файлов dir/a-d/b *.jpg > join.txt rem склеиваем все JPG в один по-порядку. Итоговый файл MJPEG: result.bin @copy /y nul result.bin @for /f "tokens=*" %%f in (join.txt) do copy /b result.bin +"%%f" result.bin pause Интересно, какие условия кодирования JPEG необходимы для безошибочного декодирования "Кедром"? Изменено 21 апреля, 2022 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 21 апреля, 2022 Опубликовано 21 апреля, 2022 · Жалоба 5 часов назад, repstosw сказал: Обнаружил ещё одну интересную деталь с декодированием JPEG. Ну это как-бы не секрет, сколько раз замечал, что в фильмах mpeg4, например, в зависимости, какой декодер используется, тоже бывают артефакты. 5 часов назад, repstosw сказал: делал софтовый плеер для его воспроизведения Каково его быстродействие? Например на гигагерцовом А7 какое разрешение может тянуть без заметных тормозов? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 21 апреля, 2022 Опубликовано 21 апреля, 2022 (изменено) · Жалоба 2 hours ago, mantech said: Каково его быстродействие? Например на гигагерцовом А7 какое разрешение может тянуть без заметных тормозов? Я это делал очень давно: на STM32H743 и TMS320C6745. У первого 400 МГц, у второго 456 МГц. Кадр 320x240. Тащил 25-30 FPS. 8 hours ago, repstosw said: Обнаружил ещё одну интересную деталь с декодированием JPEG. Сделал видео в формате MJPEG из 900 фреймов (которые представляют собой обычные JPEG, склеенные между собой). При воспроизведении получившегося MJPEG на ПК всё идёт нормально. Но если этот MJPEG воспроизводится на "Кедр" A13, то 5 фреймов декодируются с ошибкой (бит 1 в регистре статуса =1) и выглядят как артефакт в виде вспышки. Выходит, что "Кедр" ещё не каждый JPEG понимает, нужны какие-то определённые условия при кодировании. Нашёл причину этого поведения. Чтобы не было "битых" декодирований, нужно каждый раз перед декодированием, сбрасывать декодер: MACC_VE_RESET=0x1; //reset on MACC_VE_RESET=0x0; //reset off decode_jpeg(&jpeg); https://linux-sunxi.org/VE_Register_guide#MACC_VE_RESET Сбрасывать именно через этот регистр, остальное не приводит к положительному результату. В этом случае без ошибок декодируются все кадры JPEG. P.S. Попутно обнаружил, что повторное декодирование фрейма, завершившееся ошибкой, также исправляет ситуацию. Что привело меня к выводу о том, что желателен сброс перед каждым декодированием. P.P.S. Из граблей программы ещё обнаружил вот здесь: void set_huffman_tables(struct jpeg_t *jpeg) { uint32_t buffer[512]; ... В случае если стека маловато (мы пишем eGON.BT0 boot0 без загрузчика), программа не пойдёт. Увеличить стек или сделать массив глобальным(вынести перед функцией) или статическим: void set_huffman_tables(struct jpeg_t *jpeg) { static uint32_t buffer[512]; Изменено 21 апреля, 2022 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 21 апреля, 2022 Опубликовано 21 апреля, 2022 (изменено) · Жалоба 1 час назад, repstosw сказал: uint32_t buffer[512]; Ну по 2кило внутри функции стараюсь никогда не объявлять - стека жалко, да и непредсказуемость переполнения, если таких функций не одна... 1 час назад, repstosw сказал: нужно каждый раз перед декодированием, сбрасывать декодер: А сколько по времени идет сброс? И интересно, в случае видеопотока mpeg, тут сбросами не отделаешься... Предположу, что сброс - это костыль, скорее всего какой-то регистр не очищается в программе после завершения декодирования. Изменено 21 апреля, 2022 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 21 апреля, 2022 Опубликовано 21 апреля, 2022 (изменено) · Жалоба 43 minutes ago, mantech said: А сколько по времени идет сброс? И интересно, в случае видеопотока mpeg, тут сбросами не отделаешься... Предположу, что сброс - это костыль, скорее всего какой-то регистр не очищается в программе после завершения декодирования. Совсем ничего. Две записи в регистр. Без дополнительных времён ожидания между сбросом и отпусканием. Конверсия кадра YUV в RGB с детайлизацией (спрямлением в видеопамяти) занимает гораздо большее время. Это конечно может сделать и видео-система, но кто об этом расскажет? Очевидно да, костыль... Просто никто блок-диаграммы и состояния не расписывает, в частности, как циклически декодировать фреймы. Каждый изголяется по мере своих возможностей. 43 minutes ago, mantech said: Ну по 2кило внутри функции стараюсь никогда не объявлять - стека жалко, да и непредсказуемость переполнения, если таких функций не одна... Это вышеупомянутый сорец с гитхаба. У Ozelot в исходнике также сделано :) Очевидно, что если это запускается под Линуксом или другой осью или со своим загрузчиком, то это вообще не проблема. Делаю стек пару мегабайт, если приложение во внешней памяти. P.S. Нашёл что у A13 "Кедр" идёт на номинальных 180 МГц. А у меня стоял дефолтный PLL4 384 МГц + делитель на 2 (тот самый недокументированный бит 16) = 192 МГц, что немного завышено. Установил тактовую как положено: PLL4_CFG_REG=(1UL<<31)|(1<<16)|(15<<8)|(0<<4)|0; //set 180 MHz (for A13) Clock VE and Enable PLL4 delay_ms(1000); //увы, бита готовности PLL в том регистре нет! :( VE_CFG_REG|=(1UL<<31)|1; //clock on PLL4 and disable reset Теперь работает и без того недокументированного бита... P.S. Теперь надо попробовать всё это перетащить на V3s. Интересно, на какой тактовой частоте у него работает "Кедр" ? Изменено 21 апреля, 2022 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 49 21 апреля, 2022 Опубликовано 21 апреля, 2022 · Жалоба 1 час назад, repstosw сказал: Интересно, на какой тактовой частоте у него работает "Кедр" ? Думаю не ниже, чем в А13. 1 час назад, repstosw сказал: Очевидно, что если это запускается под Линуксом или другой осью или со своим загрузчиком, то это вообще не проблема. Так-то да, но вот теперь вопрос - почему под подобными осями программы становятся в разы толще и памяти требуют вагон... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 22 апреля, 2022 Опубликовано 22 апреля, 2022 · Жалоба 19 hours ago, mantech said: Так-то да, но вот теперь вопрос - почему под подобными осями программы становятся в разы толще и памяти требуют вагон... Об этом можно много говорить... Современная культура программирования - превращать всё в неповоротливые фрейм-ворки... Размен качества на количество... Ради бабла. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться