basesrc: Allow for suppressing the initial negotiation
Submitted by Carlos Rafael Giani
Link to original bug (#797332)
Description
Run this example:
gst-launch-1.0 audiotestsrc ! "audio/x-raw,rate=44100" ! interaudiosink interaudiosrc ! fakesink sync=true silent=false -v
We'd expect this to negotiate the downstream caps to 44100 Hz. This is also what happens - but initially, the caps are set to 48000 Hz instead. Here's the output:
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = event ******* (fakesink0:sink) E (type: stream-start (10254), GstEventStreamStart, stream-id=(string)ea61450f33201961286324e03482a1c5, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)2;) 0x7f0e5c004c20
/GstPipeline:pipeline0/GstInterAudioSrc:interaudiosrc0.GstPad:src: caps = audio/x-raw, format=(string)S16LE, rate=(int)48000, channels=(int)2, layout=(string)interleaved
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = event ******* (fakesink0:sink) E (type: caps (12814), GstEventCaps, caps=(GstCaps)"audio/x-raw,\ format=(string)S16LE,\ rate=(int)48000,\ channels=(int)2,\ layout=(string)interleaved";) 0x7f0e5c004c90
/GstPipeline:pipeline0/GstAudioTestSrc:audiotestsrc0.GstPad:src: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1
/GstPipeline:pipeline0/GstInterAudioSink:interaudiosink0.GstPad:sink: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1
Setting pipeline to PLAYING ...
New clock: GstSystemClock
/GstPipeline:pipeline0/GstInterAudioSrc:interaudiosrc0.GstPad:src: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = event ******* (fakesink0:sink) E (type: caps (12814), GstEventCaps, caps=(GstCaps)"audio/x-raw,\ format=(string)S16LE,\ layout=(string)interleaved,\ rate=(int)44100,\ channels=(int)1";) 0x7f0e5c004d00
/GstPipeline:pipeline0/GstFakeSink:fakesink0.GstPad:sink: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = event ******* (fakesink0:sink) E (type: segment (17934), GstEventSegment, segment=(GstSegment)"GstSegment, flags=(GstSegmentFlags)GST_SEGMENT_FLAG_NONE, rate=(double)1, applied-rate=(double)1, format=(GstFormat)GST_FORMAT_TIME, base=(guint64)0, offset=(guint64)0, start=(guint64)0, stop=(guint64)18446744073709551615, time=(guint64)0, position=(guint64)0, duration=(guint64)18446744073709551615;";) 0x7f0e5c004de0
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = preroll *******
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = chain ******* (fakesink0:sink) (2400 bytes, dts: none, pts: 0:00:00.000470130, duration: 0:00:00.027210884, offset: 0, offset_end: 1200, flags: 00004840 discont gap tag-memory , meta: none) 0x7f0e540086b0
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = chain ******* (fakesink0:sink) (2204 bytes, dts: none, pts: 0:00:00.027681014, duration: 0:00:00.024988662, offset: 1200, offset_end: 2302, flags: 00000000 , meta: none) 0x7f0e540087c0
/GstPipeline:pipeline0/GstFakeSink:fakesink0: last-message = chain ******* (fakesink0:sink) (2204 bytes, dts: none, pts: 0:00:00.052669676, duration: 0:00:00.024988662, offset: 2302, offset_end: 3404, flags: 00000000 , meta: none) 0x7f0e540088d0
The reason for these initial 48000 Hz is that right at the beginning, basesrc tries to come up with fixated src caps. However, at that point, interaudiosrc does not have the actual caps yet (that is, the caps for the data that comes from interaudiosink). So, instead, interaudiosrc's fixate() function is called to fixate the template caps. The interaudiosrc.c fixate function contains this line:
gst_structure_fixate_field_nearest_int (structure, "rate", 48000);
This is not a bug in interaudiosrc. Rather, the basesrc class tries to output a caps event too early. It would be better if it were possible to inform basesrc that the srccaps will be known later, and that until then, it should not try to push a caps event downstream. It would be good to add functions to the API for this purpose.