Здравствуйте, Sharov, Вы писали:
S>1) А каков жизненный цикл буффера, от src до sink'а, это что-то типа tcp\ip, когда каждый элемент(слой) добавляет S>к буфферу какую-то конкретную инф-ию или как? Вот например на вход h264parse идет сырое видео из src, а что на выходе -- S>какой-то новый буффер или старый с какой-то инф-ей, пригодной для следующих эл-ов, типа, avdec_h264?
Ну, так глубоко я этот вопрос не копал — ты же понимаешь, что проработкой вопроса начинаешь заниматься только тогда, когда этот вопрос жмёт. В nvh264enc плотно копался, даже результаты лучше чем у них получились (форкнулся от них лет 5 назад, а они потом серьёзно переделали многое). А вот в парсерах не копался. Вот, можешь посмотреть, чего они там делают:
Ну, тут опять же, я такую задачу не решал, и чтобы ответить на этот вопрос мне копать надо. У нас в проекте большой объём доп. инфо, привязанной к видео, (значения датчиков, состояние оборудования, измерения, комментарии и т.д.) Когда принималось решение о стратегии реализации всего этого, занимался этим другой человек. Было принято решение сохранять всё это как отдельный объект и синхронизировать с видео по timeline. Для наших задач достаточно точности синхронизации в 1 сек. Так что...
Здравствуйте, sergey2b, Вы писали:
S>Скажите пожалуйста как вы считаете сможет gstreamer записывать 4 потока без GPU S>И хватит ли ему например 1g ram если это mp4 по 3 часа каждый
Маловато данных:
1. Разрешение, fps?
2. Что на входе?
3. Во что кодируем — h264?
4. Железо какого уровня? 1G — только для его нужд?
5. ОС?
Лучше всего эксперимент провести, если appsrc не требуется, то можно через gst-launch-1.0.
Re[21]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Conductor, Вы писали:
C>Маловато данных: C>1. Разрешение, fps?
Hd 60 fps
C>2. Что на входе?
4 потолка raw video в yuv420 or rgb
На выходе 4 mp4
C>3. Во что кодируем — h264?
Да h264
C>4. Железо какого уровня? 1G — только для его нужд?
12th cpu 64 g ram но под запись видео ram 1g
C>5. ОС?
Linux например Ubuntu
Re[22]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, sergey2b, Вы писали:
C>>1. Разрешение, fps? S>Hd 60 fps
C>>2. Что на входе? S>4 потолка raw video в yuv420 or rgb S>На выходе 4 mp4
C>>3. Во что кодируем — h264? S>Да h264
C>>4. Железо какого уровня? 1G — только для его нужд? S>12th cpu 64 g ram но под запись видео ram 1g
C>>5. ОС? S>Linux например Ubuntu
Ну, провёл я эксперимент. 12-го поколения у меня нет, у меня 9-ое (i5). Debian 10. К своей тестовой аппликухе я новый gstreamer не цеплял, поэтому версия 1.14.4, параметры по умолчанию.
Почему-то (надо будет разобраться почему) среди доступных muxer'ов она мне mp4 не выдаёт, поэтоому на выходе matroska (mkv). На входе — raw, 720p, 60 fps, динамичная картинка.
Результаты (загрузка процессора в % total cpu load):
1. Один экземпляр: CPU на процесс — 34%, ram — 128 МБ.
2. Два экземпляра: загрузка CPU на процесс — такая же или чуть больше, ram — такая же.
3. Три экземпляра и далее: загрузка CPU на процесс начинает снижаться (при 3 процессах — 24%, при 4 процессах — 20%), общая загрузка CPU растет ступенчато. Я довёл до 12 процессов, при этом общая загрузка процессора — 95% (соответственно, загрузка на процесс ~7%), память чуть подрастает, но остаётся в пределах 256 МБ на процесс.
Почему так происходит: при увеличении числа процессов больше 2-х, снижается битрейт. Если запись осуществляется одним процессом, то битрейт — 7 МБ/с, при 12 одновременно работающих процессах битрейт — 3 МБ/с.
Через настройки можно выставить константный битрейт, тогда, думаю, получим условно линейный рост загрузки CPU в зависимости от числа процессов.
Вывод: задача может быть решена, и поскольку планируется использование CPU более нового поколения, весьма вероятно, что не придётся использовать пониженный битрейт. По памяти всё вписывается в обозначенные условия и на более старом железе.
Re[23]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, sergey2b, Вы писали:
S>большое вам спасибо за ваш эксперемент S>мне надо подумать немного, но получаеться вполне без GPU может работать
Да не за что. Мне самому это пригодится. Задачка тут вылезает: 16 потоков, телевизионное разрешение, правда, но на 2-ом поколении, без GPU.
Так что, фактически, я преследовал свой сугубо корыстный интерес.
P.S. Почему на "Вы"-то? И принято здесь всегда было на "ты", и по возрасту мы, вроде бы, из одной категории.
Re[25]: Относительно твоих вопросов в рассылке gstreamer'а
насколько трудно сделать на gstreamer получать несколько видеопотока и записывать полученное в один mp4, а если они с разными fps
интерестно понять такое принципиально возможно или нет
Re[26]: Относительно твоих вопросов в рассылке gstreamer'а
Привет.
S>one more a question more please.
S>насколько трудно сделать на gstreamer получать несколько видеопотока и записывать полученное в один mp4, а если они с разными fps S>интерестно понять такое принципиально возможно или нет
Не понял, что требуется. Уточни, пожалуйста. Получение от нескольких источников — понял (можно, естественно). Запись в один файл — тоже понял (тоже можно).
Вопрос, как именно компоновать требуется данные от этих источников: накладывать кадр один на другой; на одном большом кадре несколько кадров; кадр от одного, кадр от другого; как-то ещё?
И с разным fps можно: у меня, например, в процессе экспорта на видео с 25 fps накладываются субтитры в виде картинки (там не только текст — значки ещё, да и текст в произвольном положении, поэтому стандартный вариант не проходит) со значительно меньшим fps.
По большому счёту — всё можно сделать, было бы желание.
Вот "улучшить" по всем параметрам зачастую сложно. Как известно: "изображение в результате обработки можно только испортить", тем или иным образом.
Re[27]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, sergey2b, Вы писали:
S>надо принять 4 видеопотока в 4k и сделать из них один mp4 в котором совмещенны видео из каждого потока те multivew
Правильно ли я понял: результирующий файл должен содержать 4 синхронизированных видеопотока и при воспроизведении они должны отображаться синхронно ("решётка" или на отдельных экранах), так?
S>каке я понял человек которому поручили это сделать столкнулся с проблемами производительности
Охотно верю.
S>мне поручили изучить gstreamer что я конечно сделаю S>и собрать его с поддержкой onevpl
Ну, мы на Nvidia-решения завязаны.
Для сборки используем cerbero и для lin-версии, и для win (кросскомпиляция). Как показала практика, работает вполне нормально. Относительно использования Intel'овских решений в мануале:
Enabling Hardware Codec Support
Starting with version 1.15.2, Cerbero has built-in support for building and packaging hardware codecs for Intel and Nvidia. If the appropriate variant is enabled, the plugin will either be built or Cerbero will error out if that's not possible.
Intel Hardware Codecs
For Intel, the variant to enable is intelmsdk which will build the msdk plugin.
You must set the INTELMEDIASDKROOT env var to point to your Intel Media SDK prefix, or you must have the SDK's pkgconfig prefix in PKG_CONFIG_PATH
Так что — тоже вполне решаемо.
S>я уже начал ходить по собеседованиям, если начинают пугать уволнением лучше самому уйти
Я читал твои темы в других разделах, в частности "visibility at work". Могу сказать только одно: тут как в анекдоте про раввина, еврейскую невесту и еврейского колхозника — если они хотят (решили) уволить, то, на мой взгляд, без разницы — решишь ты задачу, не решишь...
Re[2]: I have jpeg files in memory, how to transform them into mjpeg file?
Здравствуйте, Conductor, Вы писали:
C>На основе использования appsrc не прокатит? Что-то вроде: C>appsrc name=_appsrc ! image/jpeg,framerate=25/1,width=768,height=576 ! avimux ! filesink location=mjpeg.avi
Благодарю, а можно сразу в mp4?
Еще вопрос: "! image/jpeg,framerate=25/1,width=768,height=576 !" -- это caps для кого эл-та, для appsrc или *mux?
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
C>>На основе использования appsrc не прокатит? Что-то вроде: C>>appsrc name=_appsrc ! image/jpeg,framerate=25/1,width=768,height=576 ! avimux ! filesink location=mjpeg.avi
S>Благодарю, а можно сразу в mp4?
S>Еще вопрос: "! image/jpeg,framerate=25/1,width=768,height=576 !" -- это caps для кого эл-та, для appsrc или *mux?
Для appsrc. Точнее так: ты информируешь, что именно твой appsrc отдавать будет, чтобы muxer на это ориентировался. Ведь что в рельности отдает appsrc именно ты определяешь. Так что можно сказать, что и для *mux.
Кстати, может быть и прокатит без указания width/height, в jpeg они же внутри есть. Попробовать надо.
S>Упд: Как-то так appsrc name=_appsrc ! image/jpeg,framerate=25/1,width=768,height=576 ! mp4mux ! filesink location=mjpeg.mp4 ?
mp4mux — не поддерживает для sink image/jpeg. qtmux поддерживает, если он тебя устроит.
А ежели надо jpegs в mp4 с h264 внутри, то можно, например, так попробовать:
private static Pipeline BuildMp4FromJpegs2()
{
//Читаю jpeg файлы в памятьvar info = new DirectoryInfo("d:\\test_appsrc\\");
Files = info.GetFiles().OrderBy(p => p.CreationTime).Select(t=>t.FullName).ToList();
var pipe = (Pipeline) Parse.Launch(
"appsrc name=_appsrc ! image/jpeg,framerate=25/1,width=768,height=576 ! avimux ! filesink location=d:\\\\qqq.avi");
var appsrc = pipe.GetByName("_appsrc");
appsrc.AddSignalHandler("need-data", StartFeed);
appsrc.AddSignalHandler("seek-data", SeekData);
appsrc["stream-type"] = AppStreamType.Stream;
return pipe;
}
private static void StopFeed(object sender, EventArgs e)
{
}
private static void StartFeed(object o, EventArgs args)
{
var source = new AppSrc(((Element) o).Handle);
var file = Files[FileCounter];
var bytes = File.ReadAllBytes(file);
var buf = new Buffer(bytes)
source.PushBuffer(new Buffer(bytes));
FileCounter++;
}
Вот только смущает наличие таких сообщений в консоле: GStreamer-CRITICAL gst_segment_to_running_time: assertion 'segment->format == format' failed
Это что такое может быть?
S>>Благодарю, а можно сразу в mp4? S>>Еще вопрос: "! image/jpeg,framerate=25/1,width=768,height=576 !" -- это caps для кого эл-та, для appsrc или *mux? C>Для appsrc. Точнее так: ты информируешь, что именно твой appsrc отдавать будет, чтобы muxer на это ориентировался. Ведь что в рельности отдает appsrc именно ты определяешь. Так что можно сказать, что и для *mux. C>Кстати, может быть и прокатит без указания width/height, в jpeg они же внутри есть. Попробовать надо.
S>>Упд: Как-то так appsrc name=_appsrc ! image/jpeg,framerate=25/1,width=768,height=576 ! mp4mux ! filesink location=mjpeg.mp4 ? C>mp4mux — не поддерживает для sink image/jpeg. qtmux поддерживает, если он тебя устроит.
Понял, надо сравнить это и это.
C>А ежели надо jpegs в mp4 с h264 внутри, то можно, например, так попробовать: C>appsrc name=_appsrc ! image/jpeg,framerate=25/1,width=768,height=576 ! jpegdec ! x264enc ! mp4mux ! filesink location=mjpeg.mp4
Протестировал и "appsrc name=_appsrc ! image/jpeg, framerate=16/1,width=768,height=576 ! jpegdec ! x264enc ! mp4mux ! filesink location=d:\\\\qqq.mp4";
Работает! Файл mp4 более чем в 10 раз меньше avi файла, впечатляет.
C>Ну, очередь там где-нибудь ещё всобачить, на всякий случай. Хотя для тестового варианта и без неё прокатывает, но, в принципе, могут быть сюрпризы.
А вот тут подробнее, зачем нужна очередь и какие возможны сюрпризы?
C>gst-launch-1.0 videotestsrc num-buffers=500 ! video/x-raw, framerate='(fraction)'25/1 ! jpegenc ! image/jpeg,framerate=25/1,width=768,height=576 ! jpegdec ! x264enc ! mp4mux ! filesink location=mjpeg_h264.mp4
Этот пайплайн для каких целей?
Кодом людям нужно помогать!
Re[6]: I have jpeg files in memory, how to transform them i
Здравствуйте, Sharov, Вы писали:
S>Вот только смущает наличие таких сообщений в консоле: GStreamer-CRITICAL gst_segment_to_running_time: assertion 'segment->format == format' failed S>Это что такое может быть?
И понятно почему он такой формат ожидает: ему же поступают просто кадры, какой именно временной метке они соответствуют у него информации нет. Поэтому он ждёт, что метка будет прописана внутри буфера. Что он делает по умолчанию в том случае, если метки нет — это хороший вопрос (видеофайл же в конечном счёте формируется), в исходниках надо смотреть. Но корректный способ — это для буферов обозначать timestamp/duration (timestamp, насколько я понимаю, минимум). В С-шном варианте для этого есть макросы GST_BUFFER_TIMESTAMP, GST_BUFFER_DURATION и т.д.:
Что для этого есть в C# варианте — не знаю.
S>Протестировал и "appsrc name=_appsrc ! image/jpeg, framerate=16/1,width=768,height=576 ! jpegdec ! x264enc ! mp4mux ! filesink location=d:\\\\qqq.mp4"; S>Работает! Файл mp4 более чем в 10 раз меньше avi файла, впечатляет.
C>>Ну, очередь там где-нибудь ещё всобачить, на всякий случай. Хотя для тестового варианта и без неё прокатывает, но, в принципе, могут быть сюрпризы.
S>А вот тут подробнее, зачем нужна очередь и какие возможны сюрпризы?
Ну, сюрприз простой — пайплайн раком встанет (зависнет), и ничего с этим уже не сделаешь. У меня это происходило, например, потому, что скорость кодирования энкодера в определённый момент была недостаточна для объема поступающих данных (и это даже при том, что очередь перед ним была, но со значениями по умолчанию, проблема была решена увелечением значений параметров очереди max-size-buffers, max-size-bytes и max-size-time). С одной стороны, appsrc вроде как данные запрашивает (need data), когда уже всё переварено, тем не менее такая ситуация у меня встречалась с определёнными типами muxer'ов, даже при том, что у пайплана стояло sync=true. (Кстати, может пригодиться: если пайплайну с appsrc выставить sync=true, то callback need_data будет вызываться через промежутки, соответствущие продолжительности отображения кадра, т.е. для 25 fps, например, через ~40 мс).
C>>gst-launch-1.0 videotestsrc num-buffers=500 ! video/x-raw, framerate='(fraction)'25/1 ! jpegenc ! image/jpeg,framerate=25/1,width=768,height=576 ! jpegdec ! x264enc ! mp4mux ! filesink location=mjpeg_h264.mp4
S>Этот пайплайн для каких целей?
Просто для тестирования из консоли основной части предполагаемого функционала — не всё же сразу в коде писать. Чтобы не быть голословным, мне ж проверить надо было.
Тут встала необходимость конкатенировать два mp4 файла, смотрю на concat и сюда. Пока не получилось -- создается файл размера 2х от обоих (2 файла по 10 секунд, размер x байт каждый), но проигрывается
только 10 секунд 1-го файла:
gst-launch-1.0 concat name=c ! filesink location=result.mp4 filesrc location=1.mp4 ! c. filesrc location=2.mp4 ! c.
Нашел работающий вариант, но там надо лишние действия по формированию списка файлов делать, не критично, но все же:
Правда, автор решения пишет, что работает не всегда -- https://stackoverflow.com/q/68024094/241446 Тут еще есть обсуждение.
По итогу, все переходят на splitmuxsrc, хотя мне concat нравится больше.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте.
S>Тут встала необходимость конкатенировать два mp4 файла, смотрю на concat и сюда. Пока не получилось -- создается файл размера 2х от обоих (2 файла по 10 секунд, размер x байт каждый), но проигрывается S>только 10 секунд 1-го файла:
S>
S>gst-launch-1.0 concat name=c ! filesink location=result.mp4 filesrc location=1.mp4 ! c. filesrc location=2.mp4 ! c.
S>Второй вариант рабочий, пока возьму его, но почему concat не до конца работает?
S>Заранее благодарю.
S>Упд:
S>Нашел работающее решение, но пока не очень понимаю, почему оно работает:
S>
S>Правда, автор решения пишет, что работает не всегда -- https://stackoverflow.com/q/68024094/241446 S>Тут еще есть обсуждение. S>По итогу, все переходят на splitmuxsrc, хотя мне concat нравится больше.
В первом случае ("gst-launch-1.0 concat name=c ! filesink location=result.mp4 filesrc location=1.mp4 ! c. filesrc location=2.mp4 ! c.") он тебе сделал ровно то, что ты просил — объединил два файла как файлы, а не их содержимое (не потоки), и ему было абсолютно пофигу, что у них внутри. С тем же успехом можно было (вообще без gstreamer'а) выделить элементарный буфер размером в сумму размеров исходных файлов, и скопировать как есть в первую часть данные первого файла, а во вторую — второго. Эффект был бы тот же самый — воспроизведение доходит до конца данных первого файла и завершает работу.
S>>Правда, автор решения пишет, что работает не всегда -- https://stackoverflow.com/q/68024094/241446 S>>Тут еще есть обсуждение. S>>По итогу, все переходят на splitmuxsrc, хотя мне concat нравится больше. C>В первом случае ("gst-launch-1.0 concat name=c ! filesink location=result.mp4 filesrc location=1.mp4 ! c. filesrc location=2.mp4 ! c.") он тебе сделал ровно то, что ты просил — объединил два файла как файлы, а не их содержимое (не потоки), и ему было абсолютно пофигу, что у них внутри. С тем же успехом можно было (вообще без gstreamer'а) выделить элементарный буфер размером в сумму размеров исходных файлов, и скопировать как есть в первую часть данные первого файла, а во вторую — второго. Эффект был бы тот же самый — воспроизведение доходит до конца данных первого файла и завершает работу. C>Ведь в твоей же ссылке https://coaxion.net/blog/2014/08/concatenate-multiple-streams-gaplessly-with-gstreamer явно написано: C>
C># Basically: $ cat file1 file2 > both
C>gst-launch-1.0 concat name=c ! filesink location=both filesrc location=file1 ! c. filesrc location=file2 ! c.
Видел, вот я и подумал "ого, как просто!", а дальше умный gst вывезет что речь идет о 2х mp4 файлах. Ан нет.
C>А во втором случае объединяется уже содержимое — ты же видишь: demux + parse + mux.
Уловил, благодарю. Пока, увы, слабо ориентируюсь.
Еще вопрос в догонку -- попытался переиспользовать вот этот пайплайн:
все делаю по феншую -- 1) присваиваю всем location 2) pipeline.setstate(playing) 3)жду через шину EOS! Error (блокирующий вызов) 4) далее pipeline.setstate(ready) и pipeline.setstate(null);
и по кругу с другими файлами -- ломается, qtdemux not-linked, т.е. там pad'ы что ли как-то динамически появляются. В общем,
я этот вопрос еще поисследую, но меня интересуте другой вопрос:
а имеет ли смысл pipeline'ы переиспользовать или может проще новый создавать каждый раз? Не проводили эксперименты,
есть мнение на этот счет? Может, с конкретно этим пайплайном (см. выше), плюнуть и каждый раз занового его создавать?