<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Hello,</p>
    <p>Theoretically the queue2 element has what you are looking for and
      it has a ring buffer property.  However, at least from my own
      personal experimentation you can't seek on the data in the ring
      buffer, even if it is muxed video.  uridecodebin also has a ring
      buffer property, and it uses queue2, however it disables this
      functionality on streaming sources, so I am not exactly sure what
      the purpose of the ring buffer is actually for.  There is the
      timeshift element:</p>
    <p><a class="moz-txt-link-freetext" href="https://github.com/kkonopko/gst-fluendo-timeshift">https://github.com/kkonopko/gst-fluendo-timeshift</a></p>
    <p>But it may be deprecated for queue2.</p>
    <p>You may be better served recording to a streamable mkv file and
      using another pipeline that reads from it.  You could jump to live
      playback by using the current time of the recording pipeline,
      because you wont know the duration otherwise.  In my experience
      this works fairly well, and may achieve the same effect you are
      trying to accomplish.</p>
    <p>Hope that helps!<br>
    </p>
    <p>Cheers,<br>
      Michael.<br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 11/6/2017 2:36 PM, Fritjof Büttner
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAKzOO4anS4TWtoMFqi7wYYENZW=xTMJLK0aYRsn0MJeyOYQRoQ@mail.gmail.com">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div dir="ltr">
        <div>
          <div>
            <div>
              <div>
                <div>Hello,<br>
                  <br>
                </div>
                I am quite new to Gstreamer and it seems like an amazing
                tool to me.<br>
              </div>
              <div>I would like to create a pipeline that does the
                following:<br>
              </div>
              - get a video stream from a live source (i.e., webcam)<br>
            </div>
            - encode the live stream as is into a file<br>
          </div>
          - at the same time, show the live stream in a user interface,
          however the user is able to seek to abitrary positions in the
          entire stream.</div>
        <div>I know that I need a tee element for the two simultaneous
          tasks, but currently I am having trouble realizing the
          time-shift buffering part between the source and the
          videosink. I thought I could add a queue element before the
          sink to act as a (ring-)buffer to enable seeking.<br>
        </div>
        <div><br>
        </div>
        <div>This is my experimental pipeline so far (live videotestsrc
          instead of a webcam):<br>
        </div>
        <div><br>
          <span style="font-family:monospace,monospace">gst-launch-1.0
            videotestsrc do-timestamp=true is-live=true name=src !
            video/x-raw, format=RGB, width=640, height=480,
            framerate=20/1 ! videoconvert ! timeoverlay !  queue
            max-size-buffers=0 max-size-bytes=0 max-size-time=0 name=q !
            autovideosink</span><br>
          <br>
        </div>
        While this pipeline is running, I can send <span
          style="font-family:monospace,monospace">seek_simple</span>
        signals to the queue, which results in the frame of the
        requested timestamp being shown (verified by the timeoverlay).
        But then the output pauses and will not resume playing (pipeline
        state remains PLAYING). Weirdly, when I query the <span
          style="font-family:monospace,monospace">current-level-*</span>
        properties of the queue, it seems to be empty. In that case I
        don't understand where the seeked frame comes from. Does the
        pipeline itself also buffer data?<br>
        At one point during my experiments, I saw the queue actually
        filling up quickly (I don't recall the parameters I was using
        then), using some GB or memory after only a few seconds.<br>
        I found the <a
href="https://gstreamer.freedesktop.org/documentation/application-development/advanced/buffering.html#timeshift-buffering"
          moz-do-not-send="true">time-shift buffering</a> scenario in
        the documentation which I think describes best what I am trying
        to do, but it's only a short paragraph and there is no dedicated
        "file-ringbuffer" element, so I tried my luck with the queue. <br>
        <br>
        Is it possible to achieve my goal using Gstreamer? If so, which
        elements should I look at? And is there a way to get the total
        duration of a live pipeline? All <span
          style="font-family:monospace,monospace">query_duration</span>
        calls return -1. Lastly, is there a way to buffer minutes worth
        of live video (e.g. 720p) in memory?
        <div>
          <div><br>
          </div>
          <div>I'm curious to hear your thoughts! Many thanks in
            advance,</div>
          <div>Fritjof</div>
          <div><br>
          </div>
          <div>--<br>
          </div>
          <div><br>
          </div>
          <div>This is my experiment code in Python:<br>
          </div>
          <div>
            <pre style="color:rgb(0,0,0);background:rgb(255,255,255) none repeat scroll 0% 0%">GObject<span style="color:rgb(128,128,48)">.</span>threads_init<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(128,128,48)">)</span>
