Search code examples
gstreamermatroska

matroskamux timebar does not work when replaying video on vlc


I succely save the video streaming in .mkv with matroskamux but when I open it with vlc, I can not advance the video with the timebar. Do you have any idea? I add offset-to-zero but nothing change.

GError* error = NULL;
GstElement* source;
GstElement* filesink;
GstElement* matrox;

GstCaps* caps = gst_caps_new_simple("application/x-rtp",
           "media", G_TYPE_STRING, "video",
           "payload", G_TYPE_INT, 96,
           "encoding-name", G_TYPE_STRING, "H264",
           NULL);

pipeline = gst_parse_launch("udpsrc name=source ! rtpjitterbuffer !rtph264depay !h264parse !avdec_h264 ! tee name = t !queue !autovideoconvert !matroskamux name=matrox !filesink name=myFile t. ! queue ! videoconvert !d3dvideosink name=mysink", &error);

filesink = gst_bin_get_by_name(GST_BIN(pipeline), "myFile");
g_object_set(filesink, "location", strPathVideo.c_str(), NULL);

matrox = gst_bin_get_by_name(GST_BIN(pipeline), "matrox");
g_object_set(G_OBJECT(matrox), "offset-to-zero", true, NULL);

source = gst_bin_get_by_name(GST_BIN(pipeline), "source");
g_object_set(G_OBJECT(source), "caps", caps, NULL);
g_object_set(G_OBJECT(source), "port", m_port, NULL);

Solution

  • I tried to emulate recording branch of your pipe as realistic as I can.

    gst-launch-1.0 videotestsrc ! autovideoconvert ! x264enc ! h264parse ! avdec_h264 ! matroskamux name=matrox ! filesink location=matroska_video.mkv
    

    I cannot use timebar of vlc with this video.

    When I add EOS parameter (-e) at the end the video becomes scrollable with time bar.

    gst-launch-1.0 videotestsrc ! autovideoconvert ! x264enc ! h264parse ! avdec_h264 ! matroskamux name=matrox ! filesink location=myFile.mkv -e
    

    This is because video headers that contain time information are written at the end of stream.

    For this reason you need to add an eos handler to your pipe. I found this page in the documentation that gives an example.

    Summary from example: you add a signal handler to your pipe

    g_signal_connect (bus, "message", (GCallback) cb_message,
      pipeline);
    

    And the signal handler will look like:

    static void
    cb_message (GstBus     *bus,
                GstMessage *message,
                gpointer    user_data)
    {
      GstElement *pipeline = GST_ELEMENT (user_data);
    
      switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_ERROR:
          g_print ("we received an error!\n");
          g_main_loop_quit (loop);
          break;
        case GST_MESSAGE_EOS:
          g_print ("we reached EOS\n");
          g_main_loop_quit (loop);
          break;
        case GST_MESSAGE_APPLICATION:
        {
          if (gst_message_has_name (message, "ExPrerolled")) {
            /* it's our message */
            g_print ("we are all prerolled, do seek\n");
            gst_element_seek (pipeline,
                1.0, GST_FORMAT_TIME,
                GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
                GST_SEEK_TYPE_SET, 2 * GST_SECOND,
                GST_SEEK_TYPE_SET, 5 * GST_SECOND);
    
            gst_element_set_state (pipeline, GST_STATE_PLAYING);
          }
          break;
        }
        default:
          break;
      }
    }