GStreamer. Как установить выходной формат видеоконвертации?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 GStreamer. Как установить выходной формат видеоконвертации?

Сообщение Anonymous »


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

OpenCV запрещен

Как я представляю решение.
Нам нужна последовательность элементов:
filesrc -> decodebin -> videoconvert -> autovideosink
decodebin декодирует видеоданные из любого формата в x-raw и отправляет в videoconvert.
videoconvert преобразует видеокадры из любого формата кадров в определенный формат (например, я хочу RGB).
Мы можем использовать механизм Pad Probe для подключения нашего обратного вызова, где мы можем редактировать видео. Я хочу установить формат RGB для вывода videoconvert и работать с этим форматом в обратном вызове.

int main(int argc, char **argv) { gst_init(&argc, &argv); GstElement *pipeline = gst_pipeline_new("видеошоу"); GstElement *filesrc = gst_element_factory_make("filesrc", "videofile"); g_object_set(filesrc, «местоположение», «video.mp4», NULL); GstElement *decodebin = gst_element_factory_make("decodebin", "декодер"); GstElement *videoconvert = gst_element_factory_make("videoconvert", "конвертер"); GstElement *videosink = gst_element_factory_make("xvimagesink", "videosink"); gst_bin_add_many(GST_BIN(конвейер), filesrc, decodebin, videoconvert, Videosink, NULL); if (gst_element_link(filesrc, decodebin) != TRUE || gst_element_link(videoconvert, videosink) != TRUE) { g_printerr ("Элементы не могут быть связаны.\n"); gst_object_unref (конвейер); вернуть -1; } // связываем декодирование и видеоконвертацию через некоторое время, когда декодирование прочитает метаданные файла g_signal_connect(decodebin, "pad-added", G_CALLBACK(on_decodebin_ready), videoconvert); // устанавливаем наш обратный вызов для редактирования видео GstPad *vc_output = gst_element_get_static_pad(videoconvert, "src"); gst_pad_add_probe (vc_output, GST_PAD_PROBE_TYPE_BUFFER, on_pad_probe, NULL, NULL); gst_object_unref (vc_output); GstStateChangeReturn возврат = gst_element_set_state (конвейер, GST_STATE_PLAYING); если (рет == GST_STATE_CHANGE_FAILURE) { g_printerr ("Невозможно перевести конвейер в состояние воспроизведения.\n"); gst_object_unref (конвейер); вернуть -1; } GstBus *bus = gst_element_get_bus(конвейер); GstMessage *msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GstMessageType(GST_MESSAGE_ERROR | GST_MESSAGE_EOS)); если (сообщение != NULL) { GОшибка *ошибка; gchar *debug_info; переключатель (GST_MESSAGE_TYPE (мсг)) { случай GST_MESSAGE_ERROR: gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Ошибка получена от элемента %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Отладочная информация: %s\n", отладочная_информация? debug_info: «нет»); g_clear_error (&ошибка); g_free (debug_info); перерыв; случай GST_MESSAGE_EOS: g_print ("Достигнут конец потока.\n"); перерыв; по умолчанию: /* Нам не следует обращаться сюда, потому что мы запрашивали только ОШИБКИ и EOS */ g_printerr ("Получено неожиданное сообщение.\n"); перерыв; } gst_message_unref (сообщение); } gst_object_unref (автобус); gst_element_set_state (конвейер, GST_STATE_NULL); gst_object_unref (конвейер); вернуть 0; } static void on_decodebin_ready(GstElement *decodebin, GstPad *new_pad, GstElement *videoconvert) { GstPad *vc_input = gst_element_get_static_pad(videoconvert, "sink"); если (gst_pad_is_linked(vc_input)) { gst_object_unref (vc_input); g_print ("Мы уже связаны. Игнорирование.\n"); возвращаться; } g_print("Получена новая площадка '%s' от '%s':\n", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(decodebin)); GstCaps *new_pad_caps = gst_pad_get_current_caps(new_pad); GstStructure *new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); const gchar *new_pad_type = gst_structure_get_name(new_pad_struct); if (g_str_has_prefix(new_pad_type, "видео")) { гинт ш, ч; gst_structure_get_int(new_pad_struct, "ширина", &w); gst_structure_get_int(new_pad_struct, «высота», &h); GstPad *vc_output = gst_element_get_static_pad(videoconvert, "src"); GstCaps *new_output_caps = gst_caps_new_simple("video/x-raw", "формат", G_TYPE_STRING, "RGB", "ширина", G_TYPE_INT, ш, "высота", G_TYPE_INT, h, NULL); /* это правда, но ограничивает видео/x-raw, format=(string)RGB, width=(int)640, height=(int)360 не принимается */ bool ок = gst_pad_set_caps (vc_output, new_output_caps); gst_caps_unref (new_output_caps); GstPadLinkReturn ret = gst_pad_link(new_pad, vc_input); если (GST_PAD_LINK_FAILED(рет)) g_print("Тип %s, но ссылка не удалась.\n", new_pad_type); еще g_print("Ссылка выполнена успешно (тип '%s').\n", new_pad_type); } gst_caps_unref (new_pad_caps); gst_object_unref (vc_input); } static GstPadProbeReturn on_pad_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) { /* просто я проверяю формат видео */ GstCaps *caps = gst_pad_get_current_caps(pad); gchar *str = gst_caps_to_string(caps); g_print (строка, NULL); g_free (стр); gst_caps_unref (заглавные буквы); вернуть GST_PAD_PROBE_OK; } decodebin имеет формат I420.
И я жду srcpad для videoconvert в формате RGB, но on_pad_probe печатает YV12 > (почему?).
Также в консоли у меня появились строки:
ограничивает видео/x-raw, формат=(string)RGB, ширина=(int)640, высота=(int)360 не принимается
и
Неправильный порядок закрепленных событий, перед «началом потока» появились «заглавные буквы»

Мне просто нужно место, где я могу редактировать видеокадры. И я никак не могу привести изображение в нужный мне формат.
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»