Gst<span style="color:rgb(128,128,48)">.</span>init<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(7,71,38)">None</span><span style="color:rgb(128,128,48)">)</span>

pipeline_string <span style="color:rgb(128,128,48)">=</span> <span style="color:rgb(0,0,230)">"videotestsrc do-timestamp=true is-live=true horizontal-speed=1 name=src "</span> \
                  <span style="color:rgb(0,0,230)">"! video/x-raw, format=RGB, width=640, height=480, framerate=20/1 "</span> \
                  <span style="color:rgb(0,0,230)">"! videoconvert "</span> \
                  <span style="color:rgb(0,0,230)">"! timeoverlay shaded-background=true "</span> \
                  <span style="color:rgb(0,0,230)">"! queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 name=q "</span> \
                  <span style="color:rgb(0,0,230)">"! autovideosink"</span>

pipeline <span style="color:rgb(128,128,48)">=</span> Gst<span style="color:rgb(128,128,48)">.</span>parse_launch<span style="color:rgb(128,128,48)">(</span>pipeline_string<span style="color:rgb(128,128,48)">)</span>
source <span style="color:rgb(128,128,48)">=</span> pipeline<span style="color:rgb(128,128,48)">.</span>get_by_name<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"src"</span><span style="color:rgb(128,128,48)">)</span>
queue <span style="color:rgb(128,128,48)">=</span> pipeline<span style="color:rgb(128,128,48)">.</span>get_by_name<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"q"</span><span style="color:rgb(128,128,48)">)</span>

<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span>pipeline<span style="color:rgb(128,128,48)">.</span>set_state<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>State<span style="color:rgb(128,128,48)">.</span>PLAYING<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>

time<span style="color:rgb(128,128,48)">.</span>sleep<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,140,0)">5</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current source position:"</span><span style="color:rgb(128,128,48)">,</span> source<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current queue position:"</span><span style="color:rgb(128,128,48)">,</span> queue<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current pipeline position:"</span><span style="color:rgb(128,128,48)">,</span> pipeline<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>

seek <span style="color:rgb(128,128,48)">=</span> pipeline<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">[</span><span style="color:rgb(0,140,0)">1</span><span style="color:rgb(128,128,48)">]</span> <span style="color:rgb(68,170,221)">-</span> <span style="color:rgb(0,140,0)">3</span> <span style="color:rgb(68,170,221)">*</span> Gst<span style="color:rgb(128,128,48)">.</span>SECOND
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"seek to -3 sec:"</span><span style="color:rgb(128,128,48)">,</span> seek<span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">if</span> queue<span style="color:rgb(128,128,48)">.</span>seek_simple<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">,</span> Gst<span style="color:rgb(128,128,48)">.</span>SeekFlags<span style="color:rgb(128,128,48)">.</span>FLUSH <span style="color:rgb(68,170,221)">|</span> Gst<span style="color:rgb(128,128,48)">.</span>SeekFlags<span style="color:rgb(128,128,48)">.</span>KEY_UNIT<span style="color:rgb(128,128,48)">,</span> seek<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">:</span>
    <span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Seek OK"</span><span style="color:rgb(128,128,48)">)</span>

