ffmpeg: проблема с циклической фильтрацией

Вопросы, приемы и проблемы обработки видео

Модератор: Модераторы разделов

Ответить
nick87720z
Сообщения: 178
ОС: Gentoo / Calculate

ffmpeg: проблема с циклической фильтрацией

Сообщение nick87720z »

Немного привёл в порядок предыдущий пост.
========================================

Попробовал сделать монитор параметров на базе ffmpeg. Значения интерпретируются как пиксели, а geq занимается визуализацией.

Проблема возникла при попытки сделать график по времени, как во всяких мониторах загрузки.

Руководство ffmpeg говорит, что графы могут быть циклическими.
Казалось бы, выход есть: добавить перед выводом развилку (split), направив второй поток через сдвиг влево (convolution=0 0 1), после чего объединить со свежим потоком (выяснил, что для этого лучше подходит overlay, а не blend).

Shell

w=480; h=64
ffmpeg -nostdin -v verbose \
-f rawvideo -pixel_format gray -video_size 1x1 -codec:v rawvideo -i - \
-sws_flags bicubic \
-vf "
scale@in = 1:255:flags=neighbor,
geq@bar = lum=' if( gt(Y, H - p(X,Y)), 80 ) ',
scale@bar = 0:$h
[new];

[accum_in]
convolution = '1 0 0':0mode=row,
nullsink, nullsrc = ${w}x${h}
[accum_out];

[accum_out] [new]
overlay = W-1:shortest=true,
split = 2
[accum_in] [sink];

[sink] scale@sink = flags=neighbor, format = gray
" -vcodec rawvideo -f rawvideo -
Заодно - тестовый генератор синусоиды:

Shell

stdbuf -o0 yes | LANG=C stdbuf -o0 awk '{
v = v + 0.01
printf "%c", int((sin(v) + 1)/2 * 255)
}'
И просмотр (для бенчмарка лучше так, а не "-f opengl" в ffmpeg):

Shell

ffplay -v quiet -s ${w}x${h} -pix_fmt gray -f rawvideo -framerate 100000 -
(всё соединяется через конвейер)

Это для начала - то, что работает. На моём Intel B950 дошло до 1670fps.

В аккумуляторе - заглушка, форсирующая нужный размер кадра, одновременно делающая его бесполезным. Если заглушку убрать, то перестаёт работать (даже graph2dot ругается).

Код: Выделить всё

Input #0, rawvideo, from 'pipe:':
  Duration: N/A, start: 0.000000, bitrate: 0 kb/s
  Stream #0:0: Video: rawvideo, 1 reference frame (Y800 / 0x30303859), gray, 1x1, 0 kb/s, 25 tbr, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> rawvideo (native))
[scale@in @ 0x56062520d9a0] w:1 h:255 flags:'neighbor' interl:0
[scale@bar @ 0x560625283e40] w:0 h:64 flags:'bicubic' interl:0
[scale@sink @ 0x5606252857a0] w:iw h:ih flags:'neighbor' interl:0
[graph 0 input from stream 0:0 @ 0x560625285fb0] w:1 h:1 pixfmt:gray tb:1/25 fr:25/1 sar:0/1
[Parsed_split_5 @ 0x560625284ba0] circular filter chain detected
[scale@in @ 0x56062520d9a0] w:1 h:1 fmt:gray sar:0/1 -> w:1 h:255 fmt:gray sar:0/1 flags:0x10
[scale@bar @ 0x560625283e40] w:1 h:255 fmt:gray sar:0/1 -> w:1 h:64 fmt:yuva420p sar:0/1 flags:0x4
[Parsed_overlay_4 @ 0x560625284cf0] main w:0 h:0 fmt:yuva420p overlay w:1 h:64 fmt:yuva420p
[Parsed_overlay_4 @ 0x560625284cf0] [framesync @ 0x560625284dc8] Selected 1/25 time base
[Parsed_overlay_4 @ 0x560625284cf0] [framesync @ 0x560625284dc8] Sync level 2
[swscaler @ 0x5606252ae2d0] Value 0.000000 for parameter 'srcw' out of range [1 - 2.14748e+09]
[swscaler @ 0x5606252ae2d0] Value 0.000000 for parameter 'srch' out of range [1 - 2.14748e+09]
[swscaler @ 0x5606252ae2d0] Value 0.000000 for parameter 'dstw' out of range [1 - 2.14748e+09]
[swscaler @ 0x5606252ae2d0] Value 0.000000 for parameter 'dsth' out of range [1 - 2.14748e+09]
[scale@sink @ 0x5606252857a0] w:0 h:0 fmt:yuva420p sar:0/0 -> w:0 h:0 fmt:gray sar:0/0 flags:0x10
[Parsed_convolution_3 @ 0x5606252845d0] [IMGUTILS @ 0x7ffe3b0646c0] Picture size 0x0 is invalid
Error reinitializing filters!
Пока только и вижу - на каком-то этапе получается кадр нулевого размера.
Если вставить scale=$w:$h перед split - это только убавляет ругательство про srcw/srch, а convolution всё-равно видит нулевой кадр.

Единственное, что работает и при этом полезно - это столбчатый индикатор на все 480 значений, которые выполняют роль истории. Разумеется, geq вынужден считать все 480 столбцов, что для производительности - не айс.

Shell

stdbuf -o0 yes | \
LANG=C stdbuf -o0 awk -v W=$w '
BEGIN {
for (i=0; i < W; i++) {
h[i] = 0
printf "\0"
}
i = 0
}{
p = i

v = v + 0.01
h[i] = int((sin(v) + 1)/2 * 255)
do{ i = (i + 1) % W
printf "%c", h[i]
}while (i != p)

i = (i + 1) % W
}' \
| stdbuf -o0 cat \
| stdbuf -o0 ffmpeg -nostdin -v verbose \
-f rawvideo -pixel_format gray -video_size ${w}x1 -codec:v rawvideo -i - \
-sws_flags bicubic \
-vf "
scale=$w:255:nearest,
geq=lum='
if( gt(Y, H - p(X,Y) * H / 255),
80
)',
scale=$w:$h,
drawtext=text=Example:x=3:y=3:font=serif:fontsize=10:fontcolor=white,format=gray
" -vcodec rawvideo -f rawvideo - \
| SDL_AUDIODRIVER=alsa ffplay -v quiet -s ${w}x${h} -pix_fmt gray -vcodec rawvideo -f rawvideo -framerate 20000 -


У меня вытянуло только 70fps.

Также пробовал showwaves - работает, но принцип совсем не тот (он обновляет только когда сэмплы полностью перерисуют кадр, слева направо). Также пробовал oscilloscope - но для графика он полностью бесполезен; я пробовал только одиночный столбец, для графика нужно разветвить на 480 потоков, для каждого значения в графике (а это только простая линия, без заполнения).

В общем, нужна помощь.
Спасибо сказали:
Ответить