Not able to play opus encoded data without oggmux and oggdemux - linux

sender pipeline
pulsesrc name=audio_cap mute=0 ! queue ! audiorate ! queue ! audioconvert ! audioresample name=aud_resample ! audio/x-raw,rate=48000 ! queue silent=true max-size-buffers=100 flush-on-eos=true ! opusenc ! queue ! appsink sync=false async=false
Rx pipeline
appsrc caps="audio/x-opus" ! audio/x-opus,channel-mapping-family=0 ! queue ! opusdec ! audioconvert ! audioresample ! audio/x-raw,format=S16LE,rate=44100,channels=2 ! audiorate ! autoaudiosink
But if add oggmux and oggdemux it will start playing
Rx working pipeline
appsrc caps="audio/x-opus" ! audio/x-opus,channel-mapping-family=0 ! queue ! opusparse ! oggmux ! queue ! oggdemux ! opusdec ! audioconvert ! audioresample ! audio/x-raw,format=S16LE,rate=44100,channels=2 ! audiorate ! autoaudiosink

This is by design. An Opus decoder needs to be fed full opus packets.
Unfortunately, if you just turn your RAW packets that come out of the encoder into a stream of bytes, there is no way to get back to the original packet boundaries.
So you need a container like ogg or mpegts so that the original packet can be recreated.
See also https://www.rfc-editor.org/rfc/rfc6716 section 3

I have faced with almost the same problem. I have created a plugin at the end, but originally it didn't work either. Then I realized that I need to push a gst_event_new_caps event to the source pad and the receiving pipeline started to work.
GStreamer plugin src -> opusdec sink gives "error: decoder not initialized"

Related

Gstreamer duplicate 2channel audio

I would like to generate 2 audio tones using audiotestsrc but then duplicate those two channels across 16 channels (i.e 8channels of the one tone and 8channels of the other).
I have a command that generates 2 tones for 2 channels:
gst-launch-1.0 interleave name=i ! audioconvert ! wavenc ! filesink location=file.wav audiotestsrc wave=0 freq=100 volume=0.4 ! decodebin ! audioconvert ! "audio/x-raw,channels=1,channel-mask=(bitmask)0x1" ! queue ! i.sink_0 audiotestsrc wave=1 freq=150 volume=0.4 ! decodebin ! audioconvert ! "audio/x-raw,channels=1,channel-mask=(bitmask)0x2" ! queue ! i.sink_1
I also have a command that generates 1 tone across 16 channels:
gst-launch-1.0 audiotestsrc wave=0 freq=100 volume=0.4 ! audio/x-raw,rate=48000,format=S16BE ! queue ! capssetter caps="audio/x-raw,channels=16,rate=48000,channel-mask=(bitmask)0xffff" ! audioconvert ! audioresample ! wavenc ! filesink location=test.wav
So my question:
Is there a way to combine these two commands?
I tried a few different options and assumed a bitmask of
0xaaaa and 0x5555 would be needed to "map" which channels get which tones.
But I keep running into syntax errors or
WARNING: erroneous pipeline: could not link capssetter0 to i
WARNING: erroneous pipeline: could not link queue0 to i
I feel like I'm close but not quite there.
any help would be greatly appreciated.
Looks like I found a solution that works at least for an even output channel count:
gst-launch-1.0 interleave name=i audiotestsrc wave=0 freq=100 volume=0.4 ! decodebin ! audioconvert ! audio/x-raw,format=S16BE,channels=1,channel-mask=(bitmask)0x1 ! queue ! i.sink_0 audiotestsrc wave=2 freq=100 volume=0.4 ! decodebin ! audioconvert ! audio/x-raw,format=S16BE,channels=1,channel-mask=(bitmask)0x1 ! queue ! i.sink_1 i.src ! capssetter caps=audio/x-raw,format=S16BE,channels=6,channel-mask=(bitmask)0x3f ! audioconvert ! audioresample ! wavenc ! filesink location=test.wav
So the next trick would be to handle an odd output channel count. i.e 5
I tried mapping the output to 6 channels but using a channel-mask=0x1f.
Also tried mapping output to 6 channels then using:
! audioconvert ! capssetter caps="audio/x-raw,format=S16BE,channels=5,channel-mask=(bitmask)0x1f" !
neither of these worked.

