Есть специалисты по gstreamer'у на форуме? Есть поток от ip камеры, допустим хочу нарезать
на mp4 чанки длиной по 10сек. Пайплайн сделал, несложно, но необходимо получать для каждого фрейма
capture time, т.е. timestamp камеры. Ну или для каждого чанка timestamp главного кадра.
Как это можно сделать?
Здравствуйте, Sharov, Вы писали:
S>Заранее благодарю.
Про pts уже написали, но это не с каждой камеры есть и не всегда означает именно таймстемп.
Если у тебя rtsp камера, то в каждом пакете с кадром есть ntp таймстемп. В зависимости от условий, для сетевых камер такая штука может быть намного лучше и полезнее, чем pts. Например, для синхронизации видео с нескольких разных камер. Или для установления времени какого-нибудь события.
Как получить тайкой таймстемп? Ручками при разборе протокола. Например, он есть в ffmpeg, но оно дальше никуда не идёт и остаётся внутри ffmpeg. Вот тут есть патч для ffmpeg, который ntp таймстемп не теряет, а прикрепляет к AVPacket'у. Такого в стандартном ffmpeg нет и не будет. Как можно такое получить от gstreamer — хз, надо искать, но сомневаюсь, что есть.
Здравствуйте, Nuzhny, Вы писали:
N>Здравствуйте, Sharov, Вы писали:
S>>Заранее благодарю.
N>Про pts уже написали, но это не с каждой камеры есть и не всегда означает именно таймстемп. N>Если у тебя rtsp камера, то в каждом пакете с кадром есть ntp таймстемп. В зависимости от условий, для сетевых камер такая штука может быть намного лучше и полезнее, чем pts. Например, для синхронизации видео с нескольких разных камер. Или для установления времени какого-нибудь события.
Да, выше написал про физ. время камеры. Но мне для gstreamer'а нужно.
Видел. Вот у меня пайплайн rtspsrc ! rtph264depay ! h264parse ! splitmuxsink .
При этом я использую свой sink, а не filesink (splitmuxsink["sink"] = appSink)
Вот код appsink'а:
private static void AppSink_NewSample(object o, NewSampleArgs args)
{
if (o is AppSink aps)
{
var sample = aps.PullSample();
var buf = sample.Buffer;
buf.Map(out var info, MapFlags.Read);
//application/x-rtpvar tsMeta = buf.GetReferenceTimestampMeta();
//NOTE tsMeta shouldn't be null there...
buf.Unmap(info);
}
Counter++;
}
И вот tsMeta возвращает пустую структуру, timestamp 0. И что надо добавить, чтобы там эта инф-ия была
Имею в виду "How to reuse pipeline to read different mp4 files. Few questions." и "Pipeline set state to Ready hangs pipeline.".
1. decodebin и playbin — это, грубо говоря, такие хитрые элементы, которые, фактически, служат всего лишь для того, чтобы подобрать правильные элементы для построения графа. По моему опыту с точки зрения быстродействия что filesrc + decodebin, что playbin — один хрен. Особенно если учеть, что основные затраты времени — они уже после формирования, непосредственно при воспроизведении. Если ты посмотришь результирующий граф, то увидишь, насколько он изменился.
2. Относительно переиспользования и зависания. У нас в своё время не получилось, правда, это было раннем этапе. Именно поэтому я полез в реализацию qt multimedia, и, собственно, перетащил её вариант, использующий gstreamer на винду, полагая, что qt-шникам виднее, как правильно использовать. Там на каждой изменение, например, для записи (preview -> record, record -> preview) строится новый pipeline. Сейчас сильно подозреваю, что проблема с переиспользованием в том, что при завершении воспроизведения файла приходит eos, и какие-то элементы переходит в условно "невосстановимое" состояние. Но надо, конечно, включать более детальный лог и смотреть исходники.
3. Ну и дополнительно. Не знаю, как сделано для шарпа, но внутри там всё в основном асинхронное, т.е., если ты высталяешь некое состояние пайплайну, то это не зачит, что оно на том же стеке будет выставлено. Не учёт этого зачастую приводит к проблемам.
Ну и последнее: не ожидай, что тебе в рассылке на каждый вопрос ответят. Как показывает практика, там точно отвечают либо на критичный, либо на интересный для отвечающего вопрос.
Надеюсь, что был полезен. Удачи!
Re[2]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Conductor, Вы писали:
C>Имею в виду "How to reuse pipeline to read different mp4 files. Few questions." и "Pipeline set state to Ready hangs pipeline.".
О, круто благодарю.
C>1. decodebin и playbin — это, грубо говоря, такие хитрые элементы, которые, фактически, служат всего лишь для того, чтобы подобрать правильные элементы для построения графа. По моему опыту с точки зрения быстродействия что filesrc + decodebin, что playbin — один хрен. Особенно если учеть, что основные затраты времени — они уже после формирования, непосредственно при воспроизведении. Если ты посмотришь результирующий граф, то увидишь, насколько он изменился.
С playbin у меня вообще не пошло: пытался добавить свой appsink вместо video-sink -- вылетало окно с показом кадра,
пытался линковать playbin и appsink -- просто падало. Т.е. пока filesrc + decodebin+appsink без альтернативы.
C>2. Относительно переиспользования и зависания. У нас в своё время не получилось, правда, это было раннем этапе. Именно поэтому я полез в реализацию qt multimedia, и, собственно, перетащил её вариант, использующий gstreamer на винду, полагая, что qt-шникам виднее, как правильно использовать. Там на каждой изменение, например, для записи (preview -> record, record -> preview) строится новый pipeline. Сейчас сильно подозреваю, что проблема с переиспользованием в том, что при завершении воспроизведения файла приходит eos, и какие-то элементы переходит в условно "невосстановимое" состояние. Но надо, конечно, включать более детальный лог и смотреть исходники.
Да, я еще погоняю под Debug. У меня такой вариант использования -- нахожу нужный кадр, конвертирую в jpeg, перевожу pipe в Ready.
И далее по кругу, с другим файлом. Ну т.е. один pipe для чтения файлов, а не 1 к 1. Ну так вот, после pipe.SetState(Ready) -- блочится
на этой строке. Буду более детально смотреть, т.к. совершенное не понятно что не так. Тут пишут, что надо в Ready переводить.
C>3. Ну и дополнительно. Не знаю, как сделано для шарпа, но внутри там всё в основном асинхронное, т.е., если ты высталяешь некое состояние пайплайну, то это не зачит, что оно на том же стеке будет выставлено. Не учёт этого зачастую приводит к проблемам.
Ага, многопоток там лютый. Иной раз жаль, что нету опции делать все синхронно. Т.е. вся логика на колбэках строится по сути.
C>Ну и последнее: не ожидай, что тебе в рассылке на каждый вопрос ответят. Как показывает практика, там точно отвечают либо на критичный, либо на интересный для отвечающего вопрос.
Ну вот в июле отвечали более-менее, с августа вообще тишина -- период отпусков, видимо.
C>Надеюсь, что был полезен. Удачи!
Благодарю! Кстати, я там еще один вопрос задал: зная номер n кадра из видео как быстрее его получить --
frame stepper (pullsample) n-1 раз, или можно как-то сделать Seek с буфферами?
Кодом людям нужно помогать!
Re[3]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>С playbin у меня вообще не пошло: пытался добавить свой appsink вместо video-sink -- вылетало окно с показом кадра, S>пытался линковать playbin и appsink -- просто падало. Т.е. пока filesrc + decodebin+appsink без альтернативы.
Сложно так сказать почему — смотреть надо.
S>Да, я еще погоняю под Debug. У меня такой вариант использования -- нахожу нужный кадр, конвертирую в jpeg, перевожу pipe в Ready. S>И далее по кругу, с другим файлом. Ну т.е. один pipe для чтения файлов, а не 1 к 1. Ну так вот, после pipe.SetState(Ready) -- блочится S>на этой строке. Буду более детально смотреть, т.к. совершенное не понятно что не так. Тут пишут, что надо в Ready переводить.
У тебя там блочится на первой же итерации? И такой вопрос: а не занимает ли у тебя перевод конвертация достаточно продолжительное время? По моему опыту в большинстве случаев виснет если буфера переполнены. Я бы попробовал queue в пайплайн добавить. Сначала без ограничения размера и посмотрел бы, как размер памяти процесса себя ведёт. Ну и менял бы параметры, если используется SetState, только после того, как получено сообщение, что состояние изменено. Ты bus-овские сообщения обрабатываешь?
S>Благодарю! Кстати, я там еще один вопрос задал: зная номер n кадра из видео как быстрее его получить -- S>frame stepper (pullsample) n-1 раз, или можно как-то сделать Seek с буфферами?
Хороший вопрос. Сам не пробовал, но из общих соображений понятно, что gst_element_seek должен быть быстрее, однако ограничение есть:
GST_FORMAT_DEFAULT (1) –
the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video (some, but not all, elements support this; use GST_FORMAT_TIME if you don't have a good reason to query for samples/frames)
У тебя же не raw. Можно, конечно, еще попробовать по требуемому номеру кадра и fps расчитать временную метку и уже по ней seek делать. Ну и проверить, насколько точно получается.
И такой вопрос: ты решения вопросов по времени получаемых кадров в результате нашёл (предыдущие темы)?
У нас в конечном счёте решение такое сложилось (камеры в 85-90% случаев аналоговые, без времени, для оставшихся 10-15% rtsp-случаев используется тот же механизм): используем время того компа, на котором осуществляется запись — есть буфер текущего кадра, и приходящее от камеры обновляет его, запись осуществляется с фиксированным fps (appsrc) и данные берёт из буфера текущего кадра. Таким образом отвязываясь от состояния камеры, потерь кадров и т.д. Что есть в буфере кадра на текущий момент, то и считаем актуальным для камеры. Понятно, что в случае rtsp есть задержка, но для наших задач приемлемо.
Re[4]: Относительно твоих вопросов в рассылке gstreamer'а
S>>Да, я еще погоняю под Debug. У меня такой вариант использования -- нахожу нужный кадр, конвертирую в jpeg, перевожу pipe в Ready. S>>И далее по кругу, с другим файлом. Ну т.е. один pipe для чтения файлов, а не 1 к 1. Ну так вот, после pipe.SetState(Ready) -- блочится S>>на этой строке. Буду более детально смотреть, т.к. совершенное не понятно что не так. Тут пишут, что надо в Ready переводить. C>У тебя там блочится на первой же итерации?
Да.
C>И такой вопрос: а не занимает ли у тебя перевод конвертация достаточно продолжительное время?
Я вообще убрал конвертацию и просто n раз делаю pullsample в цикле (3 кадра читаю и иду дальше).
C>По моему опыту в большинстве случаев виснет если буфера переполнены. Я бы попробовал queue в пайплайн добавить. Сначала без ограничения размера и посмотрел бы, как размер памяти процесса себя ведёт.
В данном случае нет.
S>>Благодарю! Кстати, я там еще один вопрос задал: зная номер n кадра из видео как быстрее его получить -- S>>frame stepper (pullsample) n-1 раз, или можно как-то сделать Seek с буфферами? C>Хороший вопрос. Сам не пробовал, но из общих соображений понятно, что gst_element_seek должен быть быстрее, однако ограничение есть: C>
C> GST_FORMAT_DEFAULT (1) –
C>the default format of the pad/element. This can be samples for raw audio, frames/fields for raw video (some, but not all, elements support this; use GST_FORMAT_TIME if you don't have a good reason to query for samples/frames)
C>У тебя же не raw. Можно, конечно, еще попробовать по требуемому номеру кадра и fps расчитать временную метку и уже по ней seek делать. Ну и проверить, насколько точно получается.
mp4 файл. Наверное не raw. Хороший вариант с fps и временной меткой, попробую.
C>И такой вопрос: ты решения вопросов по времени получаемых кадров в результате нашёл (предыдущие темы)?
Пока как-то так:
foreach (Pad pad in splitmuxsink.Pads)
{
if (pad.Direction == PadDirection.Sink)
{
pad.AddProbe(
PadProbeType.Buffer,
(_, probeInfo) =>
{
var buf = probeInfo.Buffer;
var metaTs = buf.GetReferenceTimestampMeta();
var metaTs = buf.GetReferenceTimestampMeta();
if (metaTs.Timestamp > 0)
{
//есть точное время кадра, берем его
}
else
{
//чего-то тут придумываем
}
return PadProbeReturn.Ok;
});
}
}
Тут нашел детальное описание вопроса.
C>У нас в конечном счёте решение такое сложилось (камеры в 85-90% случаев аналоговые, без времени, для оставшихся 10-15% rtsp-случаев используется тот же механизм): используем время того компа, на котором осуществляется запись — есть буфер текущего кадра, и приходящее от камеры обновляет его, запись осуществляется с фиксированным fps (appsrc) и данные берёт из буфера текущего кадра. Таким образом отвязываясь от состояния камеры, потерь кадров и т.д. Что есть в буфере кадра на текущий момент, то и считаем актуальным для камеры. Понятно, что в случае rtsp есть задержка, но для наших задач приемлемо.
У меня для задачи критично иметь время камеры. Соотв. для случаев когда его нет, надо что-то придумывать.
Кстати, код выше (AddProbe) он вообще корректен для получения времени кадра, т.е. я могу рассчитывать на то, что в probeInfo.Buffer находится прям целый
кадр, а не какой-то чанк или вообще какие-нибудь странные данные? Пока кажется, что в буффере действительно находится фрейм.
Кодом людям нужно помогать!
Re[5]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
C>>По моему опыту в большинстве случаев виснет если буфера переполнены. Я бы попробовал queue в пайплайн добавить. Сначала без ограничения размера и посмотрел бы, как размер памяти процесса себя ведёт.
S>Вот тут я добавил больше деталей и debug сообщения -- https://lists.freedesktop.org/archives/gstreamer-devel//2023-August/081632.html
Ну вот, в пуле буфера кончились. Конкретно здесь с queue промашка вышла — я забыл, что у appsink есть своя собственная очередь с неограниченным размером по умолчанию, так что здесь дополнительная очередь проблемы не решает. А скажи, пожалуйста, если в том месте, где у тебя SetState(State.Null), вместо Null Paused выставить (у тебя же всё равно зависание на первой итерации происходит), тоже виснуть будет? Я повторил твой пример (под lin, надо будет под win попробовать, потому как по логам явная отсылка к d3d11, ты, кстати, с какой версией gstreamer работаешь?), но зависания не добился. Ежели в любом случае виснуть будет, то, на мой взгляд, следуюший шаг — это после того как все элементы в пайплайн добавятся, найти этот bufferpool и выставить ему max_buffers в 0.
S>Кстати, код выше (AddProbe) он вообще корректен для получения времени кадра, т.е. я могу рассчитывать на то, что в probeInfo.Buffer находится прям целый S>кадр, а не какой-то чанк или вообще какие-нибудь странные данные? Пока кажется, что в буффере действительно находится фрейм.
Врать не буду — не знаю, могу ориентироваться только на описание splitmuxsink. Вообще-то, ты же ему на вход вроде уже закодированный поток передаёшь, или я чего-то не понимаю.
"This element wraps a muxer and a sink, and starts a new file when the mux contents are about to cross a threshold of maximum size of maximum time, splitting at video keyframe boundaries."
Re[6]: Относительно твоих вопросов в рассылке gstreamer'а
S>>Вот тут я добавил больше деталей и debug сообщения -- https://lists.freedesktop.org/archives/gstreamer-devel//2023-August/081632.html C>Ну вот, в пуле буфера кончились. Конкретно здесь с queue промашка вышла — я забыл, что у appsink есть своя собственная очередь с неограниченным размером по умолчанию, так что здесь дополнительная очередь проблемы не решает. А скажи, пожалуйста, если в том месте, где у тебя SetState(State.Null), вместо Null Paused выставить (у тебя же всё равно зависание на первой итерации происходит), тоже виснуть будет? Я повторил твой пример (под lin, надо будет под win попробовать, потому как по логам явная отсылка к d3d11, ты, кстати, с какой версией gstreamer работаешь?), но зависания не добился. Ежели в любом случае виснуть будет, то, на мой взгляд, следуюший шаг — это после того как все элементы в пайплайн добавятся, найти этот bufferpool и выставить ему max_buffers в 0.
Вот если Paused, то не виснет. Правда пишет после
** WARNING **: 13:07:57.677: Changing the `location' property on filesrc when a file is open is not supported.
и по сути работает с одним файлом (самым первым), т.е. читать будет только из него.
Версия самая последняя (1.22 что ли).
S>>Кстати, код выше (AddProbe) он вообще корректен для получения времени кадра, т.е. я могу рассчитывать на то, что в probeInfo.Buffer находится прям целый S>>кадр, а не какой-то чанк или вообще какие-нибудь странные данные? Пока кажется, что в буффере действительно находится фрейм. C>Врать не буду — не знаю, могу ориентироваться только на описание splitmuxsink. Вообще-то, ты же ему на вход вроде уже закодированный поток передаёшь, или я чего-то не понимаю.
pipe в этом случае такой (это не то, о чем речь выше -- там я читаю mp4 файл):
rtspsrc ! rtph264depay ! h264parse ! splitmuxsink
Здравствуйте, Conductor, Вы писали:
C> Я повторил твой пример (под lin, надо будет под win попробовать, потому как по логам явная отсылка к d3d11, ты, кстати, с какой версией gstreamer работаешь?), но зависания не добился. Ежели в любом случае виснуть будет, то, на мой взгляд, следуюший шаг — это после того как все элементы в пайплайн добавятся, найти этот bufferpool и выставить ему max_buffers в 0.
Код целиком:
public static Pipeline BuildVideoReaderPipeline()
{
// Build video reader pipelinevar fileSrc = ElementFactory.Make("filesrc", "filesrc");
if (fileSrc == null)
{
throw new ArgumentNullException(nameof(fileSrc));
}
var decodebin = ElementFactory.Make("decodebin", "decodebin");
if (decodebin == null)
{
throw new ArgumentNullException(nameof(decodebin));
}
var appSink = new AppSink("my_appsink");
//appSink.NewSample += AppSink_NewSample;
appSink.EmitSignals = true;
appSink["sync"] = false;
decodebin.PadAdded += (o, args) =>
{
var appsinkPad = appSink.GetStaticPad("sink");
if (appsinkPad.IsLinked)
{
return;
}
var caps = args.NewPad.QueryCaps();
if (caps == null)
return;
args.NewPad.Link(appsinkPad);
};
fileSrc.PadAdded += (o, args) =>
{
var decPad = decodebin.GetStaticPad("sink");
if (decPad.IsLinked)
{
return;
}
var caps = args.NewPad.QueryCaps();
if (caps == null)
return;
args.NewPad.Link(decPad);
};
var pipeline = new Pipeline("video reader pipe");
pipeline.Add(fileSrc, decodebin, appSink);
var linkResult = Element.Link(fileSrc, decodebin);
linkResult = Element.Link(decodebin, appSink);
return pipeline;
}
public static void SearchFrameByNumber(Pipeline readerPipe, IEnumerable<string> videoFiles, int frameNumber)
{
if (readerPipe == null) throw new ArgumentNullException(nameof(readerPipe));
var fileSrc = readerPipe.GetByName("filesrc");
var appSink = (AppSink) readerPipe.GetByName("my_appsink");
readerPipe.SetName("frame_stepper");
var decodebin = readerPipe.GetByName("decodebin");
foreach (var videoFile in videoFiles)
{
fileSrc["location"] = videoFile;
readerPipe.SetState(State.Playing);
var step = 1; //fn тоже с 1 начинаетсяwhile (step < frameNumber)
{
appSink.PullSample();
step++;
}
Debug.SetDefaultThreshold(DebugLevel.Debug);
readerPipe.SetState(State.Null); //<-- тут виснет
fileSrc.Unlink(decodebin);
fileSrc.Link(decodebin);
}
}
Кодом людям нужно помогать!
Re[7]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Conductor, Вы писали:
C>Здравствуйте, Sharov, Вы писали:
S>>Вот если Paused, то не виснет. Правда пишет после S>>
S>>** WARNING **: 13:07:57.677: Changing the `location' property on filesrc when a file is open is not supported.
S>>и по сути работает с одним файлом (самым первым), т.е. читать будет только из него. C>Ну вот, а теперь, дождавшись того, что он перешёл в Paused, если его в Null перевести, зависнет?
Тоже самое. Собственно, если автомат состояний у них так и работает -- в Null через Paused,
соотв. что так что так результат одинаков. Виснет на SetState(Null). Выше код приложил. Может что-то не так
с параметрами appsink?
Кодом людям нужно помогать!
Re[9]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>>>Вот если Paused, то не виснет. Правда пишет после S>>>
S>>>** WARNING **: 13:07:57.677: Changing the `location' property on filesrc when a file is open is not supported.
S>>>и по сути работает с одним файлом (самым первым), т.е. читать будет только из него. C>>Ну вот, а теперь, дождавшись того, что он перешёл в Paused, если его в Null перевести, зависнет?
S>Тоже самое. Собственно, если автомат состояний у них так и работает -- в Null через Paused, S>соотв. что так что так результат одинаков. Виснет на SetState(Null).
Сдаётся мне, что в paused пайплайн у тебя так и не переходит. ::gst_element_set_state(m_pipeline, GST_STATE_PAUSED) возвращает GST_STATE_CHANGE_ASYNC, в отличии от GST_STATE_NULL, установка которого GST_STATE_CHANGE_ASYNC никогда не возвращает. И, предполагаю, что если ты после установки Paused запросишь state, то у тебя и на этом вызове повиснет, потому что в шарповом свойстве на get скорее всего используется что-то вроде ::gst_element_get_state(m_pipeline, &state, &pending, GST_CLOCK_TIME_NONE).
Автомат автоматом, но ведь по логам что получается: элементы паплайна переходят в новое состояние, но пока всё не встало кто-то еще работает и в результате заканчиваются буфера. Почему, собственно, я и подумал, что если у тебя он Paused успешно перейдёт, то и в Null потом сможет перейти.
Попробовал я под виндой — то же самое, не виснет. С разными файлами по разрешению и форматам, с задержками и без.
Отличия: 1. использование в плюсовом коде (фактически, сишном), не думаю, что это принципиально; 2. версия 1.20.6 (mingw), а не 1.22, как у тебя, здесь сказать ничего не могу, т.к. не смотрел, чего они там при переходе к 1.22 понаизменяли.
S>Выше код приложил. Может что-то не так с параметрами appsink?
Можно, конечно, попробовать с appSink["sync"] = true, но боюсь, что не поможет.
Здравствуйте, Conductor, Вы писали:
C>Здравствуйте, Sharov, Вы писали:
S>>>>Вот если Paused, то не виснет. Правда пишет после S>>>>
S>>>>** WARNING **: 13:07:57.677: Changing the `location' property on filesrc when a file is open is not supported.
S>>>>и по сути работает с одним файлом (самым первым), т.е. читать будет только из него. C>>>Ну вот, а теперь, дождавшись того, что он перешёл в Paused, если его в Null перевести, зависнет?
S>>Тоже самое. Собственно, если автомат состояний у них так и работает -- в Null через Paused, S>>соотв. что так что так результат одинаков. Виснет на SetState(Null). C>Сдаётся мне, что в paused пайплайн у тебя так и не переходит. ::gst_element_set_state(m_pipeline, GST_STATE_PAUSED) возвращает GST_STATE_CHANGE_ASYNC, в отличии от GST_STATE_NULL, установка которого GST_STATE_CHANGE_ASYNC никогда не возвращает. И, предполагаю, что если ты после установки Paused запросишь state, то у тебя и на этом вызове повиснет, потому что в шарповом свойстве на get скорее всего используется что-то вроде ::gst_element_get_state(m_pipeline, &state, &pending, GST_CLOCK_TIME_NONE). C>Автомат автоматом, но ведь по логам что получается: элементы паплайна переходят в новое состояние, но пока всё не встало кто-то еще работает и в результате заканчиваются буфера. Почему, собственно, я и подумал, что если у тебя он Paused успешно перейдёт, то и в Null потом сможет перейти.
И как побороть, а главное понять почему он там еще работает? Какой это может быть компонент?
Кстати, попробовал :
fileSrc.Unlink(decodebin);
var temp = readerPipe.SetState(State.Paused);
readerPipe.GetState(out State state, out State pending, Gst.Constants.MSECOND * 1000);
readerPipe.SetState(State.Null);
fileSrc.Link(decodebin);
Работает через раз, т.е. один файл проходит, а на втором стоп, и работает нестабильно, может и на первом файле
зависнуть.
C>Попробовал я под виндой — то же самое, не виснет. С разными файлами по разрешению и форматам, с задержками и без. C>Отличия: 1. использование в плюсовом коде (фактически, сишном), не думаю, что это принципиально; 2. версия 1.20.6 (mingw), а не 1.22, как у тебя, здесь сказать ничего не могу, т.к. не смотрел, чего они там при переходе к 1.22 понаизменяли.
Попробую на этой версии.
Кодом людям нужно помогать!
Re[10]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
S>Подумалось -- а может не использовать decodebin, может попробовать руками собрать все соотв. компоненты, которые он S>использует?
Это, само-собой, неплохой вариант, особенно если у тебя все файлы однотипные.
Re[11]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>И как побороть, а главное понять почему он там еще работает? Какой это может быть компонент?
Ну он же тебе в логах говорит про d3d11bufferpool2, явно намекая на d3d11. Визуализировать сформированный decodebin'ом пайплайн не хочешь? Думаю, что и прояснится многое и, если сам будешь формировать (о чём ты в следующем сообщении пишешь), поможет. И если явно будет виден пул как элемент, то тогда можно будет ему max_buffers выставить.
S>Кстати, попробовал :
S> fileSrc.Unlink(decodebin); S> var temp = readerPipe.SetState(State.Paused); S> readerPipe.GetState(out State state, out State pending, Gst.Constants.MSECOND * 1000); S> readerPipe.SetState(State.Null); S> fileSrc.Link(decodebin);
S>Работает через раз, т.е. один файл проходит, а на втором стоп, и работает нестабильно, может и на первом файле S>зависнуть.
И оно у тебя в логах не вопит, что отцепляешь элемент у работающего (playing) пайплайна?
Re[11]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>Подумалось -- а может не использовать decodebin, может попробовать руками собрать все соотв. компоненты, которые он S>использует?
Кстати, ты Gst.Parse.Launch по принципиальным соображениям не используешь или просто руки до него не дошли?
Re[12]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Conductor, Вы писали:
S>>Подумалось -- а может не использовать decodebin, может попробовать руками собрать все соотв. компоненты, которые он S>>использует? C>Кстати, ты Gst.Parse.Launch по принципиальным соображениям не используешь или просто руки до него не дошли?
Мне казалось, что если необходимо гибкое настраиваемое решение, то надо руками все собирать -- линковать,
добавлять пробы. А launch -- коробочный пайплайн для классических сценариев. Т.е. в случае launch контроля меньше.
Кодом людям нужно помогать!
Re[12]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Conductor, Вы писали:
S>>И как побороть, а главное понять почему он там еще работает? Какой это может быть компонент? C>Ну он же тебе в логах говорит про d3d11bufferpool2, явно намекая на d3d11. Визуализировать сформированный decodebin'ом пайплайн не хочешь? Думаю, что и прояснится многое и, если сам будешь формировать (о чём ты в следующем сообщении пишешь), поможет. И если явно будет виден пул как элемент, то тогда можно будет ему max_buffers выставить.
Здравствуйте, Sharov, Вы писали: S>>>И как побороть, а главное понять почему он там еще работает? Какой это может быть компонент? C>>Ну он же тебе в логах говорит про d3d11bufferpool2, явно намекая на d3d11. Визуализировать сформированный decodebin'ом пайплайн не хочешь? Думаю, что и прояснится многое и, если сам будешь формировать (о чём ты в следующем сообщении пишешь), поможет. И если явно будет виден пул как элемент, то тогда можно будет ему max_buffers выставить. S>http://files.rsdn.org/79401/graphviz.svg
Кажется, что такое на коленке собрал по образу и подобию, но не уверен, что все правильно и оптимально:
код
public static Pipeline BuildVideoReaderPipelineCustom()
{
// Build video reader pipelinevar fileSrc = ElementFactory.Make("filesrc", "filesrc");
if (fileSrc == null)
{
throw new ArgumentNullException(nameof(fileSrc));
}
var qtdemux = ElementFactory.Make("qtdemux", "qtdemux");
if (qtdemux == null)
{
throw new ArgumentNullException(nameof(qtdemux));
}
var queue = ElementFactory.Make("queue", "queue");
if (queue == null)
{
throw new ArgumentNullException(nameof(queue));
}
var h264parse = ElementFactory.Make("h264parse", "h264parse");
if (h264parse == null)
{
throw new ArgumentNullException(nameof(h264parse));
}
var avdec = ElementFactory.Make("avdec_h264", "avdec_h264");
if (avdec == null)
{
throw new ArgumentNullException(nameof(avdec));
}
var appSink = new AppSink("my_appsink");
//appSink.NewSample += AppSink_NewSample;
// appSink.EmitSignals = true;
appSink["sync"] = true;
h264parse.PadAdded += (o, args) =>
{
//args.Args[0] as var appsinkPad = appSink.GetStaticPad("sink");
if (appsinkPad.IsLinked)
{
return;
}
args.NewPad.Link(appsinkPad);
};
fileSrc.PadAdded += (o, args) =>
{
//args.Args[0] as var decPad = h264parse.GetStaticPad("sink");
if (decPad.IsLinked)
{
return;
}
args.NewPad.Link(decPad);
};
qtdemux.PadAdded += (o, args) =>
{
//args.Args[0] as var qPad = queue.GetStaticPad("sink");
if (qPad.IsLinked)
{
return;
}
args.NewPad.Link(qPad);
};
var pipeline = new Pipeline("video reader pipe");
pipeline.Add(fileSrc, qtdemux, queue, h264parse, avdec, appSink);
var linkResult = Element.Link(fileSrc, qtdemux);
linkResult = Element.Link(qtdemux, queue);
linkResult = Element.Link(queue, h264parse);
linkResult = Element.Link(h264parse, avdec);
linkResult = Element.Link(avdec, appSink);
return pipeline;
}
public static void SearchFrameByNumber(Pipeline readerPipe, IEnumerable<string> videoFiles, int frameNumber)
{
if (readerPipe == null) throw new ArgumentNullException(nameof(readerPipe));
var fileSrc = readerPipe.GetByName("filesrc");
var appSink = (AppSink) readerPipe.GetByName("my_appsink");
readerPipe.SetName("frame_stepper");
foreach (var videoFile in videoFiles)
{
fileSrc["location"] = videoFile;
readerPipe.SetState(State.Playing);
var step = 1; //fn тоже с 1 начинаетсяwhile (step < frameNumber)
{
var sample = appSink.PullSample();
var fn = $"{Path.GetFileNameWithoutExtension(videoFile)}_{step}.jpeg";
SaveImg(sample,Path.Combine("d:\\test_out\\",fn));
step++;
}
readerPipe.SetState(State.Ready);
}
}
Не до конца понимаю, почему простой варинат filesrc ! queue ! h264parse ! appsink не сработал...
Методом тыка что-то заработало.
Смущает несколько моментов:
1)код saveimg имеет такую строчку
var neededFrame = Global.VideoConvertSample(sample, new Caps("image/jpeg"), Constants.MSECOND * 100);
и что-то первое время по таймауту во время отладки падало, пришлось увеличить. Сейчас откатил как выше, вроде нормально, но что это было??
2) сыпятся такие сообщения
0:00:11.961293800 30572 000002232259B7E0 WARN basesrc gstbasesrc.c:3693:gst_base_src_start_complete:<filesrc> pad not activated yet
0:00:11.963705700 30572 000002232218CF00 WARN qtdemux qtdemux.c:3245:qtdemux_parse_trex:<qtdemux> failed to find fragment defaults for stream 1
Что с этим делать?
Кодом людям нужно помогать!
Re[14]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Sharov, Вы писали:
S>>>>И как побороть, а главное понять почему он там еще работает? Какой это может быть компонент? C>>>Ну он же тебе в логах говорит про d3d11bufferpool2, явно намекая на d3d11. Визуализировать сформированный decodebin'ом пайплайн не хочешь? Думаю, что и прояснится многое и, если сам будешь формировать (о чём ты в следующем сообщении пишешь), поможет. И если явно будет виден пул как элемент, то тогда можно будет ему max_buffers выставить. S>>http://files.rsdn.org/79401/graphviz.svg
S>Кажется, что такое на коленке собрал по образу и подобию, но не уверен, что все правильно и оптимально:
У тебя видеокарта на боевых машинах предполагается, и если да, то какая, NVidia? Сколько видеопотоков одновременно? Нужно смотреть загрузку CPU. Ежели всё устраивает, дык и ладно. С GPU свои заморочки есть (с ограничением экземпляров кодирования на процесс).
Decodebin у тебя d3d11h264dec выбирал, он же, вроде, hardware использует, значит, условия соответствуют. Выбор осуществляется из элементов, которые могут работать в данных условиях, элемента с максимальным рангом.
А декодировать h264 кто будет в этом пайплайне? А сейчас у тебя этим avdec занимается.
S>Методом тыка что-то заработало.
S>Смущает несколько моментов:
S>1)код saveimg имеет такую строчку S>var neededFrame = Global.VideoConvertSample(sample, new Caps("image/jpeg"), Constants.MSECOND * 100); S>и что-то первое время по таймауту во время отладки падало, пришлось увеличить. Сейчас откатил как выше, вроде нормально, но что это было??
Где-то чего-то на что-то наложилось, другой ответ мне сложно дать. А тебе и в боевой работе изображения надо будет так же сохранять? Или с ними ещё что-то делать? Там же просто плагины разные есть, может быть можно и без доп.кода обойтись. Ну и, на всякий случай, выходной формат на уровне пайплайна можно разный запросить (с помощью videconvert).
S>2) сыпятся такие сообщения S>0:00:11.961293800 30572 000002232259B7E0 WARN basesrc gstbasesrc.c:3693:gst_base_src_start_complete:<filesrc> pad not activated yet S>0:00:11.963705700 30572 000002232218CF00 WARN qtdemux qtdemux.c:3245:qtdemux_parse_trex:<qtdemux> failed to find fragment defaults for stream 1
S>Что с этим делать?
Дык, видимо, не раскочегарилось ещё. У тебя readerPipe.SetState(State.Playing) GST_STATE_CHANGE_ASYNC возвращает? А в лог плюётся во время PullSample()? Не хочешь GetState'ом подождать завершения изменения состояния? Оно как часто эти сообщения выдаёт?
Re[13]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>Мне казалось, что если необходимо гибкое настраиваемое решение, то надо руками все собирать -- линковать, S>добавлять пробы. А launch -- коробочный пайплайн для классических сценариев. Т.е. в случае launch контроля меньше.
Ну, согласись, что decodebin, например, не очень способствует гибкости и настраиваемости решения.
Launch же просто по текстовому описанию формирует пайплайн, как напишешь — так и сформирует. А ежели ты элементам имена дашь, то потом запросто из сформированного паплайна получешь требуемый элемент по имени и делай с ним всё, что хочешь. Особенно при исследовании разных вариантов пайплайна удобно: каждый раз всё в коде переписывать — застрелиться, а с launch — текстовое описание изменил и всё.
Re[15]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Conductor, Вы писали:
S>>Кажется, что такое на коленке собрал по образу и подобию, но не уверен, что все правильно и оптимально: C>У тебя видеокарта на боевых машинах предполагается, и если да, то какая, NVidia? Сколько видеопотоков одновременно?
Вообще планируется 8 потоков, 8 камер. Про gpu не знаю, но скорее всего нет.
C>Нужно смотреть загрузку CPU. Ежели всё устраивает, дык и ладно. С GPU свои заморочки есть (с ограничением экземпляров кодирования на процесс). C>Decodebin у тебя d3d11h264dec выбирал, он же, вроде, hardware использует, значит, условия соответствуют. Выбор осуществляется из элементов, которые могут работать в данных условиях, элемента с максимальным рангом. C>https://developer.ridgerun.com/wiki/index.php?title=GStreamer_modify_the_elements_rank
Ок, изучу вопрос.
S>>Не до конца понимаю, почему простой варинат filesrc ! queue ! h264parse ! appsink не сработал... C>А декодировать h264 кто будет в этом пайплайне? А сейчас у тебя этим avdec занимается.
Ну вот я не очень в предметной области разбираюсь, а зачем тогда h264parse нужен? Сразу декодировать нельзя?
S>>Методом тыка что-то заработало.
S>>Смущает несколько моментов:
S>>1)код saveimg имеет такую строчку S>>var neededFrame = Global.VideoConvertSample(sample, new Caps("image/jpeg"), Constants.MSECOND * 100); S>>и что-то первое время по таймауту во время отладки падало, пришлось увеличить. Сейчас откатил как выше, вроде нормально, но что это было?? C>Где-то чего-то на что-то наложилось, другой ответ мне сложно дать. А тебе и в боевой работе изображения надо будет так же сохранять? Или с ними ещё что-то делать? Там же просто плагины разные есть, может быть можно и без доп.кода обойтись. Ну и, на всякий случай, выходной формат на уровне пайплайна можно разный запросить (с помощью videconvert).
Да, надо будет сохранять. jpegenc я смотрел, возможно я вернусь к нему. Но кажется, что VideoConvertSample и jpenenc
это одно и тоже. Т.е. на первый взгляд, особой разницы нету. Я смотрел по исходникам VideoConvertSample и том строит
некий пайплайн, который, чую я, крайне похож на jpegenc. В коде я уже знаю номер интересного мне кадра, и мне нужно получить только его.
В случае использования jpegenc (... ! jpegenc ! appsink), это будет прогоняться для всех кадров, соотв. лишние накладные расходы.
S>>2) сыпятся такие сообщения S>>0:00:11.961293800 30572 000002232259B7E0 WARN basesrc gstbasesrc.c:3693:gst_base_src_start_complete:<filesrc> pad not activated yet S>>0:00:11.963705700 30572 000002232218CF00 WARN qtdemux qtdemux.c:3245:qtdemux_parse_trex:<qtdemux> failed to find fragment defaults for stream 1 S>>Что с этим делать? C>Дык, видимо, не раскочегарилось ещё. У тебя readerPipe.SetState(State.Playing) GST_STATE_CHANGE_ASYNC возвращает? А в лог плюётся во время PullSample()? Не хочешь GetState'ом подождать завершения изменения состояния? Оно как часто эти сообщения выдаёт?
Здравствуйте, Sharov, Вы писали:
C>>У тебя видеокарта на боевых машинах предполагается, и если да, то какая, NVidia? Сколько видеопотоков одновременно?
S>Вообще планируется 8 потоков, 8 камер. Про gpu не знаю, но скорее всего нет.
8 HD потоков? Что-то мне подсказывает, что gpu может понадобиться.
S>>>Не до конца понимаю, почему простой варинат filesrc ! queue ! h264parse ! appsink не сработал... C>>А декодировать h264 кто будет в этом пайплайне? А сейчас у тебя этим avdec занимается.
S>Ну вот я не очень в предметной области разбираюсь, а зачем тогда h264parse нужен? Сразу декодировать нельзя?
Ну, насколько я понимаю, парсер, грубо говоря, данные для декодера готовит, временем опять же заведует, запросы обрабатывает ("handles queries (POSITION/DURATION/SEEKING/FORMAT/CONVERT)"). Декодер что: ему сказали декодировать — он декодирует.
Кроме того, декодеры для одного и того же формата могут быть разные, hard/soft. Да ты же и сам по меньшей мере с двумя уже дело имел для одного и того же видео (d3d11h264dec, avdec_h264). А есть ещё и nvh264dec, например...
Здравствуйте, reversecode, Вы писали:
R>когда плясать с гстримером надоест вашему дателю R>нанимаются прогеры и делается решение под себя R>либо выбирается готовое что присутсвует на рынке
И на чем, в смысле библиотек, пилить это решение под себя?
R>любопытно только, через какое время к этому прийдет ваш датель R>я бы дал максимум полтора года от начала прод использования гстримера
пилятся исходя из бюджета
нет денег, хотим попробовать mvp — берут как вы gstreamer/ffmpeg/vlc итд
есть чуть чуть денег
на волю кодера любая либа, он сам выберет исходя из своего опыта что потянет
есть много денег
на честно порядочность кодера
может сказать что запилил свое с нуля, а внутри запихнет какое нибудь опенсорсное решение с гитхаба
либо опять же gstreamer/ffmpeg итд запихнет
либо реально запилит все с нуля
gstreamer это уровень, скрутил запустил, как то работает
да, некоторые ко умудряются занянуть его как либу/фреймворк
те же вон с хаха ру которые постоянно вак крутят
или во всяких месседжерах он как av либа интегрирован
но это уже про то как умеет продавать бизнесс
некоторым важно позицировать свой продукт как что то новое(и я такое увжаю и люблю обращать свое внимание)
а некоторым не важно что это сумер мега новый инновационные не имещий аналогов продукт построенные на основе gstreamera
а таким, пронюханого потребителя не купить, и они этого не понимают
если это решение как saas
когда потребителю должно быть до места что там под капотом
там начинается нагрузка на самих поддеживающих
такие mvp решения когда пользователи динамические
тяжело сопровождать
нужны как миниум пару devops шаровых которые будут постоянно следить и подкручивать подтюнивать на разные сложные кейсы новых юзерей
скрипты и прочая хрень
а с учетом того что это не все кейсы покрывает
то нужно будет держать под рукой еще и кодера который будет лезть в глубины того же gstreamera что бы разобраться
когда бизнессу(начальству сверху) это надоедает(а это около полтора года)
бизнесс либо переходит в этап выживания
либо он делает решительные шаги по улучшению этой модели
и выбора или чего то уже готового
либо написание своего, с расчетом уже продажи не только самого saas, но и продукта
так в какой нише и на каком этапе там сейчас вы с шефом?))
1) А каков жизненный цикл буффера, от src до sink'а, это что-то типа tcp\ip, когда каждый элемент(слой) добавляет
к буфферу какую-то конкретную инф-ию или как? Вот например на вход h264parse идет сырое видео из src, а что на выходе --
какой-то новый буффер или старый с какой-то инф-ей, пригодной для следующих эл-ов, типа, avdec_h264?
2) Как можно хранить метаинф-ию в mp4 файле для каждого фрейма, у меня был вопрос -- https://lists.freedesktop.org/archives/gstreamer-devel/2023-July/081587.html
Я не нашел как это можно сделать. Т.е. когда открою файл для чтения, например в цикле PullSample, как мне извлекать эту инф-ию?
Ответ выше по ссылке был не очень полезен...
Кодом людям нужно помогать!
Re[17]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, Sharov, Вы писали:
S>Речь идет о (максимум) 8 rtsp потоках, которые надо в mp4 загнать. Неужели это так дорого по cpu?
Я же сказал "может понадобиться". С одной стороны тебе по rtsp h264 уже приходит, так что если ты на этой машине только записью файлов будешь заниматься, то, видимо, ресурсов хватит. А вот если на этой же машине нужно какие-то доп. операции делать, кодирование/декодирование, доп. обработка и т.д., то тогда могут быть вопросы. Ведь бывает же так, что в процессе выполнения работ требования меняются. Ведь бывает же так иногда
Здравствуйте, 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'ы переиспользовать или может проще новый создавать каждый раз? Не проводили эксперименты,
есть мнение на этот счет? Может, с конкретно этим пайплайном (см. выше), плюнуть и каждый раз занового его создавать?
Здравствуйте, Conductor, Вы писали:
C>Правильно ли я понял: результирующий файл должен содержать 4 синхронизированных видеопотока и при воспроизведении они должны отображаться синхронно ("решётка" или на отдельных экранах), так?
да именно так
скажите пожалуйста а вам приходилось записывать mp4 используя gstreame одним файлом 4-5 часов подряд
я тоже думаю что на текущей работе меня уволят как только сделапю то что им срочно нужно
поэтому ищу новую работу
Здравствуйте, sergey2b, Вы писали:
S>скажите пожалуйста а вы используйте cerbero на операционной системе или в докере
Я стараюсь то, что можно, по максимуму в контейнеры распихать, особенно сборку third party. Но в нашем случае для этих целей плюшки докера особо не нужны и поэтому исторически сложилось, что используется LXC, в том числе и для cerbero.
Re[30]: Относительно твоих вопросов в рассылке gstreamer'а
Здравствуйте, sergey2b, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
C>>Правильно ли я понял: результирующий файл должен содержать 4 синхронизированных видеопотока и при воспроизведении они должны отображаться синхронно ("решётка" или на отдельных экранах), так?
S>да именно так
Ну, пайплайн-то накидать для этого варианта можно и не так сложно. Другой вопрос, что, на мой взгляд, будет минимум 2 проблемы:
1. Где именно окажется bottleneck и как его обойти;
2. Вопрос синхронизации: ежели можно принять концепцию "то, что сейчас имеется для записи, и является текущим", то — хорошо (повторюсь, для нас, например, такой вариант приемлем), а вот если нужно брать за базу значения времени камер (то, над чем Антон бьётся), то тут, конечно, забавы будет достаточно.
S>скажите пожалуйста а вам приходилось записывать mp4 используя gstreame одним файлом 4-5 часов подряд
4-5 — нет, у нас сложилось, что используются часовые фрагменты. Кстати, в gstreamer 1.16.1 баг был, что максимальный размер записанного файла 2 GB (если память мне не изменяет). А потом процесс как бы шёл (ошибка не выдавалась), но реальной записи не было. На эти грабли мы наступили, весело было.
S>я тоже думаю что на текущей работе меня уволят как только сделапю то что им срочно нужно
Уволить-то дело не хитрое, но, как грится, есть нюанс: а поддерживать разработанное решение (особенно на первых порах) им Пушкин будет или кто? Не, каждый, безусловно, кузнец своего НЕсчастья, но с их стороны будет абсолютным идиотизмом полностью рвать отношения. Может, кстати, имеет смысл целенаправленно усложнить им вопросы сопровождения?
S>поэтому ищу новую работу
Здравствуйте, Conductor, Вы писали:
C>Здравствуйте, sergey2b, Вы писали:
S>>скажите пожалуйста а вы используйте cerbero на операционной системе или в докере
C>Я стараюсь то, что можно, по максимуму в контейнеры распихать, особенно сборку third party. Но в нашем случае для этих целей плюшки докера особо не нужны и поэтому исторически сложилось, что используется LXC, в том числе и для cerbero.
я пытался собрать эти контейнеры у меня не получилось
различные ошибки при сборки часть я исправил
Linux Setup
On Linux, you will only need a distribution with python >= 3.6. Cerbero will use your package manager to install all other required packages during bootstrap.
там проблем быть не должно.
А, вспомнил нюанс: они начиная с 1.20 многое переделали (сейчас уже не помню, с репами вроде что-то), я, когда вопрос изучал, это для себя отметил, и мы, собственно, тогда и приняли решение на 1.20 перейти, потому что процесс сборки простой получился.
у нас базовая ОС ubuntu 20.04
поэтому пришлось использовать последний docker-gstreamer поддерживающий ubuntu 20.04 docker-gstreamer-2020-12-30T23-16-11Z
superuser@xxx:~/Documents/docker-gstreamer-2020-12-30T23-16-11Z$ ./build-release.sh 1.20
20.04: Pulling from library/ubuntu
Digest: sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
Status: Image is up to date for ubuntu:20.04
docker.io/library/ubuntu:20.04
[+] Building 0.2s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile-dev-dependencies 0.0s
=> => transferring dockerfile: 155B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2.35kB 0.0s
=> [1/3] FROM docker.io/library/ubuntu:20.04 0.0s
=> CACHED [2/3] COPY docker/build-gstreamer/install-dependencies / 0.0s
=> CACHED [3/3] RUN ["/install-dependencies"] 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:18b452a3f3e92ea0fb1d5e21ad275eab3dc0e803917d6a3dcd6ccaf2d7685040 0.0s
=> => naming to docker.io/restreamio/gstreamer:dev-dependencies 0.0s
[+] Building 163.8s (7/8) docker:default
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile-dev-downloaded 0.0s
=> => transferring dockerfile: 1.37kB 0.0s
=> [internal] load metadata for docker.io/restreamio/gstreamer:dev-dependencies 0.0s
=> [1/4] FROM docker.io/restreamio/gstreamer:dev-dependencies 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 3.60kB 0.0s
=> CACHED [2/4] COPY docker/build-gstreamer/download / 0.0s
=> ERROR [3/4] RUN ["/download"] 163.7s
------
> [3/4] RUN ["/download"]:
0.289 Cloning into 'gstreamer'...
132.2 /gstreamer /
133.6 Switched to a new branch '1.20'
133.6 Branch '1.20' set up to track remote branch '1.20' from 'origin'.
133.6 /
133.6 Cloning into 'libnice'...
138.5 /libnice /
138.5 Note: switching to '1dbe38d6abe74c415bf4ae44190980c61874a04f'.
138.5
138.5 You are in 'detached HEAD' state. You can look around, make experimental
138.5 changes and commit them, and you can discard any commits you make in this
138.5 state without impacting any branches by switching back to a branch.
138.5
138.5 If you want to create a new branch to retain commits you create, you may
138.5 do so (now or later) by using -c with the switch command. Example:
138.5
138.5 git switch -c <new-branch-name>
138.5
138.5 Or undo this operation with:
138.5
138.5 git switch -
138.5
138.5 Turn off this advice by setting config variable advice.detachedHead to false
138.5
138.5 HEAD is now at 1dbe38d test-fallback: fix stack buffer overflow with new candidate API
138.5 /
138.5 Cloning into 'gst-plugins-base'...
162.2 /gst-plugins-base /
162.2 error: pathspec '1.20' did not match any file(s) known to git
------
Dockerfile-dev-downloaded:30
--------------------
28 | COPY docker/build-gstreamer/download /
29 |
30 | >>> RUN ["/download"]
31 |
32 | COPY docker/build-gstreamer/compile /
--------------------
ERROR: failed to solve: process "/download" did not complete successfully: exit code: 1
и последней версией
superuser@xxx:~/Documents/docker-gstreamer-2020-12-30T23-16-11Z$ ./build-release.sh 1.22.5
20.04: Pulling from library/ubuntu
Digest: sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
Status: Image is up to date for ubuntu:20.04
docker.io/library/ubuntu:20.04
[+] Building 0.2s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile-dev-dependencies 0.0s
=> => transferring dockerfile: 155B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 2.35kB 0.0s
=> [1/3] FROM docker.io/library/ubuntu:20.04 0.0s
=> CACHED [2/3] COPY docker/build-gstreamer/install-dependencies / 0.0s
=> CACHED [3/3] RUN ["/install-dependencies"] 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:18b452a3f3e92ea0fb1d5e21ad275eab3dc0e803917d6a3dcd6ccaf2d7685040 0.0s
=> => naming to docker.io/restreamio/gstreamer:dev-dependencies 0.0s
[+] Building 165.9s (7/8) docker:default
=> [internal] load build definition from Dockerfile-dev-downloaded 0.0s
=> => transferring dockerfile: 1.37kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/restreamio/gstreamer:dev-dependencies 0.0s
=> [1/4] FROM docker.io/restreamio/gstreamer:dev-dependencies 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 3.60kB 0.0s
=> CACHED [2/4] COPY docker/build-gstreamer/download / 0.0s
=> ERROR [3/4] RUN ["/download"] 165.8s
------
> [3/4] RUN ["/download"]:
0.242 Cloning into 'gstreamer'...
136.5 /gstreamer /
137.8 Note: switching to '1.22.5'.
137.8
137.8 You are in 'detached HEAD' state. You can look around, make experimental
137.8 changes and commit them, and you can discard any commits you make in this
137.8 state without impacting any branches by switching back to a branch.
137.8
137.8 If you want to create a new branch to retain commits you create, you may
137.8 do so (now or later) by using -c with the switch command. Example:
137.8
137.8 git switch -c <new-branch-name>
137.8
137.8 Or undo this operation with:
137.8
137.8 git switch -
137.8
137.8 Turn off this advice by setting config variable advice.detachedHead to false
137.8
137.8 HEAD is now at bf6ce1d64a Release 1.22.5
137.8 /
137.8 Cloning into 'libnice'...
140.3 /libnice /
140.3 Note: switching to '1dbe38d6abe74c415bf4ae44190980c61874a04f'.
140.3
140.3 You are in 'detached HEAD' state. You can look around, make experimental
140.3 changes and commit them, and you can discard any commits you make in this
140.3 state without impacting any branches by switching back to a branch.
140.3
140.3 If you want to create a new branch to retain commits you create, you may
140.3 do so (now or later) by using -c with the switch command. Example:
140.3
140.3 git switch -c <new-branch-name>
140.3
140.3 Or undo this operation with:
140.3
140.3 git switch -
140.3
140.3 Turn off this advice by setting config variable advice.detachedHead to false
140.3
140.3 HEAD is now at 1dbe38d test-fallback: fix stack buffer overflow with new candidate API
140.3 /
140.3 Cloning into 'gst-plugins-base'...
164.3 /gst-plugins-base /
164.3 error: pathspec '1.22.5' did not match any file(s) known to git
------
Dockerfile-dev-downloaded:30
--------------------
28 | COPY docker/build-gstreamer/download /
29 |
30 | >>> RUN ["/download"]
31 |
32 | COPY docker/build-gstreamer/compile /
--------------------
ERROR: failed to solve: process "/download" did not complete successfully: exit code: 1
Здравствуйте, sergey2b, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
S>у нас базовая ОС ubuntu 20.04 S>поэтому пришлось использовать последний docker-gstreamer поддерживающий ubuntu 20.04 docker-gstreamer-2020-12-30T23-16-11Z
S>может вы сталкивались с такой ошибкой
2. Не принципиально, но 1.20 — это бранч, я tags использую (типа 1.20.6).
3. Как видно из логов, ошибка возникает при попытке переключиться на бранч/tag в gst-plugins-base и понятно почему: нет его там. И опять же понятно почему его там нет (я же писал об этом):
GStreamer 1.20 Release Notes
Development in GitLab was switched to a single git repository containing all the modules
Ты не хочешь собственный docker-контейнер замастрячить: типа, взять за основу убунтовый требуемой версии, поставить там питон (если нет его там), а дальше нехай cerbero работает — его для того и делали. Не думаю, что это будет сложно.
Здравствуйте, reversecode, Вы писали:
R>а некоторым не важно что это сумер мега новый инновационные не имещий аналогов продукт построенные на основе gstreamera
Вот есть libav который много где работает с аппаратным ускорением, и на армах, и на "интелах". Мне прямо интересно, а что вместо него использовать, чтобы оно и кодировало/декодировало, а ещё и с 0 копированием на дисплей выводило, да не в своё окно, а как текстурой в GLES?
Здравствуйте, reversecode, Вы писали:
R>libav это тот который форк отщипенцами из ffmpeg и который умер и уже больше двух лет не обновляется?
Хорошо, давай по-другому. Вот есть ffmpeg... и далее по списку вопросов выше...
немного не понятно к чему вы ведете
но давайте тыпа догадаюсь
я знаю продукты которые писали это все с нуля для себя то о чем вы говорите
в опен сорсе этого нет
в чем это вышло круче чем те кто тупо подключил очередной libav/libffmpeg ?
вышло более компактно
и с точки зрения маркетинга "более привлекательнее"
чем то как я упомянул в посте на который вы ответили
переводя на совсем протой язык
кто может делает
кто не может берет готовое
Здравствуйте, reversecode, Вы писали:
R>и с точки зрения маркетинга "более привлекательнее"
Специализированные решения буду ещё и более оптимальны и быстрее, но это уже заточка под архитектуру. R>чем то как я упомянул в посте на который вы ответили
Я пытаюсь понять в чём профит взять условный NVIDIA SDK, своять на нём и получить что-то что работает только на NVIDIA, но не на АМД и интел. С другой стороны, берётся ffmpeg и почти не меняя кода у нас есть поддержка nvidia, amd, mali, intel через тот же vaapi там, куда ffmpeg портирован, а портирован он много куда. R>кто может делает R>кто не может берет готовое
Но можно пересобрать ffmpeg без того что не нужно и он будет компактнее.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, reversecode, Вы писали:
R>>и с точки зрения маркетинга "более привлекательнее" K>Специализированные решения буду ещё и более оптимальны и быстрее, но это уже заточка под архитектуру.
R>>чем то как я упомянул в посте на который вы ответили K>Я пытаюсь понять в чём профит взять условный NVIDIA SDK, своять на нём и получить что-то что работает только на NVIDIA, но не на АМД и интел. С другой стороны, берётся ffmpeg и почти не меняя кода у нас есть поддержка nvidia, amd, mali, intel через тот же vaapi там, куда ffmpeg портирован, а портирован он много куда.
рассматривается кейс некоего транскодинга ?
если да, то условный ffmpeg может не покрывает сложных кейсов с кастомными настройками, некими другими функциями которых не вытянули в ffmpeg или багами в имплементации самого ffmpeg
амд кстати почему то многие уже забросили
intel с ваапи так себе, и он же квиксинк
nvidia набер ван по моим наблюжениям
с мали не сталкивался, но это скорее всего мобаил и делается это несколько по другому через интерфес который предоставляет сама ява андроида
или разве что какойто ембеддед без андроида
R>>кто может делает R>>кто не может берет готовое K>Но можно пересобрать ffmpeg без того что не нужно и он будет компактнее.
не будет
и вопрос не только в размере
а в том что в таких решенях разработчик хочет контроллировать максимальный контролфлов
а беря некий ffmpeg он зкрывает глаза и считает что там все ок
к примеру
одно дело когда имеешь доступ к апи к примеру нвидиии
а другое дело когда ты имеешь дело с прослойкой ffmpeg к апи нвидии
если ваш кейс покрывается полностью интерфейсом либ ffmpeg
и что внутри вам не надо знать, то да, вам подходит
а другим очевидно нет
Здравствуйте, reversecode, Вы писали:
R>рассматривается кейс некоего транскодинга ?
Рассматривается кейз когда надо что-то декодировать, рескейлить и отобразить на экране, желательно с аппаратным ускорением попробовав 2-3 интерфейса, а если поддержки нет, то откатиться до программного. В промежутке, ещё и в контейнер сохранить, а потом и в сеть отправить. NVIDIA API такое поддерживает, а Intel? R>амд кстати почему то многие уже забросили
Да-да... все прямо и забили... R>intel с ваапи так себе, и он же квиксинк
Ну хер знает https://github.com/intel/media-driver R>nvidia набер ван по моим наблюдениям
В разных сегментах своё. Где nvidia, где интел, где АРМ с мали, где тот же интел и амд как встройки в проц. Напридумывали столько, что охренеть. Завтра вообще на рокчипе будут железки и там надо будет запустить. R>с мали не сталкивался, но это скорее всего мобаил и делается это несколько по другому через интерфес который предоставляет сама ява андроида R>или разве что какойто ембеддед без андроида
И с андройдом тоже используют ffmpeg как бэкенд для медии. Прикинь! Просто до чёрта кода написано на этой базе. R>не будет
А ты пробовал? R>а другое дело когда ты имеешь дело с прослойкой ffmpeg к апи нвидии
А можешь написать что нужно такого вот экзотического? R>а другим очевидно нет
Большинству, скорее всего, не нужно.
мы в разных сферах и меряемся пипьсами разных фаун
у слона и муравья они очевидно разные
так что невижу смысла
единственное что я забыл
это всякие бонгакам сайтики где нужно стримить женские пиписьки
а это иногда те же самые обычные PC
в которых и интелл и амд
но в контексте сервер сайда они умерли
Здравствуйте, reversecode, Вы писали:
R>мы в разных сферах и меряемся пипьсами разных фаун R>у слона и муравья они очевидно разные
Обожжжи... но у кого, по итогу, больше? R>но в контексте сервер сайда они умерли
Там сейчас виртуальные GPU рулить начинают, а это нвидлиа и лицензия, наверное, в таком случае SDK лучше всего, но если есть варианты...
164.4 Need to get 148 MB of archives.
164.4 After this operation, 562 MB of additional disk space will be used.
164.4 Do you want to continue? [Y/n] Abort.
164.4 Traceback (most recent call last):
Привет.
S>но когда я полпытался сделать dockerfile столкнулся с такой проблеммой S>оргинальный файл не мой но я его творчески слегка изменил
S>Dockerfile:39 S>-------------------- S> 37 | # hack: to pass "-y" argument to apt-get install launched by "cerbero bootstrap" S> 38 | RUN sed -i 's/apt-get install/apt-get install -y/g' ./cerbero/bootstrap/linux.py S> 39 | >>> RUN ./cerbero-uninstalled bootstrap S> 40 | #RUN ./cerbero-uninstalled bootstrap \ S> 41 | # && ./cerbero-uninstalled build glib \ S>-------------------- S>ERROR: failed to solve: process "/bin/sh -c ./cerbero-uninstalled bootstrap" did not complete successfully: exit code: 1
S>я не смог найти как подставит N
S>164.4 Need to get 148 MB of archives. S>164.4 After this operation, 562 MB of additional disk space will be used. S>164.4 Do you want to continue? [Y/n] Abort. S>164.4 Traceback (most recent call last):
1. Я не понял: почему ты пытался поставить N, почему ты не хочешь поставить Y? Как он будет работать, если не установлены требуемые ему пакеты?
2. У тебя же вот это обламывается, потому что там -y нет, почему там её нет — отдельный вопрос:
(Ктати, похоже, что твой оригинальный файл довольно старый, потому что, судя по содержимому ./cerbero/bootstrap/linux.py, вот это "RUN sed -i 's/apt-get install/apt-get install -y/g' ./cerbero/bootstrap/linux.py" уже не требуется.)
Здравствуйте, sergey2b, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
S>я собрал gstreamer vaapi используя https://github.com/restreamio/docker-gstreamer S>внес несколько небольших исправлений
S>декодер HD видео 60 fps на 12700k использует 48% GPU
1 поток? 720p? Приходит h264? Декодируется для отображения? Загрузку GPU каким инструментом анализируешь, чем-нибудь типа intel-gpu-top? С общей загрузкой CPU что получилось?
48% что-то до фига.
S>>декодер HD видео 60 fps на 12700k использует 48% GPU
C>1 поток? 720p? Приходит h264? Декодируется для отображения? Загрузку GPU каким инструментом анализируешь, чем-нибудь типа intel-gpu-top? С общей загрузкой CPU что получилось? C>48% что-то до фига.
Здравствуйте, sergey2b, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
S>>>декодер HD видео 60 fps на 12700k использует 48% GPU
C>>1 поток? 720p? Приходит h264? Декодируется для отображения? Загрузку GPU каким инструментом анализируешь, чем-нибудь типа intel-gpu-top? С общей загрузкой CPU что получилось? C>>48% что-то до фига.
S>примеры для тестирования придумал не я
S>1) gst-launch-1.0 filesrc location=/temp/test.mp4 ! qtdemux ! h264parse ! vaapih264dec ! fakesink
S>2) gst-launch-1.0 filesrc location=/temp/test.mp4 ! qtdemux ! h264parse ! avdec_h264 ! fakesink
Ну, ёпрст... Кто тебе эти примеры в таком виде дал (если тестируется для отображения)?! Ведь здесь будет пахать с МАКСИМАЛЬНО ВОЗМОЖНОЙ скоростью (без привязки к реальному времени). Ведь для отображения тестируем, так? Я правильно понимаю?
Здравствуйте, sergey2b, Вы писали:
S>если не секрет а вы где то используйте gstreamer в нагруженных приложениях
Делал заказ на gstream чуваку который разрабатывал север умного видеонаблюдения. Были заказы на встройку, есть челики которые на Jetson делали шлем со встроенной камерой и даже, вроде, HUD. S>а то я почитал статью https://developer.ridgerun.com/wiki/index.php/Embedded_GStreamer_Performance_Tuning S>и насторожило везде пишут что стример всего на 10 проц медленней чем ffmpeg а из статьи по сылки получаеться что разработчик прикладывает усилия что записать поток всего 30fps
КМК, что-то подобное было бы и для ffmpeg. Всегда есть какой-то гемор когда дело доходит до оптимизации, особенно с памятью.
добрый день скажите пожалуйста как вы считаете насколько ревльно сделать на gstreamer — multivew
когда видео с 4 разных камер отображаються на одном мониторе и сохраняеться в mp4
Здравствуйте, sergey2b, Вы писали:
S>Здравствуйте, Conductor, Вы писали:
S>добрый день скажите пожалуйста как вы считаете насколько ревльно сделать на gstreamer — multivew S>когда видео с 4 разных камер отображаються на одном мониторе и сохраняеться в mp4
Ну, можно. И по-разному можно сделать. Я ж не знаю, какая там архитектура софта — что до gstreamer'а идет (appsrc или v4l2src или ещё что), что после. Так что решение будет зависеть от конкретной постановки задачи.