C ++ gstreamer - легко l oop GIF-файл - PullRequest
1 голос
/ 30 января 2020

У меня есть оболочка C ++ поверх библиотеки GStreamer, которая отображает различные типы файлов для моего приложения. В настоящее время я реализую поддержку изображений, и хотя я получил jpgs / pngs без проблем, у меня проблемы с GIF. Файл отображается правильно, он анимирован, хотя я, кажется, не могу найти способ легко oop GIF, поэтому он отображается так же, как, например, в браузере. Я работаю на Linux с Waylandsink. GStreamer версия 1.14.4.

Я пробовал много разных способов:

  1. Поиск с gst_element_seek или gst_element_seek_simple под GST_MESSAGE_EOS. Это приводит к зависанию дисплея в конце и вызывает бесконечное l oop изменений состояния (от PAUSED-> PLAYING, затем GST_MESSAGE_EOS)
  2. Установка состояния конвейера на NULL, а затем на PLAYING под GST_MESSAGE_EOS. Это работает, но создает черный промежуток между перезагрузками, что меня не устраивает, поскольку я хочу, чтобы gif равнялся l oop плавно.
  3. Поиск первого сегмента, когда конвейер переходит в состояние 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-файлов?

...