gst/audiotestsrc/gstaudiotestsrc.*: Define the default property values in the usual place.

Original commit message from CVS:
* gst/audiotestsrc/gstaudiotestsrc.c:
(gst_audio_test_src_class_init), (gst_audio_test_src_init),
(gst_audio_test_src_src_fixate), (gst_audio_test_src_setcaps),
(gst_audio_test_src_start), (gst_audio_test_src_stop),
(gst_audio_test_src_do_seek), (gst_audio_test_src_check_get_range),
(gst_audio_test_src_create):
* gst/audiotestsrc/gstaudiotestsrc.h:
Define the default property values in the usual place.
Implement start/stop to reset values correctly.
Calculate the sample size only once when we negotiate.
Rename some values to make more sense.
Keep track of our byte range.
Add support for pull based scheduling. Disabled for now until we have
the whole stack working.
Set the BUFFER_OFFSET correctly.
This commit is contained in:
Wim Taymans 2008-10-10 15:45:15 +00:00
parent b735321f58
commit 81f5117fa9
3 changed files with 172 additions and 67 deletions

View file

@ -1,3 +1,21 @@
2008-10-10 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/audiotestsrc/gstaudiotestsrc.c:
(gst_audio_test_src_class_init), (gst_audio_test_src_init),
(gst_audio_test_src_src_fixate), (gst_audio_test_src_setcaps),
(gst_audio_test_src_start), (gst_audio_test_src_stop),
(gst_audio_test_src_do_seek), (gst_audio_test_src_check_get_range),
(gst_audio_test_src_create):
* gst/audiotestsrc/gstaudiotestsrc.h:
Define the default property values in the usual place.
Implement start/stop to reset values correctly.
Calculate the sample size only once when we negotiate.
Rename some values to make more sense.
Keep track of our byte range.
Add support for pull based scheduling. Disabled for now until we have
the whole stack working.
Set the BUFFER_OFFSET correctly.
2008-10-10 Sebastian Dröge <sebastian.droege@collabora.co.uk>
Based on a patch by: xavierb at gmail dot com

View file

