<div dir="ltr">Sebastian,<div><br></div><div>Thanks for your response. As you surmised, the problem is that I'm not finalizing the MP4 file -- but it's not for lack of trying.</div><div><br></div><div>Inspired by the example in the App Developers Manual, I'd been trying to finalize the file by sending an EOS through the bin that contains the mux and filesink. I can make that work, but the EOS also tends to want to shut down the whole pipeline, which isn't what I want. So then I found that I could override the bin's handle_message method to discard the EOS before it bubbled up to the pipeline. It works, but what a mess!</div>
<div><br></div><div>So I was happy to see the solution that you linked below that shows the code simply setting the bin to GST_STATE_NULL to trigger the finalizing of the file. But I can't seem to get that to work in my app. The critical difference seems to be that as soon as I decide that the muxer has seen all the data intended for the current file, I want to block the sourcepad on the queue upstream of the bin so that the queue resumes accumulating video. And my impression is that if I'm blocking buffers on that pad (with GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER), the transition to NULL state doesn't finalize the file -- the elements transition to GST_STATE_NULL, but the finalization code isn't called.</div>
<div><br></div><div>I understand that the bin is operating in a thread created by the upstream queue, so I can sort of see how blocking the queue's source pad might cause problems for the bin. But if I unblock the queue's source pad, then data is going to need to stream somewhere and that's not what I want. So I feel like I'm stuck.</div>
<div><br></div><div>The critical bits of code are:</div><div><br></div><div><div><font face="courier new, monospace">static GstPadProbeReturn</font></div><div><font face="courier new, monospace">blockpad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)</font></div>
<div><font face="courier new, monospace">{</font></div><div><font face="courier new, monospace">  app_data * app = user_data;</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">  gst_element_set_state (app->bin, GST_STATE_NULL);</font></div>
<div><font face="courier new, monospace">  gst_bin_remove (GST_BIN(app->pipeline), app->bin);</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">  return GST_PAD_PROBE_OK;</font></div>
<div><font face="courier new, monospace">}</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">void block_pipeline(app_data *app)</font></div><div><font face="courier new, monospace">{</font></div>
<div><font face="courier new, monospace">  g_print ("Blocking pipeline...\n");</font></div><div><font face="courier new, monospace">  app->blockpad_probe_id = gst_pad_add_probe (app->blockpad,</font></div>
<div><font face="courier new, monospace">      GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_BUFFER,</font></div><div><font face="courier new, monospace">      blockpad_probe_cb, app, NULL);</font></div><div><font face="courier new, monospace">}</font></div>
<div><font face="courier new, monospace"><br></font></div></div><div><br></div><div>And the tail of the log looks like this (note the absence of the message "Updating remaining values and sending last data") which the muxer emits when it properly finalizes a file):</div>
<div><br></div><div><div><font face="courier new, monospace">0:00:21.687079000 88586 0x7fe8b40f48a0 LOG                    qtmux gstqtmux.c:2442:gst_qt_mux_handle_buffer:<mux> selected pad video_0 with time 0:00:19.766666666</font></div>
<div><font face="courier new, monospace">0:00:21.687123000 88586 0x7fe8b40f48a0 LOG                    qtmux gstqtmux.c:2315:gst_qt_mux_add_buffer:<mux> Pad (video_0) dts updated to 0:00:19.666666666</font></div><div>
<font face="courier new, monospace">0:00:21.687142000 88586 0x7fe8b40f48a0 LOG                    qtmux gstqtmux.c:2319:gst_qt_mux_add_buffer:<mux> Adding 1 samples to track, duration: 100 size: 6145 chunk offset: 1665581</font></div>
<div><font face="courier new, monospace">0:00:21.687157000 88586 0x7fe8b40f48a0 DEBUG                  qtmux gstqtmux.c:2347:gst_qt_mux_add_buffer: dts: 0:00:19.633333333 pts: 0:00:19.599999999 timebase_dts: 58900 pts_offset: -100</font></div>
<div><font face="courier new, monospace">0:00:21.687178000 88586 0x7fe8b40f48a0 LOG                    qtmux gstqtmux.c:1203:gst_qt_mux_send_buffer:<mux> sending buffer size 6145</font></div><div><font face="courier new, monospace">0:00:21.687188000 88586 0x7fe8b40f48a0 LOG                    qtmux gstqtmux.c:1219:gst_qt_mux_send_buffer:<mux> downstream</font></div>
<div><span style="font-family:'courier new',monospace">0:00:21.720409000 88586 0x7fe8b40f48a0 DEBUG                  qtmux gstqtmux.c:3232:gst_qt_mux_release_pad:<mux> Releasing mux:video_0</span><br></div><div>
<font face="courier new, monospace">0:00:21.720431000 88586 0x7fe8b40f48a0 DEBUG                  qtmux gstqtmux.c:3236:gst_qt_mux_release_pad: Checking mux:video_0</font></div></div><div><br></div><div><br></div><div>Also, to answer some of your questions:</div>
<div><br></div><div> * yes, the source is "is-live"</div><div> * I'm setting the queue's max-size-bytes to 10 MB for now; leaky = downstream</div><div> * I haven't implemented the key frame check yet, but I see how to do that</div>
<div class="gmail_extra"> * what is avc stream format? Does that mean setting x264enc byte-stream=true?</div><div class="gmail_extra"><br>Thanks again for any enlightenment you can offer; I really appreciate it.</div><div class="gmail_extra">
<br></div><div class="gmail_extra">-Todd</div><div class="gmail_extra"><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 28, 2013 at 6:53 AM, Sebastian Dröge <span dir="ltr"><<a href="mailto:sebastian@centricular.com" target="_blank">sebastian@centricular.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class=""><div class="h5">On Fr, 2013-12-27 at 10:04 -0500, Todd Agulnick wrote:<br>

