После еще нескольких экспериментов с GStreamer и библиотекой RTSP-сервера ситуация с обработкой ошибок усложняется.
Нормальный путь
Канонический способ увидеть ошибки в конвейере GStreamer - добавить наблюдателя в шину конвейера и прослушивать сообщения об ошибках.
def watcher(bus, message, *user_data);
if message.type == Gst.MessageType.ERROR:
error, message = message.parse_error()
# TODO: Do something with the error
my_pipeline.get_bus().add_watch(
GLib.PRIORITY_DEFAULT,
watcher,
None)
Однако вы не можете сделать это с конвейерами, которые вы предоставляете GstRtspServer. Это связано с тем, что GstRtspServer ожидает установки собственного наблюдателя на шину конвейера, и только один наблюдатель может быть подключен к шине одновременно. Это особенно прискорбно, потому что это мешает нам слушать любые события в конвейере, а не только ошибки.
Мой обходной путь
Мы можем разделить конвейер на две части: одну, которая отвечает за подверженный ошибкам процесс соединения с исходным и декодирующим кадрами, и другую, которая отвечает за кодирование результирующих кадров и загрузку их для GstRtspServer. Затем мы можем использовать плагин intervideo для связи между ними.
Например, допустим, вы пытаетесь выполнить потоковую передачу из файла в формате VP8. Наш первый конвейер, отвечающий за чтение и декодирование кадров, будет выглядеть так:
filesrc location="{filepath}" ! decodebin ! intervideosink channel="file-channel"
... и наш второй конвейер, отвечающий за кодирование и загрузку кадра, будет выглядеть так:
intervideosrc channel="file-channel" ! videoconvert ! vp8enc deadline=1 ! rtpvp8pay name=pay0 pt=96
Ключевым моментом здесь является то, что GstRtspServer должен управлять только вторым конвейером, поскольку именно конвейер предоставляет полезные данные. Первый управляется нами, и мы можем прикрепить к нему нашего собственного наблюдателя.
который разумно реагирует на ошибки и делает все, что нам нужно. Конечно, это не идеальное решение, потому что мы не можем реагировать на ошибки, связанные с кодированием и полезной нагрузкой, но мы получили возможность получать ошибки, связанные с чтением файла и его декодированием. Теперь мы также можем выполнять другие задачи, связанные с сообщениями, например, перехватывать сообщение о завершении потока для зацикливания видеофайла.