C ++ gstreamer-无缝循环GIF文件

时间:2020-01-30 11:05:22

标签: c++ gstreamer

我在GStreamer库上有一个C ++包装程序,它为我的应用程序显示各种文件类型。我目前正在实现对图像的支持,尽管我使jpgs / pngs正常工作没有任何问题,但我在使用GIF时遇到了麻烦。该文件显示正确,正在制作动画,尽管我似乎找不到任何无缝循环GIF的方法,因此它显示的方式与浏览器相同。我正在使用Waylandsink开发Linux。 GStreamer版本1.14.4。

我尝试了许多不同的方法:

  1. gst_element_seek下以gst_element_seek_simpleGST_MESSAGE_EOS进行搜索。这样会将显示屏挂在最后,并产生无限的状态变化循环(从PAUSED-> PLAYING后跟GST_MESSAGE_EOS
  2. 将管道状态设置为NULL,然后在PLAYING下设置为GST_MESSAGE_EOS。这项工作有效,但是在重新加载之间产生了一个黑缝,这让我不满意,因为我希望gif无缝循环。
  3. 当管道进入PLAYING状态时寻求第一段,然后在GST_MESSAGE_SEGMENT_DONE下寻找。在第一帧时直接跳到EOS。

这是我建立管道的方式:

m_pipeline = gst_parse_launch("playbin uri=file:///home/user/test.gif video-sink=waylandsink");

这是我的循环:

  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);

如何像使用GIF循环一样使循环无缝?

0 个答案:

没有答案