> Hi,<br>
><br>
> I'm trying to build a server application that allows a client to request a<br>
> video covering a specific time range in the recent past from a camera<br>
> attached to the server.<br>
><br>
> My plan is to block the source pad of a leaky queue which is set up to hold<br>
> ~ 1 GB of encoded video, with the queue always running full and dropping<br>
> old video as the new video arrives. The first part of the pipeline looks<br>
> something like:<br>
><br>
> videotestsrc ! videoconvert ! queue ! x264enc ! queue<br>
><br>
> On a signal from the the client, the controlling app would unblock the<br>
> queue's source pad, inspecting each buffer as it comes through: drop any<br>
> buffers that are before the requested time window, pass through to a mux<br>
> and filesink any buffers within the requested window, and send along an EOS<br>
> to wrap things up and block the queue again as soon as it sees a buffer<br>
> timestamped after the requested window. (Requests will always be<br>
> non-overlapping and in chronological order.)<br>
><br>
> To handle a request, the app would append to the above pipeline:<br>
><br>
> mp4mux ! filesink<br>
><br>
> ... and then tear those elements down again to wait for the next request.<br>
><br>
> My questions are:<br>
><br>
>  * Are blocking probes the right tool here? The documentation suggests that<br>
> blocking probes are really intended for short-term blockages, but in this<br>
> system the normal state is that the stream is blocked and accumulating in<br>
> the queue. I worry whether this will have unexpected consequences, and<br>
> indeed my experiments thus far have failed to produce a proper MP4 file.<br>
<br>
</div></div>Is your source creating data in real time? What limits are you using on<br>
the queue? In general this should work if the source is creating data in<br>
real time.<br>
<br>
How did your experiments fail so far? Did you make sure the MP4 files<br>
are finalized before trying to play them back (i.e. the muxer got the<br>
EOS event and rewrote the headers)? MP4 does not support streaming<br>
unfinished files. If you need to stream the files to the client<br>
"immediately" before finishing them you have to implement something like<br>
DASH with fragmented MP4 files.<br>
<br>
Do you make sure that the first h264 data you pass to the muxer contains<br>
a keyframe and that the h264 data is in avc stream format?<br>
<div class="im"><br>
>  * Do you know of any examples of similar problems and solutions on the 1.x<br>
> codebase? The only examples I've been able to find are pre-1.x. (For<br>
> example, this one:<br>
> <a href="http://gstreamer-devel.966125.n4.nabble.com/Dynamically-updating-filesink-location-at-run-time-on-the-fly-tt4660569.html#a4660577" target="_blank">http://gstreamer-devel.966125.n4.nabble.com/Dynamically-updating-filesink-location-at-run-time-on-the-fly-tt4660569.html#a4660577</a><br>

> )<br>
<br>
</div>Yes, check this for example:<br>
<a href="http://lists.freedesktop.org/archives/gstreamer-devel/2013-December/045246.html" target="_blank">http://lists.freedesktop.org/archives/gstreamer-devel/2013-December/045246.html</a><br>
<br>
This code is creating a new muxer and filesink every now and then.<br>
<span class=""><font color="#888888"><br>
--<br>
Sebastian Dröge, Centricular Ltd - <a href="http://www.centricular.com" target="_blank">http://www.centricular.com</a><br>
Expertise, Straight from the Source<br>
</font></span><br>_______________________________________________<br>
gstreamer-devel mailing list<br>
<a href="mailto:gstreamer-devel@lists.freedesktop.org">gstreamer-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel</a><br>
<br></blockquote></div><br></div></div>