У меня есть оболочка C ++ поверх библиотеки GStreamer, которая отображает различные типы файлов для моего приложения. В настоящее время я реализую поддержку изображений, и хотя я получил jpgs / pngs без проблем, у меня проблемы с GIF. Файл отображается правильно, он анимирован, хотя я, кажется, не могу найти способ легко oop GIF, поэтому он отображается так же, как, например, в браузере. Я работаю на Linux с Waylandsink. GStreamer версия 1.14.4.
Я пробовал много разных способов:
- Поиск с
gst_element_seek
или gst_element_seek_simple
под GST_MESSAGE_EOS
. Это приводит к зависанию дисплея в конце и вызывает бесконечное l oop изменений состояния (от PAUSED-> PLAYING, затем GST_MESSAGE_EOS
) - Установка состояния конвейера на
NULL
, а затем на PLAYING
под GST_MESSAGE_EOS
. Это работает, но создает черный промежуток между перезагрузками, что меня не устраивает, поскольку я хочу, чтобы gif равнялся l oop плавно. - Поиск первого сегмента, когда конвейер переходит в состояние
PLAYING
, а затем искать обратно под GST_MESSAGE_SEGMENT_DONE
. Это переходит прямо к EOS в первом кадре.
Вот как я строю конвейер:
m_pipeline = gst_parse_launch("playbin uri=file:///home/user/test.gif video-sink=waylandsink");
Вот мой l oop:
m_ret = gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
if (m_ret == GST_STATE_CHANGE_FAILURE) {
g_printerr("Unable to set the pipeline to the playing state.\n");
gst_object_unref(m_pipeline);
exit(0);
}
m_bus = gst_element_get_bus(m_pipeline);
m_terminate = FALSE;
GError *err;
gchar *debug_info;
bool seekOnce = false;
do {
m_msg =
gst_bus_timed_pop_filtered(m_bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_SEGMENT_DONE));
/* Parse message */
if (m_msg != NULL) {
switch (GST_MESSAGE_TYPE(m_msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error(m_msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n",
GST_OBJECT_NAME(m_msg->src), err->message);
g_printerr("Debugging information: %s\n",
debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
m_terminate = TRUE;
break;
case GST_MESSAGE_EOS:
g_print("Received EOS!\n");
// This produces no errors but loops PAUSED->PLAYING->EOS
if(gst_element_seek(m_pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
g_print("SEEK FAILED!\n");
}
// this loops, but since it's re-starting the entire pipeline the loop is not seamless
//gst_element_set_state(m_pipeline, GST_STATE_NULL);
//gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
break;
case GST_MESSAGE_STATE_CHANGED:
if (GST_MESSAGE_SRC(m_msg) == GST_OBJECT(m_pipeline)) {
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed(m_msg, &old_state, &new_state,
&pending_state);
g_print("Pipeline state changed from %s to %s\n",
gst_element_state_get_name(old_state),
gst_element_state_get_name(new_state));
if(new_state == GstState::GST_STATE_PLAYING) {
// this jumps straight to EOS on the first frame, GST_MESSAGE_SEGMENT_DONE is not received at all
if(!seekOnce)
// gst_element_seek_simple(m_pipeline, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH), 0);
seekOnce = true;
}
}
}
break;
case GST_MESSAGE_SEGMENT_DONE:
//gst_element_seek_simple(m_pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_SEGMENT, 0);
break;
default:
/* We should not reach here */
g_printerr("Unexpected message received.\n");
break;
}
gst_message_unref(m_msg);
}
} while (!m_terminate);
Как мне сделать l oop бесшовным, как это должно быть с зацикливанием GIF-файлов?