...
 
Commits (3)
......@@ -83,7 +83,7 @@ gst_audio_buffer_clip (GstBuffer * buffer, const GstSegment * segment,
GstAudioMeta *meta;
GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
guint64 offset = GST_BUFFER_OFFSET_NONE, offset_end = GST_BUFFER_OFFSET_NONE;
gsize trim, size, osize;
gint trim, size, osize;
gboolean change_duration = TRUE, change_offset = TRUE, change_offset_end =
TRUE;
......@@ -222,37 +222,10 @@ gst_audio_buffer_clip (GstBuffer * buffer, const GstSegment * segment,
ret = gst_buffer_make_writable (ret);
GST_BUFFER_DURATION (ret) = duration;
}
} else if (meta && meta->layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
/* modify only the meta to avoid making copies of the planes */
gint i;
ret = gst_buffer_make_writable (buffer);
meta = gst_buffer_get_audio_meta (buffer);
meta->samples = size;
for (i = 0; i < meta->channels; i++) {
meta->offsets[i] += trim * bpf / meta->channels;
}
GST_BUFFER_TIMESTAMP (ret) = timestamp;
if (change_duration)
GST_BUFFER_DURATION (ret) = duration;
if (change_offset)
GST_BUFFER_OFFSET (ret) = offset;
if (change_offset_end)
GST_BUFFER_OFFSET_END (ret) = offset_end;
} else {
/* resize the buffer, effectively cutting out all
* the samples that are no longer relevant */
/* convert samples to bytes */
trim *= bpf;
size *= bpf;
GST_DEBUG ("trim %" G_GSIZE_FORMAT " size %" G_GSIZE_FORMAT, trim, size);
ret = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, trim, size);
gst_buffer_unref (buffer);
/* cut out all the samples that are no longer relevant */
GST_DEBUG ("trim %d, size %d", trim, size);
ret = gst_audio_buffer_truncate (buffer, bpf, trim, size);
GST_DEBUG ("timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
if (ret) {
......@@ -265,8 +238,75 @@ gst_audio_buffer_clip (GstBuffer * buffer, const GstSegment * segment,
if (change_offset_end)
GST_BUFFER_OFFSET_END (ret) = offset_end;
} else {
GST_ERROR ("copy_region failed");
GST_ERROR ("gst_audio_buffer_truncate failed");
}
}
return ret;
}
/**
* gst_audio_buffer_truncate:
* @buffer: (transfer full): The buffer to truncate.
* @bpf: size of one audio frame in bytes. This is the size of one sample *
* number of channels.
* @trim: the number of samples to remove from the beginning of the buffer
* @samples: the final number of samples that should exist in this buffer or -1
* to use all the remaining samples if you are only removing samples from the
* beginning.
*
* Truncate the buffer to finally have @samples number of samples, removing
* the necessary amount of samples from the end and @trim number of samples
* from the beginning.
*
* After calling this function the caller does not own a reference to
* @buffer anymore.
*
* Returns: (transfer full): the truncated buffer or %NULL if the arguments
* were invalid
*
* Since: UNRELEASED
*/
GstBuffer *
gst_audio_buffer_truncate (GstBuffer * buffer, gint bpf, gint trim,
gint samples)
{
GstAudioMeta *meta = NULL;
GstBuffer *ret = NULL;
gint orig_samples, i;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
g_return_val_if_fail (trim >= 0, NULL);
meta = gst_buffer_get_audio_meta (buffer);
orig_samples = meta ? meta->samples : gst_buffer_get_size (buffer) / bpf;
g_return_val_if_fail (trim < orig_samples, NULL);
g_return_val_if_fail (samples == -1 || trim + samples <= orig_samples, NULL);
if (samples == -1)
samples = orig_samples - trim;
/* nothing to truncate */
if (samples == orig_samples)
return buffer;
if (!meta || meta->layout == GST_AUDIO_LAYOUT_INTERLEAVED) {
/* interleaved */
ret = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, trim * bpf,
samples * bpf);
gst_buffer_unref (buffer);
if ((meta = gst_buffer_get_audio_meta (ret)))
meta->samples = samples;
} else {
/* non-interleaved */
ret = gst_buffer_make_writable (buffer);
meta = gst_buffer_get_audio_meta (buffer);
meta->samples = samples;
for (i = 0; i < meta->channels; i++) {
meta->offsets[i] += trim * bpf / meta->channels;
}
}
return ret;
}
......@@ -94,6 +94,9 @@ GstBuffer * gst_audio_buffer_clip (GstBuffer *buffer,
const GstSegment *segment,
gint rate, gint bpf);
GST_EXPORT
GstBuffer * gst_audio_buffer_truncate (GstBuffer *buffer,
gint bpf, gint trim, gint samples);
G_END_DECLS
......
......@@ -167,11 +167,11 @@ enum
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define CAPS \
GST_AUDIO_CAPS_MAKE ("{ S32LE, U32LE, S16LE, U16LE, S8, U8, F32LE, F64LE }") \
", layout = (string) { interleaved, non-interleaved }"
", layout = (string) { interleaved }"
#else
#define CAPS \
GST_AUDIO_CAPS_MAKE ("{ S32BE, U32BE, S16BE, U16BE, S8, U8, F32BE, F64BE }") \
", layout = (string) { interleaved, non-interleaved }"
", layout = (string) { interleaved }"
#endif
static GstStaticPadTemplate gst_adder_src_template =
......
......@@ -439,6 +439,7 @@ gst_audio_rate_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK;
GstClockTimeDiff diff;
gint rate, bpf;
GstAudioMeta *meta;
audiorate = GST_AUDIO_RATE (parent);
......@@ -492,8 +493,9 @@ gst_audio_rate_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
in_time = audiorate->next_ts;
}
meta = gst_buffer_get_audio_meta (buf);
in_size = gst_buffer_get_size (buf);
in_samples = in_size / bpf;
in_samples = meta ? meta->samples : in_size / bpf;
audiorate->in += in_samples;
/* calculate the buffer offset */
......@@ -549,6 +551,11 @@ gst_audio_rate_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
fillmap.size);
gst_buffer_unmap (fill, &fillmap);
if (audiorate->info.layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
gst_buffer_add_audio_meta (fill, audiorate->info.finfo->format,
audiorate->info.layout, audiorate->info.channels, cursamples, NULL);
}
GST_DEBUG_OBJECT (audiorate, "inserting %" G_GUINT64_FORMAT " samples",
cursamples);
......@@ -591,7 +598,7 @@ gst_audio_rate_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
} else if (in_offset < audiorate->next_offset) {
/* need to remove samples */
if (in_offset_end <= audiorate->next_offset) {
guint64 drop = in_size / bpf;
guint64 drop = in_samples;
audiorate->drop += drop;
......@@ -607,24 +614,16 @@ gst_audio_rate_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
goto beach;
} else {
guint64 truncsamples;
guint truncsize, leftsize;
GstBuffer *trunc;
guint64 truncsamples, leftsamples;
/* truncate buffer */
truncsamples = audiorate->next_offset - in_offset;
truncsize = truncsamples * bpf;
leftsize = in_size - truncsize;
leftsamples = in_samples - truncsamples;
trunc =
gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, truncsize,
leftsize);
gst_buffer_unref (buf);
buf = trunc;
buf = gst_audio_buffer_truncate (buf, bpf, truncsamples, leftsamples);
audiorate->drop += truncsamples;
audiorate->out += (leftsize / bpf);
audiorate->out += leftsamples;
GST_DEBUG_OBJECT (audiorate, "truncating %" G_GUINT64_FORMAT " samples",
truncsamples);
......