1 /* GStreamer 2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> 3 * 2005 Wim Taymans <wim@fluendo.com> 4 * 5 * gstaudiobasesink.h: 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public 18 * License along with this library; if not, write to the 19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23 /* a base class for audio sinks. 24 * 25 * It uses a ringbuffer to schedule playback of samples. This makes 26 * it very easy to drop or insert samples to align incoming 27 * buffers to the exact playback timestamp. 28 * 29 * Subclasses must provide a ringbuffer pointing to either DMA 30 * memory or regular memory. A subclass should also call a callback 31 * function when it has played N segments in the buffer. The subclass 32 * is free to use a thread to signal this callback, use EIO or any 33 * other mechanism. 34 * 35 * The base class is able to operate in push or pull mode. The chain 36 * mode will queue the samples in the ringbuffer as much as possible. 37 * The available space is calculated in the callback function. 38 * 39 * The pull mode will pull_range() a new buffer of N samples with a 40 * configurable latency. This allows for high-end real time 41 * audio processing pipelines driven by the audiosink. The callback 42 * function will be used to perform a pull_range() on the sinkpad. 43 * The thread scheduling the callback can be a real-time thread. 44 * 45 * Subclasses must implement a GstAudioRingBuffer in addition to overriding 46 * the methods in GstBaseSink and this class. 47 */ 48 49 #ifndef __GST_AUDIO_AUDIO_H__ 50 #include <gst/audio/audio.h> 51 #endif 52 53 #ifndef __GST_AUDIO_BASE_SINK_H__ 54 #define __GST_AUDIO_BASE_SINK_H__ 55 56 #include <gst/base/gstbasesink.h> 57 58 G_BEGIN_DECLS 59 60 #define GST_TYPE_AUDIO_BASE_SINK (gst_audio_base_sink_get_type()) 61 #define GST_AUDIO_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_BASE_SINK,GstAudioBaseSink)) 62 #define GST_AUDIO_BASE_SINK_CAST(obj) ((GstAudioBaseSink*)obj) 63 #define GST_AUDIO_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_BASE_SINK,GstAudioBaseSinkClass)) 64 #define GST_AUDIO_BASE_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIO_BASE_SINK, GstAudioBaseSinkClass)) 65 #define GST_IS_AUDIO_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_BASE_SINK)) 66 #define GST_IS_AUDIO_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_BASE_SINK)) 67 68 /** 69 * GST_AUDIO_BASE_SINK_CLOCK: 70 * @obj: a #GstAudioBaseSink 71 * 72 * Get the #GstClock of @obj. 73 */ 74 #define GST_AUDIO_BASE_SINK_CLOCK(obj) (GST_AUDIO_BASE_SINK (obj)->clock) 75 /** 76 * GST_AUDIO_BASE_SINK_PAD: 77 * @obj: a #GstAudioBaseSink 78 * 79 * Get the sink #GstPad of @obj. 80 */ 81 #define GST_AUDIO_BASE_SINK_PAD(obj) (GST_BASE_SINK (obj)->sinkpad) 82 83 /** 84 * GstAudioBaseSinkSlaveMethod: 85 * @GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE: Resample to match the master clock 86 * @GST_AUDIO_BASE_SINK_SLAVE_SKEW: Adjust playout pointer when master clock 87 * drifts too much. 88 * @GST_AUDIO_BASE_SINK_SLAVE_NONE: No adjustment is done. 89 * @GST_AUDIO_BASE_SINK_SLAVE_CUSTOM: Use custom clock slaving algorithm (Since: 1.6) 90 * 91 * Different possible clock slaving algorithms used when the internal audio 92 * clock is not selected as the pipeline master clock. 93 */ 94 typedef enum 95 { 96 GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE, 97 GST_AUDIO_BASE_SINK_SLAVE_SKEW, 98 GST_AUDIO_BASE_SINK_SLAVE_NONE, 99 GST_AUDIO_BASE_SINK_SLAVE_CUSTOM 100 } GstAudioBaseSinkSlaveMethod; 101 102 typedef struct _GstAudioBaseSink GstAudioBaseSink; 103 typedef struct _GstAudioBaseSinkClass GstAudioBaseSinkClass; 104 typedef struct _GstAudioBaseSinkPrivate GstAudioBaseSinkPrivate; 105 106 /** 107 * GstAudioBaseSinkDiscontReason: 108 * @GST_AUDIO_BASE_SINK_DISCONT_REASON_NO_DISCONT: No discontinuity occurred 109 * @GST_AUDIO_BASE_SINK_DISCONT_REASON_NEW_CAPS: New caps are set, causing renegotiotion 110 * @GST_AUDIO_BASE_SINK_DISCONT_REASON_FLUSH: Samples have been flushed 111 * @GST_AUDIO_BASE_SINK_DISCONT_REASON_SYNC_LATENCY: Sink was synchronized to the estimated latency (occurs during initialization) 112 * @GST_AUDIO_BASE_SINK_DISCONT_REASON_ALIGNMENT: Aligning buffers failed because the timestamps are too discontinuous 113 * @GST_AUDIO_BASE_SINK_DISCONT_REASON_DEVICE_FAILURE: Audio output device experienced and recovered from an error but introduced latency in the process (see also gst_audio_base_sink_report_device_failure()) 114 * 115 * Different possible reasons for discontinuities. This enum is useful for the custom 116 * slave method. 117 * 118 * Since: 1.6 119 */ 120 typedef enum 121 { 122 GST_AUDIO_BASE_SINK_DISCONT_REASON_NO_DISCONT, 123 GST_AUDIO_BASE_SINK_DISCONT_REASON_NEW_CAPS, 124 GST_AUDIO_BASE_SINK_DISCONT_REASON_FLUSH, 125 GST_AUDIO_BASE_SINK_DISCONT_REASON_SYNC_LATENCY, 126 GST_AUDIO_BASE_SINK_DISCONT_REASON_ALIGNMENT, 127 GST_AUDIO_BASE_SINK_DISCONT_REASON_DEVICE_FAILURE 128 } GstAudioBaseSinkDiscontReason; 129 130 /** 131 * GstAudioBaseSinkCustomSlavingCallback: 132 * @sink: a #GstAudioBaseSink 133 * @etime: external clock time 134 * @itime: internal clock time 135 * @requested_skew: skew amount requested by the callback 136 * @discont_reason: reason for discontinuity (if any) 137 * @user_data: user data 138 * 139 * This function is set with gst_audio_base_sink_set_custom_slaving_callback() 140 * and is called during playback. It receives the current time of external and 141 * internal clocks, which the callback can then use to apply any custom 142 * slaving/synchronization schemes. 143 * 144 * The external clock is the sink's element clock, the internal one is the 145 * internal audio clock. The internal audio clock's calibration is applied to 146 * the timestamps before they are passed to the callback. The difference between 147 * etime and itime is the skew; how much internal and external clock lie apart 148 * from each other. A skew of 0 means both clocks are perfectly in sync. 149 * itime > etime means the external clock is going slower, while itime < etime 150 * means it is going faster than the internal clock. etime and itime are always 151 * valid timestamps, except for when a discontinuity happens. 152 * 153 * requested_skew is an output value the callback can write to. It informs the 154 * sink of whether or not it should move the playout pointer, and if so, by how 155 * much. This pointer is only NULL if a discontinuity occurs; otherwise, it is 156 * safe to write to *requested_skew. The default skew is 0. 157 * 158 * The sink may experience discontinuities. If one happens, discont is TRUE, 159 * itime, etime are set to GST_CLOCK_TIME_NONE, and requested_skew is NULL. 160 * This makes it possible to reset custom clock slaving algorithms when a 161 * discontinuity happens. 162 * 163 * Since: 1.6 164 */ 165 typedef void (*GstAudioBaseSinkCustomSlavingCallback) (GstAudioBaseSink *sink, GstClockTime etime, GstClockTime itime, GstClockTimeDiff *requested_skew, GstAudioBaseSinkDiscontReason discont_reason, gpointer user_data); 166 167 /** 168 * GstAudioBaseSink: 169 * 170 * Opaque #GstAudioBaseSink. 171 */ 172 struct _GstAudioBaseSink { 173 GstBaseSink element; 174 175 /*< protected >*/ /* with LOCK */ 176 /* our ringbuffer */ 177 GstAudioRingBuffer *ringbuffer; 178 179 /* required buffer and latency in microseconds */ 180 guint64 buffer_time; 181 guint64 latency_time; 182 183 /* the next sample to write */ 184 guint64 next_sample; 185 186 /* clock */ 187 GstClock *provided_clock; 188 189 /* with g_atomic_; currently rendering eos */ 190 gboolean eos_rendering; 191 192 /*< private >*/ 193 GstAudioBaseSinkPrivate *priv; 194 195 gpointer _gst_reserved[GST_PADDING]; 196 }; 197 198 /** 199 * GstAudioBaseSinkClass: 200 * @parent_class: the parent class. 201 * @create_ringbuffer: create and return a #GstAudioRingBuffer to write to. 202 * @payload: payload data in a format suitable to write to the sink. If no 203 * payloading is required, returns a reffed copy of the original 204 * buffer, else returns the payloaded buffer with all other metadata 205 * copied. 206 * 207 * #GstAudioBaseSink class. Override the vmethod to implement 208 * functionality. 209 */ 210 struct _GstAudioBaseSinkClass { 211 GstBaseSinkClass parent_class; 212 213 /* subclass ringbuffer allocation */ 214 GstAudioRingBuffer* (*create_ringbuffer) (GstAudioBaseSink *sink); 215 216 /* subclass payloader */ 217 GstBuffer* (*payload) (GstAudioBaseSink *sink, 218 GstBuffer *buffer); 219 /*< private >*/ 220 gpointer _gst_reserved[GST_PADDING]; 221 }; 222 223 GST_AUDIO_API 224 GType gst_audio_base_sink_get_type(void); 225 226 GST_AUDIO_API 227 GstAudioRingBuffer * 228 gst_audio_base_sink_create_ringbuffer (GstAudioBaseSink *sink); 229 230 GST_AUDIO_API 231 void gst_audio_base_sink_set_provide_clock (GstAudioBaseSink *sink, gboolean provide); 232 233 GST_AUDIO_API 234 gboolean gst_audio_base_sink_get_provide_clock (GstAudioBaseSink *sink); 235 236 GST_AUDIO_API 237 void gst_audio_base_sink_set_slave_method (GstAudioBaseSink *sink, 238 GstAudioBaseSinkSlaveMethod method); 239 GST_AUDIO_API 240 GstAudioBaseSinkSlaveMethod 241 gst_audio_base_sink_get_slave_method (GstAudioBaseSink *sink); 242 243 GST_AUDIO_API 244 void gst_audio_base_sink_set_drift_tolerance (GstAudioBaseSink *sink, 245 gint64 drift_tolerance); 246 GST_AUDIO_API 247 gint64 gst_audio_base_sink_get_drift_tolerance (GstAudioBaseSink *sink); 248 249 GST_AUDIO_API 250 void gst_audio_base_sink_set_alignment_threshold (GstAudioBaseSink * sink, 251 GstClockTime alignment_threshold); 252 GST_AUDIO_API 253 GstClockTime 254 gst_audio_base_sink_get_alignment_threshold (GstAudioBaseSink * sink); 255 256 GST_AUDIO_API 257 void gst_audio_base_sink_set_discont_wait (GstAudioBaseSink * sink, 258 GstClockTime discont_wait); 259 GST_AUDIO_API 260 GstClockTime 261 gst_audio_base_sink_get_discont_wait (GstAudioBaseSink * sink); 262 263 GST_AUDIO_API 264 void 265 gst_audio_base_sink_set_custom_slaving_callback (GstAudioBaseSink * sink, 266 GstAudioBaseSinkCustomSlavingCallback callback, 267 gpointer user_data, 268 GDestroyNotify notify); 269 270 GST_AUDIO_API 271 void gst_audio_base_sink_report_device_failure (GstAudioBaseSink * sink); 272 273 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstAudioBaseSink, gst_object_unref) 274 275 G_END_DECLS 276 277 #endif /* __GST_AUDIO_BASE_SINK_H__ */ 278