Перейти к содержанию
    

Allwinner T113-s3 уделал HiFi4 DSP. Смеяться или плакать?

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 - там всё более прозрачнее и понятнее.:biggrin:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Игрался с аппаратным кодированием/декодированием 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, буду очень признателен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Ozelot said:

Игрался с аппаратным кодированием/декодированием jpeg на F1C100S. Все заработало. Были нюансы. Основной: в sram нужно разрешить аппаратное использование памяти соответствующими модулями (SRAM Controller Register Guide).

Спасибо, попробую разобраться.

Вы можете дать ссылку на гитхаб какой именно пример с кодированием-декодированием JPEG у вас заработал?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удалось запустить "Кедр" в режиме кодирования JPEG на доске с Allwinner A13. :sun_bespectacled:

Было несколько граблей, одна из них связана с безалаберным оформлением даташита на A13, другая - с безалаберным написанием кода, взятого с github.

 

Первая грабля - не расписаны биты делителя для PLL4 (VE_PLL). В V3s расписано, в исходниках Линукса этот делитель установлен.  Если 16-бит оставить равным 0, то "Кедр" будет работать неправильно: каждый раз длина и содержимое сжатого кадра будут  разными.

 

За такие грабли в документации, я считаю, нужно руки отрывать!

 

1.thumb.jpg.2dc7519800ba99cfc8e04733aa0ddbc6.jpg

 

Вторая грабля - здесь при создании бинарного файла нужно было написать "wb", а не "w".  Иначе jpeg-файл выходит битым. Заметил не сразу, потратил на это несколько часов, прежде чем понял, что грешит не кодек, а запись данных в файл.

 

2.jpg.a6d7e6bf0028c2609667a0acf3d0cf6b.jpg 

 

В целом всё работает. Правда, этот кодек не умеет создавать заголовки 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

 

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, repstosw сказал:

Правда, этот кодек не умеет создавать заголовки JPEG

Дак вроде аппаратные корки этим и не занимались никогда, что кодеры, что декодеры, они работали только с чистыми данными пакетов.

ЗЫ. Честно говоря, эти корки мне интересны только с т.з. декодирования видео...

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот простой проект jpeg-декодера для f1c100s. Можно запускать на Lichee Nano. Аппаратное декодирование занимает 3-4mS, потом программное преобразование YUV->RGB 60mS (это можно сделать  быстрее аппаратно).

Исходник: jpgdec.7z

 

flower.thumb.jpg.0dbdb552c5b4f37124509c2cf94d1a8e.jpg

girl.thumb.jpg.647555911e1dc1806028b14772349eea.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С декодером 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)

Screenshot_2022-04-16 VE Register guide - linux-sunxi org.png

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, repstosw сказал:

"Кедр" может и H264 кодировать/декодировать.

Это уже интереснее))  Если получится - отпишитесь...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 необходимы для безошибочного декодирования "Кедром"?

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, repstosw сказал:

Обнаружил ещё одну интересную деталь с декодированием JPEG.

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

5 часов назад, repstosw сказал:

делал софтовый плеер для его воспроизведения

Каково его быстродействие? Например на гигагерцовом А7 какое разрешение может тянуть без заметных тормозов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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];

 

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, repstosw сказал:

uint32_t buffer[512];

Ну по 2кило внутри функции стараюсь никогда не объявлять - стека жалко, да и непредсказуемость переполнения, если таких функций не одна...

1 час назад, repstosw сказал:

нужно каждый раз перед декодированием, сбрасывать декодер:

А сколько по времени идет сброс? И интересно, в случае видеопотока mpeg, тут сбросами не отделаешься...

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

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

43 minutes ago, mantech said:

А сколько по времени идет сброс? И интересно, в случае видеопотока mpeg, тут сбросами не отделаешься...

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

 

Совсем ничего. Две записи в регистр. Без дополнительных времён ожидания между сбросом и отпусканием. 

Конверсия кадра YUV в RGB с детайлизацией (спрямлением в видеопамяти) занимает гораздо большее время.

Это конечно может сделать и видео-система, но кто об этом расскажет? :biggrin:

 

Очевидно да, костыль...    Просто никто блок-диаграммы и состояния не расписывает, в частности, как циклически декодировать фреймы. Каждый изголяется по мере своих возможностей.

 

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.

Интересно, на какой тактовой частоте у него работает "Кедр" ?

Изменено пользователем repstosw

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, repstosw сказал:

Интересно, на какой тактовой частоте у него работает "Кедр" ?

Думаю не ниже, чем в А13.

1 час назад, repstosw сказал:

Очевидно, что если это запускается под Линуксом или другой осью или со своим загрузчиком, то это вообще не проблема.

Так-то да, но вот теперь вопрос - почему под подобными осями программы становятся в разы толще и памяти требуют вагон...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 hours ago, mantech said:

Так-то да, но вот теперь вопрос - почему под подобными осями программы становятся в разы толще и памяти требуют вагон...

Об этом можно много говорить... Современная культура программирования - превращать всё в неповоротливые фрейм-ворки...  Размен качества на количество... Ради бабла.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...