I'm experimenting with the videomixer and videomixer2 elements, and having very good luck with them when using live streams. I want to add file-based streams into the mix, and have them either repeat or disappear upon completion.<div>
<br></div><div>Repeating a single stream is relatively easy. We can listen for the EOS event on the bus callback and seek to the beginning when the event arrives:</div><div><br></div><div>=====================================================================</div>
<div>gboolean bus_cb (GstBus *bus, GstMessage *message, gpointer data) {</div><div>...</div><div><div><span class="Apple-tab-span" style="white-space:pre"> </span>switch (GST_MESSAGE_TYPE (message)) {</div><div>...</div><div>
<span class="Apple-tab-span" style="white-space:pre"> </span>case GST_MESSAGE_EOS:</div></div><div><div><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span>if (!gst_element_seek_simple (GST_ELEMENT(pipeline), GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 1)) {</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span>g_warning ("Failed to Return to Beginning of Stream\n");</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span>}</div></div><div><span class="Apple-tab-span" style="white-space:pre"> </span><span class="Apple-tab-span" style="white-space:pre"> </span>break;</div>
<div>...</div><div>=====================================================================</div><div><br></div><div>Works fine, but the "src" in the "message" variable seems to originate from the pipeline, and not any of the elements linked to the filesrc. So with this approach I seem to be tied to seeking on the entire pipeline instead of a subelement.</div>
<div><br></div><div>The next approach I tried was to create a new element "infinitestream". I figured maybe I could trap the EOS event in this element and seek to the beginning for just a filesrc, like so:</div>
<div><br></div><div>gst-launch videomixer2 name=mix sink_0::zorder=1 sink_1::zorder=0 ! ffmpegcolorspace ! video/x-raw-rgb ! ximagesink sync=false filesrc location=videofile.mp4 ! decodebin2 ! identity sync=true ! infinitestream ! ffmpegcolorspace ! video/x-raw-yuv ! mix. videotestsrc pattern=snow is-live=TRUE ! mix.</div>
<div><br></div><div>This comes close, with the stream successfully repeating and playing at the correct rate, but the live pads in the mixer become frozen.</div><div><br></div><div>Here is the relevant code in "infinitestream":</div>
<div><br></div><div>=====================================================================</div><div><div>static void</div><div>gst_infinite_stream_class_init (GstInfiniteStreamClass * klass)</div><div>{</div><div>...</div>
<div> GST_BASE_TRANSFORM_CLASS (klass)->event =</div><div> GST_DEBUG_FUNCPTR (gst_infinitestream_sink_eventfunc);</div><div>...</div><div>}</div></div><div><br></div><div>...</div><div><br></div><div><div>static gboolean</div>
<div>gst_infinitestream_sink_eventfunc (GstBaseTransform * trans, GstEvent * event) {</div><div> if(event->type != GST_EVENT_EOS) {</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>return TRUE;</div>
<div> }</div><div><br></div><div> if (!gst_element_seek_simple (GST_ELEMENT(trans), GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 1)) {</div><div> g_warning ("Infinite Loop Failed to Return to Beginning of Stream\n");</div>
<div> }</div><div><br></div><div> return FALSE;</div><div>}</div></div><div>=====================================================================</div><div><br></div><div>Could anyone comment on this approach? Is there anything I can do out-of-the-box to implement this behavior, or would a change to the gstreamer source be necessary? I'd be happy to investigate such a change if anyone can point me in the right direction.</div>