Внимание! Перед тем как создавать тему на форуме, воспользуйтесь поиском! Пользователь создавший тему, которая уже была, будет немедленно забанен! Читайте правила названия тем. Пользователи создавшие тему с непонятными заголовками, к примеру: "Помогите, Схема, Резистор, Хелп и т.п." также будут заблокированны навсегда. Пользователь создавший тему не по разделу форума будет немедленно забанен! Уважайте форум, и вас также будут уважать!
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Статистика программы по куче:
CODE
Total Bytes: 245264
Размер потребляемой кучи (heap) зависит от размера кадра и опций декодирования.
Видно, что данная версия декодера H264 при разрешении 160x128 не сможет работать на микроконтролллере STM32F407, потому что недостаточно оперативной памяти - есть два фрагментированных куска: 128 + 64 кБ. Проверил на практике: при переполнении кучи память не выделяется и возвращает NULL.
Дополнительно, декодер хочет 4 кБ стека, при 3 кБ программа уже аварийно завершается.
Полная статистика по куче аттаче:
Это сообщение отредактировал Gospodin_Riba - Jan 16 2018, 01:14 PM
;------------------------------------ HEAP 128 KB maximum as possible !!! Heap_Mem EQU 0x20000000 Heap_Size EQU 0x00020000 __heap_base EQU Heap_Mem __heap_limit EQU Heap_Mem+Heap_Size-4 ;------------------------------------
Ну и сегмент данных начинается с 0x10001000 и имеет размер 60 кБ ровно.
Ну и сорцы + проект работающего декодера H264 + показ кадров. Работает довольно быстро. К плате STM32F4-Discovery нужно подцепить дисплей к FSMC и SD-карту к SDIO.
SD-карта отформатирована FAT32, нужно залить на неё файл видео с названием "48.264"
Всё есть в приложенном архиве ниже (там же и прошивка в папке obj/led.hex).
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Вот такой вот кадр
Для разрешения 160x128 на работу декодера H264 -надо от 240 кБ оперативной памяти непрерывным куском... Для STM32F407 только вариант с внешней SRAM по FSMC совместно с дисплеем...
Это сообщение отредактировал Gospodin_Riba - Jan 16 2018, 01:28 PM
Присоединённое изображение (Нажмите для увеличения)
--------------------
По всем вопросам пишите на почту: repstosw2018 [собака] gmail [точка] com Энтузиазм заканчивается, когда начинается Кризис. Рождается Капитализм :)
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE (ведущий специалист @ Jan 15 2018, 05:33 PM)
С топикстартером контакт не удалось установить (странно, как можно жить без почтового ящика). Вот ссыль, там проект, на 407ом разжимают h264, там же если глубже полазить найдутся программные порты на стм32 множества проигрывателей (APE FLAC OGG MP3). Дерзайте.
Группа: Автор
Сообщений: 2484
Пользователь №: 144
Регистрация: 26-April 05
Место жительства: г. Салават
рыба мне то за что, я тут так сказать просто с боку на подтанцовке ))) я даже в среде работать не умею с этими стм, максимум что я могу это турбо паскаль под дос или пик бейсик, в микростудии плюс ,ну еще немного ругательной ардуиной играюсь, стм мне пока что не по зубам, могу только повторять проекты, вот если бы ты снял видео урок как установить и настроить среду или даже несколько примеров работы в среде и с демо бордами на стм, вот тогда цены бы тебе небыло, на русском языке толковых примеров не видел разве что мп3 плеер в журнале хакер. У Макса куча сорцев не реализованных, времени нет, работа семья ипотека и много других слов отражающих действительность, я тут тоже теряюсь месяцев по 3 в поисках зароботка, да у меня и специфика другая я больше по запаять и разработать в железе нежели софт писать ..... короче на примере своего проекта поснимай видео прям с экрана ну и голос машинный вставь, как сделать машинный голос ты лучше меня знаешь ,а где твои уроки разместить найдем. В этом случае ты найдешь единомышленников не только в таких как я мечтателях но и среди профессионалов, да и просто это поможет многим начать понимать старшие 32 разрядные контроллеры, я вот вроде понимаю на уровне железа поверхностно как оно работает но сталкнусь с ошибками которые за частую кривыми библиотеками вызванны или с ошибками с неправильно назначенными переменными и буду долго биться головой в стену, а на старте это довольно частые ошибки у новичков.
Это сообщение отредактировал intel - Jan 16 2018, 04:39 PM
--------------------
Если радиоэлектроника наркотик , то я наркоман со стажем!!!
С кучей там просто решено. Китаец написал "свою" работу с памятью. Я пользовал ее уже на своем плеере разжимая флак. FLAC очень прожорлив до памяти,а у стм32л476 всего 128кб оперативы (может и меньше, не суть). Так вот суть в том - что китаец делает массив типа char mass[65535*2] а потом скармливает его своей функе выделения кучи. Только потом весь проект работает строго на этой функе (выпросил памяти - поработал - отдал назад). Благодаря этому можно немного "обмануть" систему.
QUOTE (ведущий специалист @ Jan 16 2018, 10:47 PM)
С кучей там просто решено. Китаец написал "свою" работу с памятью. Я пользовал ее уже на своем плеере разжимая флак. FLAC очень прожорлив до памяти,а у стм32л476 всего 128кб оперативы (может и меньше, не суть). Так вот суть в том - что китаец делает массив типа char mass[65535*2] а потом скармливает его своей функе выделения кучи. Только потом весь проект работает строго на этой функе (выпросил памяти - поработал - отдал назад). Благодаря этому можно немного "обмануть" систему.
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE (ведущий специалист @ Jan 16 2018, 06:47 PM)
С кучей там просто решено. Китаец написал "свою" работу с памятью. Я пользовал ее уже на своем плеере разжимая флак. FLAC очень прожорлив до памяти,а у стм32л476 всего 128кб оперативы (может и меньше, не суть). Так вот суть в том - что китаец делает массив типа char mass[65535*2] а потом скармливает его своей функе выделения кучи. Только потом весь проект работает строго на этой функе (выпросил памяти - поработал - отдал назад). Благодаря этому можно немного "обмануть" систему.
Китаец просто не в курсе, что в стартапе Кейла нужно задавать значения системных переменных стека и кучи(что собственно и видно из его ассемблерного стартапа *.s).
Покурив сорцы, стало быть понятно как он выкрутился.
1)
CODE
tables.h
Здесь заранее просчитанные данные, которые хранятся во Flash. В референсном коде выделялась память из кучи и в неё просчитывались данные. Это высвободило 45 кБ кучи... сразу!
Здесь китаец выделил 10 кБ на один пожатый фрейм видео. В референсном коде был огроменный calloc(100000,... Поэтому всегда есть вероятность нарваться на фрейм больше 10 кБ и завешать контроллер. Нужно выставлять определённые опции кодирования, чтобы не превышать 10кб на буфер.
static uint8_t *decode_nal(H264Context *h, uint8_t *src, int *dst_length, int *consumed, int length) { ... if(!h->s.mybuf)h->s.mybuf=mymalloc(SRAMIN1,sizeof(Publicbuf)); ...
Китаец крутится как уж на сковородке, в разных местах кода он выделяет память то изучастка SRAM1, то из участка SRAM2. Этим преодолевается проблемы, связанные с выделением кучи во фрагментированных адресных пространствах STM32F4xx (128кБ с адреса 0x20000000 и 64 кБ с адреса 0x10000000 ). Был бы MMU как в ARM9, можно было обойти фрагментированность виртуальными адресами, создав таблицу трансляции физических адресов на виртуальные. Ну и под простенькие массивы у него в виде выделений из кучи.
Чем-то похоже это на хакерство, применяемое во времена архаичных Z80, 6502 и им подобным , когда памяти как кот наплакал
7) В исходниках китайца удалены алгоритмы и структурные данные энтропийного кодирования (CABAC), в итоге имеем кастрированный H264, причем без cabac размер файла видео будет чуть-больше.
Так что никакого обмана c нехваткой памяти тут нет! Такая программа будет работать нестабильно, из-за потенциального риска выйти запределы кучи, стека, памяти : причем это будет зависить от конкретного видео-потока и его параметров сжатия.
QUOTE (romanetz)
А обычные malloc/free нельзя переопределять?
А чем кейловские malloc/realloc/free не устраивают? При правильной настройке будут работать.
Ну как продвижения? Я наверное единственный кому интересно продолжение? Удалось ли немного подоптимизировать? Я к тому, к примеру если купить какой нить stm32h7 , там на борту метр оперативы и честных 400 мегагерц, есть ли шанс получить к примеру 320х480 изображение?
А я все таки заказал stm32l4r9vit6 буду выводить плеер версии 3, так сказать релиз. Для мультимедии бы попер stm32h743vit6 но я их не успел заказать, кто то перед носом выкупил последние 3, то что осталось - жутко дорогое. Так что облом с h7.
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE
Ну как продвижения? Я наверное единственный кому интересно продолжение? Удалось ли немного подоптимизировать?
Вариант китайца с форума не заработал. Портанул его сорцы на ПК, поток не декодирууется, программа вылетает в экспешн. Очень вполне вероятно, что используется конкретная версия кодека с определёнными настройками.
Мой вариант также декодирует поток, полученный кодеком, который выкладывал здесь.
Доработал свой вариант до 160x128, память трещит по швам и её еле как хватило. Пришлось ещё задействовать 4 кБ батареечной памяти.
Звук только ADPCM, на декод MP3 не хватило памяти (что с моим вариантом сорцов MP3, что с китайским).
Тем не менее, выкладываю сорцы рабочей версии видео-декодера H264 160x128 + звуковой декодер IMA ADPCM.
Там же и прошивка (obj/led.hex) и медиа-данные для тестов:
Это сообщение отредактировал Gospodin_Riba - Jan 25 2018, 11:35 AM
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE (ведущий специалист @ Jan 23 2018, 02:48 PM)
Ну как продвижения? Я наверное единственный кому интересно продолжение? Удалось ли немного подоптимизировать? Я к тому, к примеру если купить какой нить stm32h7 , там на борту метр оперативы и честных 400 мегагерц, есть ли шанс получить к примеру 320х480 изображение?
У меня другая побрякушка на базе ADSP Blackfin BF532/533 + SDRAM 32/64 MB + видео на ПЛИС. Гонится до 800 МГц, по дефолту 400 МГц. Можно портировать и посмотреть на ней, но там нет аппаратной поддержки Floating Point.
Ну и A13, v3s без дела пока лежат,руки не доходят их освоить.
На счет stm32h7 не скажу,не работал. Но ARM + FP - это хорошо.
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE (ведущий специалист @ Jan 24 2018, 06:39 PM)
А я все таки заказал stm32l4r9vit6 буду выводить плеер версии 3, так сказать релиз. Для мультимедии бы попер stm32h743vit6 но я их не успел заказать, кто то перед носом выкупил последние 3, то что осталось - жутко дорогое. Так что облом с h7.
Плеер чего? Если речь идет о сорцах того китайца, то там при открытии его в Кейле глюк: выставлено памяти меньше, чем пишет задействованное при линковке. Очень удивило, в моем случае мои проекты выдают ошибку, если объем памяти в проекте стоит меньше, чем надо, то не собирает бинарник.
Ну и вообще, стараюсь вначале проверить и отладить работу сорцов на "большом брате" ПК, затем если всё ОК, переношу на контроллеры. Очень удобно, не надо Флешь жечь лишний раз и спасает от затыков типа printf, assert и других.
Вот видео работы чистого декодирования H264 потока без звука и синхронизации:
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
Я тут бился 4 дня головой об стену с проблемой синхронизации видео и звука. Звук уходил постепенно вперёд видео, и через 30 минут уже достигал разница 3-4 секунды.
Думал, что синхронизирую не так или кадры попадаются тормозные, чего только не пробовал...
А оказалось, что проблема с некорректным декодированием потока: иногда видео замирает на одном кадре, может быть duplicate frames. Но факт, что при разжатии 25 минутной видео-записи вышло на 3000 фрейма больше, чем у оригинала!
Решение было найдено- нашел другой кодек - T264 вместо x264, который дает на выходе поток, без замираний и число разжатых фреймов совпало с оригиналом.
Сорцы кодека T264 прикладываю. Пересобрал его DJGPP, работает. Совместим с декодером H264 на STM32. Энкодер только под процессор INTEL+MMX+SSE(asm). Декодер кроссплатформенный (проверено, вырезал все asm-сорцы). Хотел T264 портировать на STM32F4, но его аппетиты по памяти оказались ещё больше.
В идеале, конечно, надо искать энкодер от того декодера, что используется в STM32. AVCcoder h264 ???
Пришлось замедлить показ фрейма на +0.075% С коррекцией проверил воспроизведение на нескольких тестовых потоках - работает как надо.
Единственное ограничение: параметры сжатия/качества должны стоять такими, чтобы не превысить размер MPEG-буфера при декодировании за 8 кБ.
Для этого написал программу ниже, она декодирует поток и пишет размер каждого сжатого фрейма, и если вылетает за пределы, сообщает об этом. Таким образомвсегда можно найти максимальное качество и не вылезти за пределы.
А может, к звуку и привязываться? Изменение частоты кадров в небольших пределах совершенно незаметно, в отличие от изменения частоты звука (хотя кому как...)
Это сообщение отредактировал romanetz - Jan 26 2018, 07:29 AM
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE (romanetz @ Jan 26 2018, 07:27 AM)
А может, к звуку и привязываться? Изменение частоты кадров в небольших пределах совершенно незаметно, в отличие от изменения частоты звука (хотя кому как...)
В версиях MJPEG+ADPCM и MJPEG+MP3 так и сделано. Но в версии с H264 из-за нехватки памяти пришлось апдейт звука делать в самом обработчике прерывания (подгрузку с файла в половинки кольцевого буфера). Потому что буфер короткий и время его воспроизведения намного короче времени декодирования+показа одного фрейма. В итоге имеем отрисовку фрейма параллельно с многократными прерываниями по звуку. В этом случае обработка прерываний тоже вносит некую задержку и цепляться на количество отыгранных аудио-семплов не корректно.
Нужен некий аппаратный счетчик, и я его нашел - счетчик тактов ядра процессора. Тактовая частота и частота дискретизации звука - синхронны (если не учитывать латентность логики делителей частоты), значит , синхронизируя по количеству тактов, синхронизируемся и по звуку.
И ещё,я вроде откопал тот самый кодек, который используют китайцы в своих плеерах. Им оказался x264 древней версии. С его использованием, надобность в коррекции отпала и теперь так:
QUOTE
#define VSYNC ((u32)(CPU_FREQ/FPS))
Без всяких корректирующих коэффициентов 0,0075%, тестировал на получасовых тестовых записях. Звук синхронно с видео (герои открывают рот во время разговора вовремя )
Вот этот чудо-кодек (ещё более ранняя версия, чем та, что выше выкладывал):
Далее полученный YUV конвертим в H264, без CABAC, с максимальным качеством кадра CRF=1, с подавлением шума NR=1, НО с ограничением по битрейту и размеру буфера (чтобыне вылезти за пределы максимального размера MPEG буфера), bufsize - 12% от maxrate. Обязательно указываем minimum GOP Size равное числу фреймов видео - вданном случае оно 17759 фреймов. Число фреймов можно узнать из пункта 1) - ffmpeg его пишит после завершения кодирования. В этом случае замирания фреймов (duplicate frames ?) не будет и звук будет чётко синхронизироваться с видео, число фреймов в оригинале (пункт 1) будет совпадать с числом фреймов пункта 2).
x264.exe - тот, что постом выше. При указанных параметрах кодирования, не было замечено НИ ОДНОГО артефакта! Размер bufsize должен быть 12% от maxrate, при их увеличении есть риск выйти за пределы памяти STM32. В примере подобраны оптимальные рабочиез начения.
Далее находим максимальный уровень громкости, и если он ниже 0 дБ, то увеличиваем уровень громкости (нормализуем амплитуду) на эту величину со знаком плюс:
3)
CODE
ffmpeg.exe -i 0.wav -af "volume=3.0dB" 1.wav
Здесь мы подняли громкость на 3 дБ (предполагалось, что из предыдущего шага к примеру узнали, что максимальная громкость была -3 дБ )
4)
CODE
imacodec.exe 1.wav 0.ima 2.wav
Тут мы сконвертим в ADPCM (выигрыш в 4 раза по размеру).
В итоге имеем 0.264 и 0.ima- их использовать для STM32f4 плеера.
RAW YUV видео можно просмотреть через FFPLAY (входит впакет ffmpeg):
В заключение, выкладываю сорцы относительно не старой версии декодера H264 от ffmpeg - всё отлично собралось и работает. Даже x264 не нужен, эта версия декодера понимает даже h264-поток от ffmpeg, чего не может делать китайские версии для STM32. Но к сожалению, он прожорлив к памяти (уже более чем пол-метра нужно):
Группа: Автор
Сообщений: 2137
Пользователь №: 116127
Регистрация: 26-April 16
QUOTE (Gospodin_Riba @ Jan 26 2018, 04:46 PM)
Обязательно указываем minimum GOP Size равное числу фреймов видео - вданном случае оно 17759 фреймов. Число фреймов можно узнать из пункта 1) - ffmpeg.............
Тогда в потоке будет всего лишь один опорный I-фрейм, остальные будут P-фреймами. B-фреймов тут в принципе быть не должно, потому что китайский декодер их не понимает.
Тоесть весь поток будет выглядеть так: IPPPPPPPPPPPPPPPPPP..... В некоторых случаях это не есть хорошо.
Поэтому было проведено дополнительное расследование в работе декодера, и выяснилось, что в функции декодирования фрейма даётся отмашка на отрисовку даже в случае чтения NAL_SPS и NAL_PPS (что это такое -можно узнать, раскурив FAQ по H264).
Отрисовка должна быть только при чтении данных опорных или предсказуемых фреймов: NAL_SLICE или NAL_IDR_SLICE. Тоесть - переделать в файле h264.c функцию:
CODE
int decode_frame(AVCodecContext *avctx, void *data, int *data_size,uint8_t *buf, int buf_size) { ...
// *data_size = sizeof(AVFrame); if((h->nal_unit_type==NAL_SLICE)||(h->nal_unit_type==NAL_IDR_SLICE))*data_size = sizeof(AVFrame); //!!! Только в этих случаях отображать картинку
В данном случае переменная data_size = got_picture даёт отмашку на отрисовку кадра, и это надо делать только при состояниях NAL_SLICE или NAL_IDR_SLICE, а не когда вздумается.
Так что теперь GOP Size может быть любым, и видео-поток может содержать более одного опорного (I) фрейма и прекрасно синхронизируется со звуком и количество фреймов совпадает при энкоде и декоде:
IPPPPIPPPPIPPPP...
Ну и конечно же сорце всего проекта с прошивкой:
Это сообщение отредактировал Gospodin_Riba - Jan 29 2018, 11:36 AM
Так какой повторить код, старый или последним постом? Немного запутался. Хочу попробывать запустить на дискавери ф7, там вроде сдрам на борту, ну и чисто ради интереса проверить насколько ф7 вытянет картинку.