ARG_PERIODCOUNT,
ARG_PERIODSIZE,
ARG_BUFFERSIZE,
- ARG_DEBUG,
ARG_AUTORECOVER,
- ARG_MMAP
+ ARG_MMAP,
+ ARG_MAXDISCONT
};
static GstElement *parent_class = NULL;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MMAP,
g_param_spec_boolean ("mmap", "Use mmap'ed access", "Wether to use mmap (faster) or standard read/write (more compatible)",
TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAXDISCONT,
+ g_param_spec_uint64 ("max-discont", "Maximum Discontinuity", "GStreamer timeunits before the timestamp syncing starts dropping/insertting samples",
+ /* rounding errors */ 1000, GST_SECOND, GST_ALSA_DEFAULT_DISCONT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
element_class->change_state = gst_alsa_change_state;
element_class->request_new_pad = gst_alsa_request_new_pad;
case ARG_MMAP:
this->mmap = g_value_get_boolean (value);
return;
+ case ARG_MAXDISCONT:
+ this->max_discont = (GstClockTime) g_value_get_uint64 (value);
+ return;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
return;
case ARG_MMAP:
g_value_set_boolean (value, this->mmap);
break;
+ case ARG_MAXDISCONT:
+ g_value_set_uint64 (value, (guint64) this->max_discont);
+ return;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
samplestamp = gst_alsa_timestamp_to_samples (this, GST_BUFFER_TIMESTAMP (pad->buf));
if (!GST_BUFFER_TIMESTAMP_IS_VALID (pad->buf) ||
/* difference between them is < GST_ALSA_DEVIATION */
- ((this->transmitted + GST_ALSA_DEVIATION > samplestamp) &&
- (this->transmitted < GST_ALSA_DEVIATION + samplestamp))) {
+ ((this->transmitted + gst_alsa_timestamp_to_samples (this, this->max_discont) >= samplestamp) &&
+ (this->transmitted <= gst_alsa_timestamp_to_samples (this, this->max_discont) + samplestamp))) {
no_difference:
pad->size = pad->buf->size;
pad->data = pad->buf->data;
int samples = MIN (bytes, samplestamp - this->transmitted) *
(element->numpads == 1 ? this->format->channels : 1);
int size = samples * snd_pcm_format_physical_width (this->format->format) / 8;
- g_print ("Allocating %d bytes (%d silent samples) now to resync to timestamp\n", size, samples);
+ g_print ("Allocating %d bytes (%ld silent samples) now to resync to timestamp\n", size, MIN (bytes, samplestamp - this->transmitted));
pad->data = g_malloc (size);
if (!pad->data) {
g_warning ("GstAlsa: error allocating %d bytes, buffers unsynced now.", size);
}
pad->behaviour = 1;
} else if (gst_alsa_samples_to_bytes (this, this->transmitted - samplestamp) >= pad->buf->size) {
+ g_print ("Skipping %lu samples to resync (complete buffer)\n", gst_alsa_bytes_to_samples (this, pad->buf->size));
/* this buffer is way behind */
gst_buffer_unref (pad->buf);
pad->buf = NULL;
continue;
} else if (this->transmitted > samplestamp) {
gint difference = gst_alsa_samples_to_bytes (this, this->transmitted - samplestamp);
+ g_print ("Skipping %lu samples to resync\n", (gulong) this->transmitted - samplestamp);
/* this buffer is only a bit behind */
pad->size = pad->buf->size - difference;
pad->data = pad->buf->data + difference;
GstClockTimeDiff diff;
GstAlsaClock *this = GST_ALSA_CLOCK (clock);
- entry_time = this->get_time (this->owner);
+ entry_time = gst_alsa_clock_get_internal_time (clock);
diff = GST_CLOCK_ENTRY_TIME (entry) - gst_clock_get_time (clock);
if (diff < 0)
" now %" G_GUINT64_FORMAT,
target, GST_CLOCK_ENTRY_TIME (entry), entry_time);
- while (this->get_time (this->owner) < target && this->last_unlock < entry_time) {
+ while (gst_alsa_clock_get_internal_time (clock) < target && this->last_unlock < entry_time) {
g_usleep (gst_alsa_clock_get_resolution (clock) * G_USEC_PER_SEC / GST_SECOND);
}
#define GST_ALSA_MAX_CHANNELS 64 /* we don't support more than 64 channels */
#define GST_ALSA_MIN_RATE 8000
#define GST_ALSA_MAX_RATE 192000
-/* max allowed deviation between timestamp and playback pointer before killing/inserting samples
- should be >= 1 to allow rounding errors on timestamp <=> samplerate conversions */
-#define GST_ALSA_DEVIATION 2
+/* max allowed discontinuity in time units between timestamp and playback pointer
+ before killing/inserting samples
+ should be big enough to allow smoothing errors on different video formats */
+#define GST_ALSA_DEFAULT_DISCONT (GST_SECOND / 10)
#define GST_ALSA(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_ALSA, GstAlsa)
#define GST_ALSA_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_ALSA, GstAlsaClass)
We will event insert silent samples or
drop some to sync to incoming timestamps.
*/
+ GstClockTime max_discont; /* max difference between current
+ playback timestamp and buffers timestamps
+ */
};
struct _GstAlsaClass {
GstElementClass parent_class;