Здравствуйте, Conductor, Вы писали:
S>>Да, я еще погоняю под Debug. У меня такой вариант использования -- нахожу нужный кадр, конвертирую в jpeg, перевожу pipe в Ready.
S>>И далее по кругу, с другим файлом. Ну т.е. один pipe для чтения файлов, а не 1 к 1. Ну так вот, после pipe.SetState(Ready) -- блочится
S>>на этой строке. Буду более детально смотреть, т.к. совершенное не понятно что не так. Тут пишут, что надо в Ready переводить.
C>У тебя там блочится на первой же итерации?
Да.
C>И такой вопрос: а не занимает ли у тебя перевод конвертация достаточно продолжительное время?
Я вообще убрал конвертацию и просто n раз делаю pullsample в цикле (3 кадра читаю и иду дальше).
C>По моему опыту в большинстве случаев виснет если буфера переполнены. Я бы попробовал queue в пайплайн добавить. Сначала без ограничения размера и посмотрел бы, как размер памяти процесса себя ведёт.
Вот тут я добавил больше деталей и debug сообщения --
https://lists.freedesktop.org/archives/gstreamer-devel//2023-August/081632.html
C>Ну и менял бы параметры, если используется SetState, только после того, как получено сообщение, что состояние изменено. Ты bus-овские сообщения обрабатываешь?
В данном случае нет.
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 находится прям целый
кадр, а не какой-то чанк или вообще какие-нибудь странные данные? Пока кажется, что в буффере действительно находится фрейм.