First, thanks a lot for this project, highly appreciated!
I'm building a pipeline which uses an appsrc
, is fed raw PCM data and encodes to webm/opus. The result is read back using an appsink
.
gst.ParseLaunch("appsrc name=appsrc format=time is-live=true do-timestamp=true block=true max-bytes=128000 ! audio/x-raw,format=S16LE,channels=1,rate=48000,layout=interleaved ! audioconvert ! audioresample ! opusenc bitrate=128000 bitrate-type=vbr ! webmmux ! appsink name=appsink")
As per the GST docs, one should call gst_app_src_end_of_stream()
once one is done feeding data:
https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c
When the last byte is pushed into appsrc, you must call gst_app_src_end_of_stream () to make it send an EOS downstream.
When not sending EOS, the pipeline will hang as appsink.PullSample
will block forever.
Something similar has been discussed in issue #11 and the related PR #12 added the required code to make it possible to send an EOS event from Go's gst. The issue cited the code which says that either the above mentioned function or a normal EOS signal could be used.
I tried using the newly possible code (appsrc.SendEvent(gst.NewEosEvent())
) and the pipeline would no longer hang. However, it would randomly lose the last samples. As I am working with rather short fragments (~200ms chunks of raw PCM), I'm sometimes losing all the samples except for some 150 bytes of header information. This seems to depend on timing. When adding a short sleep (10ms were sufficient in my tests) between the .PushBuffer()
call and the .SendEvent(gst.NewEosEvent())
call, the problem vanished. However, this feels wrong and as I am working on something timing-critical, I want to avoid that sleep call.
After lots of research, I have found that others struggled with such problems as well when using a signal instead of the documented function call:
http://gstreamer-devel.966125.n4.nabble.com/How-to-handle-EOS-from-an-appsrc-to-ensure-all-frames-are-played-out-before-pipeline-closes-td4671225.html#a4671257
Therefore, I assume that the function call and the signal do not behave exactly the same. I suspect that the signal may either propagate through the pipeline immediately after being sent without the pipeline having actually finished all processing. I'm not familiar enough with C or GST to find the actual spot which would explain the difference.
However, a quick test shows that using the function call works. I am no longer losing any samples even when running without the sleep call.
I therefore propose exposing the required function gst_app_src_end_of_stream()
to Go. I will submit a PR in a minute.