@ -67,6 +67,13 @@ GST_ELEMENT_DETAILS ("Audio test source",
"Creates audio test signals of given frequency and volume",
"Stefan Kost <ensonic@users.sf.net>");
#define DEFAULT_SAMPLES_PER_BUFFER 1024
#define DEFAULT_WAVE GST_AUDIO_TEST_SRC_WAVE_SINE
#define DEFAULT_FREQ 440.0
#define DEFAULT_VOLUME 0.8
#define DEFAULT_IS_LIVE FALSE
#define DEFAULT_TIMESTAMP_OFFSET G_GINT64_CONSTANT (0)
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
enum
{
@ -77,6 +84,7 @@ enum
PROP_VOLUME,
PROP_IS_LIVE,
PROP_TIMESTAMP_OFFSET,
PROP_LAST
};
@ -143,6 +151,7 @@ static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc,
static void gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps);
static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc);
static gboolean gst_audio_test_src_check_get_range (GstBaseSrc * basesrc);
static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc,
GstSegment * segment);
static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc,
@ -152,6 +161,8 @@ static void gst_audio_test_src_change_wave (GstAudioTestSrc * src);
static void gst_audio_test_src_get_times (GstBaseSrc * basesrc,
GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc);
static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc);
static GstFlowReturn gst_audio_test_src_create (GstBaseSrc * basesrc,
guint64 offset, guint length, GstBuffer ** buffer);
@ -181,35 +192,42 @@ gst_audio_test_src_class_init (GstAudioTestSrcClass * klass)
g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER,
g_param_spec_int ("samplesperbuffer", "Samples per buffer",
"Number of samples in each outgoing buffer",
1, G_MAXINT, 1024, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_WAVE, g_param_spec_enum ("wave", "Waveform", "Oscillator waveform", GST_TYPE_AUDIO_TEST_SRC_WAVE, /* enum type */
GST_AUDIO_TEST_SRC_WAVE_SINE, /* default value */
1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_WAVE,
g_param_spec_enum ("wave", "Waveform", "Oscillator waveform",
GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_FREQ,
g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
0.0, 20000.0, 440.0,
0.0, 20000.0, DEFAULT_FREQ,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_VOLUME,
g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0,
1.0, 0.8,
1.0, DEFAULT_VOLUME,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_IS_LIVE,
g_param_spec_boolean ("is-live", "Is Live",
"Whether to act as a live source", FALSE,
"Whether to act as a live source", DEFAULT_IS_LIVE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
"Timestamp offset",
"An offset added to timestamps set on buffers (in ns)", G_MININT64,
G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps);
gstbasesrc_class->is_seekable =
GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable);
gstbasesrc_class->check_get_range =
GST_DEBUG_FUNCPTR (gst_audio_test_src_check_get_range);
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek);
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query);
gstbasesrc_class->get_times =
GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times);
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop);
gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create);
}
@ -222,18 +240,19 @@ gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class)
src->samplerate = 44100;
src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE;
src->volume = 0.8;
src->freq = 440.0;
src->volume = DEFAULT_VOLUME;
src->freq = DEFAULT_FREQ;
/* we operate in time */
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
gst_base_src_set_live (GST_BASE_SRC (src), FALSE);
gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE);
src->samples_per_buffer = 1024;
src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER;
src->generate_samples_per_buffer = src->samples_per_buffer;
src->timestamp_offset = G_GINT64_CONSTANT (0);
src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET;
src->wave = GST_AUDIO_TEST_SRC_WAVE_SINE;
src->wave = DEFAULT_WAVE;
}
static void
@ -245,6 +264,8 @@ gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0);
GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate);
gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate);
name = gst_structure_get_name (structure);
@ -266,6 +287,8 @@ gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0);
ret = gst_structure_get_int (structure, "rate", &src->samplerate);
GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate);
name = gst_structure_get_name (structure);
if (strcmp (name, "audio/x-raw-int") == 0) {
ret &= gst_structure_get_int (structure, "width", &width);
@ -277,6 +300,26 @@ gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps)
GST_AUDIO_TEST_SRC_FORMAT_F64;
}
/* allocate a new buffer suitable for this pad */
switch (src->format) {
case GST_AUDIO_TEST_SRC_FORMAT_S16:
src->sample_size = sizeof (gint16);
break;
case GST_AUDIO_TEST_SRC_FORMAT_S32:
src->sample_size = sizeof (gint32);
break;
case GST_AUDIO_TEST_SRC_FORMAT_F32:
src->sample_size = sizeof (gfloat);
break;
case GST_AUDIO_TEST_SRC_FORMAT_F64:
src->sample_size = sizeof (gdouble);
break;
default:
/* can't really happen */
ret = FALSE;
break;
}
gst_audio_test_src_change_wave (src);
return ret;
@ -676,7 +719,7 @@ gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples)
if (src->accumulator >= M_PI_M2) \
src->accumulator -= M_PI_M2; \
\
if ((src->n_samples + i)%src->samplerate < 1600) { \
if ((src->next_sample + i)%src->samplerate < 1600) { \
samples[i] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \
} else { \
samples[i] = 0; \
@ -784,6 +827,30 @@ gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer,
}
}
static gboolean
gst_audio_test_src_start (GstBaseSrc * basesrc)
{
GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc);
src->next_sample = 0;
src->next_byte = 0;
src->next_time = 0;
src->check_seek_stop = FALSE;
src->eos_reached = FALSE;
src->tags_pushed = FALSE;
src->accumulator = 0;
return TRUE;
}
static gboolean
gst_audio_test_src_stop (GstBaseSrc * basesrc)
{
return TRUE;
}
/* seek to time, will be called when we operate in push mode. In pull mode we
* get the requiested byte offset. */
static gboolean
gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
{
@ -794,16 +861,17 @@ gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment)
time = segment->last_stop;
/* now move to the time indicated */
src->n_samples =
src->next_sample =
gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND);
src->running_time =
gst_util_uint64_scale_int (src->n_samples, GST_SECOND, src->samplerate);
src->next_byte = src->next_sample * src->sample_size;
src->next_time =
gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate);
g_assert (src->running_time <= time);
g_assert (src->next_time <= time);
if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
time = segment->stop;
src->n_samples_stop = gst_util_uint64_scale_int (time, src->samplerate,
src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate,
GST_SECOND);
src->check_seek_stop = TRUE;
} else {
@ -821,6 +889,13 @@ gst_audio_test_src_is_seekable (GstBaseSrc * basesrc)
return TRUE;
}
static gboolean
gst_audio_test_src_check_get_range (GstBaseSrc * basesrc)
{
/* if we can operate in pull mode */
return DEFAULT_CAN_ACTIVATE_PULL;
}
static GstFlowReturn
gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
guint length, GstBuffer ** buffer)
@ -829,14 +904,11 @@ gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
GstAudioTestSrc *src;
GstBuffer *buf;
GstClockTime next_time;
gint64 n_samples;
gint sample_size;
gint64 next_sample, next_byte;
guint bytes, samples;
src = GST_AUDIO_TEST_SRC (basesrc);
if (src->eos_reached)
return GST_FLOW_UNEXPECTED;
/* example for tagging generated data */
if (!src->tags_pushed) {
GstTagList *taglist;
@ -852,62 +924,75 @@ gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset,
src->tags_pushed = TRUE;
}
if (src->eos_reached)
return GST_FLOW_UNEXPECTED;
/* if no length was given, use our default length in samples otherwise convert
* the length in bytes to samples. */
if (length == -1)
samples = src->samples_per_buffer;
else
samples = length / src->sample_size;
/* if no offset was given, use our next logical byte */
if (offset == -1)
offset = src->next_byte;
/* now see if we are at the byteoffset we think we are */
if (offset != src->next_byte) {
GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset);
/* we have a discont in the expected sample offset, do a 'seek' */
src->next_sample = src->next_byte / src->sample_size;
src->next_time =
gst_util_uint64_scale_int (src->next_sample, GST_SECOND,
src->samplerate);
src->next_byte = offset;
}
/* check for eos */
if (src->check_seek_stop &&
(src->n_samples_stop > src->n_samples) &&
(src->n_samples_stop < src->n_samples + src->samples_per_buffer)
(src->sample_stop > src->next_sample) &&
(src->sample_stop < src->next_sample + samples)
) {
/* calculate only partial buffer */
src->generate_samples_per_buffer = src->n_samples_stop - src->n_samples;
n_samples = src->n_samples_stop;
src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
next_sample = src->sample_stop;
src->eos_reached = TRUE;
} else {
/* calculate full buffer */
src->generate_samples_per_buffer = src->samples_per_buffer;
n_samples = src->n_samples + src->samples_per_buffer;
}
next_time = gst_util_uint64_scale (n_samples, GST_SECOND,
(guint64) src->samplerate);
/* allocate a new buffer suitable for this pad */
switch (src->format) {
case GST_AUDIO_TEST_SRC_FORMAT_S16:
sample_size = sizeof (gint16);
break;
case GST_AUDIO_TEST_SRC_FORMAT_S32:
sample_size = sizeof (gint32);
break;
case GST_AUDIO_TEST_SRC_FORMAT_F32:
sample_size = sizeof (gfloat);
break;
case GST_AUDIO_TEST_SRC_FORMAT_F64:
sample_size = sizeof (gdouble);
break;
default:
sample_size = -1;
GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL),
("format wasn't negotiated before get function"));
return GST_FLOW_NOT_NEGOTIATED;
break;
src->generate_samples_per_buffer = samples;
next_sample = src->next_sample + samples;
}
if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->n_samples,
src->generate_samples_per_buffer * sample_size,
GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
bytes = src->generate_samples_per_buffer * src->sample_size;
if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->next_sample,
bytes, GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) {
return res;
}
GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->running_time;
GST_BUFFER_OFFSET_END (buf) = n_samples;
GST_BUFFER_DURATION (buf) = next_time - src->running_time;
next_byte = src->next_byte + bytes;
next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND,
src->samplerate);
gst_object_sync_values (G_OBJECT (src), src->running_time);
GST_LOG_OBJECT (src, "samplerate %d", src->samplerate);
GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT,
next_sample, GST_TIME_ARGS (next_time));
src->running_time = next_time;
src->n_samples = n_samples;
GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time;
GST_BUFFER_OFFSET (buf) = src->next_sample;
GST_BUFFER_OFFSET_END (buf) = next_sample;
GST_BUFFER_DURATION (buf) = next_time - src->next_time;
gst_object_sync_values (G_OBJECT (src), src->next_time);
src->next_time = next_time;
src->next_sample = next_sample;
src->next_byte = next_byte;
GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT,
length, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
src->generate_samples_per_buffer,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
src->process (src, GST_BUFFER_DATA (buf));

View file

@ -107,14 +107,16 @@ struct _GstAudioTestSrc {
/* audio parameters */
gint samplerate;
gint samples_per_buffer;
gint sample_size;
GstAudioTestSrcFormat format;
/*< private >*/
gboolean tags_pushed; /* send tags just once ? */
GstClockTimeDiff timestamp_offset; /* base offset */
GstClockTime running_time; /* total running time */
gint64 n_samples; /* total samples sent */
gint64 n_samples_stop;
GstClockTime next_time; /* next timestamp */
gint64 next_sample; /* next sample to send */
gint64 next_byte; /* next byte to send */
gint64 sample_stop;
gboolean check_seek_stop;
gboolean eos_reached;
gint generate_samples_per_buffer; /* used to generate a partial buffer */