<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current source position:"</span><span style="color:rgb(128,128,48)">,</span> source<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current queue position:"</span><span style="color:rgb(128,128,48)">,</span> queue<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current pipeline position:"</span><span style="color:rgb(128,128,48)">,</span> pipeline<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Queue buffer level:"</span><span style="color:rgb(128,128,48)">,</span> queue<span style="color:rgb(128,128,48)">.</span>get_property<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"current-level-buffers"</span><span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">,</span>
      <span style="color:rgb(0,0,230)">"- bytes:"</span><span style="color:rgb(128,128,48)">,</span> humanize<span style="color:rgb(128,128,48)">.</span>naturalsize<span style="color:rgb(128,128,48)">(</span>queue<span style="color:rgb(128,128,48)">.</span>get_property<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"current-level-bytes"</span><span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">,</span> binary<span style="color:rgb(128,128,48)">=</span><span style="color:rgb(7,71,38)">True</span><span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">,</span>
      <span style="color:rgb(0,0,230)">"- time:"</span><span style="color:rgb(128,128,48)">,</span> queue<span style="color:rgb(128,128,48)">.</span>get_property<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"current-level-time"</span><span style="color:rgb(128,128,48)">)</span> <span style="color:rgb(68,170,221)">/</span> Gst<span style="color:rgb(128,128,48)">.</span>SECOND<span style="color:rgb(128,128,48)">)</span>

time<span style="color:rgb(128,128,48)">.</span>sleep<span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,140,0)">2</span><span style="color:rgb(128,128,48)">)</span>
seek <span style="color:rgb(128,128,48)">=</span> source<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">[</span><span style="color:rgb(0,140,0)">1</span><span style="color:rgb(128,128,48)">]</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"Current source position:"</span><span style="color:rgb(128,128,48)">,</span> source<span style="color:rgb(128,128,48)">.</span>query_position<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">)</span><span style="color:rgb(128,128,48)">)</span>
<span style="color:rgb(128,0,0);font-weight:bold">print</span><span style="color:rgb(128,128,48)">(</span><span style="color:rgb(0,0,230)">"jump to front"</span><span style="color:rgb(128,128,48)">,</span> seek<span style="color:rgb(128,128,48)">)</span>
queue<span style="color:rgb(128,128,48)">.</span>seek_simple<span style="color:rgb(128,128,48)">(</span>Gst<span style="color:rgb(128,128,48)">.</span>Format<span style="color:rgb(128,128,48)">.</span>TIME<span style="color:rgb(128,128,48)">,</span> Gst<span style="color:rgb(128,128,48)">.</span>SeekFlags<span style="color:rgb(128,128,48)">.</span>FLUSH <span style="color:rgb(68,170,221)">|</span> Gst<span style="color:rgb(128,128,48)">.</span>SeekFlags<span style="color:rgb(128,128,48)">.</span>KEY_UNIT<span style="color:rgb(128,128,48)">,</span> seek<span style="color:rgb(128,128,48)">)</span></pre>
          </div>
          <div><br>
          </div>
          These are the print outputs:</div>
        <div><br>
        </div>
        <div><span style="font-family:monospace,monospace">Current
            source position: (True, cur=5026269432)<br>
            Current queue position: (True, cur=5026269432)<br>
            Current pipeline position: (True, cur=4950176384)<br>
            seek to -3 sec: 1950209076<br>
            Seek OK<br>
            Current source position: (True, cur=1950209076)<br>
            Current queue position: (True, cur=1950209076)<br>
            Current pipeline position: (False, cur=0)<br>
            Queue buffer level: 0 - bytes: 0 Bytes - time: 0.0<br>
            Current source position: (True, cur=2126269432)<br>
            jump to front 2126269432</span><br>
        </div>
        <div>
          <div><br>
          </div>
        </div>
      </div>
      <br>
      -- <br>
      This message has been scanned for viruses and dangerous content by
      <br>
      <a href="http://www.efa-project.org" moz-do-not-send="true"><b>E.F.A.
          Project</b></a>, and is believed to be clean.
      <br>
      <a
href="http://lsefa1.linear-systems.com/cgi-bin/learn-msg.cgi?id=70954100053.A34D3&token=76824e6ec9ca9feec880e5e6c636502e"
        moz-do-not-send="true">Click here to report this message as
        spam.</a>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
gstreamer-devel mailing list
<a class="moz-txt-link-abbreviated" href="mailto:gstreamer-devel@lists.freedesktop.org">gstreamer-devel@lists.freedesktop.org</a>
<a class="moz-txt-link-freetext" href="https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel">https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>