Generating MP4 from HLS in gstreamer

I am trying to generate MP4s from HLS streams with discontinuity tags. Since the videos are from the same source the FPS and the WXH are the same.
I tested with the following pipeline to demux and play it and it works fine
gst-launch-1.0 -v souphttpsrc location=<HLS_URL> ! hlsdemux ! decodebin name=decoder \
! queue ! autovideosink decoder. ! queue ! autoaudiosink
To this I added the x264 enc and avenc_aac encoder to save it to a file and it keeps failing on
"gstadaptivedemux.c(2651): _src_chain (): /GstPipeline:pipeline0/GstHLSDemux:hlsdemux0"
Failing Pipeline
gst-launch-1.0 -v mp4mux name=mux faststart=true presentation-time=true ! filesink location=dipoza.mp4 \
souphttpsrc location=<HLS_URL> ! hlsdemux ! decodebin name=decoder ! queue name=q1 ! \
videoconvert ! queue name=q2 ! x264enc name=encoder ! mux. decoder. \
! queue name=q3 ! audioconvert ! queue name=q4 ! avenc_aac ! mux.
I really appreciate any help in this.
After a lot of debugging, I found the issue with my pipeline. Thanks a lot to #FlorianZwoch for asking me to move to voaacenc encoder.
voaacenc is not installed by default in gst-plugins-bad for mac. I so I had to use
brew reinstall gst-plugins-bad --with-libvo-aacenc
The following pipeline worked well with my application.
gst-launch-1.0 --gst-debug=3 mp4mux name=mux ! \
filesink location=xxxx.mp4 souphttpsrc location=<hls url> ! decodebin name=decode ! \
videoconvert ! videorate ! video/x-raw, framerate=50/1 ! queue ! x264enc ! mux. decode. ! \
audioconvert ! voaacenc ! mux.
Also in my HLS stream video segments some had 50FPS and some had 59.97FPS. So I used a videorate to default to 50. This might need to change depending on your segments
For those folks who want a C++ code of the same, please checkout my github page

Can't record both video and sound from TV card using Gstreamer

I have a SAA7134 TV card. I want to record a video with sound using Gstreamer. This command I use to make sure I can hear the audio and it works
gst-launch-1.0 alsasrc device="hw:1,0" ! queue ! audioconvert ! alsasink
This command proves that I can watch the video (also works fine)
gst-launch-1.0 v4l2src device=/dev/video0 ! xvimagesink
This command works fine and allows me to write the sound to a file
gst-launch-1.0 alsasrc device="hw:1,0" ! queue ! audioconvert ! wavenc ! filesink location=/home/out/testout.wav
But this command only writes the video without any sound
gst-launch-1.0 v4l2src device=/dev/video0 ! queue ! videoconvert ! jpegenc ! mux. alsasrc device="hw:1,0" ! queue ! audioconvert ! lamemp3enc bitrate=192 ! mux. avimux name=mux ! filesink location=/home/out/testout.avi
the same for
gst-launch-1.0 v4l2src device=/dev/video0 ! queue ! videoconvert ! theoraenc ! mux. alsasrc device="hw:1,0" ! queue ! audioconvert ! vorbisenc ! mux. oggmux name=mux ! filesink location=/home/out/testout.ogg
How to solve the problem? Thank you.
P.S. I use Ubuntu 16.04.3 LTS.
It looks like I missed one important detail about using gst-launch syntax. I took a better look and found this:
The -e option forces EOS on sources before shutting the pipeline down. This is useful when we write to files and want to shut down by killing gst-launch using CTRL+C or with the kill command
When I tested this option I finally got both the video and audio.

