Пока игрался с ffmpeg - внезапно реализовал сведение графики почти тройного разрешения в субпиксельное по принципу, ранее предложенному с использованием imagemagick: https://legacy.imagemagick.org/discourse-server/viewtopic.php?t=19120
Если строку фильтров ffmpeg засунуть в конфиг плейера типа mpv, то можно смотреть в сверх-качестве прямо в плейере. Хотя тут ещё зависит от железа. На моём Intel B950 (нет ни opencl ни cuda) - при просмотре 4k в разрешении 1600x900 - сам ffmpeg выдаёт от силы 7fps, mpv ещё меньше. Но это без vaapi, т.к. формат файла не поддерживается (с vaapi должно быть чуть больше). Поэтому нормально протестирован только программный вариант, с opencl и cuda могу только надеяться, что заработает .
Программный вариант - просмотр в самом ffmpeg:
Shell
# Определяемся с размером на экране, в моём случае - разрешение 1900x600
w=1900
h=600
vidfile=...
ffmpeg -hwaccel auto \
-i "$vidfile" \
-vf "zscale=${w}*3:$h:filter=bilinear, rgbashift=rh=1:bh=-1, scale=$w:$h:flags=area" \
-f opengl "My video"
Пример, для mpv необходимо добавить следующую строку в ~/.config/mpv/mpv.conf:
Код: Выделить всё
vf=zscale=1600*3:900:filter=bilinear,rgbashift=rh=1:bh=-1,scale=1600:900:flags=area
Полный список вариантов для hwdec (работает и для других параметров):
Код: Выделить всё
mpv --hwdec=help
Пиксель, как минимальный элемент, имеющий цвет, не может быть уже 3 субпикселов для стандартной модела RGB, однако позиция может быть любой. При этом каждый субпиксел одновременно входит в 3 полных пикселя. Такое изображение почти невозможно отличить от натурального при выводе на экран. Даже больше - в этом и есть залог натуральности (или как бы сейчас сказали - ламповости).
Разбор цепочки фильтров.
- Сначала получается нужное разрешение, но с размером, умноженным на размер субпиксельной сетки внутри пикселя (этот шаг обязателен, хоть с патентами, хоть без). В моём случае - zscale из zimg оказался быстрее встроенного scale.
- Субпиксели сводятся за счёт смещения соответствующих каналов. Есть два способа: rgbashift и convolution, из которых rgbashift - быстрее (в варианте с imagemagick используется конволюция).
- Размываем на ширину пикселя - должны охватываться все цветовые конпоненты. В нашем случае используется просто уменьшается разрешение методом area - что аналогично пикселизации и последующему сведению методом neighbor. К сожалению, в zscale нет метода area.
Код: Выделить всё
convolution=1 1 1:1 1 1:1 1 1:1 1 1:0mode=row:1mode=row:2mode=row:3mode=row
Код: Выделить всё
gblur=sigma=1.0:sigmaV=0
На моём железе - чистый ffmpeg вытягивает 6-7fps при просмотре 4k на 1600x900 без ускорения (есть vaapi, но нужный формат файла не поддерживается). К сожалению, у меня нет ни opencl ни cuda, поэтому протестировать заточенный под них вариант невозможно - могу только предположить, сколько они вытянут; mpv выдаёт ещё меньше (с теми же фильтрами), лучшее примение при таком подходе - остановить воспроизведение и смаковать отдельные кадры (как вариант - скриншотить на обои).
Аппаратное ускорение (нужно проверять)
Фильтрация с ускорением в основном та же, что и без. Среди фильтров ffmpeg есть варианты *_opencl и *_cuda, специально для соответствующех режимов ускорения. Однако не все эффекты в цепочки присутствуют в этом списке (точнее - только один, хотя могу ошибаться).
Что меняется:
- Плагин rgbashift есть только в одном варианте, зато есть convolution_opencl и convolution_cuda есть. Обычный convolution на моём железе понижает fps сразу почти до 3. Однако ускоренные варианты, скорее всего, стоит попробовать.
- Также добавляются дополнительные элементы - для загрузки в железо и выгрузки обратно.
- Перед convolution - обязательно форсировать формат gbrp, т.к. он работает с компонентами цветовой модели, а с видео - на входе обычно YUV, так что разультат может быть совсем не тот.
- Можно попробовать вариант avgblur вместо scale в режиме area.
Код: Выделить всё
-hwaccel opencl
...
-vf "
zscale=3*$w:$h:filter=bilinear,
format=gbrp,
hwupload,
convolution_opencl=2m=1 1 1 0 0:0m=1 1 1:1m=0 0 1 1 1:1 1 1:0mode=row:1mode=row:2mode=row:3mode=row,
hwdownload,
scale=$w:$h:flags=neighbor"
Код: Выделить всё
vf=zscale=3*1600:900:filter=bilinear,format=gbrp,hwupload,convolution_opencl=2m="1 1 1 0 0":0m="1 1 1":1m="0 0 1 1 1":"1 1 1":0mode=row:1mode=row:2mode=row:3mode=row,hwdownload,scale=1600:900:flags=neighbor
Если с OpenCL заработает - поделитесь результатами
_______________________________________
С cuda тоже интересно, хотя я так понял - где cuda, там и opencl.
Фильтр program_opencl мог бы пригодиться, если под него написать чего-нибудь.