Earlier this month I wrote a new GStreamer element that is now integrated into core and will be part of the 1.6 release. It solves yet another commonly asked question on the mailing lists and IRC: How to concatenate multiple streams without gaps between them as if they were a single stream. This is solved by the concat element now.
Here are some examples about how it can be used:
# 100 frames of the SMPTE test pattern, then the ball pattern gst-launch-1.0 concat name=c ! videoconvert ! videoscale ! autovideosink videotestsrc num-buffers=100 ! c. videotestsrc num-buffers=100 pattern=ball ! c. # Basically: $ cat file1 file2 > both gst-launch-1.0 concat name=c ! filesink location=both filesrc location=file1 ! c. filesrc location=file2 ! c. # Demuxing two MP4 files with h264 and passing them through the same decoder instance # Note: this works better if both streams have the same h264 configuration gst-launch-1.0 concat name=c ! queue ! avdec_h264 ! queue ! videoconvert ! videoscale ! autovideosink filesrc location=1.mp4 ! qtdemux ! h264parse ! c. filesrc location=2.mp4 ! qtdemux ! h264parse ! c.
If you run this in an application that also reports time and duration you will see that concat preserves the stream time, i.e. the position reporting goes back to 0 when switching to the next stream and the duration is always the one of the current stream. However the running time will be continuously increasing from stream to stream.
Also as you can notice, this only works for a single stream (i.e. one video stream or one audio stream, not a container stream with audio and video). To gaplessly concatenate multiple streams that contain multiple streams (e.g. one audio and one video track) one after another a more complex pipeline involving multiple concat elements and the streamsynchronizer element will be necessary to keep everything synchronized.
Details
The concat element has request sinkpads, and it concatenates streams in the order in which those sinkpads were requested. All streams except for the currently playing one are blocked until the currently playing one sends an EOS event, and then the next stream will be unblocked. You can request and release sinkpads at any time, and releasing the currently playing sinkpad will cause concat to switch to the next one immediately.
Currently concat only works with segments in GST_FORMAT_TIME and GST_FORMAT_BYTES format, and requires all streams to have the same segment format.
From an application side you could implement the same behaviour as concat implements by using pad probes (waiting for EOS) and using pad offsets (gst_pad_set_offset()) to adjust the running times. But by using the concat element this should be a lot easier to implement.