gst-launch-1.0 can't stream audio/video through UDP and display it on a window simultaneously

I am successfully streaming a file (audio/video) through UDP on Windows and watching it on another machine with VLC (this was covered on Stackoverflow before):
gst-launch-1.0 -v filesrc location=video.mkv ! decodebin name=dec ! videoconvert ! x264enc ! video/x-h264 ! mpegtsmux name=mux ! queue ! udpsink host=127.0.0.1 port=5000 sync=true dec. ! queue ! audioconvert ! voaacenc ! audio/mpeg ! queue ! mux.
You can test this on VLC: Media > Open Network Stream > Network URL > udp://#:5000
However, while the video is being streamed I would like to also display it on a window, so I could watch the stream myself (no audio needed).
To accomplish this, I started with a series of small experiments so I could change the original pipeline without any surprises. If you are reading this question you know my plan didn't work so well.
My first experiment was to display just the video on single window:
gst-launch-1.0 -v filesrc location=video.mkv ! decodebin ! autovideosink
Then, I changed it to display the same video on 2 windows, to make sure I understood how to work with multithreading:
gst-launch-1.0 -v filesrc location=video.mkv ! decodebin name=dec ! queue ! tee name=t t. ! queue ! videoconvert ! autovideosink t. ! autovideosink
Finally, it came the moment to blend those 2 parts together and stream the video through the network while it is displayed locally. The result is not what I expected, of course: only the first frame appears to be streamed and then everything freezes:
gst-launch-1.0 -v filesrc location=video.mkv ! decodebin name=dec ! tee name=t ! queue ! autovideosink t. ! queue ! videoconvert ! x264enc ! video/x-h264 ! mpegtsmux name=mux ! queue ! udpsink host=127.0.0.1 port=5000 sync=true dec. ! queue ! audioconvert ! voaacenc ! audio/mpeg ! queue ! mux.
It seems that the data is not flowing through the pipeline anymore (for some reason unknown to me) and my attempt to add autovideosink broke everything.
Any tips on how to do this correctly?
The right moment to split the data is right after filesrc:
gst-launch-1.0 -v filesrc location=video.mkv ! tee name=t ! queue ! decodebin ! autovideosink t. ! queue ! decodebin name=dec ! videoconvert ! x264enc ! video/x-h264 ! mpegtsmux name=mux ! queue ! udpsink host=127.0.0.1 port=5000 sync=true dec. ! queue ! audioconvert ! voaacenc ! audio/mpeg ! queue ! mux.
So the data flows directly to autovideosink before anything else happens while the other thread also joins at this very same moment, carrying the data flow to queue and the 2nd decodebin.

how to mux audio and video in gstreamer

I'm trying to mux a .ogv only video file
with a .mp3 file to get a .ogv file with both video and audio, in gstreamer (v0.10). I try this pipeline :
gst-launch-0.10 filesrc location="video.ogv" ! oggdemux ! queue ! oggmux name=mux ! filesink location="test.ogv" filesrc location="audio.mp3" ! audioconvert ! vorbisenc ! queue ! mux.
When I use this command line, i get an error :
ERROR : of element /GstPipeline:pipeline0/GstAudioConvert:audioconvert0 : not negotiated
Additional debogging information :
gstbasetransform.c(2541): gst_base_transform_handle_buffer (): /GstPipeline:pipeline0/GstAudioConvert:audioconvert0:
not negotiated
ERROR : the pipeline refuse to pass in preparation phase
I can't see what's wrong. Any suggestion ?
Thanks.
You need to add an MP3 decoder between the filesrc and audioconvert, or just decodebin e.g.
gst-launch-0.10 filesrc location="video.ogv" ! oggdemux ! queue ! oggmux name=mux ! filesink location="test.ogv"
filesrc location="audio.mp3" ! decodebin ! audioconvert ! vorbisenc ! queue ! mux.

Resources